|
|
1.1 root 1: /*
2: * sh/exec1.c
3: * The Bourne shell.
4: * Shell part of execution.
5: */
6:
7: #include <assert.h>
8: #include "sh.h"
9:
10: static char no_last_command [] = "";
11: static char * lastcmd = no_last_command;
12:
13: char *skipredir();
14:
15: /*
16: * Execute the given node, wait for completion, return status.
17: */
18: command (np)
19: register NODE *np;
20: {
21: register int f; /* Pid of command */
22: int mynllflag; /* Saved fork not forced flag */
23: CON con; /* Control link for break/continue */
24: char *innp, **inlp; /* for NFOR */
25: NODE *cnode; /* for NCASE */
26: char *cname; /* for NCASE */
27:
28: if (ret_done)
29: return;
30: mynllflag = nllflag;
31: innp = NULL;
32: inlp = NULL;
33: cnode = NULL;
34: f = 0;
35:
36: con.c_next = sesp->s_con;
37: con.c_node = np;
38: con.c_bpp = savebuf ();
39: con.c_temp = NULL;
40: sesp->s_con = & con;
41:
42: switch (setjmp (con.c_envl)) {
43: case 0: /* initial setjmp */
44: break;
45: case 1: /* continue */
46: np = con.c_node;
47: break;
48: case 2: /* break */
49: goto break2;
50: default:
51: panic (1);
52: NOTREACHED;
53: }
54:
55: for ( ; np != NULL; np = np->n_next) {
56: if (ret_done)
57: break; /* "return" interrupts control flow */
58: recover(ICMD);
59: f = 0;
60: nllflag = mynllflag;
61:
62: switch (np->n_type) {
63: case NCOMS:
64: f = comscom (np->n_auxp);
65: break;
66:
67: case NFOR:
68: if (innp == NULL) {
69: innp = np->n_strp;
70: nargc = 0;
71: nargv = makargl();
72: for (np = np->n_next->n_auxp; np; np = np->n_next)
73: eval (np->n_strp, EARGS);
74: inlp = nargv;
75: np = con.c_node;
76:
77: assert (con.c_temp == NULL);
78: con.c_temp = capture_temp ();
79: }
80: continue;
81:
82: case NFOR2:
83: /* do_done_list->n_next == this node */
84: if (* inlp == NULL || assnvar (innp, * inlp ++) == NULL)
85: break;
86: continue;
87:
88: case NWHILE:
89: /* do_done_list->n_next == this node */
90: nllflag = 0;
91:
92: if (con.c_temp == NULL)
93: con.c_temp = capture_temp ();
94:
95: if (command (np->n_auxp))
96: break;
97: continue;
98:
99: case NUNTIL:
100: /* do_done_list->n_next == this node */
101: nllflag = 0;
102:
103: if (con.c_temp == NULL)
104: con.c_temp = capture_temp ();
105:
106: if (! command (np->n_auxp))
107: break;
108: continue;
109:
110: case NBRAC:
111: command (np->n_auxp);
112: break;
113:
114: case NPARN:
115: if (nllflag || (f = clone()) == 0) {
116: exit (command (np->n_auxp));
117: NOTREACHED;
118: }
119: break;
120:
121: case NIF:
122: nllflag = 0;
123: if (! command (np->n_auxp->n_auxp))
124: np = np->n_auxp;
125: else if (np->n_next == NULL)
126: slret = 0; /* exit status 0 if no elsepart */
127: continue;
128:
129: case NELSE:
130: command (np->n_auxp);
131: break;
132:
133: case NCASE:
134: eval (np->n_strp, EWORD);
135: if (errflag)
136: break;
137: cname = duplstr (strt, 0);
138: continue;
139:
140: case NCASE2:
141: cnode = np->n_auxp;
142: continue;
143:
144: case NCASE3:
145: /* end of pattern list == next NCASE2 node */
146: eval (np->n_strp, EPATT);
147: if (errflag)
148: break;
149: if (match (strt, cname)) {
150: command (cnode);
151: break;
152: }
153: continue;
154:
155: case NLIST:
156: nllflag = 0;
157: command (np->n_auxp);
158: continue;
159:
160: case NANDF:
161: nllflag = 0;
162: if (command (np->n_auxp))
163: break;
164: continue;
165:
166: case NORF:
167: nllflag = 0;
168: if (! command (np->n_auxp))
169: break;
170: continue;
171:
172: case NBACK:
173: if ((f = clone ()) == 0) {
174: static char *iov[] = { "0</dev/null", NULL };
175:
176: bckflag++;
177: dflttrp (IBACK);
178: redirect (iov, NULL);
179: exit (command (np->n_auxp));
180: NOTREACHED;
181: }
182: sback = f;
183: prints ("%d\n", f);
184: f = 0;
185: continue;
186:
187: case NPIPE:
188: f = pipecoms (np);
189: break;
190:
191: case NFUNC:
192: def_shell_fn (np, capture_temp ());
193: break;
194:
195: case NRET:
196: if (in_sh_fn == 0) {
197: printe ("return not inside shell function");
198: break;
199: }
200: ret_done ++; /* to interrupt control flow */
201: if (np->n_strp [0] != '\0') {
202: eval (np->n_strp, EARGS);
203: slret = atoi (strt);
204: }
205: return slret;
206:
207: default:
208: panic (2);
209: NOTREACHED;
210: }
211: break;
212:
213: }
214: break2:
215: nllflag = mynllflag;
216: if (sesp->s_con != NULL)
217: sesp->s_con = sesp->s_con->c_next;
218: if (f)
219: waitc (f);
220: if (slret)
221: assnvar ("LASTERROR", lastcmd);
222:
223: DESTROY_CON (& con);
224:
225: if (eflag && (slret || errflag)) {
226: reset (RUABORT);
227: NOTREACHED;
228: }
229: return slret;
230: }
231:
232: /*
233: * Run a simple command.
234: * Anything but.
235: */
236: #define FARGS 1
237: #define FIORS 2
238: #define FASSG 4
239:
240: comscom (np)
241: register NODE *np;
242: {
243: register int f;
244: register char **app, *s, *s1, *sp;
245: int nputs, nargs;
246:
247: nargc = 1;
248: nargv = makargl();
249: nargv = addargl(nargv, "sh");
250: niovp = makargl();
251: nenvp = makargl();
252: nctlp = NULL;
253: /*
254: * Scan for arguments.
255: * or a control node.
256: */
257: nputs = 0;
258: f = 0;
259: for ( ; np; np = np->n_next) {
260: #ifdef VERBOSE
261: prints (" <node %d>", np->n_type);
262: #endif
263: switch (np->n_type) {
264: case NIORS:
265: f |= FIORS;
266: #if 0
267: /* Old code. */
268: eval(np->n_strp, EWORD);
269: niovp = addargl(niovp, duplstr(strt, 0));
270: if (xflag)
271: nputs += puta(nputs, strt);
272: #else
273: /*
274: * New code by steve 1/24/91.
275: * This allows globs in redirection args.
276: */
277: s = skipredir(np->n_strp);
278: nargs = nargc;
279: eval(s, EARGS); /* expand as arg */
280: for (s1 = np->n_strp, sp = strt; s1 < s; )
281: *sp++ = *s1++;
282: strcpy(sp, nargv[nargs]); /* build redir arg */
283: niovp = addargl(niovp, duplstr(strt, 0));
284: if (xflag)
285: nputs += puta(nputs, strt);
286: --nargc;
287: for (app = nargv+nargs; *app; app++) {
288: *app = *(app + 1); /* shift remaining args */
289: if (xflag && *app != NULL)
290: nputs += puta(nputs, *app);
291: }
292: #endif
293: continue;
294: case NARGS:
295: f |= FARGS;
296: nargs = nargc;
297: eval(np->n_strp, EARGS);
298: if (xflag)
299: for (app = nargv+nargs; *app; )
300: nputs += puta(nputs, *app++);
301: continue;
302: case NASSG:
303: if (kflag || (f&FARGS)==0) {
304: f |= FASSG;
305: eval(np->n_strp, EWORD);
306: nenvp = addargl(nenvp, duplstr(strt, 0));
307: if (xflag)
308: nputs += puta(nputs, strt);
309: } else {
310: nargs = nargc;
311: eval(np->n_strp, EARGS);
312: if (xflag)
313: for (app = nargv+nargs; *app; )
314: nputs += puta(nputs, *app++);
315: }
316: continue;
317: case NCTRL:
318: if (nctlp != NULL) {
319: panic (3);
320: NOTREACHED;
321: }
322: f |= FARGS;
323: nctlp = np;
324: continue;
325: default:
326: panic (4);
327: NOTREACHED;
328: }
329: }
330: if (xflag && nputs)
331: prints ("\n");
332: #ifdef VERBOSE
333: if (xflag) {
334: prints("\t<%o flag, %d put, %d arg, %o arv, %o env, %o iov>\n",
335: f, nputs, nargc-1, *(nargv+1), *nenvp, *niovp);
336: }
337: #endif
338:
339: nargv += 1; /* Skip over "sh" */
340: nargc -= 1;
341:
342: /* Last chance to quit */
343: #ifdef VERBOSE
344: if (xflag) prints("errflag = %o\n", errflag);
345: #endif
346: if (errflag || nflag)
347: return 0;
348:
349: /* And away we go */
350: if (lastcmd != no_last_command)
351: sfree (lastcmd);
352: if (* nargv)
353: lastcmd = duplstr (* nargv, 1);
354: else
355: lastcmd = no_last_command;
356: switch (f) {
357: case 0:
358: return 0;
359: case FARGS:
360: if (nctlp) {
361: command(nctlp->n_auxp);
362: return 0;
363: }
364: case FARGS| FIORS:
365: case FARGS| FASSG:
366: case FARGS| FIORS| FASSG:
367: if (shell_function () || shell_builtin ())
368: return 0;
369: break;
370: case FIORS:
371: break;
372: case FASSG:
373: case FIORS| FASSG:
374: for (app = nenvp ; * app !=NULL; )
375: setsvar (* app ++);
376: if ((f & ~ FASSG) ==0) {
377: slret = 0;
378: return 0;
379: }
380: break;
381: default:
382: panic (5);
383: NOTREACHED;
384: }
385: if (nllflag || (f = clone ()) == 0) {
386: if (redirect (niovp, NULL) < 0) {
387: slret = 1;
388: } else if (nargc) {
389: dflttrp (ICMD);
390: nenvp = envlvar (nenvp);
391: flexec ();
392: slret = 1;
393: } else if (nctlp)
394: command (nctlp->n_auxp);
395: exit (slret);
396: NOTREACHED;
397: }
398: return f;
399: }
400:
401: puta(n, p)
402: char *p;
403: {
404: if (n)
405: prints(" ");
406: #ifdef VERBOSE
407: else
408: prints("<%d> ", getpid());
409: #endif
410: prints("%s", p);
411: return (1);
412: }
413:
414: /*
415: * Execute a pipe command.
416: * Fork, if necessary, a subshell to execute the pipe.
417: * Fork each segment off.
418: * Wait for last, save slret, wait for all, return slret from last.
419: */
420: pipecoms(np)
421: register NODE *np;
422: {
423: register int f;
424: register int p1st = 0;
425: int pipev[2];
426:
427: if ( ! nllflag && (f = clone()) != 0)
428: return (f);
429: while (np->n_type == NPIPE) {
430: if (f = pipeline(pipev)) {
431: /* Parent takes right hand side */
432: np = np->n_next;
433: if (p1st == 0)
434: p1st = f;
435: dup2(pipev[0], 0);
436: if (pipev[0] != 0)
437: close(pipev[0]);
438: close(pipev[1]);
439: } else {
440: /* Child takes left hand side */
441: np = np->n_auxp;
442: dup2(pipev[1], 1);
443: close(pipev[0]);
444: if (pipev[1] != 1)
445: close(pipev[1]);
446: exit(command(np));
447: NOTREACHED;
448: }
449: }
450: if (f = clone()) {
451: /* Parent waits out pipe line */
452: spipe = p1st;
453: close(0);
454: if (f = waitc(f))
455: waitc(p1st);
456: exit(f);
457: NOTREACHED;
458: } else {
459: /* Child takes the pipe tail */
460: exit(command(np));
461: NOTREACHED;
462: }
463: }
464:
465: /*
466: * Skip a redirection arg, return pointer to following nonspace.
467: */
468: char *
469: skipredir(s) register char *s;
470: {
471: if (*s >= '1' && *s <= '9')
472: ++s;
473: if (*s == '>' || *s == '<')
474: ++s;
475: if (*s == '>' || *s == '<')
476: ++s;
477: if (*s == '&')
478: ++s;
479: while (*s == ' ' || *s == '\t')
480: ++s;
481: return s;
482: }
483:
484: /* end of sh/exec1.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.