xref: /original-bsd/old/sh/xec.c (revision b288febc)
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