xref: /original-bsd/old/sh/xec.c (revision b288febc)
1 #ifndef lint
2 static char sccsid[] = "@(#)xec.c	4.7 05/08/89";
3 #endif
4 
5 #
6 /*
7  * UNIX shell
8  *
9  * S. R. Bourne
10  * Bell Telephone Laboratories
11  *
12  */
13 
14 #include	"defs.h"
15 #include	"sym.h"
16 #include	"pathnames.h"
17 
18 LOCAL INT	parent;
19 
20 SYSTAB		commands;
21 
22 
23 
24 /* ========	command execution	========*/
25 
26 
execute(argt,execflg,pf1,pf2)27 execute(argt, execflg, pf1, pf2)
28 	TREPTR		argt;
29 	INT		*pf1, *pf2;
30 {
31 	/* `stakbot' is preserved by this routine */
32 	REG TREPTR	t;
33 	STKPTR		sav=savstak();
34 
35 	sigchk();
36 
37 	IF (t=argt) ANDF execbrk==0
38 	THEN	REG INT		treeflgs;
39 		INT		oldexit, type;
40 		REG STRING	*com;
41 
42 		treeflgs = t->tretyp; type = treeflgs&COMMSK;
43 		oldexit=exitval; exitval=0;
44 
45 		SWITCH type IN
46 
47 		case TCOM:
48 			BEGIN
49 			STRING		a1;
50 			INT		argn, internal;
51 			ARGPTR		schain=gchain;
52 			IOPTR		io=t->treio.treio;
53 			gchain=0;
54 			argn = getarg(t);
55 			com=scan(argn);
56 			a1=com[1]; gchain=schain;
57 
58 			IF argn==0 ORF (internal=syslook(com[0],commands))
59 			THEN	setlist(t->comnod.comset, 0);
60 			FI
61 
62 			IF argn ANDF (flags&noexec)==0
63 			THEN	/* print command if execpr */
64 				IF flags&execpr
65 				THEN	argn=0;	prs(execpmsg);
66 					WHILE com[argn]!=ENDARGS
67 					DO prs(com[argn++]); blank() OD
68 					newline();
69 				FI
70 
71 				SWITCH internal IN
72 
73 				case SYSDOT:
74 					IF a1
75 					THEN	REG INT		f;
76 
77 						IF (f=pathopen(getpath(a1), a1)) < 0
78 						THEN failed(a1,notfound);
79 						ELSE execexp(0,f);
80 						FI
81 					FI
82 					break;
83 
84 				case SYSTIMES:
85 					{
86 					L_INT	t[4]; times(t);
87 					prt(t[2]); blank(); prt(t[3]); newline();
88 					}
89 					break;
90 
91 				case SYSEXIT:
92 					exitsh(a1?stoi(a1):oldexit);
93 
94 				case SYSNULL:
95 					io=0;
96 					break;
97 
98 				case SYSCONT:
99 					execbrk = -loopcnt; break;
100 
101 				case SYSBREAK:
102 					IF (execbrk=loopcnt) ANDF a1
103 					THEN breakcnt=stoi(a1);
104 					FI
105 					break;
106 
107 				case SYSTRAP:
108 					IF a1
109 					THEN	BOOL	clear;
110 						IF (clear=digit(*a1))==0
111 						THEN	++com;
112 						FI
113 						WHILE *++com
114 						DO INT	i;
115 						   IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP
116 						   THEN	failed(*com,badtrap);
117 						   ELIF clear
118 						   THEN	clrsig(i);
119 						   ELSE	replace(&trapcom[i],a1);
120 							IF *a1
121 							THEN	getsig(i);
122 							ELSE	ignsig(i);
123 							FI
124 						   FI
125 						OD
126 					ELSE	/* print out current traps */
127 						INT		i;
128 
129 						FOR i=0; i<MAXTRAP; i++
130 						DO IF trapcom[i]
131 						   THEN	prn(i); prs(colon); prs(trapcom[i]); newline();
132 						   FI
133 						OD
134 					FI
135 					break;
136 
137 				case SYSEXEC:
138 					com++;
139 					initio(io); ioset=0; io=0;
140 					IF a1==0 THEN break FI
141 
142 				case SYSLOGIN:
143 					flags |= forked;
144 					oldsigs(); execa(com); done();
145 
146 				case SYSCD:
147 					IF flags&rshflg
148 					THEN	failed(com[0],restricted);
149 					ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0
150 					THEN	failed(a1,baddir);
151 					FI
152 					break;
153 
154 				case SYSSHFT:
155 					IF dolc<1
156 					THEN	error(badshift);
157 					ELSE	dolv++; dolc--;
158 					FI
159 					assnum(&dolladr, dolc);
160 					break;
161 
162 				case SYSWAIT:
163 					await(-1);
164 					break;
165 
166 				case SYSREAD:
167 					exitval=readvar(&com[1]);
168 					break;
169 
170 /*
171 				case SYSTST:
172 					exitval=testcmd(com);
173 					break;
174 */
175 
176 				case SYSSET:
177 					IF a1
178 					THEN	INT	argc;
179 						argc = options(argn,com);
180 						IF argc>1
181 						THEN	setargs(com+argn-argc);
182 						FI
183 					ELIF t->comnod.comset==0
184 					THEN	/*scan name chain and print*/
185 						namscan(printnam);
186 					FI
187 					break;
188 
189 				case SYSRDONLY:
190 					exitval=N_RDONLY;
191 				case SYSXPORT:
192 					IF exitval==0 THEN exitval=N_EXPORT; FI
193 
194 					IF a1
195 					THEN	WHILE *++com
196 						DO attrib(lookup(*com), exitval) OD
197 					ELSE	namscan(printflg);
198 					FI
199 					exitval=0;
200 					break;
201 
202 				case SYSEVAL:
203 					IF a1
204 					THEN	execexp(a1,&com[2]);
205 					FI
206 					break;
207 
208                                 case SYSUMASK:
209                                         if (a1) {
210                                                 int c, i;
211                                                 i = 0;
212                                                 while ((c = *a1++) >= '0' &&
213                                                         c <= '7')
214                                                         i = (i << 3) + c - '0';
215                                                 umask(i);
216                                         } else {
217                                                 int i, j;
218                                                 umask(i = umask(0));
219                                                 prc('0');
220                                                 for (j = 6; j >= 0; j -= 3)
221                                                         prc(((i>>j)&07) + '0');
222                                                 newline();
223                                         }
224                                         break;
225 
226 				default:
227 					internal=builtin(argn,com);
228 
229 				ENDSW
230 
231 				IF internal
232 				THEN	IF io THEN error(illegal) FI
233 					chktrap();
234 					break;
235 				FI
236 			ELIF t->treio.treio==0
237 			THEN	break;
238 			FI
239 			END
240 
241 		case TFORK:
242 			IF execflg ANDF (treeflgs&(FAMP|FPOU))==0
243 			THEN	parent=0;
244 			ELSE	WHILE (parent=fork()) == -1
245 				DO sigchk(); alarm(10); pause() OD
246 			FI
247 
248 			IF parent
249 			THEN	/* This is the parent branch of fork;    */
250 				/* it may or may not wait for the child. */
251 				IF treeflgs&FPRS ANDF flags&ttyflg
252 				THEN	prn(parent); newline();
253 				FI
254 				IF treeflgs&FPCL THEN closepipe(pf1) FI
255 				IF (treeflgs&(FAMP|FPOU))==0
256 				THEN	await(parent);
257 				ELIF (treeflgs&FAMP)==0
258 				THEN	post(parent);
259 				ELSE	assnum(&pcsadr, parent);
260 				FI
261 
262 				chktrap();
263 				break;
264 
265 
266 			ELSE	/* this is the forked branch (child) of execute */
267 				flags |= forked; iotemp=0;
268 				postclr();
269 				settmp();
270 
271 				/* Turn off INTR and QUIT if `FINT'  */
272 				/* Reset ramaining signals to parent */
273 				/* except for those `lost' by trap   */
274 				oldsigs();
275 				IF treeflgs&FINT
276 				THEN	signal(INTR,1); signal(QUIT,1);
277 				FI
278 
279 				/* pipe in or out */
280 				IF treeflgs&FPIN
281 				THEN	rename(pf1[INPIPE],0);
282 					close(pf1[OTPIPE]);
283 				FI
284 				IF treeflgs&FPOU
285 				THEN	rename(pf2[OTPIPE],1);
286 					close(pf2[INPIPE]);
287 				FI
288 
289 				/* default std input for & */
290 				IF treeflgs&FINT ANDF ioset==0
291 				THEN	rename(chkopen(_PATH_DEVNULL),0);
292 				FI
293 
294 				/* io redirection */
295 				initio(t->treio.treio);
296 				IF type!=TCOM
297 				THEN	execute(t->forknod.forktre,1);
298 				ELIF com[0]!=ENDARGS
299 				THEN	setlist(t->comnod.comset,N_EXPORT);
300 					execa(com);
301 				FI
302 				done();
303 			FI
304 
305 		case TPAR:
306 			rename(dup(2),output);
307 			execute(t->parnod.partre,execflg);
308 			done();
309 
310 		case TFIL:
311 			BEGIN
312 			   INT pv[2]; chkpipe(pv);
313 			   IF execute(t->lstnod.lstlef, 0, pf1, pv)==0
314 			   THEN	execute(t->lstnod.lstrit, execflg, pv, pf2);
315 			   ELSE	closepipe(pv);
316 			   FI
317 			END
318 			break;
319 
320 		case TLST:
321 			execute(t->lstnod.lstlef,0);
322 			execute(t->lstnod.lstrit,execflg);
323 			break;
324 
325 		case TAND:
326 			IF execute(t->lstnod.lstlef,0)==0
327 			THEN	execute(t->lstnod.lstrit,execflg);
328 			FI
329 			break;
330 
331 		case TORF:
332 			IF execute(t->lstnod.lstlef,0)!=0
333 			THEN	execute(t->lstnod.lstrit,execflg);
334 			FI
335 			break;
336 
337 		case TFOR:
338 			BEGIN
339 			   NAMPTR	n = lookup(t->fornod.fornam);
340 			   STRING	*args;
341 			   DOLPTR	argsav=0;
342 
343 			   IF t->fornod.forlst==0
344 			   THEN    args=dolv+1;
345 				   argsav=useargs();
346 			   ELSE	   ARGPTR	schain=gchain;
347 				   gchain=0;
348 				   trim((args=scan(getarg(t->fornod.forlst)))[0]);
349 				   gchain=schain;
350 			   FI
351 			   loopcnt++;
352 			   WHILE *args!=ENDARGS ANDF execbrk==0
353 			   DO	assign(n,*args++);
354 				execute(t->fornod.fortre,0);
355 				IF execbrk<0 THEN execbrk=0 FI
356 			   OD
357 			   IF breakcnt THEN breakcnt-- FI
358 			   execbrk=breakcnt; loopcnt--;
359 			   argfor=freeargs(argsav);
360 			END
361 			break;
362 
363 		case TWH:
364 		case TUN:
365 			BEGIN
366 			   INT		i=0, saveflg;
367 
368 			   saveflg = flags&errflg;
369 			   loopcnt++;
370 			   WHILE execbrk==0
371 			   DO flags &= ~errflg;
372 			      i=execute(t->whnod.whtre,0);
373 			      flags |= saveflg;
374 			      IF (i==0)!=(type==TWH) THEN break FI
375 			      i=execute(t->whnod.dotre,0);
376 			      IF execbrk<0 THEN execbrk=0 FI
377 			   OD
378 			   IF breakcnt THEN breakcnt-- FI
379 			   execbrk=breakcnt; loopcnt--; exitval=i;
380 			END
381 			break;
382 
383 		case TIF:
384 			BEGIN
385 			   INT		i, saveflg;
386 
387 			   saveflg = flags&errflg;
388 			   flags &= ~errflg;
389 			   i=execute(t->ifnod.iftre,0);
390 			   flags |= saveflg;
391 			   IF i==0
392 			   THEN	execute(t->ifnod.thtre,execflg);
393 			   ELSE	execute(t->ifnod.eltre,execflg);
394 			   FI
395 			END
396 			break;
397 
398 		case TSW:
399 			BEGIN
400 			   REG STRING	r = mactrim(t->swnod.swarg);
401 			   REG REGPTR	eg = t->swnod.swlst;
402 			   WHILE eg
403 			   DO	ARGPTR		rex=eg->regptr;
404 				WHILE rex
405 				DO	REG STRING	s;
406 					IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s))
407 					THEN	execute(eg->regcom,0);
408 						eg=0; break;
409 					ELSE	rex=rex->argnxt;
410 					FI
411 				OD
412 				IF eg THEN eg=eg->regnxt FI
413 			   OD
414 			END
415 			break;
416 		ENDSW
417 		exitset();
418 	FI
419 
420 	sigchk();
421 	tdystak(sav);
422 	return(exitval);
423 }
424 
425 
execexp(s,f)426 execexp(s,f)
427 	STRING		s;
428 	UFD		f;
429 {
430 	FILEBLK		fb;
431 	push(&fb);
432 	IF s
433 	THEN	estabf(s); fb.feval=f;
434 	ELIF f>=0
435 	THEN	initf(f);
436 	FI
437 	execute(cmd(NL, NLFLG|MTFLG),0);
438 	pop();
439 }
440