ast@cs.vu.nl (Andy Tanenbaum) (12/20/87)
I have incorporated various fixes from the network into the shell. Here are diff files that you can apply to the V1.2 shell sources to generate the revised shell sources. When you are done, you should get something like this: -rw-r--r-- 1 ast 7321 Dec 19 16:46 sh.h -rw-r--r-- 1 ast 14508 Dec 19 16:46 sh1.c -rw-r--r-- 1 ast 11571 Dec 19 16:46 sh2.c -rw-r--r-- 1 ast 16881 Dec 19 16:46 sh3.c -rw-r--r-- 1 ast 12423 Dec 19 16:46 sh4.c -rw-r--r-- 1 ast 9219 Dec 19 16:49 sh5.c -rw-r--r-- 1 ast 92 Dec 19 16:50 sh6.c Please post any new bug reports to the net. Andy Tanenbaum (ast@cs.vu.nl) ----------------------- shar file with shell source diffs ------------------ : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin echo Extracting \s\h\.\h\.\d\i\f\f sed 's/^X//' > \s\h\.\h\.\d\i\f\f << '+ END-OF-FILE '\s\h\.\h\.\d\i\f\f X113,116c113 X< union { X< char *io_name; /* file name */ X< struct block *io_here; /* here structure pointer */ X< } io_un; X--- X> char *io_name; /* file name */ X261,266c258,261 X< #define XIO 4 /* file IO */ X< #define XHERE 0x80 /* Any of the above inside a here document */ X< #define XMASK 0x7f /* Get the actual task */ X< X< /* in substitution */ X< #define INSUB() ((e.iop->task&XMASK)==XGRAVE||(e.iop->task&XMASK)==XDOLL) X--- X> #define XIO 3 /* file IO */ X> X> /* in substitution */ X> #define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL) X273a269 X> int herechar(); X301c297 X< struct io *setbase(/* struct io * */); X--- X> struct io *setbase(/* struct io * */); X329a326 X> int getarea(/* char *obj */); + END-OF-FILE sh.h.diff chmod 'u=rw,g=r,o=r' \s\h\.\h\.\d\i\f\f set `sum \s\h\.\h\.\d\i\f\f` sum=$1 case $sum in 11281) :;; *) echo 'Bad sum in '\s\h\.\h\.\d\i\f\f >&2 esac echo Extracting \s\h\1\.\c\.\d\i\f\f sed 's/^X//' > \s\h\1\.\c\.\d\i\f\f << '+ END-OF-FILE '\s\h\1\.\c\.\d\i\f\f X213c213,215 X< freearea(areanum = 1); X--- X> areanum = 1; X> freehere(areanum); X> freearea(areanum); X907a910,916 X> int X> getarea(cp) X> char *cp; X> { X> return ((struct region*)cp-1)->area; X> } X> + END-OF-FILE sh1.c.diff chmod 'u=rw,g=r,o=r' \s\h\1\.\c\.\d\i\f\f set `sum \s\h\1\.\c\.\d\i\f\f` sum=$1 case $sum in 52924) :;; *) echo 'Bad sum in '\s\h\1\.\c\.\d\i\f\f >&2 esac echo Extracting \s\h\2\.\c\.\d\i\f\f sed 's/^X//' > \s\h\2\.\c\.\d\i\f\f << '+ END-OF-FILE '\s\h\2\.\c\.\d\i\f\f X125,129c125,131 X< while ((c = yylex(0)) == ';' || c == '&' || multiline && c == '\n') { X< if (c == '&') X< t = block(TASYNC, t, NOBLOCK, NOWORDS); X< if ((p = andor()) == NULL) X< return(t); X--- X> if((peeksym = yylex(0)) == '&') X> t = block(TASYNC, t, NOBLOCK, NOWORDS); X> while ((c = yylex(0)) == ';' || c == '&' || multiline && c == '\n') { X> if ((p = andor()) == NULL) X> return(t); X> if((peeksym = yylex(0)) == '&') X> p = block(TASYNC, p, NOBLOCK, NOWORDS); X136a139 X> X559c562 X< iop->io_un.io_name = cp; X--- X> iop->io_name = cp; + END-OF-FILE sh2.c.diff chmod 'u=rw,g=r,o=r' \s\h\2\.\c\.\d\i\f\f set `sum \s\h\2\.\c\.\d\i\f\f` sum=$1 case $sum in 41193) :;; *) echo 'Bad sum in '\s\h\2\.\c\.\d\i\f\f >&2 esac echo Extracting \s\h\3\.\c\.\d\i\f\f sed 's/^X//' > \s\h\3\.\c\.\d\i\f\f << '+ END-OF-FILE '\s\h\3\.\c\.\d\i\f\f X177a178 X> freehere(areanum); X270,271d270 X< if (t->type == TPAREN) X< exit(execute(t->left, NOPIPE, NOPIPE, FEXEC)); X275a275,276 X> if (t->type == TPAREN) X> exit(execute(t->left, NOPIPE, NOPIPE, FEXEC)); X322c323 X< cp = iop->io_un.io_name; X--- X> cp = iop->io_name; X343c344 X< u = herein(iop->io_un.io_here, iop->io_flag&IOXHERE); X--- X> u = herein(iop->io_name, iop->io_flag&IOXHERE); + END-OF-FILE sh3.c.diff chmod 'u=rw,g=r,o=r' \s\h\3\.\c\.\d\i\f\f set `sum \s\h\3\.\c\.\d\i\f\f` sum=$1 case $sum in 31980) :;; *) echo 'Bad sum in '\s\h\3\.\c\.\d\i\f\f >&2 esac echo Extracting \s\h\4\.\c\.\d\i\f\f sed 's/^X//' > \s\h\4\.\c\.\d\i\f\f << '+ END-OF-FILE '\s\h\4\.\c\.\d\i\f\f X350,354c350,352 X< X< /* jrp debug */ X< scraphere(); X< X< freearea(areanum = 1); /* free old space */ X--- X> areanum = 1; X> freehere(areanum); X> freearea(areanum); /* free old space */ X726a725,737 X> X> char * X> memcpy(ato, from, nb) X> register char *ato, *from; X> register int nb; X> { X> register char *to; X> X> to = ato; X> while (--nb >= 0) X> *to++ = *from++; X> return(ato); X> } + END-OF-FILE sh4.c.diff chmod 'u=rw,g=r,o=r' \s\h\4\.\c\.\d\i\f\f set `sum \s\h\4\.\c\.\d\i\f\f` sum=$1 case $sum in 42392) :;; *) echo 'Bad sum in '\s\h\4\.\c\.\d\i\f\f >&2 esac echo Extracting \s\h\5\.\c\.\d\i\f\f sed 's/^X//' > \s\h\5\.\c\.\d\i\f\f << '+ END-OF-FILE '\s\h\5\.\c\.\d\i\f\f X29c29 X< if ((ec != '"') && (ec != '\'')) { X--- X> if (ec != '\'') { X237a238,255 X> * Return the characters from a here temp file. X> */ X> int X> herechar(ap) X> register struct ioarg *ap; X> { X> char c; X> X> X> if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) { X> close(ap->afile); X> c = 0; X> } X> return (c); X> X> } X> X> /* X413,424c431,438 X< } *herelist; X< X< struct block { X< char *b_linebuf; X< char *b_next; X< char b_tmpfile[50]; X< int b_fd; X< }; X< X< static struct block *readhere(); X< X< #define NCPB 2048 /* here text block allocation unit */ X--- X> }; X> X> static struct here *inhere; /* list of hear docs while parsing */ X> static struct here *acthere; /* list of active here documents */ X> X> static char *readhere(); X> X> #define NCPB 100 /* here text block allocation unit */ X439,444c453,457 X< h->h_iop->io_un.io_here = NULL; X< h->h_next = NULL; X< if (herelist == 0) X< herelist = h; X< else X< for (lh = herelist; lh!=NULL; lh = lh->h_next) X--- X> h->h_next = NULL; X> if (inhere == 0) X> inhere = h; X> else X> for (lh = inhere; lh!=NULL; lh = lh->h_next) X462,681c475,608 X< for (h = herelist; h != NULL; h = h->h_next) { X< h->h_iop->io_un.io_here = X< readhere(h->h_tag, h->h_dosub? 0: '\'', X< h->h_iop->io_flag & IOXHERE); X< } X< herelist = NULL; X< } X< X< static struct block * X< readhere(s, ec, nolit) X< register char *s; X< { X< register struct block *bp; X< register c; X< jmp_buf ev; X< X< bp = (struct block *) space(sizeof(*bp)); X< if (bp == 0) X< return(0); X< bp->b_linebuf = (char *)space(NCPB); X< if (bp->b_linebuf == 0) { X< /* jrp - should release bp here... */ X< return(0); X< } X< if (newenv(setjmp(errpt = ev)) == 0) { X< if (e.iop == iostack && e.iop->iofn == filechar) { X< pushio(e.iop->arg, filechar); X< e.iobase = e.iop; X< } X< X< /* jrp changes */ X< bp->b_linebuf[0] = 0; X< bp->b_next = bp->b_linebuf; X< bp->b_tmpfile[0] = 0; X< bp->b_fd = -1; X< for (;;) { X< while ((c = getc(ec)) != '\n' && c) { X< if (ec == '\'') X< c &= ~ QUOTE; X< if (savec(c, bp, nolit) == 0) { X< c = 0; X< break; X< } X< } X< savec(0, bp, nolit); X< if (strcmp(s, bp->b_linebuf) == 0 || c == 0) X< break; X< savec('\n', bp, nolit); X< } X< *bp->b_linebuf = 0; X< if (c == 0) { X< prs("here document `"); prs(s); err("' unclosed"); X< } X< quitenv(); X< } X< return(bp); X< } X< X< static X< savec(c, bp, nolit) X< register struct block *bp; X< { X< /* jrp - gutted routine completely, modified to use temp file. */ X< X< /* If the file is not open, see if a filename needs to be X< * created. If so, create one. Then create the file. X< */ X< char * lp; X< char * cp; X< static int inc; X< int len; X< X< if(bp->b_fd < 0) { X< if(bp->b_tmpfile[0] == 0) { X< /* Key this by the PID plus a tag... */ X< for (cp = bp->b_tmpfile, lp = "/tmp/shtm"; X< (*cp = *lp++) != '\0'; cp++) X< ; X< X< inc = (inc + 1) % 100; X< lp = putn(getpid()*100 + inc); X< for (; (*cp = *lp++) != '\0'; cp++) X< ; X< } X< X< /* Create the file, then open it for X< * read/write access. After opening the X< * file, unlink it to it'll go away when X< * we're through using it. X< */ X< bp->b_fd = creat(bp->b_tmpfile, 0600); X< close(bp->b_fd); X< bp->b_fd = open(bp->b_tmpfile, 2); X< unlink(bp->b_tmpfile); X< if(bp->b_fd < 0) { X< return(0); X< } X< } X< X< /* Stuff the character into the line buffer. If it's a X< * newline, then insert it before the trailing null, write X< * out the line, and reset the line buffer. X< */ X< if(c == '\n') { X< bp->b_next[-1] = '\n'; X< bp->b_next[0] = '\0'; X< len = strlen(bp->b_linebuf); X< X< /* Write this out, unless the line ended X< * with a backslash... X< */ X< if((len > 1) && (bp->b_next[-2] != '\\')) { X< write_linebuf(bp, nolit); X< } X< X< return(1); X< } X< else { X< if(bp->b_next == &(bp->b_linebuf[NCPB - 1])) { X< prs("here: line buffer full\n"); X< return(0); X< } X< *(bp->b_next++) = c; X< return(1); X< } X< } X< X< write_linebuf(bp, nolit) X< struct block * bp; X< { X< X< char c; X< jmp_buf ev; X< X< if(nolit) { X< if (newenv(setjmp(errpt = ev)) == 0) { X< PUSHIO(aword, bp->b_linebuf, strchar); X< setbase(e.iop); X< e.iop->task |= XHERE; X< while ((c = subgetc(0, 0)) != 0) { X< c &= ~ QUOTE; X< write(bp->b_fd, &c, sizeof c); X< } X< quitenv(); X< X< } X< } X< else { X< write(bp->b_fd, bp->b_linebuf, strlen(bp->b_linebuf)); X< } X< X< /* Zap the line buffer for next time... */ X< bp->b_next = bp->b_linebuf; X< bp->b_linebuf[0] = 0; X< } X< X< herein(bp, xdoll) X< struct block *bp; X< { X< int ret_fd; X< X< if (bp == 0) X< return(-1); X< X< /* If we have a temp file, then rewind it to the beginning */ X< if(bp->b_fd < 0) { X< return(-1); X< } X< X< lseek(bp->b_fd, 0L, 0); X< X< /* Free up this block pointer, as we're X< * not going to need it anymore. X< */ X< xfree(bp->b_linebuf); X< xfree(bp); X< X< return(bp->b_fd); X< } X< X< scraphere() X< { X< struct here * h; X< struct here * nexth; X< struct block * bp; X< X< X< /* Close and unlink any files associated with X< * heres in progress, and free up all the X< * associated structures. X< */ X< h = herelist; X< while(h != NULL) { X< nexth = h->h_next; X< bp = (struct block *)h->h_iop->io_un.io_here; X< if(bp != NULL) { X< if(bp->b_fd >= 0) { close(bp->b_fd); } X< if(*bp->b_tmpfile) { unlink(bp->b_tmpfile); } X< xfree(bp->b_linebuf); X< xfree(bp); X< } X< xfree(h); X< h = nexth; X< } X< X< herelist = NULL; X< } X< X< char * X< memcpy(ato, from, nb) X< register char *ato, *from; X< register int nb; X< { X< register char *to; X< X< to = ato; X< while (--nb >= 0) X< *to++ = *from++; X< return(ato); X< } X--- X> for (h = inhere; h != NULL; h = inhere) { X> h->h_iop->io_name = readhere(h->h_tag, h->h_dosub? 0: '\''); X> /* relink from inhere to acthere list */ X> inhere = h->h_next; X> h->h_next = acthere; X> acthere = h; X> } X> inhere = h; X> } X> X> static char * X> readhere(s, ec) X> register char *s; X> { X> int tf; X> char tname[30]; X> register c; X> jmp_buf ev; X> char line [LINELIM+1]; X> char *next; X> X> tempname(tname); X> tf = creat(tname, 0600); X> if (tf < 0) X> return (0); X> if (newenv(setjmp(errpt = ev)) != 0) X> return (0); X> if (e.iop == iostack && e.iop->iofn == filechar) { X> pushio(e.iop->arg, filechar); X> e.iobase = e.iop; X> } X> for (;;) { X> if (talking && e.iop <= iostack) X> prs(cprompt->value); X> next = line; X> while ((c = getc(ec)) != '\n' && c) { X> if (ec == '\'') X> c &= ~ QUOTE; X> if (next >= &line[LINELIM]) { X> c = 0; X> break; X> } X> *next++ = c; X> } X> *next = 0; X> if (strcmp(s, line) == 0 || c == 0) X> break; X> *next++ = '\n'; X> write (tf, line, (int)(next-line)); X> } X> if (c == 0) { X> prs("here document `"); prs(s); err("' unclosed"); X> } X> close(tf); X> quitenv(); X> /* correct area? */ X> return (strsave(tname, areanum)); X> } X> X> /* X> * open here temp file. X> * if unquoted here, expand here temp file into second temp file. X> */ X> herein(hname, xdoll) X> char *hname; X> { X> register hf, tf; X> X> if (hname == 0) X> return(-1); X> hf = open(hname, 0); X> if (hf < 0) X> return (-1); X> if (xdoll) { X> char c; X> char tname[30]; X> jmp_buf ev; X> X> tempname(tname); X> if ((tf = creat(tname, 0600)) < 0) X> return (-1); X> if (newenv(setjmp(errpt = ev)) == 0) { X> PUSHIO(afile, hf, herechar); X> setbase(e.iop); X> while ((c = subgetc(0, 0)) != 0) { X> c &= ~ QUOTE; X> write(tf, &c, sizeof c); X> } X> quitenv(); X> } else X> unlink(tname); X> close(tf); X> tf = open(tname, 0); X> unlink(tname); X> return (tf); X> } else X> return (hf); X> } X> X> scraphere() X> { X> inhere = NULL; X> } X> X> /* unlink here temp files before a freearea(area) */ X> freehere(area) X> int area; X> { X> register struct here *h, *hl; X> X> hl = NULL; X> for (h = acthere; h != NULL; hl = h, h = h->h_next) X> if (getarea(h) >= area) { X> if (h->h_iop->io_name != NULL) X> unlink(h->h_iop->io_name); X> if (hl == NULL) X> acthere = h->h_next; X> else X> hl->h_next = h->h_next; X> } X> } X> X> tempname(tname) X> char *tname; X> { X> static int inc; X> register char *cp, *lp; X> X> for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++) X> ; X> lp = putn(getpid()*1000 + inc++); X> for (; (*cp = *lp++) != '\0'; cp++) X> ; X> } + END-OF-FILE sh5.c.diff chmod 'u=rw,g=r,o=r' \s\h\5\.\c\.\d\i\f\f set `sum \s\h\5\.\c\.\d\i\f\f` sum=$1 case $sum in 19080) :;; *) echo 'Bad sum in '\s\h\5\.\c\.\d\i\f\f >&2 esac exit 0