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