blob: edd0e667d4dec02c0ab5ff6e07ed23455f4cd56f
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * strings implementation for busybox |
4 | * |
5 | * Copyright 2003 Tito Ragusa <farmatito@tiscali.it> |
6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ |
9 | //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. |
15 | |
16 | //applet:IF_STRINGS(APPLET(strings, BB_DIR_USR_BIN, BB_SUID_DROP)) |
17 | |
18 | //kbuild:lib-$(CONFIG_STRINGS) += strings.o |
19 | |
20 | //usage:#define strings_trivial_usage |
21 | //usage: "[-fo] [-t o/d/x] [-n LEN] [FILE]..." |
22 | //usage:#define strings_full_usage "\n\n" |
23 | //usage: "Display printable strings in a binary file\n" |
24 | //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)" |
31 | |
32 | #include "libbb.h" |
33 | |
34 | #define WHOLE_FILE 1 |
35 | #define PRINT_NAME 2 |
36 | #define PRINT_OFFSET 4 |
37 | #define SIZE 8 |
38 | #define PRINT_RADIX 16 |
39 | |
40 | int strings_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
41 | int strings_main(int argc UNUSED_PARAM, char **argv) |
42 | { |
43 | int c, status = EXIT_SUCCESS; |
44 | unsigned n, count; |
45 | off_t offset; |
46 | FILE *file; |
47 | char *string; |
48 | const char *fmt = "%s: "; |
49 | const char *n_arg = "4"; |
50 | /* default for -o */ |
51 | const char *radix = "o"; |
52 | char *radix_fmt; |
53 | |
54 | getopt32(argv, "afon:t:", &n_arg, &radix); |
55 | /* -a is our default behaviour */ |
56 | /*argc -= optind;*/ |
57 | argv += optind; |
58 | |
59 | n = xatou_range(n_arg, 1, INT_MAX); |
60 | string = xzalloc(n + 1); |
61 | n--; |
62 | |
63 | 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 | |
68 | if (!*argv) { |
69 | fmt = "{%s}: "; |
70 | *--argv = (char *)bb_msg_standard_input; |
71 | } |
72 | |
73 | do { |
74 | file = fopen_or_warn_stdin(*argv); |
75 | if (!file) { |
76 | status = EXIT_FAILURE; |
77 | continue; |
78 | } |
79 | offset = 0; |
80 | count = 0; |
81 | do { |
82 | c = fgetc(file); |
83 | if (isprint_asciionly(c) || c == '\t') { |
84 | if (count > n) { |
85 | bb_putchar(c); |
86 | } else { |
87 | string[count] = c; |
88 | if (count == n) { |
89 | if (option_mask32 & PRINT_NAME) { |
90 | printf(fmt, *argv); |
91 | } |
92 | if (option_mask32 & (PRINT_OFFSET | PRINT_RADIX)) { |
93 | printf(radix_fmt, offset - n); |
94 | } |
95 | fputs(string, stdout); |
96 | } |
97 | count++; |
98 | } |
99 | } else { |
100 | if (count > n) { |
101 | bb_putchar('\n'); |
102 | } |
103 | count = 0; |
104 | } |
105 | offset++; |
106 | } while (c != EOF); |
107 | fclose_if_not_stdin(file); |
108 | } while (*++argv); |
109 | |
110 | if (ENABLE_FEATURE_CLEAN_UP) { |
111 | free(string); |
112 | free(radix_fmt); |
113 | } |
114 | |
115 | fflush_stdout_and_exit(status); |
116 | } |
117 |