+/* xec.c 4.2 83/02/09 */
+
+#
+/*
+ * 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 argn==0 ORF (internal=syslook(com[0],commands))
+ THEN setlist(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 i<MINTRAP
+ THEN failed(*com,badtrap);
+ ELIF clear
+ THEN clrsig(i);
+ ELSE replace(&trapcom[i],a1);
+ IF *a1
+ THEN getsig(i);
+ ELSE ignsig(i);
+ FI
+ FI
+ OD
+ ELSE /* print out current traps */
+ INT i;
+
+ FOR i=0; i<MAXTRAP; i++
+ DO IF trapcom[i]
+ THEN prn(i); prs(colon); prs(trapcom[i]); newline();
+ FI
+ OD
+ FI
+ break;
+
+ case SYSEXEC:
+ com++;
+ initio(io); ioset=0; io=0;
+ IF a1==0 THEN break FI
+
+ case SYSLOGIN:
+ flags |= forked;
+ oldsigs(); execa(com); done();
+
+ case SYSCD:
+ IF flags&rshflg
+ THEN failed(com[0],restricted);
+ ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0
+ THEN failed(a1,baddir);
+ FI
+ break;
+
+ case SYSSHFT:
+ IF dolc<1
+ THEN error(badshift);
+ ELSE dolv++; dolc--;
+ FI
+ assnum(&dolladr, dolc);
+ break;
+
+ case SYSWAIT:
+ await(-1);
+ break;
+
+ case SYSREAD:
+ exitval=readvar(&com[1]);
+ break;
+
+/*
+ case SYSTST:
+ exitval=testcmd(com);
+ break;
+*/
+
+ case SYSSET:
+ IF a1
+ THEN INT argc;
+ argc = options(argn,com);
+ IF argc>1
+ THEN setargs(com+argn-argc);
+ FI
+ ELIF 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 rename(pf1[INPIPE],0);
+ close(pf1[OTPIPE]);
+ FI
+ IF treeflgs&FPOU
+ THEN rename(pf2[OTPIPE],1);
+ close(pf2[INPIPE]);
+ FI
+
+ /* default std input for & */
+ IF treeflgs&FINT ANDF ioset==0
+ THEN rename(chkopen(devnull),0);
+ FI
+
+ /* io redirection */
+ initio(t->treio);
+ IF type!=TCOM
+ THEN execute(t->forktre,1);
+ ELIF com[0]!=ENDARGS
+ THEN setlist(t->comset,N_EXPORT);
+ execa(com);
+ FI
+ done();
+ FI
+
+ case TPAR:
+ rename(dup(2),output);
+ execute(t->partre,execflg);
+ done();
+
+ case TFIL:
+ BEGIN
+ INT pv[2]; chkpipe(pv);
+ IF execute(t->lstlef, 0, pf1, pv)==0
+ THEN execute(t->lstrit, execflg, pv, pf2);
+ ELSE closepipe(pv);
+ FI
+ END
+ break;
+
+ case TLST:
+ execute(t->lstlef,0);
+ execute(t->lstrit,execflg);
+ break;
+
+ case TAND:
+ IF execute(t->lstlef,0)==0
+ THEN execute(t->lstrit,execflg);
+ FI
+ break;
+
+ case TORF:
+ IF execute(t->lstlef,0)!=0
+ THEN execute(t->lstrit,execflg);
+ FI
+ break;
+
+ case TFOR:
+ BEGIN
+ NAMPTR n = lookup(t->fornam);
+ STRING *args;
+ DOLPTR argsav=0;
+
+ IF t->forlst==0
+ THEN args=dolv+1;
+ argsav=useargs();
+ ELSE ARGPTR schain=gchain;
+ gchain=0;
+ trim((args=scan(getarg(t->forlst)))[0]);
+ gchain=schain;
+ FI
+ loopcnt++;
+ WHILE *args!=ENDARGS ANDF execbrk==0
+ DO assign(n,*args++);
+ execute(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(t->whtre,0)==0)==(type==TWH)
+ DO i=execute(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(t->iftre,0)==0
+ THEN execute(t->thtre,execflg);
+ ELSE execute(t->eltre,execflg);
+ FI
+ break;
+
+ case TSW:
+ BEGIN
+ REG STRING r = mactrim(t->swarg);
+ t=t->swlst;
+ WHILE t
+ DO ARGPTR rex=t->regptr;
+ WHILE rex
+ DO REG STRING s;
+ IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s))
+ THEN execute(t->regcom,0);
+ t=0; break;
+ ELSE rex=rex->argnxt;
+ FI
+ OD
+ IF t THEN t=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=f;
+ ELIF f>=0
+ THEN initf(f);
+ FI
+ execute(cmd(NL, NLFLG|MTFLG),0);
+ pop();
+}