This is slightly more involved than just calling setlinebuf(3) because the code was already implicitly flushing more than once per line thanks to all the calls to the 'x' wrappers around stdio.
I've un-'x'ed putsl and putsn, given that the only caller doesn't want to flush that often, but I left them in lib/ for now. As usual I haven't added a bogus short option to correspond to --line-buffered because I fear that one day (when it's many years of existing practice too late to fix either side) we'll end up with a collision. Tested by looking at `strace -e write` output when running `grep fpu_ /proc/cpuinfo > /dev/null` with and without --line-buffered (the redirection is necessary because stdout is line buffered by default if it's a terminal). --- lib/lib.c | 17 +++++++++++++++++ lib/lib.h | 4 ++-- lib/xwrap.c | 19 ------------------- toys/posix/grep.c | 31 ++++++++++++++++--------------- 4 files changed, 35 insertions(+), 36 deletions(-)
From a11d054c523cbcd7714e3d97beec8743e154d567 Mon Sep 17 00:00:00 2001 From: Elliott Hughes <[email protected]> Date: Sun, 24 Feb 2019 14:19:10 -0800 Subject: [PATCH] grep: add --line-buffered and fix regular buffering. This is slightly more involved than just calling setlinebuf(3) because the code was already implicitly flushing more than once per line thanks to all the calls to the 'x' wrappers around stdio. I've un-'x'ed putsl and putsn, given that the only caller doesn't want to flush that often, but I left them in lib/ for now. As usual I haven't added a bogus short option to correspond to --line-buffered because I fear that one day (when it's many years of existing practice too late to fix either side) we'll end up with a collision. Tested by looking at `strace -e write` output when running `grep fpu_ /proc/cpuinfo > /dev/null` with and without --line-buffered (the redirection is necessary because stdout is line buffered by default if it's a terminal). --- lib/lib.c | 17 +++++++++++++++++ lib/lib.h | 4 ++-- lib/xwrap.c | 19 ------------------- toys/posix/grep.c | 31 ++++++++++++++++--------------- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 76d5765c..b85db90e 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -131,6 +131,23 @@ ssize_t writeall(int fd, void *buf, size_t len) return count; } +// Put string with length (does not append newline) +void putsl(char *s, int len) +{ + int out; + + while (len != (out = fwrite(s, 1, len, stdout))) { + if (out<1) perror_exit("write"); + len -= out; + s += out; + } +} + +void putsn(char *s) +{ + putsl(s, strlen(s)); +} + // skip this many bytes of input. Return 0 for success, >0 means this much // left after input skipped. off_t lskip(int fd, off_t offset) diff --git a/lib/lib.h b/lib/lib.h index bdabd4a2..5824ca93 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -125,8 +125,6 @@ char *xstrdup(char *s); void *xmemdup(void *s, long len); char *xmprintf(char *format, ...) printf_format; void xprintf(char *format, ...) printf_format; -void xputsl(char *s, int len); -void xputsn(char *s); void xputs(char *s); void xputc(char c); void xflush(void); @@ -193,6 +191,8 @@ void error_msg_raw(char *msg); void perror_msg_raw(char *msg); void error_exit_raw(char *msg); void perror_exit_raw(char *msg); +void putsl(char *s, int len); +void putsn(char *s); ssize_t readall(int fd, void *buf, size_t len); ssize_t writeall(int fd, void *buf, size_t len); off_t lskip(int fd, off_t offset); diff --git a/lib/xwrap.c b/lib/xwrap.c index 12016a21..9adf850f 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -156,25 +156,6 @@ void xprintf(char *format, ...) xflush(); } -// Put string with length (does not append newline) -void xputsl(char *s, int len) -{ - int out; - - while (len != (out = fwrite(s, 1, len, stdout))) { - if (out<1) perror_exit("write"); - len -= out; - s += out; - } - xflush(); -} - -// xputs with no newline -void xputsn(char *s) -{ - xputsl(s, strlen(s)); -} - // Write string to stdout with newline, flushing and checking for errors void xputs(char *s) { diff --git a/toys/posix/grep.c b/toys/posix/grep.c index c9a30882..6583b5e1 100644 --- a/toys/posix/grep.c +++ b/toys/posix/grep.c @@ -10,7 +10,7 @@ * echo hello | grep -f </dev/null * -USE_GREP(NEWTOY(grep, "(color):;S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rsvwcl(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EFw]", TOYFLAG_BIN)) +USE_GREP(NEWTOY(grep, "(color):;(line-buffered);S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rsvwcl(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EFw]", TOYFLAG_BIN)) USE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN)) USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN)) @@ -95,15 +95,14 @@ static void outline(char *line, char dash, char *name, long lcount, long bcount, if (!trim && FLAG(o)) return; if (name && FLAG(H)) printf("%s%s%s%c", TT.purple, name, TT.cyan, dash); if (FLAG(c)) { - printf("%s%ld", TT.grey, lcount); - xputc(TT.outdelim); + printf("%s%ld%c", TT.grey, lcount, TT.outdelim); } else if (lcount && FLAG(n)) numdash(lcount, dash); if (bcount && FLAG(b)) numdash(bcount-1, dash); if (line) { - if (FLAG(color)) xputsn(FLAG(o) ? TT.red : TT.grey); + if (FLAG(color)) putsn(FLAG(o) ? TT.red : TT.grey); // support embedded NUL bytes in output - xputsl(line, trim); - xputc(TT.outdelim); + putsl(line, trim); + putchar(TT.outdelim); } } @@ -255,7 +254,7 @@ static void do_grep(int fd, char *name) // At least one line we didn't print since match while -ABC active if (bars) { - xputs(bars); + puts(bars); bars = 0; } matched++; @@ -265,7 +264,7 @@ static void do_grep(int fd, char *name) xexit(); } if (FLAG(l)) { - xprintf("%s%c", name, TT.outdelim); + printf("%s%c", name, TT.outdelim); free(line); fclose(file); return; @@ -292,10 +291,10 @@ static void do_grep(int fd, char *name) if (matched==1) outline(FLAG(color) ? 0 : line, ':', name, lcount, bcount, ulen); if (FLAG(color)) { - xputsn(TT.grey); - if (mm->rm_so) xputsl(line, mm->rm_so); - xputsn(TT.red); - xputsl(line+mm->rm_so, mm->rm_eo-mm->rm_so); + putsn(TT.grey); + if (mm->rm_so) putsl(line, mm->rm_so); + putsn(TT.red); + putsl(line+mm->rm_so, mm->rm_eo-mm->rm_so); } if (TT.A) after = TT.A+1; @@ -311,9 +310,9 @@ static void do_grep(int fd, char *name) if (matched) { // Finish off pending line color fragment. if (FLAG(color) && !FLAG(o)) { - xputsn(TT.grey); - if (ulen > start-line) xputsl(start, ulen-(start-line)); - xputc(TT.outdelim); + putsn(TT.grey); + if (ulen > start-line) putsl(start, ulen-(start-line)); + putchar(TT.outdelim); } mcount++; } else { @@ -485,6 +484,8 @@ void grep_main(void) if (!FLAG(h) && toys.optc>1) toys.optflags |= FLAG_H; + if (FLAG(line_buffered)) setlinebuf(stdout); + if (FLAG(s)) { close(2); xopen_stdio("/dev/null", O_RDWR); -- 2.21.0.rc2.261.ga7da99ff1b-goog
_______________________________________________ Toybox mailing list [email protected] http://lists.landley.net/listinfo.cgi/toybox-landley.net
