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