From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from relay1.UU.NET ([192.48.96.5]) by hawkwind.utcs.toronto.edu with SMTP id <2223>; Tue, 21 Sep 1993 17:09:03 -0400 Received: from spool.uu.net (via LOCALHOST) by relay1.UU.NET with SMTP (5.61/UUNET-internet-primary) id AA00959; Tue, 21 Sep 93 17:08:27 -0400 Received: from srg.UUCP by uucp3.uu.net with UUCP/RMAIL (queueing-rmail) id 170612.20930; Tue, 21 Sep 1993 17:06:12 EDT Received: from ceres.srg.af.mil by srg.srg.af.mil id aa08987; Tue, 21 Sep 93 17:01:33 EDT From: culliton@srg.af.mil (Tom Culliton x2278) X-Mailer: SCO System V Mail (version 3.2) To: rc@hawkwind.utcs.toronto.edu Subject: A patch to add builtin read Date: Tue, 21 Sep 1993 17:01:36 -0400 Message-Id: <9309211701.aa18991@ceres.srg.af.mil> OK, here it is. I've hacked up Alan's read to support readline and make my earlier realloc patch unnecessary, and made context diff's of all the affected files. The diffs assume you've been keeping up with the bug fix patches posted here. (If anyone wants a complete set of diffs against a virgin copy of 1.4 let me know and I'll mail it to you.) You'll also have to create the addon directory before applying the patch and fiddle your makefile appropriately to enable this. It trips clean and an hour of poking at it hasn't turned up any obvious stupidity. Please let me know if you turn anything up. Tom ------------------------------------------------------------------------------ *** addon.h.old Mon Sep 20 20:41:32 1993 --- addon.h Mon Sep 20 18:55:16 1993 *************** *** 36,38 **** --- 36,55 ---- extern void b_test(char **av); #endif + + #ifdef READ + + #undef ADDONS + #ifndef DWS + #define ADDONS { b_read, "read" }, + #else + #define ADDONS { b_read, "read" },\ + { b_access, "access" },\ + { b_test, "test" },\ + { b_test, "[" }, + #endif + + + extern void b_read(char **av); + + #endif *** addon.c.old Mon Sep 20 20:41:24 1993 --- addon.c Mon Sep 20 18:29:21 1993 *************** *** 20,22 **** --- 20,35 ---- #include "addon/test.c" #endif + + #ifdef READ + #ifndef DWS + #include + + #include "rc.h" /* for bool TRUE, FALSE */ + #include "addon.h" + #endif + + + #include "addon/read.c" + + #endif *** input.c.old Mon Sep 20 20:54:42 1993 --- input.c Tue Sep 21 15:29:11 1993 *************** *** 85,91 **** #ifdef READLINE #ifndef SVSIGS ! static char *rc_readline(char *prompt) { char *r; interrupt_happened = FALSE; if (!setjmp(slowbuf.j)) { --- 85,91 ---- #ifdef READLINE #ifndef SVSIGS ! char *rc_readline(char *prompt) { char *r; interrupt_happened = FALSE; if (!setjmp(slowbuf.j)) { *** addon/read.c.old Tue Sep 21 16:32:09 1993 --- addon/read.c Tue Sep 21 16:01:08 1993 *************** *** 0 **** --- 1,80 ---- + /* + b_reads -- read a single line, terminated by \n or EOF, from the standard + input, and assign the line without the terminator to av[1]. + */ + + #ifdef READLINE + #ifndef SVSIGS + extern char *rc_readline(char *); + #else + extern char *readline(char *); + #define rc_readline readline + #endif /* SVSIGS */ + extern void add_history(char *); + #endif + + static int + readchar(int fd) + { + unsigned char c; + + if (read(fd, &c, 1) == 1) + return c; + else + return EOF; + } + + void + b_read(char **av) + { + char *name; + int c; + char *line; + SIZE_T len; + SIZE_T max_len; + SIZE_T max_len_quantum; + + /* check usage is "read name" */ + if (av[1] == NULL) + rc_error("missing variable name"); + if (av[2] != NULL) + rc_error("too many arguments to read"); + name = av[1]; + + #ifdef READLINE + if (isatty(0)) { + line = rc_readline(NULL); + if (line == NULL) { + line = ealloc(1); + *line = '\0'; + c = EOF; + } else { + if (*line != '\0') + add_history(line); + c = '\n'; + } + } else + #endif + { + /* read a single line from stdin */ + len = 0; + max_len = max_len_quantum = 256; + line = ealloc(max_len); + do { + c = readchar(0); + if (len == max_len) + line = erealloc(line, max_len += max_len_quantum); + if (c == '\n' || c == EOF) + line[len] = 0; + else + line[len] = c; + len++; + } while (c != '\n' && c != EOF); + } + /* assign whatever we read to the variable */ + assign(word(name, NULL), word(line, NULL), FALSE); + efree(line); + + /* return TRUE if we terminated with a \n, otherwise FALSE */ + set(c == '\n'); + } *** addon/trip.read.old Tue Sep 21 16:32:09 1993 --- addon/trip.read Mon Sep 20 20:46:40 1993 *************** *** 0 **** --- 1,53 ---- + # trip.read -- check a read implementation performs like a true v7 sh read + + fn check { + echo $1 $2 + ./rc -c $2 + if ( ! ~ $status $1 ) { + echo failed: $2 + } + } + + check 0 true + check 1 false + + nl = ' + ' + ifs = $nl + + file = /etc/passwd + first = `{ cat $file } + first = $first(1) + + echo 'start of trip.read' + + # check read X and read '*' return 0 + check 0 'exec <$file ; read X' + check 0 'exec <$file ; read ''*''' + + # check read, read 1, read '=', and read '' return 1 + check 1 'exec <$file ; read' + check 1 'exec <$file ; read 1' + check 1 'exec <$file ; read ''=''' + check 1 'exec <$file ; read ''''' + + # check read X correctly reads first line + check 0 'exec <$file; read X ; ~ $X $first' + check 0 'echo -n $first | { read X ; ~ $X $first }' + + # check read '*' correctly reads first line, preserves $0 + check 0 'exec <$file ; old0 = $0 ; read ''*'' ; ~ $0 $old0 && ~ $1 $first && ~ $#* 1' + + # check read returns 1 on EOF and I/O error + check 1 'exec