|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #include "sh.h"
3:
4: /*
5: * C shell
6: */
7:
8: execute(t, pipein, pipeout)
9: register struct command *t;
10: int *pipein, *pipeout;
11: {
12: int pid, flags, pv[2];
13: register struct command *t1;
14: register char *cp;
15: bool forked = 0;
16: bool shudint, shudhup;
17: #ifdef VFORK
18: int (*savint)(), vffree();
19: int ochild, osetintr, ohaderr, otimflg, odidfds, odidcch;
20: int oSHIN, oSHOUT, oSHDIAG, oOLDSTD;
21: int isvfork = 0;
22: #endif
23:
24: if (t == 0)
25: return;
26: switch (t->t_dtyp) {
27:
28: case TCOM:
29: cp = t->t_dcom[0];
30: if ((cp[0] & (QUOTE|TRIM)) == QUOTE)
31: strcpy(cp, cp + 1);
32: if ((t->t_dflg & FREDO) == 0)
33: Dfix(t); /* $ " ' \ */
34: /* fall into... */
35:
36: case TPAR:
37: flags = t->t_dflg;
38: if (flags & FPOU)
39: mypipe(pipeout);
40: /*
41: * A child will be interruptible only under very
42: * certain conditions:
43: * we must be monkeying with interrupts
44: * the child must not be &'ed
45: * we must not have had an "onintr -"
46: */
47: shudint = setintr && (flags & FINT) == 0 && (!gointr || !eq(gointr, "-"));
48: shudhup = (flags & FAND) == 0;
49:
50: /*
51: * Must do << early so parent will know
52: * where input pointer should be
53: */
54: if (flags & FHERE)
55: close(0), heredoc(t->t_dlef);
56:
57: /*
58: * If not executing commands then
59: * all we must do is read forward in the input to
60: * account for << redirection if present.
61: */
62: if (noexec) {
63: if (flags & FHERE)
64: close(0);
65: return;
66: }
67:
68: set("status", "0");
69: pid = 0;
70:
71: /*
72: * Built-in functions
73: */
74: if (t->t_dtyp == TCOM && isbfunc(t->t_dcom[0])) {
75: /*
76: * If output is piped, or running & and we would
77: * eventually fork for non-builtin commands,
78: * then do it now, so we won't block.
79: */
80: if ((flags & (FPOU|FAND)) && (flags & FPAR) == 0)
81: pid = dofork(shudint, shudhup), forked++;
82:
83: /*
84: * If the builtin is actually executed (some, e.g.
85: * time and nice may refuse to execute here)
86: * then either exit (if we forked) or close i/o
87: * and continue execution (if we didn't).
88: */
89: if (pid == 0) {
90: doio(t, pipein, pipeout);
91: if (flags & FPOU) {
92: close(pipeout[0]), close(pipeout[1]);
93: pipeout[0] = pipeout[1] = -1;
94: }
95: if (setintr && forked) {
96: if (shudint)
97: signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
98: signal(SIGTERM, parterm);
99: if (flags & FINT)
100: setintr = 0;
101: }
102: if (func(t, pipein, pipeout)) {
103: if (forked)
104: exitstat();
105: if (didfds && !(t->t_dflg & FREDO))
106: donefds();
107: return;
108: }
109: }
110: }
111:
112: /*
113: * Now, we must make a new process since either the
114: * command is non-builtin, a parenthesized list,
115: * or builtin such as time or nice which really
116: * requires a child.
117: */
118: if (!forked && (flags & FPAR) == 0)
119: #ifdef VFORK
120: if (t->t_dtyp == TPAR || (flags&FREDO) ||
121: eq(t->t_dcom[0], "nice") || eq(t->t_dcom[0], "nohup"))
122: #endif
123: pid = dofork(shudint, shudhup);
124: #ifdef VFORK
125: else {
126: savint = signal(SIGINT, SIG_IGN);
127: ochild = child; osetintr = setintr;
128: ohaderr = haderr; otimflg = timflg;
129: odidfds = didfds; odidcch = didcch;
130: oSHIN = SHIN; oSHOUT = SHOUT;
131: oSHDIAG = SHDIAG; oOLDSTD = OLDSTD;
132: Vsav = Vdp = 0; Vav = 0;
133: isvfork++;
134: pid = vfork();
135: if (pid < 0) {
136: signal(SIGINT, savint);
137: error("No more processes");
138: }
139: if (pid == 0) {
140: child++;
141: signal(SIGINT, shudint ? SIG_DFL : savint);
142: if (!shudhup)
143: signal(SIGHUP, SIG_IGN);
144: } else {
145: child = ochild; setintr = osetintr;
146: haderr = ohaderr; timflg = otimflg;
147: didfds = odidfds; didcch = odidcch;
148: SHIN = oSHIN; SHOUT = oSHOUT;
149: SHDIAG = oSHDIAG; OLDSTD = oOLDSTD;
150: xfree(Vsav), Vsav = 0;
151: xfree(Vdp), Vdp = 0;
152: xfree(Vav), Vav = 0;
153: signal(SIGINT, savint);
154: }
155: }
156: #endif
157: if (pid != 0) {
158: /*
159: * The parent path (or nobody does this if
160: * (flags & FPAR), i.e. date in (set;date))
161: */
162: if (didfds == 0 && (flags & FPIN))
163: close(pipein[0]), close(pipein[1]);
164: if (didfds && !(t->t_dflg & FREDO))
165: donefds();
166: if (flags & FPRS)
167: printf("%d\n", pid), set("child", putn(pid));
168: /*
169: * Unless output is piped or command is &
170: * wait for it.
171: */
172: if (t->t_dtyp == TCOM)
173: cadd(pid, t->t_dcom[0]);
174: else
175: cadd(pid, "()");
176: if ((flags & (FPOU|FAND)) == 0)
177: pwait(pid);
178: return;
179: }
180:
181: /*
182: * Insure that this (child) shell doesn't muck on
183: */
184: child++;
185:
186: /*
187: * If havent yet, finally set up the file descriptors.
188: */
189: doio(t, pipein, pipeout);
190: if (flags & FPOU)
191: close(pipeout[0]), close(pipeout[1]);
192:
193: /*
194: * If mucking with interrupts fix interrupt, quit,
195: * and terminate handling ... in any case set setintr
196: * to 0 if we are not interruptible so that no further
197: * interrupt mucking occurs.
198: */
199: if (setintr) {
200: if (shudint) {
201: signal(SIGQUIT, SIG_DFL);
202: #ifdef VFORK
203: if (isvfork)
204: signal(SIGINT, vffree);
205: else
206: #endif
207: signal(SIGINT, SIG_DFL);
208: }
209: signal(SIGTERM, parterm);
210: if (flags & FINT)
211: setintr = 0;
212: }
213:
214: /*
215: * For () commands must put new 0,1,2 in FSH* and recurse
216: */
217: if (t->t_dtyp == TPAR) {
218: t1 = t->t_dspr;
219: t1->t_dflg |= flags & FINT;
220: OLDSTD = dcopy(0, FOLDSTD);
221: SHOUT = dcopy(1, FSHOUT);
222: SHDIAG = dcopy(2, FSHDIAG);
223: close(SHIN), SHIN = -1;
224: didcch = 0, didfds = 0;
225: execute(t1);
226: exitstat();
227: }
228: if (eq(t->t_dcom[0], "nice")) {
229: /* sigh...
230: nice(20);
231: nice(-10);
232: */
233: cp = t->t_dcom[1];
234: if (any(cp[0], "+-"))
235: nice(getn(cp)), lshift(t->t_dcom, 2);
236: else
237: nice(4), lshift(t->t_dcom, 1);
238: t->t_dflg = FPAR | FREDO;
239: execute(t);
240: exitstat();
241: }
242: if (eq(t->t_dcom[0], "nohup")) {
243: if (setintr == 0)
244: signal(SIGHUP, SIG_IGN);
245: signal(SIGTERM, SIG_IGN);
246: lshift(t->t_dcom, 1);
247: t->t_dflg = FPAR | FREDO;
248: execute(t);
249: exitstat();
250: }
251: doexec(t);
252: /* no return */
253:
254: case TFIL:
255: flags = t->t_dflg;
256: t1 = t->t_dcar;
257: t1->t_dflg |= FPOU | (flags & (FPIN|FINT|FPRS|FDIAG));
258: execute(t1, pipein, pv);
259: t1 = t->t_dcdr;
260: t1->t_dflg |= FPIN | (flags & (FPOU|FINT|FAND|FPRS|FPAR));
261: execute(t1, pv, pipeout);
262: return;
263:
264: case TLST:
265: flags = t->t_dflg & FINT;
266: if (t1 = t->t_dcar)
267: t1->t_dflg |= flags, execute(t1);
268: if (t1 = t->t_dcdr)
269: t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
270: return;
271:
272: case TOR:
273: case TAND:
274: flags = t->t_dflg & FINT;
275: if (t1 = t->t_dcar) {
276: t1->t_dflg |= flags, execute(t1);
277: if ((getn(value("status")) == 0) == (t->t_dtyp == TAND))
278: return;
279: }
280: if (t1 = t->t_dcdr)
281: t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
282: return;
283: }
284: }
285:
286: #ifdef VFORK
287: vffree()
288: {
289: register char **v;
290:
291: if (v = gargv)
292: gargv = 0, xfree(gargv);
293: if (v = pargv)
294: pargv = 0, xfree(pargv);
295: _exit(1);
296: }
297: #endif
298:
299: doio(t, pipein, pipeout)
300: register struct command *t;
301: int *pipein, *pipeout;
302: {
303: register char *cp;
304: register int flags = t->t_dflg;
305: char *dp;
306:
307: if (didfds || (flags & FREDO))
308: return;
309: if (flags & FHERE)
310: goto skipin;
311: close(0);
312: if (cp = t->t_dlef) {
313: cp = globone(dp = Dfix1(cp));
314: xfree(dp);
315: xfree(cp);
316: if (open(cp, 0) < 0)
317: Perror(cp);
318: } else if (flags & FPIN)
319: dup(pipein[0]), close(pipein[0]), close(pipein[1]);
320: else if (flags & FINT)
321: close(0), open("/dev/null", 0);
322: else
323: dup(OLDSTD);
324:
325: skipin:
326: close(1);
327: if (cp = t->t_drit) {
328: cp = globone(dp = Dfix1(cp));
329: xfree(dp);
330: xfree(cp);
331: if ((flags & FCAT) && open(cp, 1) >= 0)
332: lseek(1, 0l, 2);
333: else {
334: if (!(flags & FANY) && adrof("noclobber")) {
335: if (flags & FCAT)
336: Perror(cp);
337: chkclob(cp);
338: }
339: #ifdef V6
340: if (creat(cp, 0644) < 0)
341: Perror(cp);
342: #else
343: if (creat(cp, 0666) < 0)
344: Perror(cp);
345: #endif
346: }
347: } else
348: dup((flags & FPOU) ? pipeout[1] : SHOUT);
349:
350: close(2);
351: dup((flags & FDIAG) ? 1 : SHDIAG);
352: didfds = 1;
353: }
354:
355: dofork(shudint, shudhup)
356: bool shudint, shudhup;
357: {
358: register int pid, (*savint)();
359:
360: savint = signal(SIGINT, SIG_IGN);
361: pid = fork();
362: if (pid < 0) {
363: signal(SIGINT, savint);
364: error("No more processes");
365: }
366: if (pid == 0) {
367: child++;
368: signal(SIGINT, shudint ? SIG_DFL : savint);
369: if (!shudhup)
370: signal(SIGHUP, SIG_IGN);
371: } else
372: signal(SIGINT, savint);
373: return (pid);
374: }
375:
376: mypipe(pv)
377: register int *pv;
378: {
379:
380: if (pipe(pv) < 0)
381: goto oops;
382: pv[0] = dmove(pv[0], -1);
383: pv[1] = dmove(pv[1], -1);
384: if (pv[0] >= 0 && pv[1] >= 0)
385: return;
386: oops:
387: error("Can't make pipe");
388: }
389:
390: chkclob(cp)
391: register char *cp;
392: {
393: struct stat stb;
394:
395: if (stat(cp, &stb) < 0)
396: return;
397: if ((stb.st_mode & S_IFMT) == S_IFCHR)
398: return;
399: error("%s: File exists", cp);
400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.