blob: 4d9bfe6901cd96f15db6daacd37b36ea10cb37b7 [file] [log] [blame]
Eric Andersenef5e8f82002-11-07 02:09:37 +00001/* vi: set sw=4 ts=4: */
2/*
3 * strings implementation for busybox
4 *
Denis Vlasenko4b570942008-11-23 14:58:14 +00005 * Copyright 2003 Tito Ragusa <farmatito@tiscali.it>
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00006 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02007 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Eric Andersenef5e8f82002-11-07 02:09:37 +00008 */
Denys Vlasenkofb4da162016-11-22 23:14:24 +01009//config:config STRINGS
10//config: bool "strings"
11//config: default y
12//config: help
13//config: strings prints the printable character sequences for each file
14//config: specified.
Eric Andersenef5e8f82002-11-07 02:09:37 +000015
Denys Vlasenkof88e3bf2016-11-22 23:54:17 +010016//applet:IF_STRINGS(APPLET(strings, BB_DIR_USR_BIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_STRINGS) += strings.o
19
Pere Orga5bc8c002011-04-11 03:29:49 +020020//usage:#define strings_trivial_usage
Tito Ragusa69312e82016-10-24 21:52:10 +020021//usage: "[-fo] [-t o/d/x] [-n LEN] [FILE]..."
Pere Orga5bc8c002011-04-11 03:29:49 +020022//usage:#define strings_full_usage "\n\n"
23//usage: "Display printable strings in a binary file\n"
Tito Ragusa69312e82016-10-24 21:52:10 +020024//We usually don't bother user with "nop" options. They work, but are not shown:
25////usage: "\n -a Scan whole file (default)"
26//unimplemented alternative is -d: Only strings from initialized, loaded data sections
27//usage: "\n -f Precede strings with filenames"
28//usage: "\n -o Precede strings with octal offsets"
29//usage: "\n -t o/d/x Precede strings with offsets in base 8/10/16"
30//usage: "\n -n LEN At least LEN characters form a string (default 4)"
Pere Orga5bc8c002011-04-11 03:29:49 +020031
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000032#include "libbb.h"
Eric Andersenef5e8f82002-11-07 02:09:37 +000033
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +020034#define WHOLE_FILE 1
35#define PRINT_NAME 2
36#define PRINT_OFFSET 4
37#define SIZE 8
Tito Ragusa69312e82016-10-24 21:52:10 +020038#define PRINT_RADIX 16
Rob Landley16cd02e2005-06-07 03:21:20 +000039
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000040int strings_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000041int strings_main(int argc UNUSED_PARAM, char **argv)
Eric Andersenef5e8f82002-11-07 02:09:37 +000042{
Denis Vlasenko787d9262007-06-17 12:19:07 +000043 int n, c, status = EXIT_SUCCESS;
Denis Vlasenko787d9262007-06-17 12:19:07 +000044 unsigned count;
45 off_t offset;
Denis Vlasenko62a90cd2008-03-17 09:07:36 +000046 FILE *file;
Rob Landley16cd02e2005-06-07 03:21:20 +000047 char *string;
48 const char *fmt = "%s: ";
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +000049 const char *n_arg = "4";
Tito Ragusa69312e82016-10-24 21:52:10 +020050 /* default for -o */
51 const char *radix = "o";
52 char *radix_fmt;
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000053
Tito Ragusa69312e82016-10-24 21:52:10 +020054 getopt32(argv, "afon:t:", &n_arg, &radix);
Rob Landley16cd02e2005-06-07 03:21:20 +000055 /* -a is our default behaviour */
Denis Vlasenko787d9262007-06-17 12:19:07 +000056 /*argc -= optind;*/
Eric Andersenef5e8f82002-11-07 02:09:37 +000057 argv += optind;
58
Denis Vlasenko787d9262007-06-17 12:19:07 +000059 n = xatou_range(n_arg, 1, INT_MAX);
Rob Landleya6e131d2006-05-29 06:43:55 +000060 string = xzalloc(n + 1);
Rob Landley16cd02e2005-06-07 03:21:20 +000061 n--;
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000062
Tito Ragusa69312e82016-10-24 21:52:10 +020063 if ((radix[0] != 'd' && radix[0] != 'o' && radix[0] != 'x') || radix[1] != 0)
64 bb_show_usage();
65
66 radix_fmt = xasprintf("%%7"OFF_FMT"%s ", radix);
67
Denis Vlasenko787d9262007-06-17 12:19:07 +000068 if (!*argv) {
Rob Landley16cd02e2005-06-07 03:21:20 +000069 fmt = "{%s}: ";
Denis Vlasenko787d9262007-06-17 12:19:07 +000070 *--argv = (char *)bb_msg_standard_input;
Eric Andersen65ddf772003-01-13 23:19:31 +000071 }
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000072
Rob Landley16cd02e2005-06-07 03:21:20 +000073 do {
Denis Vlasenko62a90cd2008-03-17 09:07:36 +000074 file = fopen_or_warn_stdin(*argv);
Denis Vlasenko787d9262007-06-17 12:19:07 +000075 if (!file) {
76 status = EXIT_FAILURE;
77 continue;
78 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000079 offset = 0;
80 count = 0;
81 do {
82 c = fgetc(file);
Denys Vlasenko8684cbb2009-11-18 11:34:43 +010083 if (isprint_asciionly(c) || c == '\t') {
Denis Vlasenko787d9262007-06-17 12:19:07 +000084 if (count > n) {
Denis Vlasenko4daad902007-09-27 10:20:47 +000085 bb_putchar(c);
Denis Vlasenko787d9262007-06-17 12:19:07 +000086 } else {
87 string[count] = c;
88 if (count == n) {
Denis Vlasenko4b570942008-11-23 14:58:14 +000089 if (option_mask32 & PRINT_NAME) {
Rob Landley16cd02e2005-06-07 03:21:20 +000090 printf(fmt, *argv);
91 }
Tito Ragusa69312e82016-10-24 21:52:10 +020092 if (option_mask32 & (PRINT_OFFSET | PRINT_RADIX)) {
93 printf(radix_fmt, offset - n);
Rob Landley16cd02e2005-06-07 03:21:20 +000094 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000095 fputs(string, stdout);
Eric Andersen92b7e7b2003-03-13 18:49:45 +000096 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000097 count++;
Eric Andersen92b7e7b2003-03-13 18:49:45 +000098 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000099 } else {
100 if (count > n) {
Denis Vlasenko4daad902007-09-27 10:20:47 +0000101 bb_putchar('\n');
Denis Vlasenko787d9262007-06-17 12:19:07 +0000102 }
103 count = 0;
104 }
105 offset++;
106 } while (c != EOF);
107 fclose_if_not_stdin(file);
108 } while (*++argv);
Rob Landley658d2cf2005-09-08 03:11:58 +0000109
Tito Ragusa69312e82016-10-24 21:52:10 +0200110 if (ENABLE_FEATURE_CLEAN_UP) {
Bernhard Reutner-Fischer08173132006-02-27 22:34:41 +0000111 free(string);
Tito Ragusa69312e82016-10-24 21:52:10 +0200112 free(radix_fmt);
113 }
Rob Landley658d2cf2005-09-08 03:11:58 +0000114
Denis Vlasenkof0ed3762006-10-26 23:21:47 +0000115 fflush_stdout_and_exit(status);
Eric Andersenef5e8f82002-11-07 02:09:37 +0000116}