#ifndef lint static char sccsid[] = "@(#)xec.c 4.3 8/11/83"; #endif # /* * 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 i1 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(); }