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