2010/9/3 Jilles Tjoelker <[email protected]>:
> 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;
}