xref: /aosp_15_r20/external/toybox/toys/posix/strings.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /*strings.c - print the strings of printable characters in files.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2014 Kyung-su Kim <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2014 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker  *
6*cf5a6c84SAndroid Build Coastguard Worker  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/strings.html
7*cf5a6c84SAndroid Build Coastguard Worker  *
8*cf5a6c84SAndroid Build Coastguard Worker  * Deviations from posix: we don't readahead to the end of the string to see
9*cf5a6c84SAndroid Build Coastguard Worker  * if it ends with NUL or newline before printing. Add -o. We always do -a
10*cf5a6c84SAndroid Build Coastguard Worker  * (and accept but don't document the flag), but that's sort of conformant.
11*cf5a6c84SAndroid Build Coastguard Worker  * Posix' STDOUT section says things like "%o %s" and we support 64 bit offsets.
12*cf5a6c84SAndroid Build Coastguard Worker  *
13*cf5a6c84SAndroid Build Coastguard Worker  * TODO: utf8 strings
14*cf5a6c84SAndroid Build Coastguard Worker 
15*cf5a6c84SAndroid Build Coastguard Worker USE_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
16*cf5a6c84SAndroid Build Coastguard Worker 
17*cf5a6c84SAndroid Build Coastguard Worker config STRINGS
18*cf5a6c84SAndroid Build Coastguard Worker   bool "strings"
19*cf5a6c84SAndroid Build Coastguard Worker   default y
20*cf5a6c84SAndroid Build Coastguard Worker   help
21*cf5a6c84SAndroid Build Coastguard Worker     usage: strings [-fo] [-t oxd] [-n LEN] [FILE...]
22*cf5a6c84SAndroid Build Coastguard Worker 
23*cf5a6c84SAndroid Build Coastguard Worker     Display printable strings in a binary file
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker     -f	Show filename
26*cf5a6c84SAndroid Build Coastguard Worker     -n	At least LEN characters form a string (default 4)
27*cf5a6c84SAndroid Build Coastguard Worker     -o	Show offset (ala -t d)
28*cf5a6c84SAndroid Build Coastguard Worker     -t	Show offset type (o=octal, d=decimal, x=hexadecimal)
29*cf5a6c84SAndroid Build Coastguard Worker */
30*cf5a6c84SAndroid Build Coastguard Worker 
31*cf5a6c84SAndroid Build Coastguard Worker #define FOR_strings
32*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
33*cf5a6c84SAndroid Build Coastguard Worker 
GLOBALS(long n;char * t;)34*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
35*cf5a6c84SAndroid Build Coastguard Worker   long n;
36*cf5a6c84SAndroid Build Coastguard Worker   char *t;
37*cf5a6c84SAndroid Build Coastguard Worker )
38*cf5a6c84SAndroid Build Coastguard Worker 
39*cf5a6c84SAndroid Build Coastguard Worker static void do_strings(int fd, char *filename)
40*cf5a6c84SAndroid Build Coastguard Worker {
41*cf5a6c84SAndroid Build Coastguard Worker   int nread, i, wlen = TT.n, count = 0;
42*cf5a6c84SAndroid Build Coastguard Worker   off_t offset = 0;
43*cf5a6c84SAndroid Build Coastguard Worker   char *string = 0, pattern[8];
44*cf5a6c84SAndroid Build Coastguard Worker 
45*cf5a6c84SAndroid Build Coastguard Worker   if (TT.t) if (!(string = strchr("oxd", *TT.t))) error_exit("-t needs oxd");
46*cf5a6c84SAndroid Build Coastguard Worker   sprintf(pattern, "%%7ll%c ", string ? *string : 'd');
47*cf5a6c84SAndroid Build Coastguard Worker 
48*cf5a6c84SAndroid Build Coastguard Worker   // input buffer can wrap before we have enough data to output, so
49*cf5a6c84SAndroid Build Coastguard Worker   // copy start of string to temporary buffer until enough to output
50*cf5a6c84SAndroid Build Coastguard Worker   string = xzalloc(wlen+1);
51*cf5a6c84SAndroid Build Coastguard Worker 
52*cf5a6c84SAndroid Build Coastguard Worker   for (i = nread = 0; ;i++) {
53*cf5a6c84SAndroid Build Coastguard Worker     if (i >= nread) {
54*cf5a6c84SAndroid Build Coastguard Worker       nread = read(fd, toybuf, sizeof(toybuf));
55*cf5a6c84SAndroid Build Coastguard Worker       i = 0;
56*cf5a6c84SAndroid Build Coastguard Worker       if (nread < 0) perror_msg_raw(filename);
57*cf5a6c84SAndroid Build Coastguard Worker       if (nread < 1) {
58*cf5a6c84SAndroid Build Coastguard Worker         if (count) goto flush;
59*cf5a6c84SAndroid Build Coastguard Worker         break;
60*cf5a6c84SAndroid Build Coastguard Worker       }
61*cf5a6c84SAndroid Build Coastguard Worker     }
62*cf5a6c84SAndroid Build Coastguard Worker 
63*cf5a6c84SAndroid Build Coastguard Worker     offset++;
64*cf5a6c84SAndroid Build Coastguard Worker     if ((toybuf[i]>=32 && toybuf[i]<=126) || toybuf[i]=='\t') {
65*cf5a6c84SAndroid Build Coastguard Worker       if (count == wlen) fputc(toybuf[i], stdout);
66*cf5a6c84SAndroid Build Coastguard Worker       else {
67*cf5a6c84SAndroid Build Coastguard Worker         string[count++] = toybuf[i];
68*cf5a6c84SAndroid Build Coastguard Worker         if (count == wlen) {
69*cf5a6c84SAndroid Build Coastguard Worker           if (FLAG(f)) printf("%s: ", filename);
70*cf5a6c84SAndroid Build Coastguard Worker           if (FLAG(o) || FLAG(t)) printf(pattern, (long long)(offset - wlen));
71*cf5a6c84SAndroid Build Coastguard Worker           printf("%s", string);
72*cf5a6c84SAndroid Build Coastguard Worker         }
73*cf5a6c84SAndroid Build Coastguard Worker       }
74*cf5a6c84SAndroid Build Coastguard Worker       continue;
75*cf5a6c84SAndroid Build Coastguard Worker     }
76*cf5a6c84SAndroid Build Coastguard Worker flush:
77*cf5a6c84SAndroid Build Coastguard Worker     // End of previous string
78*cf5a6c84SAndroid Build Coastguard Worker     if (count == wlen) xputc('\n');
79*cf5a6c84SAndroid Build Coastguard Worker     count = 0;
80*cf5a6c84SAndroid Build Coastguard Worker   }
81*cf5a6c84SAndroid Build Coastguard Worker   xclose(fd);
82*cf5a6c84SAndroid Build Coastguard Worker   free(string);
83*cf5a6c84SAndroid Build Coastguard Worker }
84*cf5a6c84SAndroid Build Coastguard Worker 
strings_main(void)85*cf5a6c84SAndroid Build Coastguard Worker void strings_main(void)
86*cf5a6c84SAndroid Build Coastguard Worker {
87*cf5a6c84SAndroid Build Coastguard Worker   loopfiles(toys.optargs, do_strings);
88*cf5a6c84SAndroid Build Coastguard Worker }
89