blob: d0e6379871206d3b6314e4a445b053251fe8f75f [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
Pere Orga5bc8c002011-04-11 03:29:49 +020016//usage:#define strings_trivial_usage
Tito Ragusa69312e82016-10-24 21:52:10 +020017//usage: "[-fo] [-t o/d/x] [-n LEN] [FILE]..."
Pere Orga5bc8c002011-04-11 03:29:49 +020018//usage:#define strings_full_usage "\n\n"
19//usage: "Display printable strings in a binary file\n"
Tito Ragusa69312e82016-10-24 21:52:10 +020020//We usually don't bother user with "nop" options. They work, but are not shown:
21////usage: "\n -a Scan whole file (default)"
22//unimplemented alternative is -d: Only strings from initialized, loaded data sections
23//usage: "\n -f Precede strings with filenames"
24//usage: "\n -o Precede strings with octal offsets"
25//usage: "\n -t o/d/x Precede strings with offsets in base 8/10/16"
26//usage: "\n -n LEN At least LEN characters form a string (default 4)"
Pere Orga5bc8c002011-04-11 03:29:49 +020027
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000028#include "libbb.h"
Eric Andersenef5e8f82002-11-07 02:09:37 +000029
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +020030#define WHOLE_FILE 1
31#define PRINT_NAME 2
32#define PRINT_OFFSET 4
33#define SIZE 8
Tito Ragusa69312e82016-10-24 21:52:10 +020034#define PRINT_RADIX 16
Rob Landley16cd02e2005-06-07 03:21:20 +000035
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000036int strings_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000037int strings_main(int argc UNUSED_PARAM, char **argv)
Eric Andersenef5e8f82002-11-07 02:09:37 +000038{
Denis Vlasenko787d9262007-06-17 12:19:07 +000039 int n, c, status = EXIT_SUCCESS;
Denis Vlasenko787d9262007-06-17 12:19:07 +000040 unsigned count;
41 off_t offset;
Denis Vlasenko62a90cd2008-03-17 09:07:36 +000042 FILE *file;
Rob Landley16cd02e2005-06-07 03:21:20 +000043 char *string;
44 const char *fmt = "%s: ";
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +000045 const char *n_arg = "4";
Tito Ragusa69312e82016-10-24 21:52:10 +020046 /* default for -o */
47 const char *radix = "o";
48 char *radix_fmt;
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000049
Tito Ragusa69312e82016-10-24 21:52:10 +020050 getopt32(argv, "afon:t:", &n_arg, &radix);
Rob Landley16cd02e2005-06-07 03:21:20 +000051 /* -a is our default behaviour */
Denis Vlasenko787d9262007-06-17 12:19:07 +000052 /*argc -= optind;*/
Eric Andersenef5e8f82002-11-07 02:09:37 +000053 argv += optind;
54
Denis Vlasenko787d9262007-06-17 12:19:07 +000055 n = xatou_range(n_arg, 1, INT_MAX);
Rob Landleya6e131d2006-05-29 06:43:55 +000056 string = xzalloc(n + 1);
Rob Landley16cd02e2005-06-07 03:21:20 +000057 n--;
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000058
Tito Ragusa69312e82016-10-24 21:52:10 +020059 if ((radix[0] != 'd' && radix[0] != 'o' && radix[0] != 'x') || radix[1] != 0)
60 bb_show_usage();
61
62 radix_fmt = xasprintf("%%7"OFF_FMT"%s ", radix);
63
Denis Vlasenko787d9262007-06-17 12:19:07 +000064 if (!*argv) {
Rob Landley16cd02e2005-06-07 03:21:20 +000065 fmt = "{%s}: ";
Denis Vlasenko787d9262007-06-17 12:19:07 +000066 *--argv = (char *)bb_msg_standard_input;
Eric Andersen65ddf772003-01-13 23:19:31 +000067 }
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000068
Rob Landley16cd02e2005-06-07 03:21:20 +000069 do {
Denis Vlasenko62a90cd2008-03-17 09:07:36 +000070 file = fopen_or_warn_stdin(*argv);
Denis Vlasenko787d9262007-06-17 12:19:07 +000071 if (!file) {
72 status = EXIT_FAILURE;
73 continue;
74 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000075 offset = 0;
76 count = 0;
77 do {
78 c = fgetc(file);
Denys Vlasenko8684cbb2009-11-18 11:34:43 +010079 if (isprint_asciionly(c) || c == '\t') {
Denis Vlasenko787d9262007-06-17 12:19:07 +000080 if (count > n) {
Denis Vlasenko4daad902007-09-27 10:20:47 +000081 bb_putchar(c);
Denis Vlasenko787d9262007-06-17 12:19:07 +000082 } else {
83 string[count] = c;
84 if (count == n) {
Denis Vlasenko4b570942008-11-23 14:58:14 +000085 if (option_mask32 & PRINT_NAME) {
Rob Landley16cd02e2005-06-07 03:21:20 +000086 printf(fmt, *argv);
87 }
Tito Ragusa69312e82016-10-24 21:52:10 +020088 if (option_mask32 & (PRINT_OFFSET | PRINT_RADIX)) {
89 printf(radix_fmt, offset - n);
Rob Landley16cd02e2005-06-07 03:21:20 +000090 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000091 fputs(string, stdout);
Eric Andersen92b7e7b2003-03-13 18:49:45 +000092 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000093 count++;
Eric Andersen92b7e7b2003-03-13 18:49:45 +000094 }
Denis Vlasenko787d9262007-06-17 12:19:07 +000095 } else {
96 if (count > n) {
Denis Vlasenko4daad902007-09-27 10:20:47 +000097 bb_putchar('\n');
Denis Vlasenko787d9262007-06-17 12:19:07 +000098 }
99 count = 0;
100 }
101 offset++;
102 } while (c != EOF);
103 fclose_if_not_stdin(file);
104 } while (*++argv);
Rob Landley658d2cf2005-09-08 03:11:58 +0000105
Tito Ragusa69312e82016-10-24 21:52:10 +0200106 if (ENABLE_FEATURE_CLEAN_UP) {
Bernhard Reutner-Fischer08173132006-02-27 22:34:41 +0000107 free(string);
Tito Ragusa69312e82016-10-24 21:52:10 +0200108 free(radix_fmt);
109 }
Rob Landley658d2cf2005-09-08 03:11:58 +0000110
Denis Vlasenkof0ed3762006-10-26 23:21:47 +0000111 fflush_stdout_and_exit(status);
Eric Andersenef5e8f82002-11-07 02:09:37 +0000112}