xref: /third_party/toybox/toys/posix/strings.c (revision 0f66f451)
1/*strings.c - print the strings of printable characters in files.
2 *
3 * Copyright 2014 Kyung-su Kim <kaspyx@gmail.com>
4 * Copyright 2014 Kyungwan Han <asura321@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
15USE_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
16
17config 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
34GLOBALS(
35  long n;
36  char *t;
37)
38
39static void do_strings(int fd, char *filename)
40{
41  int nread, i, wlen = TT.n, 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 (FLAG(f)) printf("%s: ", filename);
70          if (FLAG(o) || FLAG(t)) printf(pattern, (long long)(offset - wlen));
71          printf("%s", string);
72        }
73      }
74      continue;
75    }
76flush:
77    // End of previous string
78    if (count == wlen) xputc('\n');
79    count = 0;
80  }
81  free(string);
82}
83
84void strings_main(void)
85{
86  loopfiles(toys.optargs, do_strings);
87}
88