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