From: Alan Cox Date: Sat, 9 May 2015 23:14:15 +0000 (+0100) Subject: /bin/sh: Minimal changes to get the real Bourne shell building X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=b8fe3c7c3d9276f274e51b7cdf2c2bba7aac752c;p=FUZIX.git /bin/sh: Minimal changes to get the real Bourne shell building There is a *lot* to do here to get this working (including writing setjmp and longjmp for the 6809 port!). Getting it working on the other compilers will need full ansification Also note FIXME pieces for other bodges that will need dealing with before its useful Still it weights in at 28K so it should just about fit with some care on a Dragon-nx-32 ! --- diff --git a/Applications/V7/cmd/sh/Makefile.6809 b/Applications/V7/cmd/sh/Makefile.6809 new file mode 100644 index 00000000..e51101ea --- /dev/null +++ b/Applications/V7/cmd/sh/Makefile.6809 @@ -0,0 +1,46 @@ +PLATFORM = 6809 +CC = m6809-unknown-gcc +# These are wrappers for lwasm and lwar +ASM = m6809-unknown-as +AR = m6809-unknown-ar +LINKER = lwlink +CFLAGS = -I../../../../Library/include -I../../../../Library/include/6502 +COPT = -Os +LINKER_OPT = --format=raw -L../../../../Library/libs -lc6809 +LIBGCCDIR = $(dir $(shell $(CC) -print-libgcc-file-name)) +LINKER_OPT += -L$(LIBGCCDIR) -lgcc +LINKER_OPT += --script=../../../util/$(TARGET).link +ASM_OPT = -o +CRT0 = ../../../../Library/libs/crt0_6809.o + +.SUFFIXES: .c .o + + +SRCS = args.c blok.c builtin.c cmd.c ctype.c error.c expand.c fault.c io.c \ + macro.c main.c msg.c name.c print.c service.c setbrk.c stak.c \ + string.c xec.c glob.c + +# Workaround for gcc 6809 +SRCS_HARD = word.c + + +OBJS = $(SRCS:.c=.o) +OBJS_HARD = $(SRCS_HARD:.c=.o) + +all: sh + +$(OBJS): $(SRCS) $(CRT0) + +$(OBJS): %.o : %.c + $(CC) -c $(CFLAGS) $(COPT) $< + +$(OBJS_HARD): $(SRCS_HARD) + +sh: $(OBJS) $(OBJS_HARD) + $(LINKER) -o $@ $(LINKER_OPT) $(CRT0) $(OBJS) $(OBJS_HARD) + +clean: + rm -f $(OBJS) sh $(SRCS:.c=) core *~ + +rmbak: + rm -f *~ core diff --git a/Applications/V7/cmd/sh/args.c b/Applications/V7/cmd/sh/args.c new file mode 100644 index 00000000..c92e5517 --- /dev/null +++ b/Applications/V7/cmd/sh/args.c @@ -0,0 +1,140 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include +#include "defs.h" + +LOCAL STRING *copyargs(); +LOCAL DOLPTR dolh; + +CHAR flagadr[10]; + +CHAR flagchar[] = { + 'x', 'n', 'v', 't', 's', 'i', 'e', 'r', 'k', 'u', 0 +}; +INT flagval[] = { + execpr, noexec, readpr, oneflg, stdflg, intflg, errflg, rshflg, keyflg, setflg, 0 +}; + +/* ======== option handling ======== */ + + +INT options(argc,argv) + STRING *argv; + INT argc; +{ + REG STRING cp; + REG STRING *argp=argv; + REG STRING flagc; + STRING flagp; + + IF argc>1 ANDF *argp[1]=='-' + THEN cp=argp[1]; + flags &= ~(execpr|readpr); + WHILE *++cp + DO flagc=flagchar; + + WHILE *flagc ANDF *flagc != *cp DO flagc++ OD + IF *cp == *flagc + THEN flags |= flagval[flagc-flagchar]; + ELIF *cp=='c' ANDF argc>2 ANDF comdiv==0 + THEN comdiv=argp[2]; + argp[1]=argp[0]; argp++; argc--; + ELSE failed(argv[1],badopt); + FI + OD + argp[1]=argp[0]; argc--; + FI + + /* set up $- */ + flagc=flagchar; + flagp=flagadr; + WHILE *flagc + DO IF flags&flagval[flagc-flagchar] + THEN *flagp++ = *flagc; + FI + flagc++; + OD + *flagp++=0; + + return(argc); +} + +void setargs(argi) + STRING argi[]; +{ + /* count args */ + REG STRING *argp=argi; + REG INT argn=0; + + WHILE Rcheat(*argp++)!=ENDARGS DO argn++ OD + + /* free old ones unless on for loop chain */ + freeargs(dolh); + dolh=(DOLPTR)copyargs(argi,argn); /* sets dolv */ + assnum(&dolladr,dolc=argn-1); +} + +DOLPTR +freeargs(blk) + DOLPTR blk; +{ + REG STRING *argp; + REG DOLPTR argr=0; + REG DOLPTR argblk; + + IF argblk=blk + THEN argr = argblk->dolnxt; + IF (--argblk->doluse)==0 + THEN FOR argp=(STRING *)argblk->dolarg; Rcheat(*argp)!=ENDARGS; argp++ + DO free(*argp) OD + free(argblk); + FI + FI + return(argr); +} + +LOCAL STRING * copyargs(from, n) + STRING from[]; +{ + REG STRING * np=(STRING *)alloc(sizeof(STRING*)*n+3*BYTESPERWORD); + REG STRING * fp=from; + REG STRING * pp=np; + + ((DOLPTR)np)->doluse=1; /* use count */ + np=(STRING *)((DOLPTR)np)->dolarg; + dolv=np; + + WHILE n-- + DO *np++ = make(*fp++) OD + *np++ = ENDARGS; + return(pp); +} + +clearup() +{ + /* force `for' $* lists to go away */ + WHILE argfor=freeargs(argfor) DONE + + /* clean up io files */ + WHILE pop() DONE +} + +DOLPTR useargs() +{ + IF dolh + THEN dolh->doluse++; + dolh->dolnxt=argfor; + return(argfor=dolh); + ELSE return(0); + FI +} diff --git a/Applications/V7/cmd/sh/blok.c b/Applications/V7/cmd/sh/blok.c new file mode 100644 index 00000000..0a6686d0 --- /dev/null +++ b/Applications/V7/cmd/sh/blok.c @@ -0,0 +1,113 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + + +/* + * storage allocator + * (circular first fit strategy) + */ + +#define BUSY 01 +#define busy(x) (Rcheat((x)->word)&BUSY) + +POS brkincr=BRKINCR; +BLKPTR blokp; /*current search pointer*/ +BLKPTR bloktop=BLK(end); /*top of arena (last blok)*/ + + + +ADDRESS alloc(nbytes) + POS nbytes; +{ + REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD); + + LOOP INT c=0; + REG BLKPTR p = blokp; + REG BLKPTR q; + REP IF !busy(p) + THEN WHILE !busy(q = p->word) DO p->word = q->word OD + IF ADR(q)-ADR(p) >= rbytes + THEN blokp = BLK(ADR(p)+rbytes); + IF q > blokp + THEN blokp->word = p->word; + FI + p->word=BLK(Rcheat(blokp)|BUSY); + return(ADR(p+1)); + FI + FI + q = p; p = BLK(Rcheat(p->word)&~BUSY); + PER p>q ORF (c++)==0 DONE + addblok(rbytes); + POOL +} + +void addblok(reqd) + POS reqd; +{ + IF stakbas!=staktop + THEN REG STKPTR rndstak; + REG BLKPTR blokstak; + + pushstak(0); + rndstak=(STKPTR)round(staktop,BYTESPERWORD); + blokstak=BLK(stakbas)-1; + blokstak->word=stakbsy; stakbsy=blokstak; + bloktop->word=BLK(Rcheat(rndstak)|BUSY); + bloktop=BLK(rndstak); + FI + reqd += brkincr; reqd &= ~(brkincr-1); + blokp=bloktop; + bloktop=bloktop->word=BLK(Rcheat(bloktop)+reqd); + bloktop->word=BLK(ADR(end)+1); + BEGIN + REG STKPTR stakadr=STK(bloktop+2); + staktop=movstr(stakbot,stakadr); + stakbas=stakbot=stakadr; + END +} + +void free(void *ap) +{ + BLKPTR p; + + IF (p=ap) ANDF pword) &= ~BUSY; + FI +} + +#ifdef DEBUG +chkbptr(ptr) + BLKPTR ptr; +{ + INT exf=0; + REG BLKPTR p = end; + REG BLKPTR q; + INT us=0, un=0; + + LOOP + q = Rcheat(p->word)&~BUSY; + IF p==ptr THEN exf++ FI + IF qbloktop THEN abort(3) FI + IF p==bloktop THEN break FI + IF busy(p) + THEN us += q-p; + ELSE un += q-p; + FI + IF p>=q THEN abort(4) FI + p=q; + POOL + IF exf==0 THEN abort(1) FI + prn(un); prc(SP); prn(us); prc(NL); +} +#endif diff --git a/Applications/V7/cmd/sh/brkincr.h b/Applications/V7/cmd/sh/brkincr.h new file mode 100644 index 00000000..9c26e134 --- /dev/null +++ b/Applications/V7/cmd/sh/brkincr.h @@ -0,0 +1,4 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +#define BRKINCR 01000 +#define BRKMAX 04000 diff --git a/Applications/V7/cmd/sh/builtin.c b/Applications/V7/cmd/sh/builtin.c new file mode 100644 index 00000000..50aca079 --- /dev/null +++ b/Applications/V7/cmd/sh/builtin.c @@ -0,0 +1,4 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +builtin() +{return(0);} diff --git a/Applications/V7/cmd/sh/cmd.c b/Applications/V7/cmd/sh/cmd.c new file mode 100644 index 00000000..d539b337 --- /dev/null +++ b/Applications/V7/cmd/sh/cmd.c @@ -0,0 +1,416 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" +#include "sym.h" + +LOCAL IOPTR inout(); +LOCAL void chkword(); +LOCAL void chksym(); +LOCAL TREPTR term(); +LOCAL TREPTR makelist(); +LOCAL TREPTR list(); +LOCAL REGPTR syncase(); +LOCAL TREPTR item(); +LOCAL int skipnl(); +LOCAL void prsym(); +LOCAL void synbad(); + + +/* ======== command line decoding ========*/ + + + + +TREPTR makefork(flgs, i) + INT flgs; + TREPTR i; +{ + REG FORKPTR t; + + t=(FORKPTR)getstak(FORKTYPE); + t->forktyp=flgs|TFORK; + t->forktre=i; + t->forkio=0; + return(TREPTR)(t); +} + +LOCAL TREPTR makelist(type,i,r) + INT type; + TREPTR i, r; +{ + REG LSTPTR t; + + IF i==0 ORF r==0 + THEN synbad(); + ELSE t = (LSTPTR)getstak(LSTTYPE); + t->lsttyp = type; + t->lstlef = i; t->lstrit = r; + FI + return(TREPTR)(t); +} + +/* + * cmd + * empty + * list + * list & [ cmd ] + * list [ ; cmd ] + */ + +TREPTR cmd(sym,flg) + REG INT sym; + INT flg; +{ + REG TREPTR i, e; + + i = list(flg); + + IF wdval==NL + THEN IF flg&NLFLG + THEN wdval=';'; chkpr(NL); + FI + ELIF i==0 ANDF (flg&MTFLG)==0 + THEN synbad(); + FI + + SWITCH wdval IN + + case '&': + IF i + THEN i = makefork(FINT|FPRS|FAMP, i); + ELSE synbad(); + FI + + case ';': + IF e=cmd(sym,flg|MTFLG) + THEN i=makelist(TLST, i, e); + FI + break; + + case EOFSYM: + IF sym==NL + THEN break; + FI + + default: + IF sym + THEN chksym(sym); + FI + + ENDSW + return(i); +} + +/* + * list + * term + * list && term + * list || term + */ + +LOCAL TREPTR list(flg) +{ + REG TREPTR r; + REG INT b; + + r = term(flg); + WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM) + DO r = makelist((b ? TAND : TORF), r, term(NLFLG)); + OD + return(r); +} + +/* + * term + * item + * item |^ term + */ + +LOCAL TREPTR term(flg) +{ + REG TREPTR t; + + reserv++; + IF flg&NLFLG + THEN skipnl(); + ELSE word(); + FI + + IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|') + THEN return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG)))); + ELSE return(t); + FI +} + +LOCAL REGPTR syncase(esym) + REG INT esym; +{ + skipnl(); + IF wdval==esym + THEN return(0); + ELSE REG REGPTR r=(REGPTR)getstak(REGTYPE); + r->regptr=0; + LOOP wdarg->argnxt=r->regptr; + r->regptr=wdarg; + IF wdval ORF ( word()!=')' ANDF wdval!='|' ) + THEN synbad(); + FI + IF wdval=='|' + THEN word(); + ELSE break; + FI + POOL + r->regcom=cmd(0,NLFLG|MTFLG); + IF wdval==ECSYM + THEN r->regnxt=syncase(esym); + ELSE chksym(esym); + r->regnxt=0; + FI + return(r); + FI +} + +/* + * item + * + * ( cmd ) [ < in ] [ > out ] + * word word* [ < in ] [ > out ] + * if ... then ... else ... fi + * for ... while ... do ... done + * case ... in ... esac + * begin ... end + */ + +LOCAL TREPTR item(flag) + BOOL flag; +{ + REG TREPTR t; + REG IOPTR io; + + IF flag + THEN io=inout((IOPTR)0); + ELSE io=0; + FI + + SWITCH wdval IN + + case CASYM: + BEGIN + t=(TREPTR)getstak(SWTYPE); + chkword(); + ((SWPTR)t)->swarg=wdarg->argval; + skipnl(); chksym(INSYM|BRSYM); + ((SWPTR)t)->swlst=syncase(wdval==INSYM?ESSYM:KTSYM); + ((SWPTR)t)->swtyp=TSW; + break; + END + + case IFSYM: + BEGIN + REG INT w; + t=(TREPTR)getstak(IFTYPE); + ((IFPTR)t)->iftyp=TIF; + ((IFPTR)t)->iftre=cmd(THSYM,NLFLG); + ((IFPTR)t)->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG); + ((IFPTR)t)->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0)); + IF w==EFSYM THEN return(t) FI + break; + END + + case FORSYM: + BEGIN + t=(TREPTR)getstak(FORTYPE); + ((FORPTR)t)->fortyp=TFOR; + ((FORPTR)t)->forlst=0; + chkword(); + ((FORPTR)t)->fornam=wdarg->argval; + IF skipnl()==INSYM + THEN chkword(); + ((FORPTR)t)->forlst=(COMPTR)item(0); + IF wdval!=NL ANDF wdval!=';' + THEN synbad(); + FI + chkpr(wdval); skipnl(); + FI + chksym(DOSYM|BRSYM); + ((FORPTR)t)->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG); + break; + END + + case WHSYM: + case UNSYM: + BEGIN + t=(TREPTR)getstak(WHTYPE); + ((WHPTR)t)->whtyp=(wdval==WHSYM ? TWH : TUN); + ((WHPTR)t)->whtre = cmd(DOSYM,NLFLG); + ((WHPTR)t)->dotre = cmd(ODSYM,NLFLG); + break; + END + + case BRSYM: + t=cmd(KTSYM,NLFLG); + break; + + case '(': + BEGIN + REG PARPTR p; + p=(PARPTR)getstak(PARTYPE); + p->partre=cmd(')',NLFLG); + p->partyp=TPAR; + t=makefork(0,p); + break; + END + + default: + IF io==0 + THEN return(0); + FI + + case 0: + BEGIN + REG ARGPTR argp; + REG ARGPTR *argtail; + REG ARGPTR *argset=0; + INT keywd=1; + t=(TREPTR)getstak(COMTYPE); + ((COMPTR)t)->comio=io; /*initial io chain*/ + argtail = &(((COMPTR)t)->comarg); + WHILE wdval==0 + DO argp = wdarg; + IF wdset ANDF keywd + THEN argp->argnxt=(ARGPTR)argset; + argset=(ARGPTR *)argp; + ELSE *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg; + FI + word(); + IF flag + THEN ((COMPTR)t)->comio=inout(((COMPTR)t)->comio); + FI + OD + + ((COMPTR)t)->comtyp=TCOM; + ((COMPTR)t)->comset=(ARGPTR)argset; + *argtail=0; + return(t); + END + + ENDSW + reserv++; word(); + IF io=inout(io) + THEN t=makefork(0,t); t->treio=io; + FI + return(t); +} + + +LOCAL int skipnl() +{ + WHILE (reserv++, word()==NL) DO chkpr(NL) OD + return(wdval); +} + +LOCAL IOPTR inout(lastio) + IOPTR lastio; +{ + REG INT iof; + REG IOPTR iop; + REG CHAR c; + + iof=wdnum; + + SWITCH wdval IN + + case DOCSYM: + iof |= IODOC; break; + + case APPSYM: + case '>': + IF wdnum==0 THEN iof |= 1 FI + iof |= IOPUT; + IF wdval==APPSYM + THEN iof |= IOAPP; break; + FI + + case '<': + IF (c=nextc(0))=='&' + THEN iof |= IOMOV; + ELIF c=='>' + THEN iof |= IORDW; + ELSE peekc=c|MARK; + FI + break; + + default: + return(lastio); + ENDSW + + chkword(); + iop=(IOPTR)getstak(IOTYPE); + iop->ioname=wdarg->argval; + iop->iofile=iof; + IF iof&IODOC + THEN iop->iolst=iopend; iopend=iop; + FI + word(); iop->ionxt=inout(lastio); + return(iop); +} + +LOCAL void chkword() +{ + IF word() + THEN synbad(); + FI +} + +LOCAL void chksym(sym) +{ + REG INT x = sym&wdval; + IF ((x&SYMFLG) ? x : sym) != wdval + THEN synbad(); + FI +} + +LOCAL void prsym(sym) +{ + IF sym&SYMFLG + THEN REG SYSPTR sp=reserved; + WHILE sp->sysval + ANDF sp->sysval!=sym + DO sp++ OD + prs(sp->sysnam); + ELIF sym==EOFSYM + THEN prs(endoffile); + ELSE IF sym&SYMREP THEN prc(sym) FI + IF sym==NL + THEN prs("newline"); + ELSE prc(sym); + FI + FI +} + +LOCAL void synbad() +{ + prp(); prs(synmsg); + IF (flags&ttyflg)==0 + THEN prs(atline); prn(standin->flin); + FI + prs(colon); + prc(LQ); + IF wdval + THEN prsym(wdval); + ELSE prs(wdarg->argval); + FI + prc(RQ); prs(unexpected); + newline(); + exitsh(SYNBAD); +} diff --git a/Applications/V7/cmd/sh/ctype.c b/Applications/V7/cmd/sh/ctype.c new file mode 100644 index 00000000..d7eadc8f --- /dev/null +++ b/Applications/V7/cmd/sh/ctype.c @@ -0,0 +1,111 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + +char _ctype1[] = { +/* 000 001 002 003 004 005 006 007 */ + _EOF, 0, 0, 0, 0, 0, 0, 0, + +/* bs ht nl vt np cr so si */ + 0, _TAB, _EOR, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + +/* sp ! " # $ % & ' */ + _SPC, 0, _DQU, 0, _DOL1, 0, _AMP, 0, + +/* ( ) * + , - . / */ + _BRA, _KET, 0, 0, 0, 0, 0, 0, + +/* 0 1 2 3 4 5 6 7 */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* 8 9 : ; < = > ? */ + 0, 0, 0, _SEM, _LT, 0, _GT, 0, + +/* @ A B C D E F G */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* H I J K L M N O */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* P Q R S T U V W */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* X Y Z [ \ ] ^ _ */ + 0, 0, 0, 0, _BSL, 0, _HAT, 0, + +/* ` a b c d e f g */ + _LQU, 0, 0, 0, 0, 0, 0, 0, + +/* h i j k l m n o */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* p q r s t u v w */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* x y z { | } ~ del */ + 0, 0, 0, 0, _BAR, 0, 0, 0 +}; + + +char _ctype2[] = { +/* 000 001 002 003 004 005 006 007 */ + 0, 0, 0, 0, 0, 0, 0, 0, + +/* bs ht nl vt np cr so si */ + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + +/* sp ! " # $ % & ' */ + 0, _PCS, 0, _NUM, _DOL2, 0, 0, 0, + +/* ( ) * + , - . / */ + 0, 0, _AST, _PLS, 0, _MIN, 0, 0, + +/* 0 1 2 3 4 5 6 7 */ + _DIG, _DIG, _DIG, _DIG, _DIG, _DIG, _DIG, _DIG, + +/* 8 9 : ; < = > ? */ + _DIG, _DIG, 0, 0, 0, _EQ, 0, _QU, + +/* @ A B C D E F G */ + _AT, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, + +/* H I J K L M N O */ + _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, + +/* P Q R S T U V W */ + _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, + +/* X Y Z [ \ ] ^ _ */ + _UPC, _UPC, _UPC, _SQB, 0, 0, 0, _UPC, + +/* ` a b c d e f g */ + 0, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, + +/* h i j k l m n o */ + _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, + +/* p q r s t u v w */ + _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, + +/* x y z { | } ~ del */ + _LPC, _LPC, _LPC, _CBR, 0, _CKT, 0, 0 +}; + diff --git a/Applications/V7/cmd/sh/ctype.h b/Applications/V7/cmd/sh/ctype.h new file mode 100644 index 00000000..e50019a1 --- /dev/null +++ b/Applications/V7/cmd/sh/ctype.h @@ -0,0 +1,92 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + + +/* table 1 */ +#define T_SUB 01 +#define T_MET 02 +#define T_SPC 04 +#define T_DIP 010 +#define T_EOF 020 +#define T_EOR 040 +#define T_QOT 0100 +#define T_ESC 0200 + +/* table 2 */ +#define T_BRC 01 +#define T_DEF 02 +#define T_AST 04 +#define T_DIG 010 +#define T_FNG 020 +#define T_SHN 040 +#define T_IDC 0100 +#define T_SET 0200 + +/* for single chars */ +#define _TAB (T_SPC) +#define _SPC (T_SPC) +#define _UPC (T_IDC) +#define _LPC (T_IDC) +#define _DIG (T_DIG) +#define _EOF (T_EOF) +#define _EOR (T_EOR) +#define _BAR (T_DIP) +#define _HAT (T_MET) +#define _BRA (T_MET) +#define _KET (T_MET) +#define _SQB (T_FNG) +#define _AMP (T_DIP) +#define _SEM (T_DIP) +#define _LT (T_DIP) +#define _GT (T_DIP) +#define _LQU (T_QOT|T_ESC) +#define _BSL (T_ESC) +#define _DQU (T_QOT) +#define _DOL1 (T_SUB|T_ESC) + +#define _CBR T_BRC +#define _CKT T_DEF +#define _AST (T_AST|T_FNG) +#define _EQ (T_DEF) +#define _MIN (T_DEF|T_SHN) +#define _PCS (T_SHN) +#define _NUM (T_SHN) +#define _DOL2 (T_SHN) +#define _PLS (T_DEF|T_SET) +#define _AT (T_AST) +#define _QU (T_DEF|T_FNG|T_SHN) + +/* abbreviations for tests */ +#define _IDCH (T_IDC|T_DIG) +#define _META (T_SPC|T_DIP|T_MET|T_EOR) + +extern char _ctype1[]; + +/* nb these args are not call by value !!!! */ +#define space(c) (((c)"E)==0 ANDF _ctype1[c]&(T_SPC)) +#define eofmeta(c) (((c)"E)==0 ANDF _ctype1[c]&(_META|T_EOF)) +#define qotchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_QOT)) +#define eolchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_EOR|T_EOF)) +#define dipchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_DIP)) +#define subchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_SUB|T_QOT)) +#define escchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_ESC)) + +extern char _ctype2[]; + +#define digit(c) (((c)"E)==0 ANDF _ctype2[c]&(T_DIG)) +#define fngchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_FNG)) +#define dolchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST|T_BRC|T_DIG|T_IDC|T_SHN)) +#define defchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_DEF)) +#define setchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_SET)) +#define digchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST|T_DIG)) +#define letter(c) (((c)"E)==0 ANDF _ctype2[c]&(T_IDC)) +#define alphanum(c) (((c)"E)==0 ANDF _ctype2[c]&(_IDCH)) +#define astchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST)) diff --git a/Applications/V7/cmd/sh/defs.h b/Applications/V7/cmd/sh/defs.h new file mode 100644 index 00000000..a4619535 --- /dev/null +++ b/Applications/V7/cmd/sh/defs.h @@ -0,0 +1,294 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +//#include +#include +#include + +/* + * UNIX shell + */ + +/* error exits from various parts of shell */ +#define ERROR 1 +#define SYNBAD 2 +#define SIGFAIL 3 +#define SIGFLG 0200 + +/* command tree */ +#define FPRS 020 +#define FINT 040 +#define FAMP 0100 +#define FPIN 0400 +#define FPOU 01000 +#define FPCL 02000 +#define FCMD 04000 +#define COMMSK 017 + +#define TCOM 0 +#define TPAR 1 +#define TFIL 2 +#define TLST 3 +#define TIF 4 +#define TWH 5 +#define TUN 6 +#define TSW 7 +#define TAND 8 +#define TORF 9 +#define TFORK 10 +#define TFOR 11 + +/* execute table */ +#define SYSSET 1 +#define SYSCD 2 +#define SYSEXEC 3 +#define SYSLOGIN 4 +#define SYSTRAP 5 +#define SYSEXIT 6 +#define SYSSHFT 7 +#define SYSWAIT 8 +#define SYSCONT 9 +#define SYSBREAK 10 +#define SYSEVAL 11 +#define SYSDOT 12 +#define SYSRDONLY 13 +#define SYSTIMES 14 +#define SYSXPORT 15 +#define SYSNULL 16 +#define SYSREAD 17 +#define SYSTST 18 +#define SYSUMASK 19 + +/* used for input and output of shell */ +#define INIO 10 +#define OTIO 11 + +/*io nodes*/ +#define USERIO 10 +#define IOUFD 15 +#define IODOC 16 +#define IOPUT 32 +#define IOAPP 64 +#define IOMOV 128 +#define IORDW 256 +#define INPIPE 0 +#define OTPIPE 1 + +/* arg list terminator */ +#define ENDARGS 0 + +#include "mac.h" +#include "mode.h" +#include "name.h" + + +/* result type declarations */ +extern void *setbrk(intptr_t); +extern void sh_getenv(void); +extern STRING *sh_setenv(void); + + +#define alloc malloc +ADDRESS alloc(); +void addblok(); +STRING make(); +STRING movstr(); +TREPTR cmd(); +TREPTR makefork(); +NAMPTR lookup(); +void setname(); +void setargs(); +DOLPTR useargs(); +DOLPTR freeargs(); +REAL expr(); +STRING catpath(); +STRING getpath(); +STRING *scan(); +STRING mactrim(); +STRING macro(); +void await(); +void post(); +void exname(); +void printnam(); +void printflg(); +void prs(); +void prc(); + +#define attrib(n,f) (n->namflg |= f) +#define round(a,b) (((int)((ADR(a)+b)-1))&~((b)-1)) +#define closepipe(x) (close(x[INPIPE]), close(x[OTPIPE])) +#define eq(a,b) (cf(a,b)==0) +#define max(a,b) ((a)>(b)?(a):(b)) +#define assert(x) ; + +/* temp files and io */ +extern UFD output; +extern INT ioset; +extern IOPTR iotemp; /* files to be deleted sometime */ +extern IOPTR iopend; /* documents waiting to be read at NL */ + +/* substitution */ +extern INT dolc; +extern STRING *dolv; +extern DOLPTR argfor; +extern ARGPTR gchain; + +/* stack */ +#define BLK(x) ((BLKPTR)(x)) +#define BYT(x) ((BYTPTR)(x)) +#define STK(x) ((STKPTR)(x)) +#define ADR(x) ((char*)(x)) + +/* stak stuff */ +#include "stak.h" + +/* string constants */ +extern const char atline[]; +extern const char readmsg[]; +extern const char colon[]; +extern const char minus[]; +extern const char nullstr[]; +extern const char sptbnl[]; +extern const char unexpected[]; +extern const char endoffile[]; +extern const char synmsg[]; + +/* name tree and words */ +extern SYSTAB reserved; +extern INT wdval; +extern INT wdnum; +extern ARGPTR wdarg; +extern INT wdset; +extern BOOL reserv; + +/* prompting */ +extern const char stdprompt[]; +extern const char supprompt[]; +extern const char profile[]; + +/* built in names */ +extern NAMNOD fngnod; +extern NAMNOD ifsnod; +extern NAMNOD homenod; +extern NAMNOD mailnod; +extern NAMNOD pathnod; +extern NAMNOD ps1nod; +extern NAMNOD ps2nod; + +/* special names */ +extern char flagadr[10]; +extern STRING cmdadr; +extern STRING exitadr; +extern STRING dolladr; +extern STRING pcsadr; +extern STRING pidadr; + +extern const char defpath[]; + +/* names always present */ +extern const char mailname[]; +extern const char homename[]; +extern const char pathname[]; +extern const char fngname[]; +extern const char ifsname[]; +extern const char ps1name[]; +extern const char ps2name[]; + +/* transput */ +extern CHAR tmpout[]; +extern STRING tmpnam; +extern INT serial; +#define TMPNAM 7 +extern FILE standin; +#define input (standin->fdes) +#define eof (standin->feof) +extern INT peekc; +extern STRING comdiv; +extern const char devnull[]; + +/* flags */ +#define noexec 01 +#define intflg 02 +#define prompt 04 +#define setflg 010 +#define errflg 020 +#define ttyflg 040 +#define forked 0100 +#define oneflg 0200 +#define rshflg 0400 +#define waiting 01000 +#define stdflg 02000 +#define execpr 04000 +#define readpr 010000 +#define keyflg 020000 +extern INT flags; + +/* error exits from various parts of shell */ +#include +extern jmp_buf subshell; +extern jmp_buf errshell; + +/* fault handling */ +#include "brkincr.h" +extern POS brkincr; + +#define MINTRAP 0 +#define MAXTRAP 17 + +#define INTR 2 +#define QUIT 3 +#define MEMF 11 +#define ALARM 14 +#define KILL 15 +#define TRAPSET 2 +#define SIGSET 4 +#define SIGMOD 8 + +void fault(); +extern BOOL trapnote; +extern STRING trapcom[]; +extern BOOL trapflg[]; + +/* name tree and words */ +extern STRING *environ; +extern CHAR numbuf[]; +extern const char export[]; +extern const char readonly[]; + +/* execflgs */ +extern INT exitval; +extern BOOL execbrk; +extern INT loopcnt; +extern INT breakcnt; + +/* messages */ +extern const char mailmsg[]; +extern const char coredump[]; +extern const char badopt[]; +extern const char badparam[]; +extern const char badsub[]; +extern const char nospace[]; +extern const char notfound[]; +extern const char badtrap[]; +extern const char baddir[]; +extern const char badshift[]; +extern const char illegal[]; +extern const char restricted[]; +extern const char execpmsg[]; +extern const char notid[]; +extern const char wtfailed[]; +extern const char badcreate[]; +extern const char piperr[]; +extern const char badopen[]; +extern const char badnum[]; +extern const char arglist[]; +extern const char txtbsy[]; +extern const char toobig[]; +extern const char badexec[]; +extern const char notfound[]; +extern const char badfile[]; + +extern address end[]; + +#include "ctype.h" + diff --git a/Applications/V7/cmd/sh/dup.h b/Applications/V7/cmd/sh/dup.h new file mode 100644 index 00000000..1818e917 --- /dev/null +++ b/Applications/V7/cmd/sh/dup.h @@ -0,0 +1,12 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#define DUPFLG 0100 diff --git a/Applications/V7/cmd/sh/error.c b/Applications/V7/cmd/sh/error.c new file mode 100644 index 00000000..9b6bf2b6 --- /dev/null +++ b/Applications/V7/cmd/sh/error.c @@ -0,0 +1,85 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + + +/* ======== error handling ======== */ + +exitset() +{ + assnum(&exitadr,exitval); +} + +sigchk() +{ + /* Find out if it is time to go away. + * `trapnote' is set to SIGSET when fault is seen and + * no trap has been set. + */ + IF trapnote&SIGSET + THEN exitsh(SIGFAIL); + FI +} + +failed(s1,s2) + STRING s1, s2; +{ + prp(); prs(s1); + IF s2 + THEN prs(colon); prs(s2); + FI + newline(); exitsh(ERROR); +} + +error(s) + STRING s; +{ + failed(s,NIL); +} + +exitsh(xno) + INT xno; +{ + /* Arrive here from `FATAL' errors + * a) exit command, + * b) default trap, + * c) fault with no trap set. + * + * Action is to return to command level or exit. + */ + exitval=xno; + IF (flags & (forked|errflg|ttyflg)) != ttyflg + THEN done(); + ELSE clearup(); + longjmp(errshell,1); + FI +} + +done() +{ + REG STRING t; + IF t=trapcom[0] + THEN trapcom[0]=0; /*should free but not long */ + execexp(t,0); + FI + rmtemp(0); + exit(exitval); +} + +rmtemp(base) + IOPTR base; +{ + WHILE iotemp>base + DO unlink(iotemp->ioname); + iotemp=iotemp->iolst; + OD +} diff --git a/Applications/V7/cmd/sh/expand.c b/Applications/V7/cmd/sh/expand.c new file mode 100644 index 00000000..97fdcb50 --- /dev/null +++ b/Applications/V7/cmd/sh/expand.c @@ -0,0 +1,194 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include +#include +#define DIRSIZ 31 +#include +#include "defs.h" + + + +/* globals (file name generation) + * + * "*" in params matches r.e ".*" + * "?" in params matches r.e. "." + * "[...]" in params matches character class + * "[...a-z...]" in params matches a through z. + * + */ + +LOCAL void addg(); + + +INT expand(as,rflg) + STRING as; +{ + INT count, dirf; + BOOL dir=0; + STRING rescan = 0; + REG STRING s, cs; + ARGPTR schain = gchain; + struct dirent entry; + STATBUF statb; + + IF trapnote&SIGSET THEN return(0); FI + + s=cs=as; entry.d_name[DIRSIZ-1]=0; /* to end the string */ + + /* check for meta chars */ + BEGIN + REG BOOL slash; slash=0; + WHILE !fngchar(*cs) + DO IF *cs++==0 + THEN IF rflg ANDF slash THEN break; ELSE return(0) FI + ELIF *cs=='/' + THEN slash++; + FI + OD + END + + LOOP IF cs==s + THEN s=nullstr; + break; + ELIF *--cs == '/' + THEN *cs=0; + IF s==cs THEN s="/" FI + break; + FI + POOL + IF stat(s,&statb)>=0 + ANDF (statb.st_mode&S_IFMT)==S_IFDIR + ANDF (dirf=open(s,0))>0 + THEN dir++; + FI + count=0; + IF *cs==0 THEN *cs++=0200 FI + IF dir + THEN /* check for rescan */ + REG STRING rs; rs=cs; + + REP IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI + PER *rs++ DONE + + // FIXME: readdir + WHILE read(dirf, (void *)&entry, 32) == 32 ANDF (trapnote&SIGSET) == 0 + DO IF entry.d_ino==0 ORF + (*entry.d_name=='.' ANDF *cs!='.') + THEN continue; + FI + IF gmatch(entry.d_name, cs) + THEN addg(s,entry.d_name,rescan); count++; + FI + OD + close(dirf); + + IF rescan + THEN REG ARGPTR rchain; + rchain=gchain; gchain=schain; + IF count + THEN count=0; + WHILE rchain + DO count += expand(rchain->argval,1); + rchain=rchain->argnxt; + OD + FI + *rescan='/'; + FI + FI + + BEGIN + REG CHAR c; + s=as; + WHILE c = *s + DO *s++=(c&STRIP?c:'/') OD + END + return(count); +} + +gmatch(s, p) + REG STRING s, p; +{ + REG INT scc; + CHAR c; + + IF scc = *s++ + THEN IF (scc &= STRIP)==0 + THEN scc=0200; + FI + FI + SWITCH c = *p++ IN + + case '[': + {BOOL ok; INT lc; + ok=0; lc=077777; + WHILE c = *p++ + DO IF c==']' + THEN return(ok?gmatch(s,p):0); + ELIF c==MINUS + THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI + ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI + FI + OD + return(0); + } + + default: + IF (c&STRIP)!=scc THEN return(0) FI + + case '?': + return(scc?gmatch(s,p):0); + + case '*': + IF *p==0 THEN return(1) FI + --s; + WHILE *s + DO IF gmatch(s++,p) THEN return(1) FI OD + return(0); + + case 0: + return(scc==0); + ENDSW +} + +LOCAL void addg(as1,as2,as3) + STRING as1, as2, as3; +{ + REG STRING s1, s2; + REG INT c; + + s2 = locstak()+BYTESPERWORD; + + s1=as1; + WHILE c = *s1++ + DO IF (c &= STRIP)==0 + THEN *s2++='/'; + break; + FI + *s2++=c; + OD + s1=as2; + WHILE *s2 = *s1++ DO s2++ OD + IF s1=as3 + THEN *s2++='/'; + WHILE *s2++ = *++s1 DONE + FI + makearg(endstak(s2)); +} + +makearg(args) + REG STRING args; +{ + ((ARGPTR)args)->argnxt=gchain; + gchain=(ARGPTR)args; +} + diff --git a/Applications/V7/cmd/sh/fault.c b/Applications/V7/cmd/sh/fault.c new file mode 100644 index 00000000..c3a69cda --- /dev/null +++ b/Applications/V7/cmd/sh/fault.c @@ -0,0 +1,114 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include +#include "defs.h" + + +STRING trapcom[MAXTRAP]; +BOOL trapflg[MAXTRAP]; + +/* ======== fault handling routines ======== */ + + +void fault(sig) + REG INT sig; +{ + REG INT flag; + + signal(sig,fault); + IF sig==MEMF + THEN IF setbrk(brkincr) == -1 + THEN error(nospace); + FI + ELIF sig==ALARM + THEN IF flags&waiting + THEN done(); + FI + ELSE flag = (trapcom[sig] ? TRAPSET : SIGSET); + trapnote |= flag; + trapflg[sig] |= flag; + FI +} + +stdsigs() +{ + ignsig(QUIT); + getsig(INTR); + getsig(MEMF); + getsig(ALARM); +} + +ignsig(n) +{ + REG INT s, i; +#if 0 + // FIXME: need to do proper SIG_IGN checks/handling + IF (s=signal(i=n,1)&01)==0 + THEN trapflg[i] |= SIGMOD; + FI +#endif + return(s); +} + +getsig(n) +{ + REG INT i; + + IF trapflg[i=n]&SIGMOD ORF ignsig(i)==0 + THEN signal(i,fault); + FI +} + +oldsigs() +{ + REG INT i; + REG STRING t; + + i=MAXTRAP; + WHILE i-- + DO t=trapcom[i]; + IF t==0 ORF *t + THEN clrsig(i); + FI + trapflg[i]=0; + OD + trapnote=0; +} + +clrsig(i) + INT i; +{ + free(trapcom[i]); trapcom[i]=0; + IF trapflg[i]&SIGMOD + THEN signal(i,fault); + trapflg[i] &= ~SIGMOD; + FI +} + +chktrap() +{ + /* check for traps */ + REG INT i=MAXTRAP; + REG STRING t; + + trapnote &= ~TRAPSET; + WHILE --i + DO IF trapflg[i]&TRAPSET + THEN trapflg[i] &= ~TRAPSET; + IF t=trapcom[i] + THEN INT savxit=exitval; + execexp(t,0); + exitval=savxit; exitset(); + FI + FI + OD +} diff --git a/Applications/V7/cmd/sh/glob.c b/Applications/V7/cmd/sh/glob.c new file mode 100644 index 00000000..a9ed719a --- /dev/null +++ b/Applications/V7/cmd/sh/glob.c @@ -0,0 +1,40 @@ +int wdval; +int iopend; +int flags; +int peekc; +char *comdiv; +int breakcnt; +int loopcnt; +int execbrk; +int exitval; +int dolc; +char **dolv; +/* FIXME */ +void *argfor; +void *gchain; +int iotemp; +int iopend; +int ioset; +int output; +char *pidadr; +char *dolladr; +char *pcsadr; +char *pidadr; +char *exitadr; +char *cmdadr; +int wdset; +void *wdarg; +int reserv; +int wdnum; +int trapnote; +int end; +int serial; + +#include +jmp_buf subshell; +jmp_buf errshell; + +/* FIXME */ + +int setjmp(jmp_buf bar) {} +void longjmp(jmp_buf bar, int foo) {} \ No newline at end of file diff --git a/Applications/V7/cmd/sh/io.c b/Applications/V7/cmd/sh/io.c new file mode 100644 index 00000000..4d04a9c2 --- /dev/null +++ b/Applications/V7/cmd/sh/io.c @@ -0,0 +1,135 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" +#include "dup.h" + + +/* ======== input output and file copying ======== */ + +initf(fd) + UFD fd; +{ + REG FILE f=standin; + + f->fdes=fd; f->fsiz=((flags&(oneflg|ttyflg))==0 ? BUFSIZ : 1); + f->fnxt=f->fend=f->fbuf; f->feval=0; f->flin=1; + f->feof=FALSE; +} + +estabf(s) + REG STRING s; +{ + REG FILE f; + + (f=standin)->fdes = -1; + f->fend=length(s)+(f->fnxt=s); + f->flin=1; + return(f->feof=(s==0)); +} + +push(af) + FILE af; +{ + REG FILE f; + + (f=af)->fstak=standin; + f->feof=0; f->feval=0; + standin=f; +} + +pop() +{ + REG FILE f; + + IF (f=standin)->fstak + THEN IF f->fdes>=0 THEN close(f->fdes) FI + standin=f->fstak; + return(TRUE); + ELSE return(FALSE); + FI +} + +chkpipe(pv) + INT *pv; +{ + IF pipe(pv)<0 ORF pv[INPIPE]<0 ORF pv[OTPIPE]<0 + THEN error(piperr); + FI +} + +chkopen(idf) + STRING idf; +{ + REG INT rc; + + IF (rc=open(idf,0))<0 + THEN failed(idf,badopen); + ELSE return(rc); + FI +} + +sh_rename(f1,f2) + REG INT f1, f2; +{ + IF f1!=f2 + THEN dup2(f1, f2); + close(f1); + IF f2==0 THEN ioset|=1 FI + FI +} + +create(s) + STRING s; +{ + REG INT rc; + + IF (rc=creat(s,0666))<0 + THEN failed(s,badcreate); + ELSE return(rc); + FI +} + +tmpfil() +{ + itos(serial++); movstr(numbuf,tmpnam); + return(create(tmpout)); +} + +/* set by trim */ +BOOL nosubst; + +copy(ioparg) + IOPTR ioparg; +{ + CHAR c, *ends; + REG CHAR *cline, *clinep; + INT fd; + REG IOPTR iop; + + IF iop=ioparg + THEN copy(iop->iolst); + ends=mactrim(iop->ioname); IF nosubst THEN iop->iofile &= ~IODOC FI + fd=tmpfil(); + iop->ioname=cpystak(tmpout); + iop->iolst=iotemp; iotemp=iop; + cline=locstak(); + + LOOP clinep=cline; chkpr(NL); + WHILE (c = (nosubst ? readc() : nextc(*ends)), !eolchar(c)) DO *clinep++ = c OD + *clinep=0; + IF eof ORF eq(cline,ends) THEN break FI + *clinep++=NL; + write(fd,cline,clinep-cline); + POOL + close(fd); + FI +} diff --git a/Applications/V7/cmd/sh/mac.h b/Applications/V7/cmd/sh/mac.h new file mode 100644 index 00000000..29e5b955 --- /dev/null +++ b/Applications/V7/cmd/sh/mac.h @@ -0,0 +1,62 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#define LOCAL static +#define PROC extern +#define TYPE typedef +#define STRUCT TYPE struct +#define UNION TYPE union +#define REG register + +#define IF if( +#define THEN ){ +#define ELSE } else { +#define ELIF } else if ( +#define FI ;} + +#define BEGIN { +#define END } +#define SWITCH switch( +#define IN ){ +#define ENDSW } +#define FOR for( +#define WHILE while( +#define DO ){ +#define OD ;} +#define REP do{ +#define PER }while( +#define DONE ); +#define LOOP for(;;){ +#define POOL } + + +#define SKIP ; +#define DIV / +#define REM % +#define NEQ ^ +#define ANDF && +#define ORF || + +#define TRUE (-1) +#define FALSE 0 +#define LOBYTE 0377 +#define STRIP 0177 +#define QUOTE 0200 + +#define EOF 0 +#define NL '\n' +#define SP ' ' +#define LQ '`' +#define RQ '\'' +#define MINUS '-' +#define COLON ':' + +#define MAX(a,b) ((a)>(b)?(a):(b)) diff --git a/Applications/V7/cmd/sh/macro.c b/Applications/V7/cmd/sh/macro.c new file mode 100644 index 00000000..7f5eccf7 --- /dev/null +++ b/Applications/V7/cmd/sh/macro.c @@ -0,0 +1,239 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" +#include "sym.h" + +LOCAL CHAR quote; /* used locally */ +LOCAL CHAR quoted; /* used locally */ + +LOCAL getch(); +LOCAL comsubst(); +LOCAL flush(); + + +LOCAL STRING copyto(endch) + REG CHAR endch; +{ + REG CHAR c; + + WHILE (c=getch(endch))!=endch ANDF c + DO pushstak(c|quote) OD + zerostak(); + IF c!=endch THEN error(badsub) FI +} + +LOCAL skipto(endch) + REG CHAR endch; +{ + /* skip chars up to } */ + REG CHAR c; + WHILE (c=readc()) ANDF c!=endch + DO SWITCH c IN + + case SQUOTE: skipto(SQUOTE); break; + + case DQUOTE: skipto(DQUOTE); break; + + case DOLLAR: IF readc()==BRACE + THEN skipto('}'); + FI + ENDSW + OD + IF c!=endch THEN error(badsub) FI +} + +LOCAL getch(endch) + CHAR endch; +{ + REG CHAR d; + +retry: + d=readc(); + IF !subchar(d) + THEN return(d); + FI + IF d==DOLLAR + THEN REG INT c; + IF (c=readc(), dolchar(c)) + THEN NAMPTR n=(NAMPTR)NIL; + INT dolg=0; + BOOL bra; + REG STRING argp, v; + CHAR idb[2]; + STRING id=idb; + + IF bra=(c==BRACE) THEN c=readc() FI + IF letter(c) + THEN argp=(STRING)relstak(); + WHILE alphanum(c) DO pushstak(c); c=readc() OD + zerostak(); + n=lookup(absstak(argp)); setstak(argp); + v = n->namval; id = n->namid; + peekc = c|MARK;; + ELIF digchar(c) + THEN *id=c; idb[1]=0; + IF astchar(c) + THEN dolg=1; c='1'; + FI + c -= '0'; + v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (STRING)(dolg=0)); + ELIF c=='$' + THEN v=pidadr; + ELIF c=='!' + THEN v=pcsadr; + ELIF c=='#' + THEN v=dolladr; + ELIF c=='?' + THEN v=exitadr; + ELIF c=='-' + THEN v=flagadr; + ELIF bra THEN error(badsub); + ELSE goto retry; + FI + c = readc(); + IF !defchar(c) ANDF bra + THEN error(badsub); + FI + argp=0; + IF bra + THEN IF c!='}' + THEN argp=(STRING)relstak(); + IF (v==0)NEQ(setchar(c)) + THEN copyto('}'); + ELSE skipto('}'); + FI + argp=absstak(argp); + FI + ELSE peekc = c|MARK; c = 0; + FI + IF v + THEN IF c!='+' + THEN LOOP WHILE c = *v++ + DO pushstak(c|quote); OD + IF dolg==0 ORF (++dolg>dolc) + THEN break; + ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0)); + FI + POOL + FI + ELIF argp + THEN IF c=='?' + THEN failed(id,*argp?argp:badparam); + ELIF c=='=' + THEN IF n + THEN assign(n,argp); + ELSE error(badsub); + FI + FI + ELIF flags&setflg + THEN failed(id,badparam); + FI + goto retry; + ELSE peekc=c|MARK; + FI + ELIF d==endch + THEN return(d); + ELIF d==SQUOTE + THEN comsubst(); goto retry; + ELIF d==DQUOTE + THEN quoted++; quote^=QUOTE; goto retry; + FI + return(d); +} + +STRING macro(as) + STRING as; +{ + /* Strip "" and do $ substitution + * Leaves result on top of stack + */ + REG BOOL savqu =quoted; + REG CHAR savq = quote; + FILEHDR fb; + + push(&fb); estabf(as); + usestak(); + quote=0; quoted=0; + copyto(0); + pop(); + IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI + quote=savq; quoted=savqu; + return(fixstak()); +} + +LOCAL comsubst() +{ + /* command substn */ + FILEBLK cb; + REG CHAR d; + REG STKPTR savptr = fixstak(); + + usestak(); + WHILE (d=readc())!=SQUOTE ANDF d + DO pushstak(d) OD + + BEGIN + REG STRING argc; + trim(argc=fixstak()); + push(&cb); estabf(argc); + END + BEGIN + REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG)); + INT pv[2]; + + /* this is done like this so that the pipe + * is open only when needed + */ + chkpipe(pv); + initf(pv[INPIPE]); + execute(t, 0, 0, pv); + close(pv[OTPIPE]); + END + tdystak(savptr); staktop=movstr(savptr,stakbot); + WHILE d=readc() DO pushstak(d|quote) OD + await(0); + WHILE stakbot!=staktop + DO IF (*--staktop&STRIP)!=NL + THEN ++staktop; break; + FI + OD + pop(); +} + +#define CPYSIZ 512 + +subst(in,ot) + INT in, ot; +{ + REG CHAR c; + FILEBLK fb; + REG INT count=CPYSIZ; + + push(&fb); initf(in); + /* DQUOTE used to stop it from quoting */ + WHILE c=(getch(DQUOTE)&STRIP) + DO pushstak(c); + IF --count == 0 + THEN flush(ot); count=CPYSIZ; + FI + OD + flush(ot); + pop(); +} + +LOCAL flush(ot) +{ + write(ot,stakbot,staktop-stakbot); + IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI + staktop=stakbot; +} diff --git a/Applications/V7/cmd/sh/main.c b/Applications/V7/cmd/sh/main.c new file mode 100644 index 00000000..a1cd5e83 --- /dev/null +++ b/Applications/V7/cmd/sh/main.c @@ -0,0 +1,178 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include +#include +#include +#include "defs.h" +#include "dup.h" +#include "sym.h" +#include "timeout.h" +#include +#include + +UFD output = 2; +LOCAL BOOL beenhere = FALSE; +CHAR tmpout[20] = "/tmp/sh-"; +FILEBLK stdfile; +FILE standin = &stdfile; + +LOCAL void exfile(); + + + + +main(c, v) + INT c; + STRING v[]; +{ + REG INT rflag=ttyflg; + + /* initialise storage allocation */ + stdsigs(); + setbrk(BRKINCR); + addblok((POS)0); + + /* set names from userenv */ + sh_getenv(); + + /* look for restricted */ +/* IF c>0 ANDF any('r', *v) THEN rflag=0 FI */ + + /* look for options */ + dolc=options(c,v); + IF dolc<2 THEN flags |= stdflg FI + IF (flags&stdflg)==0 + THEN dolc--; + FI + dolv=v+c-dolc; dolc--; + + /* return here for shell file execution */ + setjmp(subshell); + + /* number of positional parameters */ + assnum(&dolladr,dolc); + cmdadr=dolv[0]; + + /* set pidname */ + assnum(&pidadr, getpid()); + + /* set up temp file names */ + settmp(); + + /* default ifs */ + dfault(&ifsnod, sptbnl); + + IF (beenhere++)==FALSE + THEN /* ? profile */ + IF *cmdadr=='-' + ANDF (input=pathopen(nullstr, profile))>=0 + THEN exfile(rflag); flags &= ~ttyflg; + FI + IF rflag==0 THEN flags |= rshflg FI + + /* open input file if specified */ + IF comdiv + THEN estabf(comdiv); input = -1; + ELSE input=((flags&stdflg) ? 0 : chkopen(cmdadr)); + comdiv--; + FI +// ELSE *execargs=(char *)dolv; /* for `ps' cmd */ + FI + + exfile(0); + done(); +} + +LOCAL void exfile(prof) +BOOL prof; +{ + REG L_INT mailtime = 0; + REG INT userid; + struct stat statb; + + /* move input */ + IF input>0 + THEN Ldup(input,INIO); + input=INIO; + FI + + /* move output to safe place */ + IF output==2 + THEN Ldup(dup(2),OTIO); + output=OTIO; + FI + + userid=getuid(); + + /* decide whether interactive */ + IF (flags&intflg) ORF ((flags&oneflg)==0 ANDF isatty(output) ANDF isatty(input)) + THEN dfault(&ps1nod, (userid?stdprompt:supprompt)); + dfault(&ps2nod, readmsg); + flags |= ttyflg|prompt; ignsig(KILL); + ELSE flags |= prof; flags &= ~prompt; + FI + + IF setjmp(errshell) ANDF prof + THEN close(input); return; + FI + + /* error return here */ + loopcnt=breakcnt=peekc=0; iopend=0; + IF input>=0 THEN initf(input) FI + + /* command loop */ + LOOP tdystak(0); + stakchk(); /* may reduce sbrk */ + exitset(); + IF (flags&prompt) ANDF standin->fstak==0 ANDF !eof + THEN IF mailnod.namval + ANDF stat(mailnod.namval,&statb)>=0 ANDF statb.st_size + ANDF (statb.st_mtime != mailtime) + ANDF mailtime + THEN prs(mailmsg) + FI + mailtime=statb.st_mtime; + prs(ps1nod.namval); alarm(TIMEOUT); flags |= waiting; + FI + + trapnote=0; peekc=readc(); + IF eof + THEN return; + FI + alarm(0); flags &= ~waiting; + execute(cmd(NL,MTFLG),0); + eof |= (flags&oneflg); + POOL +} + +chkpr(eor) +char eor; +{ + IF (flags&prompt) ANDF standin->fstak==0 ANDF eor==NL + THEN prs(ps2nod.namval); + FI +} + +settmp() +{ + itos(getpid()); serial=0; + tmpnam=movstr(numbuf,&tmpout[TMPNAM]); +} + +Ldup(fa, fb) + REG INT fa, fb; +{ + dup2(fa, fb); + close(fa); + fcntl(fb, F_SETFD, FD_CLOEXEC); +} diff --git a/Applications/V7/cmd/sh/mode.h b/Applications/V7/cmd/sh/mode.h new file mode 100644 index 00000000..d02b9a97 --- /dev/null +++ b/Applications/V7/cmd/sh/mode.h @@ -0,0 +1,202 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + */ + + +#define BYTESPERWORD (sizeof(char *)) + +TYPE char CHAR; +TYPE char BOOL; +TYPE int UFD; +TYPE int INT; +TYPE float REAL; +TYPE void *ADDRESS; +TYPE long int L_INT; +TYPE unsigned POS; +TYPE char *STRING; +TYPE int PIPE[]; +TYPE char *STKPTR; +TYPE char *BYTPTR; + +STRUCT stat STATBUF; /* defined in /usr/sys/stat.h */ +STRUCT blk *BLKPTR; +STRUCT fileblk FILEBLK; +STRUCT filehdr FILEHDR; +STRUCT fileblk *FILE; +STRUCT trenod *TREPTR; +STRUCT forknod *FORKPTR; +STRUCT comnod *COMPTR; +STRUCT swnod *SWPTR; +STRUCT regnod *REGPTR; +STRUCT parnod *PARPTR; +STRUCT ifnod *IFPTR; +STRUCT whnod *WHPTR; +STRUCT fornod *FORPTR; +STRUCT lstnod *LSTPTR; +STRUCT argnod *ARGPTR; +STRUCT dolnod *DOLPTR; +STRUCT ionod *IOPTR; +STRUCT namnod NAMNOD; +STRUCT namnod *NAMPTR; +#define NIL ((char*)0) + + +/* the following nonsense is required + * because casts turn an Lvalue + * into an Rvalue so two cheats + * are necessary, one for each context. + */ +#define Lcheat(a) (*(int *)&(a)) +#define Rcheat(a) ((int)(a)) + + +/* address puns for storage allocation */ +UNION { + FORKPTR _forkptr; + COMPTR _comptr; + PARPTR _parptr; + IFPTR _ifptr; + WHPTR _whptr; + FORPTR _forptr; + LSTPTR _lstptr; + BLKPTR _blkptr; + NAMPTR _namptr; + BYTPTR _bytptr; + } address; + + +/* heap storage */ +struct blk { + BLKPTR word; +}; + +#define BUFSIZ 64 +struct fileblk { + UFD fdes; + POS flin; + BOOL feof; + CHAR fsiz; + STRING fnxt; + STRING fend; + STRING *feval; + FILE fstak; + CHAR fbuf[BUFSIZ]; +}; + +/* for files not used with file descriptors */ +struct filehdr { + UFD fdes; + POS flin; + BOOL feof; + CHAR fsiz; + STRING fnxt; + STRING fend; + STRING *feval; + FILE fstak; + CHAR _fbuf[1]; +}; + +struct sysnod { + STRING sysnam; + INT sysval; +}; + +STRUCT sysnod SYSNOD; +STRUCT sysnod *SYSPTR; +STRUCT sysnod SYSTAB[]; + +/* this node is a proforma for those that follow */ +struct trenod { + INT tretyp; + IOPTR treio; +}; + +/* dummy for access only */ +struct argnod { + ARGPTR argnxt; + CHAR argval[1]; +}; + +struct dolnod { + DOLPTR dolnxt; + INT doluse; + CHAR dolarg[1]; +}; + +struct forknod { + INT forktyp; + IOPTR forkio; + TREPTR forktre; +}; + +struct comnod { + INT comtyp; + IOPTR comio; + ARGPTR comarg; + ARGPTR comset; +}; + +struct ifnod { + INT iftyp; + TREPTR iftre; + TREPTR thtre; + TREPTR eltre; +}; + +struct whnod { + INT whtyp; + TREPTR whtre; + TREPTR dotre; +}; + +struct fornod { + INT fortyp; + TREPTR fortre; + STRING fornam; + COMPTR forlst; +}; + +struct swnod { + INT swtyp; + STRING swarg; + REGPTR swlst; +}; + +struct regnod { + ARGPTR regptr; + TREPTR regcom; + REGPTR regnxt; +}; + +struct parnod { + INT partyp; + TREPTR partre; +}; + +struct lstnod { + INT lsttyp; + TREPTR lstlef; + TREPTR lstrit; +}; + +struct ionod { + INT iofile; + STRING ioname; + IOPTR ionxt; + IOPTR iolst; +}; + +#define FORKTYPE (sizeof(struct forknod)) +#define COMTYPE (sizeof(struct comnod)) +#define IFTYPE (sizeof(struct ifnod)) +#define WHTYPE (sizeof(struct whnod)) +#define FORTYPE (sizeof(struct fornod)) +#define SWTYPE (sizeof(struct swnod)) +#define REGTYPE (sizeof(struct regnod)) +#define PARTYPE (sizeof(struct parnod)) +#define LSTTYPE (sizeof(struct lstnod)) +#define IOTYPE (sizeof(struct ionod)) diff --git a/Applications/V7/cmd/sh/msg.c b/Applications/V7/cmd/sh/msg.c new file mode 100644 index 00000000..53a1c7e6 --- /dev/null +++ b/Applications/V7/cmd/sh/msg.c @@ -0,0 +1,139 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + + +#include "defs.h" +#include "sym.h" + +const char version[] = "\nVERSION sys137 DATE 1978 Nov 6 14:29:22\n"; + +/* error messages */ +const char badopt[] = "bad option(s)"; +const char mailmsg[] = "you have mail\n"; +const char nospace[] = "no space"; +const char synmsg[] = "syntax error"; + +const char badnum[] = "bad number"; +const char badparam[] = "parameter not set"; +const char badsub[] = "bad substitution"; +const char badcreate[] = "cannot create"; +const char illegal[] = "illegal io"; +const char restricted[] = "restricted"; +const char piperr[] = "cannot make pipe"; +const char badopen[] = "cannot open"; +const char coredump[] = " - core dumped"; +const char arglist[] = "arg list too long"; +const char txtbsy[] = "text busy"; +const char toobig[] = "too big"; +const char badexec[] = "cannot execute"; +const char notfound[] = "not found"; +const char badfile[] = "bad file number"; +const char badshift[] = "cannot shift"; +const char baddir[] = "bad directory"; +const char badtrap[] = "bad trap"; +const char wtfailed[] = "is read only"; +const char notid[] = "is not an identifier"; + +/* built in names */ +const char pathname[] = "PATH"; +const char homename[] = "HOME"; +const char mailname[] = "MAIL"; +const char fngname[] = "FILEMATCH"; +const char ifsname[] = "IFS"; +const char ps1name[] = "PS1"; +const char ps2name[] = "PS2"; + +/* string constants */ +const char nullstr[] = ""; +const char sptbnl[] = " \t\n"; +const char defpath[] = ":/bin:/usr/bin"; +const char colon[] = ": "; +const char minus[] = "-"; +const char endoffile[] = "end of file"; +const char unexpected[] = " unexpected"; +const char atline[] = " at line "; +const char devnull[] = "/dev/null"; +const char execpmsg[] = "+ "; +const char readmsg[] = "> "; +const char stdprompt[] = "$ "; +const char supprompt[] = "# "; +const char profile[] = ".profile"; + + +/* tables */ +SYSTAB reserved = { + {"in", INSYM}, + {"esac", ESSYM}, + {"case", CASYM}, + {"for", FORSYM}, + {"done", ODSYM}, + {"if", IFSYM}, + {"while", WHSYM}, + {"do", DOSYM}, + {"then", THSYM}, + {"else", ELSYM}, + {"elif", EFSYM}, + {"fi", FISYM}, + {"until", UNSYM}, + { "{", BRSYM}, + { "}", KTSYM}, + {0, 0}, +}; + +STRING sysmsg[] = { + 0, + "Hangup", + 0, /* Interrupt */ + "Quit", + "Illegal instruction", + "Trace/BPT trap", + "IOT trap", + "EMT trap", + "Floating exception", + "Killed", + "Bus error", + "Memory fault", + "Bad system call", + 0, /* Broken pipe */ + "Alarm call", + "Terminated", + "Signal 16", +}; + +const char export[] = "export"; +const char readonly[] = "readonly"; +SYSTAB commands = { + {"cd", SYSCD}, + {"read", SYSREAD}, +/* + {"[", SYSTST}, +*/ + {"set", SYSSET}, + {":", SYSNULL}, + {"trap", SYSTRAP}, + {"login", SYSLOGIN}, + {"wait", SYSWAIT}, + {"eval", SYSEVAL}, + {".", SYSDOT}, + {"newgrp", SYSLOGIN}, + {readonly, SYSRDONLY}, + {export, SYSXPORT}, + {"chdir", SYSCD}, + {"break", SYSBREAK}, + {"continue", SYSCONT}, + {"shift", SYSSHFT}, + {"exit", SYSEXIT}, + {"exec", SYSEXEC}, + {"times", SYSTIMES}, + {"umask", SYSUMASK}, + {0, 0}, +}; diff --git a/Applications/V7/cmd/sh/name.c b/Applications/V7/cmd/sh/name.c new file mode 100644 index 00000000..290d568e --- /dev/null +++ b/Applications/V7/cmd/sh/name.c @@ -0,0 +1,324 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + +LOCAL BOOL chkid(); +LOCAL void namwalk(); + + +NAMNOD ps2nod = {(NAMPTR)NIL, (NAMPTR)NIL, ps2name}, + fngnod = {(NAMPTR)NIL, (NAMPTR)NIL, fngname}, + pathnod = {(NAMPTR)NIL, (NAMPTR)NIL, pathname}, + ifsnod = {(NAMPTR)NIL, (NAMPTR)NIL, ifsname}, + ps1nod = {&pathnod, &ps2nod, ps1name}, + homenod = {&fngnod, &ifsnod, homename}, + mailnod = {&homenod, &ps1nod, mailname}; + +NAMPTR namep = &mailnod; + + +/* ======== variable and string handling ======== */ + +syslook(w,syswds) + STRING w; + SYSTAB syswds; +{ + REG CHAR first; + REG STRING s; + REG SYSPTR syscan; + + syscan=syswds; first = *w; + + WHILE s=syscan->sysnam + DO IF first == *s + ANDF eq(w,s) + THEN return(syscan->sysval); + FI + syscan++; + OD + return(0); +} + +setlist(arg,xp) + REG ARGPTR arg; + INT xp; +{ + WHILE arg + DO REG STRING s=mactrim(arg->argval); + setname(s, xp); + arg=arg->argnxt; + IF flags&execpr + THEN prs(s); + IF arg THEN blank(); ELSE newline(); FI + FI + OD +} + +void setname(argi, xp) + STRING argi; + INT xp; +{ + REG STRING argscan=argi; + REG NAMPTR n; + + IF letter(*argscan) + THEN WHILE alphanum(*argscan) DO argscan++ OD + IF *argscan=='=' + THEN *argscan = 0; + n=lookup(argi); + *argscan++ = '='; + attrib(n, xp); + IF xp&N_ENVNAM + THEN n->namenv = n->namval = argscan; + ELSE assign(n, argscan); + FI + return; + FI + FI + failed(argi,notid); +} + +replace(a, v) + REG STRING *a; + STRING v; +{ + free(*a); *a=make(v); +} + +dfault(n,v) + NAMPTR n; + STRING v; +{ + IF n->namval==0 + THEN assign(n,v) + FI +} + +assign(n,v) + NAMPTR n; + STRING v; +{ + IF n->namflg&N_RDONLY + THEN failed(n->namid,wtfailed); + ELSE replace(&n->namval,v); + FI +} + +INT readvar(names) + STRING *names; +{ + FILEBLK fb; + REG FILE f = &fb; + REG CHAR c; + REG INT rc=0; + NAMPTR n=lookup(*names++); /* done now to avoid storage mess */ + STKPTR rel=(STKPTR)relstak(); + + push(f); initf(dup(0)); + IF lseek(0,0L,1)==-1 + THEN f->fsiz=1; + FI + + LOOP c=nextc(0); + IF (*names ANDF any(c, ifsnod.namval)) ORF eolchar(c) + THEN zerostak(); + assign(n,absstak(rel)); setstak(rel); + IF *names + THEN n=lookup(*names++); + ELSE n=0; + FI + IF eolchar(c) + THEN break; + FI + ELSE pushstak(c); + FI + POOL + WHILE n + DO assign(n, nullstr); + IF *names THEN n=lookup(*names++); ELSE n=0; FI + OD + + IF eof THEN rc=1 FI + lseek(0, (long)(f->fnxt-f->fend), 1); + pop(); + return(rc); +} + +assnum(p, i) + STRING *p; + INT i; +{ + itos(i); replace(p,numbuf); +} + +STRING make(v) + STRING v; +{ + REG STRING p; + + IF v + THEN movstr(v,p=alloc(length(v))); + return(p); + ELSE return(0); + FI +} + + +NAMPTR lookup(nam) + REG STRING nam; +{ + REG NAMPTR nscan=namep; + REG NAMPTR *prev; + INT LR; + + IF !chkid(nam) + THEN failed(nam,notid); + FI + WHILE nscan + DO IF (LR=cf(nam,nscan->namid))==0 + THEN return(nscan); + ELIF LR<0 + THEN prev = &(nscan->namlft); + ELSE prev = &(nscan->namrgt); + FI + nscan = *prev; + OD + + /* add name node */ + nscan=(NAMPTR)alloc(sizeof *nscan); + nscan->namlft=nscan->namrgt=(NAMPTR)NIL; + nscan->namid=make(nam); + nscan->namval=0; nscan->namflg=N_DEFAULT; nscan->namenv=0; + return(*prev = nscan); +} + +LOCAL BOOL chkid(nam) + STRING nam; +{ + REG CHAR * cp=nam; + + IF !letter(*cp) + THEN return(FALSE); + ELSE WHILE *++cp + DO IF !alphanum(*cp) + THEN return(FALSE); + FI + OD + FI + return(TRUE); +} + +LOCAL void (*namfn)(); +namscan(fn) + void (*fn)(); +{ + namfn=fn; + namwalk(namep); +} + +LOCAL void namwalk(np) + REG NAMPTR np; +{ + IF np + THEN namwalk(np->namlft); + (*namfn)(np); + namwalk(np->namrgt); + FI +} + +void printnam(n) + NAMPTR n; +{ + REG STRING s; + + sigchk(); + IF s=n->namval + THEN prs(n->namid); + prc('='); prs(s); + newline(); + FI +} + +LOCAL STRING staknam(n) + REG NAMPTR n; +{ + REG STRING p; + + p=movstr(n->namid,staktop); + p=movstr("=",p); + p=movstr(n->namval,p); + return(getstak(p+1-ADR(stakbot))); +} + +void exname(n) + REG NAMPTR n; +{ + IF n->namflg&N_EXPORT + THEN free(n->namenv); + n->namenv = make(n->namval); + ELSE free(n->namval); + n->namval = make(n->namenv); + FI +} + +void printflg(n) + REG NAMPTR n; +{ + IF n->namflg&N_EXPORT + THEN prs(export); blank(); + FI + IF n->namflg&N_RDONLY + THEN prs(readonly); blank(); + FI + IF n->namflg&(N_EXPORT|N_RDONLY) + THEN prs(n->namid); newline(); + FI +} + +void sh_getenv(void) +{ + REG STRING *e=environ; + + WHILE *e + DO setname(*e++, N_ENVNAM) OD +} + +LOCAL INT namec; + +void countnam(n) + NAMPTR n; +{ + namec++; +} + +LOCAL STRING *argnam; + +void pushnam(n) + NAMPTR n; +{ + IF n->namval + THEN *argnam++ = staknam(n); + FI +} + +STRING *sh_setenv(void) +{ + REG STRING *er; + + namec=0; + namscan(countnam); + argnam = er = (STRING *)getstak(namec*BYTESPERWORD+BYTESPERWORD); + namscan(pushnam); + *argnam++ = 0; + return(er); +} diff --git a/Applications/V7/cmd/sh/name.h b/Applications/V7/cmd/sh/name.h new file mode 100644 index 00000000..c444fae1 --- /dev/null +++ b/Applications/V7/cmd/sh/name.h @@ -0,0 +1,27 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + + +#define N_RDONLY 0100000 +#define N_EXPORT 0040000 +#define N_ENVNAM 0020000 +#define N_ENVPOS 0007777 + +#define N_DEFAULT 0 + +struct namnod { + NAMPTR namlft; + NAMPTR namrgt; + STRING namid; + STRING namval; + STRING namenv; + INT namflg; +}; diff --git a/Applications/V7/cmd/sh/print.c b/Applications/V7/cmd/sh/print.c new file mode 100644 index 00000000..0821c107 --- /dev/null +++ b/Applications/V7/cmd/sh/print.c @@ -0,0 +1,99 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + +CHAR numbuf[6]; + + +/* printing and io conversion */ + +newline() +{ prc(NL); +} + +blank() +{ prc(SP); +} + +prp() +{ + IF (flags&prompt)==0 ANDF cmdadr + THEN prs(cmdadr); prs(colon); + FI +} + +void prs(as) + STRING as; +{ + REG STRING s; + + IF s=as + THEN write(output,s,length(s)-1); + FI +} + +void prc(c) + CHAR c; +{ + IF c + THEN write(output,&c,1); + FI +} + +prt(t) + L_INT t; +{ + REG INT hr, min, sec; + + t += 30; t /= 60; + sec=t%60; t /= 60; + min=t%60; + IF hr=t/60 + THEN prn(hr); prc('h'); + FI + prn(min); prc('m'); + prn(sec); prc('s'); +} + +prn(n) + INT n; +{ + itos(n); prs(numbuf); +} + +itos(n) +{ + REG char *abuf; REG POS a, i; INT pr, d; + abuf=numbuf; pr=FALSE; a=n; + FOR i=10000; i!=1; i/=10 + DO IF (pr |= (d=a/i)) THEN *abuf++=d+'0' FI + a %= i; + OD + *abuf++=a+'0'; + *abuf++=0; +} + +stoi(icp) +STRING icp; +{ + REG CHAR *cp = icp; + REG INT r = 0; + REG CHAR c; + + WHILE (c = *cp, digit(c)) ANDF c ANDF r>=0 + DO r = r*10 + c - '0'; cp++ OD + IF r<0 ORF cp==icp + THEN failed(icp,badnum); + ELSE return(r); + FI +} + diff --git a/Applications/V7/cmd/sh/service.c b/Applications/V7/cmd/sh/service.c new file mode 100644 index 00000000..2df45997 --- /dev/null +++ b/Applications/V7/cmd/sh/service.c @@ -0,0 +1,370 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + + +LOCAL STRING execs(); +LOCAL void gsort(); +LOCAL INT split(); + +#define ARGMK 01 + +INT errno; +STRING sysmsg[]; + +/* fault handling */ +#define ENOMEM 12 +#define ENOEXEC 8 +#define E2BIG 7 +#define ENOENT 2 +#define ETXTBSY 26 + + + +/* service routines for `execute' */ + +void initio(iop) + IOPTR iop; +{ + REG STRING ion; + REG INT iof, fd; + + IF iop + THEN iof=iop->iofile; + ion=mactrim(iop->ioname); + IF *ion ANDF (flags&noexec)==0 + THEN IF iof&IODOC + THEN subst(chkopen(ion),(fd=tmpfil())); + close(fd); fd=chkopen(tmpout); unlink(tmpout); + ELIF iof&IOMOV + THEN IF eq(minus,ion) + THEN fd = -1; + close(iof&IOUFD); + ELIF (fd=stoi(ion))>=USERIO + THEN failed(ion,badfile); + ELSE fd=dup(fd); + FI + ELIF (iof&IOPUT)==0 + THEN fd=chkopen(ion); + ELIF flags&rshflg + THEN failed(ion,restricted); + ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0 + THEN lseek(fd, 0L, 2); + ELSE fd=create(ion); + FI + IF fd>=0 + THEN sh_rename(fd,iof&IOUFD); + FI + FI + initio(iop->ionxt); + FI +} + +STRING getpath(s) + STRING s; +{ + REG STRING path; + IF any('/',s) + THEN IF flags&rshflg + THEN failed(s, restricted); + ELSE return(nullstr); + FI + ELIF (path = pathnod.namval)==0 + THEN return(defpath); + ELSE return(cpystak(path)); + FI +} + +INT pathopen(path, name) + REG STRING path, name; +{ + REG UFD f; + + REP path=catpath(path,name); + PER (f=open(curstak(),0))<0 ANDF path DONE + return(f); +} + +STRING catpath(path,name) + REG STRING path; + STRING name; +{ + /* leaves result on top of stack */ + REG STRING scanp = path, + argp = locstak(); + + WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD + IF scanp!=path THEN *argp++='/' FI + IF *scanp==COLON THEN scanp++ FI + path=(*scanp ? scanp : 0); scanp=name; + WHILE (*argp++ = *scanp++) DONE + return(path); +} + +LOCAL STRING xecmsg; +LOCAL STRING *xecenv; + +void execa(at) + STRING at[]; +{ + REG STRING path; + REG STRING *t = at; + + IF (flags&noexec)==0 + THEN xecmsg=notfound; path=getpath(*t); + namscan(exname); + xecenv=sh_setenv(); + WHILE path=execs(path,t) DONE + failed(*t,xecmsg); + FI +} + +LOCAL STRING execs(ap,t) + STRING ap; + REG STRING t[]; +{ + REG STRING p, prefix; + + prefix=catpath(ap,t[0]); + trim(p=curstak()); + + sigchk(); + execve(p, &t[0] ,xecenv); + SWITCH errno IN + + case ENOEXEC: + flags=0; + comdiv=0; ioset=0; + clearup(); /* remove open files and for loop junk */ + IF input THEN close(input) FI + close(output); output=2; + input=chkopen(p); + + /* set up new args */ + setargs(t); + longjmp(subshell,1); + + case ENOMEM: + failed(p,toobig); + + case E2BIG: + failed(p,arglist); + + case ETXTBSY: + failed(p,txtbsy); + + default: + xecmsg=badexec; + case ENOENT: + return(prefix); + ENDSW +} + +/* for processes to be waited for */ +#define MAXP 20 +LOCAL INT pwlist[MAXP]; +LOCAL INT pwc; + +postclr() +{ + REG INT *pw = pwlist; + + WHILE pw <= &pwlist[pwc] + DO *pw++ = 0 OD + pwc=0; +} + +void post(pcsid) + INT pcsid; +{ + REG INT *pw = pwlist; + + IF pcsid + THEN WHILE *pw DO pw++ OD + IF pwc >= MAXP-1 + THEN pw--; + ELSE pwc++; + FI + *pw = pcsid; + FI +} + +void await(i) + INT i; +{ + INT rc=0, wx=0; + INT w; + INT ipwc = pwc; + + post(i); + WHILE pwc + DO REG INT p; + REG INT sig; + INT w_hi; + + BEGIN + REG INT *pw=pwlist; + p=wait(&w); + WHILE pw <= &pwlist[ipwc] + DO IF *pw==p + THEN *pw=0; pwc--; + ELSE pw++; + FI + OD + END + + IF p == -1 THEN continue FI + + w_hi = (w>>8)&LOBYTE; + + IF sig = w&0177 + THEN IF sig == 0177 /* ptrace! return */ + THEN prs("ptrace: "); + sig = w_hi; + FI + IF sysmsg[sig] + THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI + prs(sysmsg[sig]); + IF w&0200 THEN prs(coredump) FI + FI + newline(); + FI + + IF rc==0 + THEN rc = (sig ? sig|SIGFLG : w_hi); + FI + wx |= w; + OD + + IF wx ANDF flags&errflg + THEN exitsh(rc); + FI + exitval=rc; exitset(); +} + +BOOL nosubst; + +trim(at) + STRING at; +{ + REG STRING p; + REG CHAR c; + REG CHAR q=0; + + IF p=at + THEN WHILE c = *p + DO *p++=c&STRIP; q |= c OD + FI + nosubst=q"E; +} + +STRING mactrim(s) + STRING s; +{ + REG STRING t=macro(s); + trim(t); + return(t); +} + +STRING *scan(argn) + INT argn; +{ + REG ARGPTR argp = (ARGPTR)(Rcheat(gchain)&~ARGMK); + REG STRING *comargn, *comargm; + + comargn=(STRING *)getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS; + + WHILE argp + DO *--comargn = argp->argval; + IF argp = argp->argnxt + THEN trim(*comargn); + FI + IF argp==0 ORF Rcheat(argp)&ARGMK + THEN gsort(comargn,comargm); + comargm = comargn; + FI + /* Lcheat(argp) &= ~ARGMK; */ + argp = (ARGPTR)(Rcheat(argp)&~ARGMK); + OD + return(comargn); +} + +LOCAL void gsort(from,to) + STRING from[], to[]; +{ + INT k, m, n; + REG INT i, j; + + IF (n=to-from)<=1 THEN return FI + + FOR j=1; j<=n; j*=2 DONE + + FOR m=2*j-1; m/=2; + DO k=n-m; + FOR j=0; j=0; i-=m + DO REG STRING *fromi; fromi = &from[i]; + IF cf(fromi[m],fromi[0])>0 + THEN break; + ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s; + FI + OD + OD + OD +} + +/* Argument list generation */ + +INT getarg(ac) + COMPTR ac; +{ + REG ARGPTR argp; + REG INT count=0; + REG COMPTR c; + + IF c=ac + THEN argp=c->comarg; + WHILE argp + DO count += split(macro(argp->argval)); + argp=argp->argnxt; + OD + FI + return(count); +} + +LOCAL INT split(s) + REG STRING s; +{ + REG STRING argp; + REG INT c; + INT count=0; + + LOOP sigchk(); argp=locstak()+BYTESPERWORD; + WHILE (c = *s++, !any(c,ifsnod.namval) && c) + DO *argp++ = c OD + IF argp==staktop+BYTESPERWORD + THEN IF c + THEN continue; + ELSE return(count); + FI + ELIF c==0 + THEN s--; + FI + IF c=expand(((ARGPTR)(argp=endstak(argp)))->argval,0) + THEN count += c; + ELSE /* assign(&fngnod, argp->argval); */ + makearg(argp); count++; + FI + Lcheat(gchain) |= ARGMK; + POOL +} diff --git a/Applications/V7/cmd/sh/setbrk.c b/Applications/V7/cmd/sh/setbrk.c new file mode 100644 index 00000000..618edf73 --- /dev/null +++ b/Applications/V7/cmd/sh/setbrk.c @@ -0,0 +1,19 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + +void *setbrk(intptr_t incr) +{ + uint8_t *a = sbrk(incr); + brkend = a + incr; + return a; +} diff --git a/Applications/V7/cmd/sh/stak.c b/Applications/V7/cmd/sh/stak.c new file mode 100644 index 00000000..4669e691 --- /dev/null +++ b/Applications/V7/cmd/sh/stak.c @@ -0,0 +1,84 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + +STKPTR stakbot=nullstr; + + + +/* ======== storage allocation ======== */ + +STKPTR getstak(asize) + INT asize; +{ /* allocate requested stack */ + REG STKPTR oldstak; + REG INT size; + + size=round(asize,BYTESPERWORD); + oldstak=stakbot; + staktop = stakbot += size; + return(oldstak); +} + +STKPTR locstak() +{ /* set up stack for local use + * should be followed by `endstak' + */ + IF brkend-stakbotADR(x) + DO free(stakbsy); + stakbsy = stakbsy->word; + OD + staktop=stakbot=max(ADR(x),ADR(stakbas)); + rmtemp(x); +} + +stakchk() +{ + IF (brkend-stakbas)>BRKINCR+BRKINCR + THEN setbrk(-BRKINCR); + FI +} + +STKPTR cpystak(x) + STKPTR x; +{ + return(endstak(movstr(x,locstak()))); +} diff --git a/Applications/V7/cmd/sh/stak.h b/Applications/V7/cmd/sh/stak.h new file mode 100644 index 00000000..115b92b3 --- /dev/null +++ b/Applications/V7/cmd/sh/stak.h @@ -0,0 +1,78 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +/* To use stack as temporary workspace across + * possible storage allocation (eg name lookup) + * a) get ptr from `relstak' + * b) can now use `pushstak' + * c) then reset with `setstak' + * d) `absstak' gives real address if needed + */ +#define relstak() (staktop-stakbot) +#define absstak(x) (stakbot+Rcheat(x)) +#define setstak(x) (staktop=absstak(x)) +#define pushstak(c) (*staktop++=(c)) +#define zerostak() (*staktop=0) + +/* Used to address an item left on the top of + * the stack (very temporary) + */ +#define curstak() (staktop) + +/* `usestak' before `pushstak' then `fixstak' + * These routines are safe against heap + * being allocated. + */ +#define usestak() {locstak();} + +/* for local use only since it hands + * out a real address for the stack top + */ +STKPTR locstak(); + +/* Will allocate the item being used and return its + * address (safe now). + */ +#define fixstak() endstak(staktop) + +/* For use after `locstak' to hand back + * new stack top and then allocate item + */ +STKPTR endstak(); + +/* Copy a string onto the stack and + * allocate the space. + */ +STKPTR cpystak(); + +/* Allocate given ammount of stack space */ +STKPTR getstak(); + +/* A chain of ptrs of stack blocks that + * have become covered by heap allocation. + * `tdystak' will return them to the heap. + */ +BLKPTR stakbsy; + +/* Base of the entire stack */ +STKPTR stakbas; + +/* Top of entire stack */ +STKPTR brkend; + +/* Base of current item */ +STKPTR stakbot; + +/* Top of current item */ +STKPTR staktop; + +/* Used with tdystak */ +STKPTR savstak(); diff --git a/Applications/V7/cmd/sh/string.c b/Applications/V7/cmd/sh/string.c new file mode 100644 index 00000000..1c80d1f5 --- /dev/null +++ b/Applications/V7/cmd/sh/string.c @@ -0,0 +1,57 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" + + +/* ======== general purpose string handling ======== */ + + +STRING movstr(a,b) + REG STRING a, b; +{ + WHILE *b++ = *a++ DONE + return(--b); +} + +INT any(c,s) + REG CHAR c; + STRING s; +{ + REG CHAR d; + + WHILE d = *s++ + DO IF d==c + THEN return(TRUE); + FI + OD + return(FALSE); +} + +INT cf(s1, s2) + REG STRING s1, s2; +{ + WHILE *s1++ == *s2 + DO IF *s2++==0 + THEN return(0); + FI + OD + return(*--s1 - *s2); +} + +INT length(as) + STRING as; +{ + REG STRING s; + + IF s=as THEN WHILE *s++ DONE FI + return(s-as); +} diff --git a/Applications/V7/cmd/sh/sym.h b/Applications/V7/cmd/sh/sym.h new file mode 100644 index 00000000..ac0d78b8 --- /dev/null +++ b/Applications/V7/cmd/sh/sym.h @@ -0,0 +1,48 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + */ + + +/* symbols for parsing */ +#define DOSYM 0405 +#define FISYM 0420 +#define EFSYM 0422 +#define ELSYM 0421 +#define INSYM 0412 +#define BRSYM 0406 +#define KTSYM 0450 +#define THSYM 0444 +#define ODSYM 0441 +#define ESSYM 0442 +#define IFSYM 0436 +#define FORSYM 0435 +#define WHSYM 0433 +#define UNSYM 0427 +#define CASYM 0417 + +#define SYMREP 04000 +#define ECSYM (SYMREP|';') +#define ANDFSYM (SYMREP|'&') +#define ORFSYM (SYMREP|'|') +#define APPSYM (SYMREP|'>') +#define DOCSYM (SYMREP|'<') +#define EOFSYM 02000 +#define SYMFLG 0400 + +/* arg to `cmd' */ +#define NLFLG 1 +#define MTFLG 2 + +/* for peekc */ +#define MARK 0100000 + +/* odd chars */ +#define DQUOTE '"' +#define SQUOTE '`' +#define LITERAL '\'' +#define DOLLAR '$' +#define ESCAPE '\\' +#define BRACE '{' diff --git a/Applications/V7/cmd/sh/timeout.h b/Applications/V7/cmd/sh/timeout.h new file mode 100644 index 00000000..83ba182c --- /dev/null +++ b/Applications/V7/cmd/sh/timeout.h @@ -0,0 +1,12 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#define TIMEOUT 0 diff --git a/Applications/V7/cmd/sh/word.c b/Applications/V7/cmd/sh/word.c new file mode 100644 index 00000000..294bcaac --- /dev/null +++ b/Applications/V7/cmd/sh/word.c @@ -0,0 +1,129 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" +#include "sym.h" + +LOCAL readb(); + + +/* ======== character handling for command lines ========*/ + + +word() +{ + REG CHAR c, d; + REG CHAR *argp=locstak()+BYTESPERWORD; + INT alpha=1; + + wdnum=0; wdset=0; + + WHILE (c=nextc(0), space(c)) DONE + IF !eofmeta(c) + THEN REP IF c==LITERAL + THEN *argp++=(DQUOTE); + WHILE (c=readc()) ANDF c!=LITERAL + DO *argp++=(c|QUOTE); chkpr(c) OD + *argp++=(DQUOTE); + ELSE *argp++=(c); + IF c=='=' THEN wdset |= alpha FI + IF !alphanum(c) THEN alpha=0 FI + IF qotchar(c) + THEN d=c; + WHILE (*argp++=(c=nextc(d))) ANDF c!=d + DO chkpr(c) OD + FI + FI + PER (c=nextc(0), !eofmeta(c)) DONE + argp=endstak(argp); + IF !letter(((ARGPTR)argp)->argval[0]) THEN wdset=0 FI + + peekc=c|MARK; + IF ((ARGPTR)argp)->argval[1]==0 ANDF (d=((ARGPTR)argp)->argval[0], digit(d)) ANDF (c=='>' ORF c=='<') + THEN word(); wdnum=d-'0'; + ELSE /*check for reserved words*/ + IF reserv==FALSE ORF (wdval=syslook(((ARGPTR)argp)->argval,reserved))==0 + THEN wdarg=(ARGPTR)argp; wdval=0; + FI + FI + + ELIF dipchar(c) + THEN IF (d=nextc(0))==c + THEN wdval = c|SYMREP; + ELSE peekc = d|MARK; wdval = c; + FI + ELSE IF (wdval=c)==EOF + THEN wdval=EOFSYM; + FI + IF iopend ANDF eolchar(c) + THEN copy(iopend); iopend=0; + FI + FI + reserv=FALSE; + return(wdval); +} + +nextc(quote) + CHAR quote; +{ + REG CHAR c, d; + IF (d=readc())==ESCAPE + THEN IF (c=readc())==NL + THEN chkpr(NL); d=nextc(quote); + ELIF quote ANDF c!=quote ANDF !escchar(c) + THEN peekc=c|MARK; + ELSE d = c|QUOTE; + FI + FI + return(d); +} + +readc() +{ + REG CHAR c; + REG INT len; + REG FILE f; + +retry: + IF peekc + THEN c=peekc; peekc=0; + ELIF (f=standin, f->fnxt!=f->fend) + THEN IF (c = *f->fnxt++)==0 + THEN IF f->feval + THEN IF estabf(*f->feval++) + THEN c=EOF; + ELSE c=SP; + FI + ELSE goto retry; /* = c=readc(); */ + FI + FI + IF flags&readpr ANDF standin->fstak==0 THEN prc(c) FI + IF c==NL THEN f->flin++ FI + ELIF f->feof ORF f->fdes<0 + THEN c=EOF; f->feof++; + ELIF (len=readb())<=0 + THEN close(f->fdes); f->fdes = -1; c=EOF; f->feof++; + ELSE f->fend = (f->fnxt = f->fbuf)+len; + goto retry; + FI + return(c); +} + +LOCAL readb() +{ + REG FILE f=standin; + REG INT len; + + REP IF trapnote&SIGSET THEN newline(); sigchk() FI + PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE + return(len); +} diff --git a/Applications/V7/cmd/sh/xec.c b/Applications/V7/cmd/sh/xec.c new file mode 100644 index 00000000..3db942fe --- /dev/null +++ b/Applications/V7/cmd/sh/xec.c @@ -0,0 +1,424 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Changes: Copyright (c) 1999 Robert Nordier. All rights reserved. */ + +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" +#include "sym.h" + +LOCAL INT parent; + +SYSTAB commands; + + + +/* ======== command execution ========*/ + + +execute(argt, execflg, pf1, pf2) + TREPTR argt; + INT *pf1, *pf2; +{ + /* `stakbot' is preserved by this routine */ + REG TREPTR t; + STKPTR sav=savstak(); + + sigchk(); + + IF (t=argt) ANDF execbrk==0 + THEN REG INT treeflgs; + INT oldexit, type; + REG STRING *com; + + treeflgs = t->tretyp; type = treeflgs&COMMSK; + oldexit=exitval; exitval=0; + + SWITCH type IN + + case TCOM: + BEGIN + STRING a1; + INT argn, internal; + ARGPTR schain=gchain; + IOPTR io=t->treio; + gchain=0; + argn = getarg(t); + com=scan(argn); + a1=com[1]; gchain=schain; + + IF (internal=syslook(com[0],commands)) ORF argn==0 + THEN setlist(((COMPTR)t)->comset, 0); + FI + + IF argn ANDF (flags&noexec)==0 + THEN /* print command if execpr */ + IF flags&execpr + THEN argn=0; prs(execpmsg); + WHILE com[argn]!=ENDARGS + DO prs(com[argn++]); blank() OD + newline(); + FI + + SWITCH internal IN + + case SYSDOT: + IF a1 + THEN REG INT f; + + IF (f=pathopen(getpath(a1), a1)) < 0 + THEN failed(a1,notfound); + ELSE execexp(0,f); + FI + FI + break; + + case SYSTIMES: + { + L_INT t[4]; times(t); + prt(t[2]); blank(); prt(t[3]); newline(); + } + break; + + case SYSEXIT: + exitsh(a1?stoi(a1):oldexit); + + case SYSNULL: + io=0; + break; + + case SYSCONT: + execbrk = -loopcnt; break; + + case SYSBREAK: + IF (execbrk=loopcnt) ANDF a1 + THEN breakcnt=stoi(a1); + FI + break; + + case SYSTRAP: + IF a1 + THEN BOOL clear; + IF (clear=digit(*a1))==0 + THEN ++com; + FI + WHILE *++com + DO INT i; + IF (i=stoi(*com))>=MAXTRAP ORF i1 + THEN setargs(com+argn-argc); + FI + ELIF ((COMPTR)t)->comset==0 + THEN /*scan name chain and print*/ + namscan(printnam); + FI + break; + + case SYSRDONLY: + exitval=N_RDONLY; + case SYSXPORT: + IF exitval==0 THEN exitval=N_EXPORT; FI + + IF a1 + THEN WHILE *++com + DO attrib(lookup(*com), exitval) OD + ELSE namscan(printflg); + FI + exitval=0; + break; + + case SYSEVAL: + IF a1 + THEN execexp(a1,&com[2]); + FI + break; + + case SYSUMASK: + if (a1) { + int c, i; + i = 0; + while ((c = *a1++) >= '0' && + c <= '7') + i = (i << 3) + c - '0'; + umask(i); + } else { + int i, j; + umask(i = umask(0)); + prc('0'); + for (j = 6; j >= 0; j -= 3) + prc(((i>>j)&07) + '0'); + newline(); + } + break; + + default: + internal=builtin(argn,com); + + ENDSW + + IF internal + THEN IF io THEN error(illegal) FI + chktrap(); + break; + FI + ELIF t->treio==0 + THEN break; + FI + END + + case TFORK: + IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 + THEN parent=0; + ELSE WHILE (parent=fork()) == -1 + DO sigchk(); alarm(10); pause() OD + FI + + IF parent + THEN /* This is the parent branch of fork; */ + /* it may or may not wait for the child. */ + IF treeflgs&FPRS ANDF flags&ttyflg + THEN prn(parent); newline(); + FI + IF treeflgs&FPCL THEN closepipe(pf1) FI + IF (treeflgs&(FAMP|FPOU))==0 + THEN await(parent); + ELIF (treeflgs&FAMP)==0 + THEN post(parent); + ELSE assnum(&pcsadr, parent); + FI + + chktrap(); + break; + + + ELSE /* this is the forked branch (child) of execute */ + flags |= forked; iotemp=0; + postclr(); + settmp(); + + /* Turn off INTR and QUIT if `FINT' */ + /* Reset ramaining signals to parent */ + /* except for those `lost' by trap */ + oldsigs(); + IF treeflgs&FINT + THEN signal(INTR,1); signal(QUIT,1); + FI + + /* pipe in or out */ + IF treeflgs&FPIN + THEN sh_rename(pf1[INPIPE],0); + close(pf1[OTPIPE]); + FI + IF treeflgs&FPOU + THEN sh_rename(pf2[OTPIPE],1); + close(pf2[INPIPE]); + FI + + /* default std input for & */ + IF treeflgs&FINT ANDF ioset==0 + THEN sh_rename(chkopen(devnull),0); + FI + + /* io redirection */ + initio(t->treio); + IF type!=TCOM + THEN execute(((FORKPTR)t)->forktre,1); + ELIF com[0]!=ENDARGS + THEN setlist(((COMPTR)t)->comset,N_EXPORT); + execa(com); + FI + done(); + FI + + case TPAR: + sh_rename(dup(2),output); + execute(((PARPTR)t)->partre,execflg); + done(); + + case TFIL: + BEGIN + INT pv[2]; chkpipe(pv); + IF execute(((LSTPTR)t)->lstlef, 0, pf1, pv)==0 + THEN execute(((LSTPTR)t)->lstrit, execflg, pv, pf2); + ELSE closepipe(pv); + FI + END + break; + + case TLST: + execute(((LSTPTR)t)->lstlef,0); + execute(((LSTPTR)t)->lstrit,execflg); + break; + + case TAND: + IF execute(((LSTPTR)t)->lstlef,0)==0 + THEN execute(((LSTPTR)t)->lstrit,execflg); + FI + break; + + case TORF: + IF execute(((LSTPTR)t)->lstlef,0)!=0 + THEN execute(((LSTPTR)t)->lstrit,execflg); + FI + break; + + case TFOR: + BEGIN + NAMPTR n = lookup(((FORPTR)t)->fornam); + STRING *args; + DOLPTR argsav=0; + + IF ((FORPTR)t)->forlst==0 + THEN args=dolv+1; + argsav=useargs(); + ELSE ARGPTR schain=gchain; + gchain=0; + trim((args=scan(getarg(((FORPTR)t)->forlst)))[0]); + gchain=schain; + FI + loopcnt++; + WHILE *args!=ENDARGS ANDF execbrk==0 + DO assign(n,*args++); + execute(((FORPTR)t)->fortre,0); + IF execbrk<0 THEN execbrk=0 FI + OD + IF breakcnt THEN breakcnt-- FI + execbrk=breakcnt; loopcnt--; + argfor=freeargs(argsav); + END + break; + + case TWH: + case TUN: + BEGIN + INT i=0; + + loopcnt++; + WHILE execbrk==0 ANDF (execute(((WHPTR)t)->whtre,0)==0)==(type==TWH) + DO i=execute(((WHPTR)t)->dotre,0); + IF execbrk<0 THEN execbrk=0 FI + OD + IF breakcnt THEN breakcnt-- FI + execbrk=breakcnt; loopcnt--; exitval=i; + END + break; + + case TIF: + IF execute(((IFPTR)t)->iftre,0)==0 + THEN execute(((IFPTR)t)->thtre,execflg); + ELSE execute(((IFPTR)t)->eltre,execflg); + FI + break; + + case TSW: + BEGIN + REG STRING r = mactrim(((SWPTR)t)->swarg); + t=(TREPTR)((SWPTR)t)->swlst; + WHILE t + DO ARGPTR rex=((REGPTR)t)->regptr; + WHILE rex + DO REG STRING s; + IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s)) + THEN execute(((REGPTR)t)->regcom,0); + t=0; break; + ELSE rex=((ARGPTR)rex)->argnxt; + FI + OD + IF t THEN t=(TREPTR)((REGPTR)t)->regnxt FI + OD + END + break; + ENDSW + exitset(); + FI + + sigchk(); + tdystak(sav); + return(exitval); +} + + +execexp(s,f) + STRING s; + UFD f; +{ + FILEBLK fb; + push(&fb); + IF s + THEN estabf(s); fb.feval=(STRING *)f; + ELIF f>=0 + THEN initf(f); + FI + execute(cmd(NL, NLFLG|MTFLG),0); + pop(); +}