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