[comp.os.minix] Patches to minix shell

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Here and in the next six messages are my fixes for the
MINIX shell.  These patches fix the following bugs:

	- Allows you to build the shell under MINIX (yay!)
	- Re-implements "<<" input redirection in a
	  non-memory-hogging way
	- $0 now returns the name of the shell script
	  rather than "/bin/sh"
	- $# now returns the correct number of arguments
	- Backslashes inside of double quotes are no longer
	  swallowed.

This first article contains a new file, "shg.c".  The reason for
this is that, in order to get the shell to build under MINIX it
is necessary to do all the external variable declarations properly
(i.e. declare them for real only once and extern for all other uses).
To do this I changed all the "extern"s in sh.h to "Extern".  For
all other files, "Extern" is declared to be "extern".  To accomplish
the "real" declaration of the variables, though, shg.c defines 
"Extern" to be the null string, then includes "sh.h".  You should
add "shg.c" to your commands makefile.

The next six articles are diff-patches to sh.h, sh1.c, sh2.c, sh3.c,
sh4.c, and sh5.c respectively.

   +----------------+  Jim Paradis                  linus--+
+--+-------------+  |  Encore Computer Corp.       necntc--|
|  | E N C O R E |  |  257 Cedar Hill St.           ihnp4--+-encore!paradis
|  +-------------+--+  Marlboro MA 01752           decvax--|
+----------------+     (617) 460-0500             talcott--+

------------------------------cut here ------------------------------

/* This is file shg.c */
#define Extern

#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include "sh.h"

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Apply this patch to sh.h

-------------------------cut here------------------------------

88,95c88,95
< char	**dolv;
< int	dolc;
< int	exstat;
< char	gflg;
< int	talking;	/* interactive (talking-type wireless) */
< int	execflg;
< int	multiline;	/* \n changed to ; */
< struct	op	*outtree;	/* result from parser */
---
> Extern	char	**dolv;
> Extern	int	dolc;
> Extern	int	exstat;
> Extern  char	gflg;
> Extern  int	talking;	/* interactive (talking-type wireless) */
> Extern  int	execflg;
> Extern  int	multiline;	/* \n changed to ; */
> Extern  struct	op	*outtree;	/* result from parser */
97,98c97,98
< xint	*failpt;
< xint	*errpt;
---
> Extern	xint	*failpt;
> Extern	xint	*errpt;
103,104c103,105
< } *brklist;
< int	isbreak;
---
> } ;
> Extern	struct brkcon	*brklist;
> Extern	int	isbreak;
127,128c128,129
< struct	wdblock	*wdlist;
< struct	wdblock	*iolist;
---
> Extern	struct	wdblock	*wdlist;
> Extern	struct	wdblock	*iolist;
152c153
< char	*flag;
---
> extern	char	*flag;
154,155c155,156
< char	*null;	/* null value for variable */
< int	intr;	/* interrupt pending */
---
> extern	char	*null;	/* null value for variable */
> extern	int	intr;	/* interrupt pending */
157,159c158,160
< char	*trap[NSIG];
< char	ourtrap[NSIG];
< int	trapset;	/* trap pending */
---
> Extern	char	*trap[NSIG];
> Extern	char	ourtrap[NSIG];
> Extern	int	trapset;	/* trap pending */
161c162
< int	inword;	/* defer traps and interrupts */
---
> extern	int	inword;	/* defer traps and interrupts */
163c164
< int	yynerrs;	/* yacc */
---
> Extern	int	yynerrs;	/* yacc */
165,166c166,167
< char	line[LINELIM];
< char	*elinep;
---
> Extern	char	line[LINELIM];
> extern	char	*elinep;
219c220
< struct	var	*vlist;		/* dictionary */
---
> Extern	struct	var	*vlist;		/* dictionary */
221,226c222,227
< struct	var	*homedir;	/* home directory */
< struct	var	*prompt;	/* main prompt */
< struct	var	*cprompt;	/* continuation prompt */
< struct	var	*path;		/* search path for commands */
< struct	var	*shell;		/* shell to interpret command files */
< struct	var	*ifs;		/* field separators */
---
> Extern	struct	var	*homedir;	/* home directory */
> Extern	struct	var	*prompt;	/* main prompt */
> Extern	struct	var	*cprompt;	/* continuation prompt */
> Extern	struct	var	*path;		/* search path for commands */
> Extern	struct	var	*shell;		/* shell to interpret command files */
> Extern	struct	var	*ifs;		/* field separators */
256c257
< struct	io	iostack[NPUSH];
---
> Extern	struct	io	iostack[NPUSH];
260c261,263
< #define	XIO	3	/* file IO */
---
> #define	XIO	4	/* file IO */
> #define XHERE	0x80	/* Any of the above inside a here document */
> #define XMASK	0x7f	/* Get the actual task */
263c266
< #define	INSUB()	(e.iop->task == XGRAVE || e.iop->task == XDOLL)
---
> #define	INSUB()	((e.iop->task&XMASK)==XGRAVE||(e.iop->task&XMASK)==XDOLL)
300c303
< struct	ioarg	temparg;	/* temporary for PUSHIO */
---
> Extern	struct	ioarg	temparg;	/* temporary for PUSHIO */
330c333
< int	areanum;	/* current allocation area */
---
> Extern	int	areanum;	/* current allocation area */

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Apply this patch to sh1.c

-----------------------cut here----------------------------

0a1
> #define Extern extern
21c22
< char	**environ;	/* environment pointer */
---
> extern	char	**environ;	/* environment pointer */
132c133
< 			if (newfile(*++argv))
---
> 			if (newfile(*++argv)) {
133a135
> 			}
163c165
< 	setval(lookup("#"), putn(dolc));
---
> 	setval(lookup("#"), putn(dolc-1));

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Apply this patch to sh2.c

---------------------------cut here-----------------------------

0a1
> #define Extern extern
70a72
> 
71a74
> 
82a86
> 
104a109
> 
122a128
> 
124a131
> 

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Apply this patch to sh3.c

-------------------------------cut here-------------------------

0a1
> #define Extern extern
269c270
< 	if (t->type == TPAREN)
---
> 	if (t->type == TPAREN) {
270a272
> 	}
275c277
< 	if (wp[0] == NULL)
---
> 	if (wp[0] == NULL) {
276a279
> 	}
526a530,534
> 
> 			/* If the file is not executable (i.e. doesn't
> 			 * have a valid a.out header) then try it as a
> 			 * shell script.
> 			 */		
529,530c537,538
< 			*v = "/bin/sh";
< 			execve(*v, v, envp);
---
> 			*v = e.linep;
> 			execve("/bin/sh", v, envp);

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Apply this patch to sh4.c

-------------------------cut here----------------------------

0a1
> #define Extern extern
234c235
< 		e.iop->task = XOTHER;
---
> 		e.iop->task =  XOTHER;
320c321
< 	for (cp = e.iop->arg.aword; *cp != '`'; cp++)
---
> 	for (cp = e.iop->arg.aword; *cp != '`'; cp++) {
324a326,327
> 	}
> 
348a352,355
> 	
> 	/* jrp debug */
> 	scraphere();
> 
353a361
> 
355a364
> 

paradis@encore.UUCP (Jim Paradis) (06/23/87)

Apply this patch to sh5.c
Strip the "|"s out from in front of this one first...
I tried to post it but inews thought I was including too much
text (grrrrrrrr!)

----------------------------cut here------------------------------
|0a1
|> #define Extern extern
|28c29
|< 	if (ec != '\'') {
|---
|> 	if ((ec != '"') && (ec != '\'')) {
|84a86
|> 
|101a104
|> 
|128c131
|< 	if (ap->aword == NULL)
|---
|> 	if (ap->aword == NULL) {
|129a133
|> 	}
|402d405
|< char *memcpy();
|416c419
|< 	char	*b_start;
|---
|> 	char	*b_linebuf;
|418,419c421,422
|< 	char	*b_line;
|< 	int	b_size;
|---
|> 	char	b_tmpfile[50];
|> 	int	b_fd;
|424c427
|< #define	NCPB	100	/* here text block allocation unit */
|---
|> #define	NCPB	2048		/* here text block allocation unit */
|438a442
|> 	h->h_iop->io_un.io_here = NULL;
|461,462c465,469
|< 	for (h = herelist; h != NULL; h = h->h_next)
|< 		h->h_iop->io_un.io_here = readhere(h->h_tag, h->h_dosub? 0: '\'');
|---
|> 	for (h = herelist; h != NULL; h = h->h_next) {
|> 		h->h_iop->io_un.io_here = 
|> 			readhere(h->h_tag, h->h_dosub? 0: '\'',
|> 				h->h_iop->io_flag & IOXHERE);
|> 	}
|467c474
|< readhere(s, ec)
|---
|> readhere(s, ec, nolit)
|476a484,488
|> 	bp->b_linebuf = (char *)space(NCPB);
|> 	if (bp->b_linebuf == 0) {
|> 		/* jrp - should release bp here... */
|> 		return(0);
|> 	}
|482,485c494,499
|< 		bp->b_size = 0;
|< 		bp->b_line = 0;
|< 		bp->b_next = 0;
|< 		bp->b_start = 0;
|---
|> 
|> 		/* jrp changes */
|> 		bp->b_linebuf[0] = 0;
|> 		bp->b_next = bp->b_linebuf;
|> 		bp->b_tmpfile[0] = 0;
|> 		bp->b_fd = -1;
|490c504
|< 				if (savec(c, bp) == 0) {
|---
|> 				if (savec(c, bp, nolit) == 0) {
|495,496c509,510
|< 			savec(0, bp);
|< 			if (strcmp(s, bp->b_line) == 0 || c == 0)
|---
|> 			savec(0, bp, nolit);
|> 			if (strcmp(s, bp->b_linebuf) == 0 || c == 0)
|498,499c512
|< 			bp->b_next[-1] = '\n';
|< 			bp->b_line = bp->b_next;
|---
|> 			savec('\n', bp, nolit);
|501c514
|< 		*bp->b_line = 0;
|---
|> 		*bp->b_linebuf = 0;
|511c524
|< savec(c, bp)
|---
|> savec(c, bp, nolit)
|514c527,535
|< 	register char *np;
|---
|> 	/* jrp - gutted routine completely, modified to use temp file. */
|> 	
|> 	/* If the file is not open, see if a filename needs to be
|> 	 * created.  If so, create one.  Then create the file.
|> 	 */
|> 	char *	lp;
|> 	char *	cp;
|> 	static int inc;
|> 	int	len;
|516,525c537,561
|< 	if (bp->b_start == NULL || bp->b_next+1 >= bp->b_start+bp->b_size) {
|< 		np = space(bp->b_size + NCPB);
|< 		if (np == 0)
|< 			return(0);
|< 		memcpy(np, bp->b_start, bp->b_size);
|< 		bp->b_size += NCPB;
|< 		bp->b_line = np + (bp->b_line-bp->b_start);
|< 		bp->b_next = np + (bp->b_next-bp->b_start);
|< 		xfree(bp->b_start);
|< 		bp->b_start = np;
|---
|> 	if(bp->b_fd < 0) {
|> 	    if(bp->b_tmpfile[0] == 0) {
|> 		/* Key this by the PID plus a tag... */
|> 		for (cp = bp->b_tmpfile, lp = "/tmp/shtm"; 
|> 		     (*cp = *lp++) != '\0'; cp++)
|> 			;
|> 
|> 		inc = (inc + 1) % 100;
|> 		lp = putn(getpid()*100 + inc);
|> 		for (; (*cp = *lp++) != '\0'; cp++)
|> 			;
|> 	    }
|> 
|> 	    /* Create the file, then open it for
|> 	     * read/write access.  After opening the
|> 	     * file, unlink it to it'll go away when
|> 	     * we're through using it.
|> 	     */
|> 	    bp->b_fd = creat(bp->b_tmpfile, 0600);
|> 	    close(bp->b_fd);
|> 	    bp->b_fd = open(bp->b_tmpfile, 2);
|> 	    unlink(bp->b_tmpfile);
|> 	    if(bp->b_fd < 0) {
|> 	        return(0);
|> 	    }
|527,528c563,589
|< 	*bp->b_next++ = c;
|< 	return(1);
|---
|> 
|> 	/* Stuff the character into the line buffer.  If it's a
|> 	 * newline, then insert it before the trailing null, write
|> 	 * out the line, and reset the line buffer.
|> 	 */
|> 	if(c == '\n') {
|> 	    bp->b_next[-1] = '\n';
|> 	    bp->b_next[0] = '\0';
|> 	    len = strlen(bp->b_linebuf);
|> 
|> 	    /* Write this out, unless the line ended
|> 	     * with a backslash...
|> 	     */
|> 	    if((len > 1) && (bp->b_next[-2] != '\\')) {
|> 		write_linebuf(bp, nolit);
|> 	    }
|> 
|> 	    return(1);
|> 	}
|> 	else {
|> 	    if(bp->b_next == &(bp->b_linebuf[NCPB - 1])) {
|> 		prs("here: line buffer full\n");
|> 		return(0);
|> 	    }
|> 	    *(bp->b_next++) = c;
|> 	    return(1);
|> 	}
|530a592,620
|> write_linebuf(bp, nolit)
|> struct block * bp;
|> {
|> 
|> 	char c;
|> 	jmp_buf ev;
|> 
|> 	if(nolit) {
|> 		if (newenv(setjmp(errpt = ev)) == 0) {
|> 			PUSHIO(aword, bp->b_linebuf, strchar);
|> 			setbase(e.iop);
|> 			e.iop->task |= XHERE;
|> 			while ((c = subgetc(0, 0)) != 0) {
|> 				c &= ~ QUOTE;
|> 				write(bp->b_fd, &c, sizeof c);
|> 			}
|> 			quitenv();
|> 		
|> 		}
|> 	}
|> 	else {
|> 		write(bp->b_fd, bp->b_linebuf, strlen(bp->b_linebuf));
|> 	}
|> 
|> 	/* Zap the line buffer for next time... */
|> 	bp->b_next = bp->b_linebuf;
|> 	bp->b_linebuf[0] = 0;
|> }
|> 
|534,537c624
|< 	register tf;
|< 	char tname[50];
|< 	static int inc;
|< 	register char *cp, *lp;
|---
|> 	int	ret_fd;
|541,549d627
|< 	for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++)
|< 		;
|< 	lp = putn(getpid()*100 + inc++);
|< 	for (; (*cp = *lp++) != '\0'; cp++)
|< 		;
|< 	if ((tf = creat(tname, 0666)) >= 0) {
|< 		if (xdoll) {
|< 			char c;
|< 			jmp_buf ev;
|551,565c629,631
|< 			if (newenv(setjmp(errpt = ev)) == 0) {
|< 				PUSHIO(aword, bp->b_start, strchar);
|< 				setbase(e.iop);
|< 				while ((c = subgetc(0, 0)) != 0) {
|< 					c &= ~ QUOTE;
|< 					write(tf, &c, sizeof c);
|< 				}
|< 				quitenv();
|< 			} else
|< 				unlink(tname);
|< 		} else
|< 			write(tf, bp->b_start, bp->b_line-bp->b_start);
|< 		close(tf);
|< 		tf = open(tname, 0);
|< 		unlink(tname);
|---
|> 	/* If we have a temp file, then rewind it to the beginning */
|> 	if(bp->b_fd < 0) {
|> 		return(-1);
|567c633,642
|< 	return(tf);
|---
|> 
|> 	lseek(bp->b_fd, 0L, 0);
|> 
|> 	/* Free up this block pointer, as we're
|> 	 * not going to need it anymore.
|> 	 */
|> 	xfree(bp->b_linebuf);
|> 	xfree(bp);
|> 
|> 	return(bp->b_fd);
|571a647,669
|> 	struct here * h;
|> 	struct here * nexth;
|> 	struct block * bp;
|> 
|> 
|> 	/* Close and unlink any files associated with
|> 	 * heres in progress, and free up all the
|> 	 * associated structures. 
|> 	 */
|> 	h = herelist;
|> 	while(h != NULL) {
|> 		nexth = h->h_next;
|> 		bp = (struct block *)h->h_iop->io_un.io_here;
|> 		if(bp != NULL) {
|> 			if(bp->b_fd >= 0) { close(bp->b_fd); }
|> 			if(*bp->b_tmpfile) { unlink(bp->b_tmpfile); }
|> 			xfree(bp->b_linebuf);
|> 			xfree(bp);
|> 		}
|> 		xfree(h);
|> 		h = nexth;
|> 	}
|>