2010/9/3 Jilles Tjoelker <jilles@xxxxxxxx>: > This patch assumes that the file descriptor is discarded afterwards (its > position does not matter). Therefore the very common construct > while read x; do > ... > done > stops working. Ohh.. thanks for that, I didn't see it. Actually "while read x" continues to work. But "reopening the file" doesn't as in : read a b < datafile echo ${a} ${b} read a b < datafile echo ${a} ${b} I attached an updated patch that corrects this pb by discarding the buffer when opening a new file. I also put everything in new files (bufreadcmd.c & .h), in order to ease its understanding. -- Steve Schnepp http://blog.pwkf.org/ > > A possible fix is to check first if the input supports seeking. If it > does, use the buffering and at the end of the line seek backwards for > the number of bytes remaining in the buffer. If it does not, read one > byte at a time. > > -- > Jilles Tjoelker > -- Steve Schnepp http://blog.pwkf.org/
Common subdirectories: dash-0.5.4/src/bltin and dash-0.5.4-patched/src/bltin diff -puN dash-0.5.4/src/bufreadcmd.c dash-0.5.4-patched/src/bufreadcmd.c --- dash-0.5.4/src/bufreadcmd.c 1970-01-01 01:00:00.000000000 +0100 +++ dash-0.5.4-patched/src/bufreadcmd.c 2010-09-04 12:31:46.000000000 +0200 @@ -0,0 +1,59 @@ +/* + * Offers a buffered read builtin + */ + +#include <unistd.h> +#include <stdlib.h> + +#include "bufreadcmd.h" + +#ifdef BUF_READ_BUILTIN_DISABLED +int dup2_wrapper(int old, int new) { + return dup2(old, new); +} +int read_stdin_bufferred(char *c) { + return read(0, buffer, 1); +} +#else // BUF_READ_BUILTIN_DISABLED + +/* + * Reads from fd 0, with a CHUNK_READ_SIZE, + * but emitting one char at a time + */ +#define CHUNK_READ_SIZE 32 +static char buffer[CHUNK_READ_SIZE]; +static int buffer_offset = 0; +static int buffer_len = 0; + +int read_stdin_bufferred(char* c) { + if (buffer_len == 0) { + // No caracter left, resetting buffer & read some more + buffer_offset = 0; + buffer_len = read(0, buffer, CHUNK_READ_SIZE); + + if (buffer_len == 0) { + // Nothing to read anymore + return 0; + } + } + + // Still some character left + *c = buffer[buffer_offset++]; + buffer_len--; + + return 1; +} + +static void _flush_readcmd(int fd) { + if (fd == 0) { + // Flush the buffer, discarding its content + buffer_len = 0; + } +} + +/* Intercept dup2() calls */ +int dup2_wrapper(int old, int new) { + _flush_readcmd(new); + return dup2(old, new); +} +#endif // BUF_READ_BUILTIN_DISABLED diff -puN dash-0.5.4/src/bufreadcmd.h dash-0.5.4-patched/src/bufreadcmd.h --- dash-0.5.4/src/bufreadcmd.h 1970-01-01 01:00:00.000000000 +0100 +++ dash-0.5.4-patched/src/bufreadcmd.h 2010-09-04 12:23:53.000000000 +0200 @@ -0,0 +1,3 @@ +/* Used for flushing the readcmd read() buffer */ +int dup2_wrapper(int to, int from); +int read_stdin_bufferred(char *c); Common subdirectories: dash-0.5.4/src/.deps and dash-0.5.4-patched/src/.deps diff -puN dash-0.5.4/src/eval.c dash-0.5.4-patched/src/eval.c --- dash-0.5.4/src/eval.c 2007-07-13 10:26:42.000000000 +0200 +++ dash-0.5.4-patched/src/eval.c 2010-09-04 12:24:55.000000000 +0200 @@ -64,6 +64,8 @@ #include "myhistedit.h" #endif +#include "bufreadcmd.h" + /* flags in argument to evaltree */ #define EV_EXIT 01 /* exit after evaluating tree */ @@ -543,11 +545,12 @@ evalpipe(union node *n, int flags) close(pip[0]); } if (prevfd > 0) { - dup2(prevfd, 0); + dup2_wrapper(prevfd, 0); + close(prevfd); } if (pip[1] > 1) { - dup2(pip[1], 1); + dup2_wrapper(pip[1], 1); close(pip[1]); } evaltreenr(lp->n, flags); @@ -625,7 +628,7 @@ evalbackcmd(union node *n, struct backcm FORCEINTON; close(pip[0]); if (pip[1] != 1) { - dup2(pip[1], 1); + dup2_wrapper(pip[1], 1); close(pip[1]); } eflag = 0; diff -puN dash-0.5.4/src/Makefile dash-0.5.4-patched/src/Makefile --- dash-0.5.4/src/Makefile 2010-09-04 13:06:05.000000000 +0200 +++ dash-0.5.4-patched/src/Makefile 2010-09-04 13:08:26.000000000 +0200 @@ -57,7 +57,7 @@ am__objects_1 = alias.$(OBJEXT) arith_yy miscbltin.$(OBJEXT) mystring.$(OBJEXT) options.$(OBJEXT) \ parser.$(OBJEXT) redir.$(OBJEXT) show.$(OBJEXT) trap.$(OBJEXT) \ output.$(OBJEXT) printf.$(OBJEXT) system.$(OBJEXT) \ - test.$(OBJEXT) times.$(OBJEXT) var.$(OBJEXT) + test.$(OBJEXT) times.$(OBJEXT) var.$(OBJEXT) bufreadcmd.$(OBJEXT) am_dash_OBJECTS = $(am__objects_1) arith.$(OBJEXT) dash_OBJECTS = $(am_dash_OBJECTS) dash_DEPENDENCIES = builtins.o init.o nodes.o signames.o syntax.o @@ -169,14 +169,14 @@ dash_CFILES = \ alias.c arith_yylex.c cd.c error.c eval.c exec.c expand.c \ histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ mystring.c options.c parser.c redir.c show.c trap.c output.c \ - bltin/printf.c system.c bltin/test.c bltin/times.c var.c + bltin/printf.c system.c bltin/test.c bltin/times.c var.c bufreadcmd.c dash_SOURCES = \ $(dash_CFILES) arith.y \ alias.h bltin/bltin.h cd.h error.h eval.h exec.h expand.h hetio.h \ init.h input.h jobs.h machdep.h mail.h main.h memalloc.h miscbltin.h \ myhistedit.h mystring.h options.h output.h parser.h redir.h shell.h \ - show.h system.h trap.h var.h + show.h system.h trap.h var.h bufreadcmd.h dash_LDADD = builtins.o init.o nodes.o signames.o syntax.o HELPERS = mkinit mksyntax mknodes mksignames diff -puN dash-0.5.4/src/miscbltin.c dash-0.5.4-patched/src/miscbltin.c --- dash-0.5.4/src/miscbltin.c 2007-07-13 10:26:43.000000000 +0200 +++ dash-0.5.4-patched/src/miscbltin.c 2010-09-04 12:23:21.000000000 +0200 @@ -55,16 +55,17 @@ #include "miscbltin.h" #include "mystring.h" #include "main.h" +#include "bufreadcmd.h" #undef rflag - /* * The read builtin. The -e option causes backslashes to escape the * following character. * * This uses unbuffered input, which may be avoidable in some cases. + * XXX - Uses _read_bufferred() that chunks read(), but emits one char at a time */ int @@ -104,7 +105,7 @@ readcmd(int argc, char **argv) backslash = 0; STARTSTACKSTR(p); for (;;) { - if (read(0, &c, 1) != 1) { + if (read_stdin_bufferred(&c) != 1) { status = 1; break; } diff -puN dash-0.5.4/src/miscbltin.h dash-0.5.4-patched/src/miscbltin.h --- dash-0.5.4/src/miscbltin.h 2007-07-13 10:26:43.000000000 +0200 +++ dash-0.5.4-patched/src/miscbltin.h 2010-09-04 10:46:02.000000000 +0200 @@ -29,3 +29,6 @@ int readcmd(int, char **); int umaskcmd(int, char **); int ulimitcmd(int, char **); + +/* Used for flushing the readcmd read() buffer */ +void flush_readcmd(int fd); diff -puN dash-0.5.4/src/redir.c dash-0.5.4-patched/src/redir.c --- dash-0.5.4/src/redir.c 2007-07-13 10:26:43.000000000 +0200 +++ dash-0.5.4-patched/src/redir.c 2010-09-04 12:25:49.000000000 +0200 @@ -56,6 +56,8 @@ #include "memalloc.h" #include "error.h" +#include "bufreadcmd.h" + #define REALLY_CLOSED -3 /* fd that was closed and still is */ #define EMPTY -2 /* marks an unused slot in redirtab */ @@ -265,14 +267,14 @@ dupredirect(redir, f) memory[fd] = 1; else #endif - if (dup2(f, fd) < 0) { + if (dup2_wrapper(f, fd) < 0) { err = errno; goto err; } return; } f = fd; - } else if (dup2(f, fd) < 0) + } else if (dup2_wrapper(f, fd) < 0) err = errno; close(f); @@ -354,7 +356,7 @@ popredir(int drop) break; default: if (!drop) - dup2(rp->renamed[i], i); + dup2_wrapper(rp->renamed[i], i); close(rp->renamed[i]); break; }