[comp.os.minix] Fixes to the shell

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