17d478c31Ssam #ifndef lint
2*b288febcSbostic static char sccsid[] = "@(#)xec.c 4.7 05/08/89";
37d478c31Ssam #endif
41355555fSmckusick
51355555fSmckusick #
61355555fSmckusick /*
71355555fSmckusick * UNIX shell
81355555fSmckusick *
91355555fSmckusick * S. R. Bourne
101355555fSmckusick * Bell Telephone Laboratories
111355555fSmckusick *
121355555fSmckusick */
131355555fSmckusick
141355555fSmckusick #include "defs.h"
151355555fSmckusick #include "sym.h"
16*b288febcSbostic #include "pathnames.h"
171355555fSmckusick
181355555fSmckusick LOCAL INT parent;
191355555fSmckusick
201355555fSmckusick SYSTAB commands;
211355555fSmckusick
221355555fSmckusick
231355555fSmckusick
241355555fSmckusick /* ======== command execution ========*/
251355555fSmckusick
261355555fSmckusick
execute(argt,execflg,pf1,pf2)271355555fSmckusick execute(argt, execflg, pf1, pf2)
281355555fSmckusick TREPTR argt;
291355555fSmckusick INT *pf1, *pf2;
301355555fSmckusick {
311355555fSmckusick /* `stakbot' is preserved by this routine */
321355555fSmckusick REG TREPTR t;
331355555fSmckusick STKPTR sav=savstak();
341355555fSmckusick
351355555fSmckusick sigchk();
361355555fSmckusick
371355555fSmckusick IF (t=argt) ANDF execbrk==0
381355555fSmckusick THEN REG INT treeflgs;
391355555fSmckusick INT oldexit, type;
401355555fSmckusick REG STRING *com;
411355555fSmckusick
421355555fSmckusick treeflgs = t->tretyp; type = treeflgs&COMMSK;
431355555fSmckusick oldexit=exitval; exitval=0;
441355555fSmckusick
451355555fSmckusick SWITCH type IN
461355555fSmckusick
471355555fSmckusick case TCOM:
481355555fSmckusick BEGIN
491355555fSmckusick STRING a1;
501355555fSmckusick INT argn, internal;
511355555fSmckusick ARGPTR schain=gchain;
5250048ca9Sbostic IOPTR io=t->treio.treio;
531355555fSmckusick gchain=0;
541355555fSmckusick argn = getarg(t);
551355555fSmckusick com=scan(argn);
561355555fSmckusick a1=com[1]; gchain=schain;
571355555fSmckusick
585628ef88Ssam IF argn==0 ORF (internal=syslook(com[0],commands))
5950048ca9Sbostic THEN setlist(t->comnod.comset, 0);
601355555fSmckusick FI
611355555fSmckusick
621355555fSmckusick IF argn ANDF (flags&noexec)==0
631355555fSmckusick THEN /* print command if execpr */
641355555fSmckusick IF flags&execpr
651355555fSmckusick THEN argn=0; prs(execpmsg);
661355555fSmckusick WHILE com[argn]!=ENDARGS
671355555fSmckusick DO prs(com[argn++]); blank() OD
681355555fSmckusick newline();
691355555fSmckusick FI
701355555fSmckusick
711355555fSmckusick SWITCH internal IN
721355555fSmckusick
731355555fSmckusick case SYSDOT:
741355555fSmckusick IF a1
751355555fSmckusick THEN REG INT f;
761355555fSmckusick
771355555fSmckusick IF (f=pathopen(getpath(a1), a1)) < 0
781355555fSmckusick THEN failed(a1,notfound);
791355555fSmckusick ELSE execexp(0,f);
801355555fSmckusick FI
811355555fSmckusick FI
821355555fSmckusick break;
831355555fSmckusick
841355555fSmckusick case SYSTIMES:
851355555fSmckusick {
861355555fSmckusick L_INT t[4]; times(t);
871355555fSmckusick prt(t[2]); blank(); prt(t[3]); newline();
881355555fSmckusick }
891355555fSmckusick break;
901355555fSmckusick
911355555fSmckusick case SYSEXIT:
921355555fSmckusick exitsh(a1?stoi(a1):oldexit);
931355555fSmckusick
941355555fSmckusick case SYSNULL:
951355555fSmckusick io=0;
961355555fSmckusick break;
971355555fSmckusick
981355555fSmckusick case SYSCONT:
991355555fSmckusick execbrk = -loopcnt; break;
1001355555fSmckusick
1011355555fSmckusick case SYSBREAK:
1021355555fSmckusick IF (execbrk=loopcnt) ANDF a1
1031355555fSmckusick THEN breakcnt=stoi(a1);
1041355555fSmckusick FI
1051355555fSmckusick break;
1061355555fSmckusick
1071355555fSmckusick case SYSTRAP:
1081355555fSmckusick IF a1
1091355555fSmckusick THEN BOOL clear;
1101355555fSmckusick IF (clear=digit(*a1))==0
1111355555fSmckusick THEN ++com;
1121355555fSmckusick FI
1131355555fSmckusick WHILE *++com
1141355555fSmckusick DO INT i;
1151355555fSmckusick IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP
1161355555fSmckusick THEN failed(*com,badtrap);
1171355555fSmckusick ELIF clear
1181355555fSmckusick THEN clrsig(i);
1191355555fSmckusick ELSE replace(&trapcom[i],a1);
1201355555fSmckusick IF *a1
1211355555fSmckusick THEN getsig(i);
1221355555fSmckusick ELSE ignsig(i);
1231355555fSmckusick FI
1241355555fSmckusick FI
1251355555fSmckusick OD
1261355555fSmckusick ELSE /* print out current traps */
1271355555fSmckusick INT i;
1281355555fSmckusick
1291355555fSmckusick FOR i=0; i<MAXTRAP; i++
1301355555fSmckusick DO IF trapcom[i]
1311355555fSmckusick THEN prn(i); prs(colon); prs(trapcom[i]); newline();
1321355555fSmckusick FI
1331355555fSmckusick OD
1341355555fSmckusick FI
1351355555fSmckusick break;
1361355555fSmckusick
1371355555fSmckusick case SYSEXEC:
1381355555fSmckusick com++;
1391355555fSmckusick initio(io); ioset=0; io=0;
1401355555fSmckusick IF a1==0 THEN break FI
1411355555fSmckusick
1421355555fSmckusick case SYSLOGIN:
1431355555fSmckusick flags |= forked;
1441355555fSmckusick oldsigs(); execa(com); done();
1451355555fSmckusick
1461355555fSmckusick case SYSCD:
1471355555fSmckusick IF flags&rshflg
1481355555fSmckusick THEN failed(com[0],restricted);
1491355555fSmckusick ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0
1501355555fSmckusick THEN failed(a1,baddir);
1511355555fSmckusick FI
1521355555fSmckusick break;
1531355555fSmckusick
1541355555fSmckusick case SYSSHFT:
1551355555fSmckusick IF dolc<1
1561355555fSmckusick THEN error(badshift);
1571355555fSmckusick ELSE dolv++; dolc--;
1581355555fSmckusick FI
1591355555fSmckusick assnum(&dolladr, dolc);
1601355555fSmckusick break;
1611355555fSmckusick
1621355555fSmckusick case SYSWAIT:
1631355555fSmckusick await(-1);
1641355555fSmckusick break;
1651355555fSmckusick
1661355555fSmckusick case SYSREAD:
1671355555fSmckusick exitval=readvar(&com[1]);
1681355555fSmckusick break;
1691355555fSmckusick
1701355555fSmckusick /*
1711355555fSmckusick case SYSTST:
1721355555fSmckusick exitval=testcmd(com);
1731355555fSmckusick break;
1741355555fSmckusick */
1751355555fSmckusick
1761355555fSmckusick case SYSSET:
1771355555fSmckusick IF a1
1781355555fSmckusick THEN INT argc;
1791355555fSmckusick argc = options(argn,com);
1801355555fSmckusick IF argc>1
1811355555fSmckusick THEN setargs(com+argn-argc);
1821355555fSmckusick FI
18350048ca9Sbostic ELIF t->comnod.comset==0
1841355555fSmckusick THEN /*scan name chain and print*/
1851355555fSmckusick namscan(printnam);
1861355555fSmckusick FI
1871355555fSmckusick break;
1881355555fSmckusick
1891355555fSmckusick case SYSRDONLY:
1901355555fSmckusick exitval=N_RDONLY;
1911355555fSmckusick case SYSXPORT:
1921355555fSmckusick IF exitval==0 THEN exitval=N_EXPORT; FI
1931355555fSmckusick
1941355555fSmckusick IF a1
1951355555fSmckusick THEN WHILE *++com
1961355555fSmckusick DO attrib(lookup(*com), exitval) OD
1971355555fSmckusick ELSE namscan(printflg);
1981355555fSmckusick FI
1991355555fSmckusick exitval=0;
2001355555fSmckusick break;
2011355555fSmckusick
2021355555fSmckusick case SYSEVAL:
2031355555fSmckusick IF a1
2041355555fSmckusick THEN execexp(a1,&com[2]);
2051355555fSmckusick FI
2061355555fSmckusick break;
2071355555fSmckusick
2081355555fSmckusick case SYSUMASK:
2091355555fSmckusick if (a1) {
2101599d6d5Ssam int c, i;
2111355555fSmckusick i = 0;
2121355555fSmckusick while ((c = *a1++) >= '0' &&
2131355555fSmckusick c <= '7')
2141355555fSmckusick i = (i << 3) + c - '0';
2151355555fSmckusick umask(i);
2161355555fSmckusick } else {
2171355555fSmckusick int i, j;
2181355555fSmckusick umask(i = umask(0));
2191355555fSmckusick prc('0');
2201355555fSmckusick for (j = 6; j >= 0; j -= 3)
2211355555fSmckusick prc(((i>>j)&07) + '0');
2221355555fSmckusick newline();
2231355555fSmckusick }
2241355555fSmckusick break;
2251355555fSmckusick
2261355555fSmckusick default:
2271355555fSmckusick internal=builtin(argn,com);
2281355555fSmckusick
2291355555fSmckusick ENDSW
2301355555fSmckusick
2311355555fSmckusick IF internal
2321355555fSmckusick THEN IF io THEN error(illegal) FI
2331355555fSmckusick chktrap();
2341355555fSmckusick break;
2351355555fSmckusick FI
23650048ca9Sbostic ELIF t->treio.treio==0
2371355555fSmckusick THEN break;
2381355555fSmckusick FI
2391355555fSmckusick END
2401355555fSmckusick
2411355555fSmckusick case TFORK:
2421355555fSmckusick IF execflg ANDF (treeflgs&(FAMP|FPOU))==0
2431355555fSmckusick THEN parent=0;
2441355555fSmckusick ELSE WHILE (parent=fork()) == -1
2451355555fSmckusick DO sigchk(); alarm(10); pause() OD
2461355555fSmckusick FI
2471355555fSmckusick
2481355555fSmckusick IF parent
2491355555fSmckusick THEN /* This is the parent branch of fork; */
2501355555fSmckusick /* it may or may not wait for the child. */
2511355555fSmckusick IF treeflgs&FPRS ANDF flags&ttyflg
2521355555fSmckusick THEN prn(parent); newline();
2531355555fSmckusick FI
2541355555fSmckusick IF treeflgs&FPCL THEN closepipe(pf1) FI
2551355555fSmckusick IF (treeflgs&(FAMP|FPOU))==0
2561355555fSmckusick THEN await(parent);
2571355555fSmckusick ELIF (treeflgs&FAMP)==0
2581355555fSmckusick THEN post(parent);
2591355555fSmckusick ELSE assnum(&pcsadr, parent);
2601355555fSmckusick FI
2611355555fSmckusick
2621355555fSmckusick chktrap();
2631355555fSmckusick break;
2641355555fSmckusick
2651355555fSmckusick
2661355555fSmckusick ELSE /* this is the forked branch (child) of execute */
2671355555fSmckusick flags |= forked; iotemp=0;
2681355555fSmckusick postclr();
2691355555fSmckusick settmp();
2701355555fSmckusick
2711355555fSmckusick /* Turn off INTR and QUIT if `FINT' */
2721355555fSmckusick /* Reset ramaining signals to parent */
2731355555fSmckusick /* except for those `lost' by trap */
2741355555fSmckusick oldsigs();
2751355555fSmckusick IF treeflgs&FINT
2761355555fSmckusick THEN signal(INTR,1); signal(QUIT,1);
2771355555fSmckusick FI
2781355555fSmckusick
2791355555fSmckusick /* pipe in or out */
2801355555fSmckusick IF treeflgs&FPIN
2811355555fSmckusick THEN rename(pf1[INPIPE],0);
2821355555fSmckusick close(pf1[OTPIPE]);
2831355555fSmckusick FI
2841355555fSmckusick IF treeflgs&FPOU
2851355555fSmckusick THEN rename(pf2[OTPIPE],1);
2861355555fSmckusick close(pf2[INPIPE]);
2871355555fSmckusick FI
2881355555fSmckusick
2891355555fSmckusick /* default std input for & */
2901355555fSmckusick IF treeflgs&FINT ANDF ioset==0
291*b288febcSbostic THEN rename(chkopen(_PATH_DEVNULL),0);
2921355555fSmckusick FI
2931355555fSmckusick
2941355555fSmckusick /* io redirection */
29550048ca9Sbostic initio(t->treio.treio);
2961355555fSmckusick IF type!=TCOM
29750048ca9Sbostic THEN execute(t->forknod.forktre,1);
2981355555fSmckusick ELIF com[0]!=ENDARGS
29950048ca9Sbostic THEN setlist(t->comnod.comset,N_EXPORT);
3001355555fSmckusick execa(com);
3011355555fSmckusick FI
3021355555fSmckusick done();
3031355555fSmckusick FI
3041355555fSmckusick
3051355555fSmckusick case TPAR:
3061355555fSmckusick rename(dup(2),output);
30750048ca9Sbostic execute(t->parnod.partre,execflg);
3081355555fSmckusick done();
3091355555fSmckusick
3101355555fSmckusick case TFIL:
3111355555fSmckusick BEGIN
3121355555fSmckusick INT pv[2]; chkpipe(pv);
31350048ca9Sbostic IF execute(t->lstnod.lstlef, 0, pf1, pv)==0
31450048ca9Sbostic THEN execute(t->lstnod.lstrit, execflg, pv, pf2);
3151355555fSmckusick ELSE closepipe(pv);
3161355555fSmckusick FI
3171355555fSmckusick END
3181355555fSmckusick break;
3191355555fSmckusick
3201355555fSmckusick case TLST:
32150048ca9Sbostic execute(t->lstnod.lstlef,0);
32250048ca9Sbostic execute(t->lstnod.lstrit,execflg);
3231355555fSmckusick break;
3241355555fSmckusick
3251355555fSmckusick case TAND:
32650048ca9Sbostic IF execute(t->lstnod.lstlef,0)==0
32750048ca9Sbostic THEN execute(t->lstnod.lstrit,execflg);
3281355555fSmckusick FI
3291355555fSmckusick break;
3301355555fSmckusick
3311355555fSmckusick case TORF:
33250048ca9Sbostic IF execute(t->lstnod.lstlef,0)!=0
33350048ca9Sbostic THEN execute(t->lstnod.lstrit,execflg);
3341355555fSmckusick FI
3351355555fSmckusick break;
3361355555fSmckusick
3371355555fSmckusick case TFOR:
3381355555fSmckusick BEGIN
33950048ca9Sbostic NAMPTR n = lookup(t->fornod.fornam);
3401355555fSmckusick STRING *args;
3411355555fSmckusick DOLPTR argsav=0;
3421355555fSmckusick
34350048ca9Sbostic IF t->fornod.forlst==0
3441355555fSmckusick THEN args=dolv+1;
3451355555fSmckusick argsav=useargs();
3461355555fSmckusick ELSE ARGPTR schain=gchain;
3471355555fSmckusick gchain=0;
34850048ca9Sbostic trim((args=scan(getarg(t->fornod.forlst)))[0]);
3491355555fSmckusick gchain=schain;
3501355555fSmckusick FI
3511355555fSmckusick loopcnt++;
3521355555fSmckusick WHILE *args!=ENDARGS ANDF execbrk==0
3531355555fSmckusick DO assign(n,*args++);
35450048ca9Sbostic execute(t->fornod.fortre,0);
3551355555fSmckusick IF execbrk<0 THEN execbrk=0 FI
3561355555fSmckusick OD
3571355555fSmckusick IF breakcnt THEN breakcnt-- FI
3581355555fSmckusick execbrk=breakcnt; loopcnt--;
3591355555fSmckusick argfor=freeargs(argsav);
3601355555fSmckusick END
3611355555fSmckusick break;
3621355555fSmckusick
3631355555fSmckusick case TWH:
3641355555fSmckusick case TUN:
3651355555fSmckusick BEGIN
36653e21493Sbostic INT i=0, saveflg;
3671355555fSmckusick
36853e21493Sbostic saveflg = flags&errflg;
3691355555fSmckusick loopcnt++;
37053e21493Sbostic WHILE execbrk==0
37153e21493Sbostic DO flags &= ~errflg;
37250048ca9Sbostic i=execute(t->whnod.whtre,0);
37353e21493Sbostic flags |= saveflg;
37453e21493Sbostic IF (i==0)!=(type==TWH) THEN break FI
37550048ca9Sbostic i=execute(t->whnod.dotre,0);
3761355555fSmckusick IF execbrk<0 THEN execbrk=0 FI
3771355555fSmckusick OD
3781355555fSmckusick IF breakcnt THEN breakcnt-- FI
3791355555fSmckusick execbrk=breakcnt; loopcnt--; exitval=i;
3801355555fSmckusick END
3811355555fSmckusick break;
3821355555fSmckusick
3831355555fSmckusick case TIF:
38453e21493Sbostic BEGIN
38553e21493Sbostic INT i, saveflg;
38653e21493Sbostic
38753e21493Sbostic saveflg = flags&errflg;
38853e21493Sbostic flags &= ~errflg;
38950048ca9Sbostic i=execute(t->ifnod.iftre,0);
39053e21493Sbostic flags |= saveflg;
39153e21493Sbostic IF i==0
39250048ca9Sbostic THEN execute(t->ifnod.thtre,execflg);
39350048ca9Sbostic ELSE execute(t->ifnod.eltre,execflg);
3941355555fSmckusick FI
39553e21493Sbostic END
3961355555fSmckusick break;
3971355555fSmckusick
3981355555fSmckusick case TSW:
3991355555fSmckusick BEGIN
40050048ca9Sbostic REG STRING r = mactrim(t->swnod.swarg);
40150048ca9Sbostic REG REGPTR eg = t->swnod.swlst;
40250048ca9Sbostic WHILE eg
40350048ca9Sbostic DO ARGPTR rex=eg->regptr;
4041355555fSmckusick WHILE rex
4051355555fSmckusick DO REG STRING s;
4061355555fSmckusick IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s))
40750048ca9Sbostic THEN execute(eg->regcom,0);
40850048ca9Sbostic eg=0; break;
4091355555fSmckusick ELSE rex=rex->argnxt;
4101355555fSmckusick FI
4111355555fSmckusick OD
41250048ca9Sbostic IF eg THEN eg=eg->regnxt FI
4131355555fSmckusick OD
4141355555fSmckusick END
4151355555fSmckusick break;
4161355555fSmckusick ENDSW
4171355555fSmckusick exitset();
4181355555fSmckusick FI
4191355555fSmckusick
4201355555fSmckusick sigchk();
4211355555fSmckusick tdystak(sav);
4221355555fSmckusick return(exitval);
4231355555fSmckusick }
4241355555fSmckusick
4251355555fSmckusick
execexp(s,f)4261355555fSmckusick execexp(s,f)
4271355555fSmckusick STRING s;
4281355555fSmckusick UFD f;
4291355555fSmckusick {
4301355555fSmckusick FILEBLK fb;
4311355555fSmckusick push(&fb);
4321355555fSmckusick IF s
4331355555fSmckusick THEN estabf(s); fb.feval=f;
4341355555fSmckusick ELIF f>=0
4351355555fSmckusick THEN initf(f);
4361355555fSmckusick FI
4371355555fSmckusick execute(cmd(NL, NLFLG|MTFLG),0);
4381355555fSmckusick pop();
4391355555fSmckusick }
440