aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/posix/strings.c73
1 files changed, 46 insertions, 27 deletions
diff --git a/toys/posix/strings.c b/toys/posix/strings.c
index d2154e79..911fc452 100644
--- a/toys/posix/strings.c
+++ b/toys/posix/strings.c
@@ -3,23 +3,29 @@
* Copyright 2014 Kyung-su Kim <kaspyx@gmail.com>
* Copyright 2014 Kyungwan Han <asura321@gmail.com>
*
- * No Standard
+ * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/strings.html
+ *
+ * Deviations from posix: we don't readahead to the end of the string to see
+ * if it ends with NUL or newline before printing. Add -o. We always do -a
+ * (and accept but don't document the flag), but that's sort of conformant.
+ * Posix' STDOUT section says things like "%o %s" and we support 64 bit offsets.
+ *
* TODO: utf8 strings
- * TODO: posix -t
-USE_STRINGS(NEWTOY(strings, "an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
+USE_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
config STRINGS
bool "strings"
default y
help
- usage: strings [-fo] [-n LEN] [FILE...]
+ usage: strings [-fo] [-t oxd] [-n LEN] [FILE...]
Display printable strings in a binary file
- -f Precede strings with filenames
+ -f Show filename
-n At least LEN characters form a string (default 4)
- -o Precede strings with decimal offsets
+ -o Show offset (ala -t d)
+ -t Show offset type (o=octal, d=decimal, x=hexadecimal)
*/
#define FOR_strings
@@ -27,38 +33,51 @@ config STRINGS
GLOBALS(
long num;
+ char *t;
)
static void do_strings(int fd, char *filename)
{
int nread, i, wlen = TT.num, count = 0;
off_t offset = 0;
- char *string = xzalloc(wlen + 1);
+ char *string = 0, pattern[8];
+
+ if (TT.t) if (!(string = strchr("oxd", *TT.t))) error_exit("-t needs oxd");
+ sprintf(pattern, "%%7ll%c ", string ? *string : 'd');
- for (;;) {
- nread = read(fd, toybuf, sizeof(toybuf));
- if (nread < 0) perror_msg_raw(filename);
- if (nread < 1) {
- if (count == wlen) xputc('\n');
- break;
+ // input buffer can wrap before we have enough data to output, so
+ // copy start of string to temporary buffer until enough to output
+ string = xzalloc(wlen+1);
+
+ for (i = nread = 0; ;i++) {
+ if (i >= nread) {
+ nread = read(fd, toybuf, sizeof(toybuf));
+ i = 0;
+ if (nread < 0) perror_msg_raw(filename);
+ if (nread < 1) {
+ if (count) goto flush;
+ break;
+ }
}
- for (i = 0; i < nread; i++, offset++) {
- if (((toybuf[i] >= 32) && (toybuf[i] <= 126)) || (toybuf[i] == '\t')) {
- if (count == wlen) fputc(toybuf[i], stdout);
- else {
- string[count++] = toybuf[i];
- if (count == wlen) {
- if (toys.optflags & FLAG_f) printf("%s: ", filename);
- if (toys.optflags & FLAG_o)
- printf("%7lld ",(long long)(offset + 1 - wlen));
- printf("%s", string);
- }
+
+ offset++;
+ if ((toybuf[i]>=32 && toybuf[i]<=126) || toybuf[i]=='\t') {
+ if (count == wlen) fputc(toybuf[i], stdout);
+ else {
+ string[count++] = toybuf[i];
+ if (count == wlen) {
+ if (toys.optflags & FLAG_f) printf("%s: ", filename);
+ if (toys.optflags & (FLAG_o|FLAG_t))
+ printf(pattern, (long long)(offset - wlen));
+ printf("%s", string);
}
- } else {
- if (count == wlen) xputc('\n');
- count = 0;
}
+ continue;
}
+flush:
+ // End of previous string
+ if (count == wlen) xputc('\n');
+ count = 0;
}
xclose(fd);
free(string);