From 3e0e8c687eee4c292db106efab20f8e565549bf8 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 18 Jan 2024 16:42:42 -0600 Subject: [PATCH] Switch stdout default to block buffering, replace xflush() with xferror(), change xputs*() to fwrite() instead of write() but add a flush to maintain previous semantics. Then add flushes and TOYFLAG_LINEBUF until the test suite passes. --- lib/lib.h | 2 +- lib/xwrap.c | 19 +++++++++---------- main.c | 6 +++++- toys/net/httpd.c | 2 +- toys/other/blkid.c | 4 ++-- toys/other/hexedit.c | 6 +++--- toys/pending/getty.c | 3 +-- toys/pending/sh.c | 2 +- toys/pending/vi.c | 6 ++++-- toys/posix/head.c | 2 +- toys/posix/tail.c | 2 +- 11 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/lib.h b/lib/lib.h index 89e15f99..da20dd10 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -115,7 +115,7 @@ char *xstrndup(char *s, size_t n); char *xstrdup(char *s); void *xmemdup(void *s, long len); char *xmprintf(char *format, ...) printf_format; -void xflush(int flush); +void xferror(FILE *fp); void xprintf(char *format, ...) printf_format; void xputsl(char *s, int len); void xputsn(char *s); diff --git a/lib/xwrap.c b/lib/xwrap.c index c47276c4..d2e787e1 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -54,7 +54,7 @@ void xexit(void) free(al); } - xflush(1); + if (fflush(0) || ferror(stdout)) if (!toys.exitval) perror_msg("write"); _xexit(); } @@ -143,10 +143,9 @@ char *xmprintf(char *format, ...) } // if !flush just check for error on stdout without flushing -void xflush(int flush) +void xferror(FILE *fp) { - if ((flush && fflush(0)) || ferror(stdout)) - if (!toys.exitval) perror_msg("write"); + if (ferror(fp)) perror_exit("write"); } void xprintf(char *format, ...) @@ -156,14 +155,15 @@ void xprintf(char *format, ...) vprintf(format, va); va_end(va); - xflush(0); + + if (ferror(stdout)) perror_exit("stdout"); } -// Put string with length (does not append newline) +// Put string with length (does not append newline) with immediate flush void xputsl(char *s, int len) { - xflush(1); - xwrite(1, s, len); + fwrite(s, 1, len, stdout); + if (fflush(stdout) || ferror(stdout)) perror_exit("stdout"); } // xputs with no newline @@ -176,13 +176,12 @@ void xputsn(char *s) void xputs(char *s) { puts(s); - xflush(0); + xferror(stdout); } void xputc(char c) { if (EOF == fputc(c, stdout)) perror_exit("write"); - xflush(0); } // daemonize via vfork(). Does not chdir("/"), caller should do that first diff --git a/main.c b/main.c index bb8377db..93cf768e 100644 --- a/main.c +++ b/main.c @@ -154,6 +154,8 @@ void check_help(char **arg) // Setup toybox global state for this command. void toy_singleinit(struct toy_list *which, char *argv[]) { + char *buf; + toys.which = which; toys.argv = argv; toys.toycount = ARRAY_LEN(toy_list); @@ -176,7 +178,8 @@ void toy_singleinit(struct toy_list *which, char *argv[]) uselocale(newlocale(LC_CTYPE_MASK, "C.UTF-8", 0) ? : newlocale(LC_CTYPE_MASK, "en_US.UTF-8", 0)); - setvbuf(stdout, 0, (which->flags & TOYFLAG_LINEBUF) ? _IOLBF : _IONBF, 0); + buf = (which->flags & TOYFLAG_LINEBUF) ? 0 : xmalloc(4096); + setvbuf(stdout, buf, buf ? _IOFBF : _IOLBF, buf ? 4096 : 0); } } @@ -291,6 +294,7 @@ void toybox_main(void) int main(int argc, char *argv[]) { // don't segfault if our environment is crazy + // TODO mooted by kernel commit dcd46d897adb7 5.17 kernel Jan 2022 if (!*argv) return 127; // Snapshot stack location so we can detect recursion depth later. diff --git a/toys/net/httpd.c b/toys/net/httpd.c index 3cb78421..845175dd 100644 --- a/toys/net/httpd.c +++ b/toys/net/httpd.c @@ -12,7 +12,7 @@ * -ifv -p [IP:]PORT -u [USER][:GRP] -c CFGFILE * cgi: SERVER_PORT SERVER_NAME REMOTE_ADDR REMOTE_HOST REQUEST_METHOD -USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN)) +USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF)) config HTTPD bool "httpd" diff --git a/toys/other/blkid.c b/toys/other/blkid.c index e78f20d8..cdeb3a6f 100644 --- a/toys/other/blkid.c +++ b/toys/other/blkid.c @@ -5,8 +5,8 @@ * See ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.24/libblkid-docs/api-index-full.html * TODO: -U and -L should require arguments -USE_BLKID(NEWTOY(blkid, "ULo:s*[!LU]", TOYFLAG_BIN)) -USE_FSTYPE(NEWTOY(fstype, "<1", TOYFLAG_BIN)) +USE_BLKID(NEWTOY(blkid, "ULo:s*[!LU]", TOYFLAG_BIN|TOYFLAG_LINEBUF)) +USE_FSTYPE(NEWTOY(fstype, "<1", TOYFLAG_BIN|TOYFLAG_LINEBUF)) config BLKID bool "blkid" diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c index 80631ac1..3a50ed9c 100644 --- a/toys/other/hexedit.c +++ b/toys/other/hexedit.c @@ -43,7 +43,7 @@ GLOBALS( static void show_error(char *what) { printf("\e[%dH\e[41m\e[37m\e[K\e[1m%s\e[0m", TT.rows+1, what); - xflush(1); + fflush(0); msleep(500); } @@ -55,7 +55,7 @@ static int prompt(char *prompt, char *initial_value) strcpy(TT.input, initial_value); while (1) { printf("\e[%dH\e[K\e[1m%s: \e[0m%s\e[?25h", TT.rows+1, prompt, TT.input); - xflush(1); + fflush(0); key = scan_key(TT.keybuf, -1); if (key < 0 || key == 27) break; @@ -252,7 +252,7 @@ void hexedit_main(void) // Display cursor and flush output highlight(x, y, FLAG(r) ? 3 : side); - xflush(1); + fflush(0); // Wait for next key key = scan_key(TT.keybuf, -1); diff --git a/toys/pending/getty.c b/toys/pending/getty.c index 8c93a250..2d68b160 100644 --- a/toys/pending/getty.c +++ b/toys/pending/getty.c @@ -166,8 +166,7 @@ static int read_login_name(void) if (!FLAG(i)) write_issue(TT.f, &uts); - printf("%s login: ", uts.nodename); - xflush(1); + dprintf(1, "%s login: ", uts.nodename); TT.buff[0] = getchar(); if (!TT.buff[0] && TT.sc > 1) return 0; // Switch speed diff --git a/toys/pending/sh.c b/toys/pending/sh.c index 37c2052d..27dab14e 100644 --- a/toys/pending/sh.c +++ b/toys/pending/sh.c @@ -2891,7 +2891,7 @@ static struct sh_process *run_command(void) //dprintf(2, "%d builtin", getpid()); for (int xx = 0; xx<=pp->arg.c; xx++) dprintf(2, "{%s}", pp->arg.v[xx]); dprintf(2, "\n"); toy_singleinit(tl, pp->arg.v); tl->toy_main(); - xflush(0); + xexit(); } toys.rebound = 0; pp->exit = toys.exitval; diff --git a/toys/pending/vi.c b/toys/pending/vi.c index 2a5e4cab..44a22a5e 100644 --- a/toys/pending/vi.c +++ b/toys/pending/vi.c @@ -548,7 +548,8 @@ static void show_error(char *fmt, ...) vprintf(fmt, va); va_end(va); printf("\e[0m"); - xflush(1); + fflush(0); + xferror(stdout); // TODO: better integration with status line: keep // message until next operation. @@ -1619,7 +1620,8 @@ static void draw_page() printf("\e[%u;%uH%s\e[%u;%uH", TT.screen_height+1, (int) (1+TT.screen_width-strlen(toybuf)), toybuf, cy_scr+1, cx_scr+1); - xflush(1); + fflush(0); + xferror(stdout); } void vi_main(void) diff --git a/toys/posix/head.c b/toys/posix/head.c index 04e1658c..58da35a0 100644 --- a/toys/posix/head.c +++ b/toys/posix/head.c @@ -6,7 +6,7 @@ * * Deviations from posix: -c -USE_HEAD(NEWTOY(head, "?n(lines)#<0=10c(bytes)#<0qv[-nc]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_HEAD(NEWTOY(head, "?n(lines)#<0=10c(bytes)#<0qv[-nc]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF)) config HEAD bool "head" diff --git a/toys/posix/tail.c b/toys/posix/tail.c index 514bd5b8..1b17fcd5 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -6,7 +6,7 @@ * * Deviations from posix: -f waits for pipe/fifo on stdin (nonblock?). -USE_TAIL(NEWTOY(tail, "?fFs:c(bytes)-n(lines)-[-cn][-fF]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_TAIL(NEWTOY(tail, "?fFs:c(bytes)-n(lines)-[-cn][-fF]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF)) config TAIL bool "tail" -- 2.39.2