114480Ssam #ifndef lint
2*37678Sbostic static char sccsid[] = "@(#)xec.c 4.7 05/08/89";
314480Ssam #endif
46710Smckusick
56710Smckusick #
66710Smckusick /*
76710Smckusick * UNIX shell
86710Smckusick *
96710Smckusick * S. R. Bourne
106710Smckusick * Bell Telephone Laboratories
116710Smckusick *
126710Smckusick */
136710Smckusick
146710Smckusick #include "defs.h"
156710Smckusick #include "sym.h"
16*37678Sbostic #include "pathnames.h"
176710Smckusick
186710Smckusick LOCAL INT parent;
196710Smckusick
206710Smckusick SYSTAB commands;
216710Smckusick
226710Smckusick
236710Smckusick
246710Smckusick /* ======== command execution ========*/
256710Smckusick
266710Smckusick
execute(argt,execflg,pf1,pf2)276710Smckusick execute(argt, execflg, pf1, pf2)
286710Smckusick TREPTR argt;
296710Smckusick INT *pf1, *pf2;
306710Smckusick {
316710Smckusick /* `stakbot' is preserved by this routine */
326710Smckusick REG TREPTR t;
336710Smckusick STKPTR sav=savstak();
346710Smckusick
356710Smckusick sigchk();
366710Smckusick
376710Smckusick IF (t=argt) ANDF execbrk==0
386710Smckusick THEN REG INT treeflgs;
396710Smckusick INT oldexit, type;
406710Smckusick REG STRING *com;
416710Smckusick
426710Smckusick treeflgs = t->tretyp; type = treeflgs&COMMSK;
436710Smckusick oldexit=exitval; exitval=0;
446710Smckusick
456710Smckusick SWITCH type IN
466710Smckusick
476710Smckusick case TCOM:
486710Smckusick BEGIN
496710Smckusick STRING a1;
506710Smckusick INT argn, internal;
516710Smckusick ARGPTR schain=gchain;
5234082Sbostic IOPTR io=t->treio.treio;
536710Smckusick gchain=0;
546710Smckusick argn = getarg(t);
556710Smckusick com=scan(argn);
566710Smckusick a1=com[1]; gchain=schain;
576710Smckusick
5810805Ssam IF argn==0 ORF (internal=syslook(com[0],commands))
5934082Sbostic THEN setlist(t->comnod.comset, 0);
606710Smckusick FI
616710Smckusick
626710Smckusick IF argn ANDF (flags&noexec)==0
636710Smckusick THEN /* print command if execpr */
646710Smckusick IF flags&execpr
656710Smckusick THEN argn=0; prs(execpmsg);
666710Smckusick WHILE com[argn]!=ENDARGS
676710Smckusick DO prs(com[argn++]); blank() OD
686710Smckusick newline();
696710Smckusick FI
706710Smckusick
716710Smckusick SWITCH internal IN
726710Smckusick
736710Smckusick case SYSDOT:
746710Smckusick IF a1
756710Smckusick THEN REG INT f;
766710Smckusick
776710Smckusick IF (f=pathopen(getpath(a1), a1)) < 0
786710Smckusick THEN failed(a1,notfound);
796710Smckusick ELSE execexp(0,f);
806710Smckusick FI
816710Smckusick FI
826710Smckusick break;
836710Smckusick
846710Smckusick case SYSTIMES:
856710Smckusick {
866710Smckusick L_INT t[4]; times(t);
876710Smckusick prt(t[2]); blank(); prt(t[3]); newline();
886710Smckusick }
896710Smckusick break;
906710Smckusick
916710Smckusick case SYSEXIT:
926710Smckusick exitsh(a1?stoi(a1):oldexit);
936710Smckusick
946710Smckusick case SYSNULL:
956710Smckusick io=0;
966710Smckusick break;
976710Smckusick
986710Smckusick case SYSCONT:
996710Smckusick execbrk = -loopcnt; break;
1006710Smckusick
1016710Smckusick case SYSBREAK:
1026710Smckusick IF (execbrk=loopcnt) ANDF a1
1036710Smckusick THEN breakcnt=stoi(a1);
1046710Smckusick FI
1056710Smckusick break;
1066710Smckusick
1076710Smckusick case SYSTRAP:
1086710Smckusick IF a1
1096710Smckusick THEN BOOL clear;
1106710Smckusick IF (clear=digit(*a1))==0
1116710Smckusick THEN ++com;
1126710Smckusick FI
1136710Smckusick WHILE *++com
1146710Smckusick DO INT i;
1156710Smckusick IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP
1166710Smckusick THEN failed(*com,badtrap);
1176710Smckusick ELIF clear
1186710Smckusick THEN clrsig(i);
1196710Smckusick ELSE replace(&trapcom[i],a1);
1206710Smckusick IF *a1
1216710Smckusick THEN getsig(i);
1226710Smckusick ELSE ignsig(i);
1236710Smckusick FI
1246710Smckusick FI
1256710Smckusick OD
1266710Smckusick ELSE /* print out current traps */
1276710Smckusick INT i;
1286710Smckusick
1296710Smckusick FOR i=0; i<MAXTRAP; i++
1306710Smckusick DO IF trapcom[i]
1316710Smckusick THEN prn(i); prs(colon); prs(trapcom[i]); newline();
1326710Smckusick FI
1336710Smckusick OD
1346710Smckusick FI
1356710Smckusick break;
1366710Smckusick
1376710Smckusick case SYSEXEC:
1386710Smckusick com++;
1396710Smckusick initio(io); ioset=0; io=0;
1406710Smckusick IF a1==0 THEN break FI
1416710Smckusick
1426710Smckusick case SYSLOGIN:
1436710Smckusick flags |= forked;
1446710Smckusick oldsigs(); execa(com); done();
1456710Smckusick
1466710Smckusick case SYSCD:
1476710Smckusick IF flags&rshflg
1486710Smckusick THEN failed(com[0],restricted);
1496710Smckusick ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0
1506710Smckusick THEN failed(a1,baddir);
1516710Smckusick FI
1526710Smckusick break;
1536710Smckusick
1546710Smckusick case SYSSHFT:
1556710Smckusick IF dolc<1
1566710Smckusick THEN error(badshift);
1576710Smckusick ELSE dolv++; dolc--;
1586710Smckusick FI
1596710Smckusick assnum(&dolladr, dolc);
1606710Smckusick break;
1616710Smckusick
1626710Smckusick case SYSWAIT:
1636710Smckusick await(-1);
1646710Smckusick break;
1656710Smckusick
1666710Smckusick case SYSREAD:
1676710Smckusick exitval=readvar(&com[1]);
1686710Smckusick break;
1696710Smckusick
1706710Smckusick /*
1716710Smckusick case SYSTST:
1726710Smckusick exitval=testcmd(com);
1736710Smckusick break;
1746710Smckusick */
1756710Smckusick
1766710Smckusick case SYSSET:
1776710Smckusick IF a1
1786710Smckusick THEN INT argc;
1796710Smckusick argc = options(argn,com);
1806710Smckusick IF argc>1
1816710Smckusick THEN setargs(com+argn-argc);
1826710Smckusick FI
18334082Sbostic ELIF t->comnod.comset==0
1846710Smckusick THEN /*scan name chain and print*/
1856710Smckusick namscan(printnam);
1866710Smckusick FI
1876710Smckusick break;
1886710Smckusick
1896710Smckusick case SYSRDONLY:
1906710Smckusick exitval=N_RDONLY;
1916710Smckusick case SYSXPORT:
1926710Smckusick IF exitval==0 THEN exitval=N_EXPORT; FI
1936710Smckusick
1946710Smckusick IF a1
1956710Smckusick THEN WHILE *++com
1966710Smckusick DO attrib(lookup(*com), exitval) OD
1976710Smckusick ELSE namscan(printflg);
1986710Smckusick FI
1996710Smckusick exitval=0;
2006710Smckusick break;
2016710Smckusick
2026710Smckusick case SYSEVAL:
2036710Smckusick IF a1
2046710Smckusick THEN execexp(a1,&com[2]);
2056710Smckusick FI
2066710Smckusick break;
2076710Smckusick
2086710Smckusick case SYSUMASK:
2096710Smckusick if (a1) {
21030366Ssam int c, i;
2116710Smckusick i = 0;
2126710Smckusick while ((c = *a1++) >= '0' &&
2136710Smckusick c <= '7')
2146710Smckusick i = (i << 3) + c - '0';
2156710Smckusick umask(i);
2166710Smckusick } else {
2176710Smckusick int i, j;
2186710Smckusick umask(i = umask(0));
2196710Smckusick prc('0');
2206710Smckusick for (j = 6; j >= 0; j -= 3)
2216710Smckusick prc(((i>>j)&07) + '0');
2226710Smckusick newline();
2236710Smckusick }
2246710Smckusick break;
2256710Smckusick
2266710Smckusick default:
2276710Smckusick internal=builtin(argn,com);
2286710Smckusick
2296710Smckusick ENDSW
2306710Smckusick
2316710Smckusick IF internal
2326710Smckusick THEN IF io THEN error(illegal) FI
2336710Smckusick chktrap();
2346710Smckusick break;
2356710Smckusick FI
23634082Sbostic ELIF t->treio.treio==0
2376710Smckusick THEN break;
2386710Smckusick FI
2396710Smckusick END
2406710Smckusick
2416710Smckusick case TFORK:
2426710Smckusick IF execflg ANDF (treeflgs&(FAMP|FPOU))==0
2436710Smckusick THEN parent=0;
2446710Smckusick ELSE WHILE (parent=fork()) == -1
2456710Smckusick DO sigchk(); alarm(10); pause() OD
2466710Smckusick FI
2476710Smckusick
2486710Smckusick IF parent
2496710Smckusick THEN /* This is the parent branch of fork; */
2506710Smckusick /* it may or may not wait for the child. */
2516710Smckusick IF treeflgs&FPRS ANDF flags&ttyflg
2526710Smckusick THEN prn(parent); newline();
2536710Smckusick FI
2546710Smckusick IF treeflgs&FPCL THEN closepipe(pf1) FI
2556710Smckusick IF (treeflgs&(FAMP|FPOU))==0
2566710Smckusick THEN await(parent);
2576710Smckusick ELIF (treeflgs&FAMP)==0
2586710Smckusick THEN post(parent);
2596710Smckusick ELSE assnum(&pcsadr, parent);
2606710Smckusick FI
2616710Smckusick
2626710Smckusick chktrap();
2636710Smckusick break;
2646710Smckusick
2656710Smckusick
2666710Smckusick ELSE /* this is the forked branch (child) of execute */
2676710Smckusick flags |= forked; iotemp=0;
2686710Smckusick postclr();
2696710Smckusick settmp();
2706710Smckusick
2716710Smckusick /* Turn off INTR and QUIT if `FINT' */
2726710Smckusick /* Reset ramaining signals to parent */
2736710Smckusick /* except for those `lost' by trap */
2746710Smckusick oldsigs();
2756710Smckusick IF treeflgs&FINT
2766710Smckusick THEN signal(INTR,1); signal(QUIT,1);
2776710Smckusick FI
2786710Smckusick
2796710Smckusick /* pipe in or out */
2806710Smckusick IF treeflgs&FPIN
2816710Smckusick THEN rename(pf1[INPIPE],0);
2826710Smckusick close(pf1[OTPIPE]);
2836710Smckusick FI
2846710Smckusick IF treeflgs&FPOU
2856710Smckusick THEN rename(pf2[OTPIPE],1);
2866710Smckusick close(pf2[INPIPE]);
2876710Smckusick FI
2886710Smckusick
2896710Smckusick /* default std input for & */
2906710Smckusick IF treeflgs&FINT ANDF ioset==0
291*37678Sbostic THEN rename(chkopen(_PATH_DEVNULL),0);
2926710Smckusick FI
2936710Smckusick
2946710Smckusick /* io redirection */
29534082Sbostic initio(t->treio.treio);
2966710Smckusick IF type!=TCOM
29734082Sbostic THEN execute(t->forknod.forktre,1);
2986710Smckusick ELIF com[0]!=ENDARGS
29934082Sbostic THEN setlist(t->comnod.comset,N_EXPORT);
3006710Smckusick execa(com);
3016710Smckusick FI
3026710Smckusick done();
3036710Smckusick FI
3046710Smckusick
3056710Smckusick case TPAR:
3066710Smckusick rename(dup(2),output);
30734082Sbostic execute(t->parnod.partre,execflg);
3086710Smckusick done();
3096710Smckusick
3106710Smckusick case TFIL:
3116710Smckusick BEGIN
3126710Smckusick INT pv[2]; chkpipe(pv);
31334082Sbostic IF execute(t->lstnod.lstlef, 0, pf1, pv)==0
31434082Sbostic THEN execute(t->lstnod.lstrit, execflg, pv, pf2);
3156710Smckusick ELSE closepipe(pv);
3166710Smckusick FI
3176710Smckusick END
3186710Smckusick break;
3196710Smckusick
3206710Smckusick case TLST:
32134082Sbostic execute(t->lstnod.lstlef,0);
32234082Sbostic execute(t->lstnod.lstrit,execflg);
3236710Smckusick break;
3246710Smckusick
3256710Smckusick case TAND:
32634082Sbostic IF execute(t->lstnod.lstlef,0)==0
32734082Sbostic THEN execute(t->lstnod.lstrit,execflg);
3286710Smckusick FI
3296710Smckusick break;
3306710Smckusick
3316710Smckusick case TORF:
33234082Sbostic IF execute(t->lstnod.lstlef,0)!=0
33334082Sbostic THEN execute(t->lstnod.lstrit,execflg);
3346710Smckusick FI
3356710Smckusick break;
3366710Smckusick
3376710Smckusick case TFOR:
3386710Smckusick BEGIN
33934082Sbostic NAMPTR n = lookup(t->fornod.fornam);
3406710Smckusick STRING *args;
3416710Smckusick DOLPTR argsav=0;
3426710Smckusick
34334082Sbostic IF t->fornod.forlst==0
3446710Smckusick THEN args=dolv+1;
3456710Smckusick argsav=useargs();
3466710Smckusick ELSE ARGPTR schain=gchain;
3476710Smckusick gchain=0;
34834082Sbostic trim((args=scan(getarg(t->fornod.forlst)))[0]);
3496710Smckusick gchain=schain;
3506710Smckusick FI
3516710Smckusick loopcnt++;
3526710Smckusick WHILE *args!=ENDARGS ANDF execbrk==0
3536710Smckusick DO assign(n,*args++);
35434082Sbostic execute(t->fornod.fortre,0);
3556710Smckusick IF execbrk<0 THEN execbrk=0 FI
3566710Smckusick OD
3576710Smckusick IF breakcnt THEN breakcnt-- FI
3586710Smckusick execbrk=breakcnt; loopcnt--;
3596710Smckusick argfor=freeargs(argsav);
3606710Smckusick END
3616710Smckusick break;
3626710Smckusick
3636710Smckusick case TWH:
3646710Smckusick case TUN:
3656710Smckusick BEGIN
36632206Sbostic INT i=0, saveflg;
3676710Smckusick
36832206Sbostic saveflg = flags&errflg;
3696710Smckusick loopcnt++;
37032206Sbostic WHILE execbrk==0
37132206Sbostic DO flags &= ~errflg;
37234082Sbostic i=execute(t->whnod.whtre,0);
37332206Sbostic flags |= saveflg;
37432206Sbostic IF (i==0)!=(type==TWH) THEN break FI
37534082Sbostic i=execute(t->whnod.dotre,0);
3766710Smckusick IF execbrk<0 THEN execbrk=0 FI
3776710Smckusick OD
3786710Smckusick IF breakcnt THEN breakcnt-- FI
3796710Smckusick execbrk=breakcnt; loopcnt--; exitval=i;
3806710Smckusick END
3816710Smckusick break;
3826710Smckusick
3836710Smckusick case TIF:
38432206Sbostic BEGIN
38532206Sbostic INT i, saveflg;
38632206Sbostic
38732206Sbostic saveflg = flags&errflg;
38832206Sbostic flags &= ~errflg;
38934082Sbostic i=execute(t->ifnod.iftre,0);
39032206Sbostic flags |= saveflg;
39132206Sbostic IF i==0
39234082Sbostic THEN execute(t->ifnod.thtre,execflg);
39334082Sbostic ELSE execute(t->ifnod.eltre,execflg);
39432206Sbostic FI
39532206Sbostic END
3966710Smckusick break;
3976710Smckusick
3986710Smckusick case TSW:
3996710Smckusick BEGIN
40034082Sbostic REG STRING r = mactrim(t->swnod.swarg);
40134082Sbostic REG REGPTR eg = t->swnod.swlst;
40234082Sbostic WHILE eg
40334082Sbostic DO ARGPTR rex=eg->regptr;
4046710Smckusick WHILE rex
4056710Smckusick DO REG STRING s;
4066710Smckusick IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s))
40734082Sbostic THEN execute(eg->regcom,0);
40834082Sbostic eg=0; break;
4096710Smckusick ELSE rex=rex->argnxt;
4106710Smckusick FI
4116710Smckusick OD
41234082Sbostic IF eg THEN eg=eg->regnxt FI
4136710Smckusick OD
4146710Smckusick END
4156710Smckusick break;
4166710Smckusick ENDSW
4176710Smckusick exitset();
4186710Smckusick FI
4196710Smckusick
4206710Smckusick sigchk();
4216710Smckusick tdystak(sav);
4226710Smckusick return(exitval);
4236710Smckusick }
4246710Smckusick
4256710Smckusick
execexp(s,f)4266710Smckusick execexp(s,f)
4276710Smckusick STRING s;
4286710Smckusick UFD f;
4296710Smckusick {
4306710Smckusick FILEBLK fb;
4316710Smckusick push(&fb);
4326710Smckusick IF s
4336710Smckusick THEN estabf(s); fb.feval=f;
4346710Smckusick ELIF f>=0
4356710Smckusick THEN initf(f);
4366710Smckusick FI
4376710Smckusick execute(cmd(NL, NLFLG|MTFLG),0);
4386710Smckusick pop();
4396710Smckusick }
440