strings.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. USE_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
  15. config STRINGS
  16. bool "strings"
  17. default y
  18. help
  19. usage: strings [-fo] [-t oxd] [-n LEN] [FILE...]
  20. Display printable strings in a binary file
  21. -f Show filename
  22. -n At least LEN characters form a string (default 4)
  23. -o Show offset (ala -t d)
  24. -t Show offset type (o=octal, d=decimal, x=hexadecimal)
  25. */
  26. #define FOR_strings
  27. #include "toys.h"
  28. GLOBALS(
  29. long n;
  30. char *t;
  31. )
  32. static void do_strings(int fd, char *filename)
  33. {
  34. int nread, i, wlen = TT.n, count = 0;
  35. off_t offset = 0;
  36. char *string = 0, pattern[8];
  37. if (TT.t) if (!(string = strchr("oxd", *TT.t))) error_exit("-t needs oxd");
  38. sprintf(pattern, "%%7ll%c ", string ? *string : 'd');
  39. // input buffer can wrap before we have enough data to output, so
  40. // copy start of string to temporary buffer until enough to output
  41. string = xzalloc(wlen+1);
  42. for (i = nread = 0; ;i++) {
  43. if (i >= nread) {
  44. nread = read(fd, toybuf, sizeof(toybuf));
  45. i = 0;
  46. if (nread < 0) perror_msg_raw(filename);
  47. if (nread < 1) {
  48. if (count) goto flush;
  49. break;
  50. }
  51. }
  52. offset++;
  53. if ((toybuf[i]>=32 && toybuf[i]<=126) || toybuf[i]=='\t') {
  54. if (count == wlen) fputc(toybuf[i], stdout);
  55. else {
  56. string[count++] = toybuf[i];
  57. if (count == wlen) {
  58. if (FLAG(f)) printf("%s: ", filename);
  59. if (FLAG(o) || FLAG(t)) printf(pattern, (long long)(offset - wlen));
  60. printf("%s", string);
  61. }
  62. }
  63. continue;
  64. }
  65. flush:
  66. // End of previous string
  67. if (count == wlen) xputc('\n');
  68. count = 0;
  69. }
  70. xclose(fd);
  71. free(string);
  72. }
  73. void strings_main(void)
  74. {
  75. loopfiles(toys.optargs, do_strings);
  76. }