xref: /csrg-svn/old/sh/xec.c (revision 37678)
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