|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley Software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)sh.sem.c 5.8 (Berkeley) 4/14/90";
9: #endif
10:
11: #include "sh.h"
12: #include "sh.proc.h"
13: #include <sys/file.h>
14: #include <sys/ioctl.h>
15: #include "pathnames.h"
16:
17: /*
18: * C shell
19: */
20:
21: static int nosigchld = 0, osigmask;
22: static int onosigchld = 0, oosigmask;
23: /*VARARGS 1*/
24: execute(t, wanttty, pipein, pipeout)
25: register struct command *t;
26: int wanttty, *pipein, *pipeout;
27: {
28: bool forked = 0;
29: struct biltins *bifunc;
30: int pid = 0;
31: int pv[2];
32:
33: if (t == 0)
34: return;
35: if ((t->t_dflg & FAND) && wanttty > 0)
36: wanttty = 0;
37: switch (t->t_dtyp) {
38:
39: case TCOM:
40: if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE)
41: (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
42: if ((t->t_dflg & FREDO) == 0)
43: Dfix(t); /* $ " ' \ */
44: if (t->t_dcom[0] == 0)
45: return;
46: /* fall into... */
47:
48: case TPAR:
49: if (t->t_dflg & FPOU)
50: mypipe(pipeout);
51: /*
52: * Must do << early so parent will know
53: * where input pointer should be.
54: * If noexec then this is all we do.
55: */
56: if (t->t_dflg & FHERE) {
57: (void) close(0);
58: heredoc(t->t_dlef);
59: if (noexec)
60: (void) close(0);
61: }
62: if (noexec)
63: break;
64:
65: set("status", "0");
66:
67: /*
68: * This mess is the necessary kludge to handle the prefix
69: * builtins: nice, nohup, time. These commands can also
70: * be used by themselves, and this is not handled here.
71: * This will also work when loops are parsed.
72: */
73: while (t->t_dtyp == TCOM)
74: if (eq(t->t_dcom[0], "nice"))
75: if (t->t_dcom[1])
76: if (any(t->t_dcom[1][0], "+-"))
77: if (t->t_dcom[2]) {
78: setname("nice");
79: t->t_nice = getn(t->t_dcom[1]);
80: lshift(t->t_dcom, 2);
81: t->t_dflg |= FNICE;
82: } else
83: break;
84: else {
85: t->t_nice = 4;
86: lshift(t->t_dcom, 1);
87: t->t_dflg |= FNICE;
88: }
89: else
90: break;
91: else if (eq(t->t_dcom[0], "nohup"))
92: if (t->t_dcom[1]) {
93: t->t_dflg |= FNOHUP;
94: lshift(t->t_dcom, 1);
95: } else
96: break;
97: else if (eq(t->t_dcom[0], "time"))
98: if (t->t_dcom[1]) {
99: t->t_dflg |= FTIME;
100: lshift(t->t_dcom, 1);
101: } else
102: break;
103: else
104: break;
105: /*
106: * Check if we have a builtin function and remember which one.
107: */
108: bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
109:
110: /*
111: * We fork only if we are timed, or are not the end of
112: * a parenthesized list and not a simple builtin function.
113: * Simple meaning one that is not pipedout, niced, nohupped,
114: * or &'d.
115: * It would be nice(?) to not fork in some of these cases.
116: */
117: if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
118: (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
119: #ifdef VFORK
120: if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc)
121: #endif
122: { forked++;
123: if (wanttty >= 0 && !nosigchld) {
124: osigmask = sigblock(sigmask(SIGCHLD));
125: nosigchld = 1;
126: }
127:
128: pid = pfork(t, wanttty);
129: if (pid == 0 && nosigchld) {
130: sigsetmask(osigmask);
131: nosigchld = 0;
132: }
133: }
134: #ifdef VFORK
135: else {
136: sig_t vffree;
137: int ochild, osetintr, ohaderr, odidfds;
138: int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
139: long omask;
140:
141: /*
142: * Prepare for the vfork by saving everything
143: * that the child corrupts before it exec's.
144: * Note that in some signal implementations
145: * which keep the signal info in user space
146: * (e.g. Sun's) it will also be necessary to
147: * save and restore the current sigvec's for
148: * the signals the child touches before it
149: * exec's.
150: */
151: if (wanttty >= 0 && !nosigchld && !noexec) {
152: osigmask = sigblock(sigmask(SIGCHLD));
153: nosigchld = 1;
154: }
155: omask = sigblock(sigmask(SIGCHLD));
156: ochild = child; osetintr = setintr;
157: ohaderr = haderr; odidfds = didfds;
158: oSHIN = SHIN; oSHOUT = SHOUT;
159: oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp;
160: oosigmask = osigmask; onosigchld = nosigchld;
161: Vsav = Vdp = 0; Vav = 0;
162: pid = vfork();
163: if (pid < 0) {
164: (void) sigsetmask(omask);
165: error("No more processes");
166: }
167: forked++;
168: if (pid) { /* parent */
169: child = ochild; setintr = osetintr;
170: haderr = ohaderr; didfds = odidfds;
171: SHIN = oSHIN;
172: SHOUT = oSHOUT; SHDIAG = oSHDIAG;
173: OLDSTD = oOLDSTD; tpgrp = otpgrp;
174: osigmask = oosigmask; nosigchld = onosigchld;
175: xfree(Vsav); Vsav = 0;
176: xfree(Vdp); Vdp = 0;
177: xfree((char *)Vav); Vav = 0;
178: /* this is from pfork() */
179: palloc(pid, t);
180: (void) sigsetmask(omask);
181: } else { /* child */
182: /* this is from pfork() */
183: int pgrp;
184: bool ignint = 0;
185:
186: if (nosigchld) {
187: sigsetmask(osigmask);
188: nosigchld = 0;
189: }
190: if (setintr)
191: ignint =
192: (tpgrp == -1 && (t->t_dflg&FINT))
193: || gointr && eq(gointr, "-");
194: pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
195: child++;
196: if (setintr) {
197: setintr = 0;
198: #ifdef notdef
199: (void) signal(SIGCHLD, SIG_DFL);
200: #endif
201: (void) signal(SIGINT, ignint ?
202: SIG_IGN : vffree);
203: (void) signal(SIGQUIT, ignint ?
204: SIG_IGN : SIG_DFL);
205: if (wanttty >= 0) {
206: (void) signal(SIGTSTP, SIG_DFL);
207: (void) signal(SIGTTIN, SIG_DFL);
208: (void) signal(SIGTTOU, SIG_DFL);
209: }
210: (void) signal(SIGTERM, parterm);
211: } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
212: (void) signal(SIGINT, SIG_IGN);
213: (void) signal(SIGQUIT, SIG_IGN);
214: }
215: if (wanttty >= 0 && tpgrp >= 0)
216: (void) setpgrp(0, pgrp);
217: if (wanttty > 0)
218: (void) ioctl(FSHTTY, TIOCSPGRP,
219: (char *)&pgrp);
220: if (tpgrp > 0)
221: tpgrp = 0;
222: if (t->t_dflg & FNOHUP)
223: (void) signal(SIGHUP, SIG_IGN);
224: if (t->t_dflg & FNICE)
225: (void) setpriority(PRIO_PROCESS,
226: 0, t->t_nice);
227: }
228:
229: }
230: #endif
231: if (pid != 0) {
232: /*
233: * It would be better if we could wait for the
234: * whole job when we knew the last process
235: * had been started. Pwait, in fact, does
236: * wait for the whole job anyway, but this test
237: * doesn't really express our intentions.
238: */
239: if (didfds==0 && t->t_dflg&FPIN) {
240: (void) close(pipein[0]);
241: (void) close(pipein[1]);
242: }
243: if ((t->t_dflg & FPOU) == 0) {
244: if (nosigchld) {
245: #ifdef foobarbaz
246: printf("DID\n");
247: #endif
248: sigsetmask(osigmask);
249: nosigchld = 0;
250: }
251: if ((t->t_dflg & FAND) == 0)
252: pwait();
253: }
254: break;
255: }
256: doio(t, pipein, pipeout);
257: if (t->t_dflg & FPOU) {
258: (void) close(pipeout[0]);
259: (void) close(pipeout[1]);
260: }
261:
262: /*
263: * Perform a builtin function.
264: * If we are not forked, arrange for possible stopping
265: */
266: if (bifunc) {
267: func(t, bifunc);
268: if (forked)
269: exitstat();
270: break;
271: }
272: if (t->t_dtyp != TPAR) {
273: doexec(t);
274: /*NOTREACHED*/
275: }
276: /*
277: * For () commands must put new 0,1,2 in FSH* and recurse
278: */
279: OLDSTD = dcopy(0, FOLDSTD);
280: SHOUT = dcopy(1, FSHOUT);
281: SHDIAG = dcopy(2, FSHDIAG);
282: (void) close(SHIN);
283: SHIN = -1;
284: didfds = 0;
285: wanttty = -1;
286: t->t_dspr->t_dflg |= t->t_dflg & FINT;
287: execute(t->t_dspr, wanttty);
288: exitstat();
289:
290: case TFIL:
291: t->t_dcar->t_dflg |= FPOU |
292: (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
293: execute(t->t_dcar, wanttty, pipein, pv);
294: t->t_dcdr->t_dflg |= FPIN |
295: (t->t_dflg & (FPOU|FAND|FPAR|FINT));
296: if (wanttty > 0)
297: wanttty = 0; /* got tty already */
298: execute(t->t_dcdr, wanttty, pv, pipeout);
299: break;
300:
301: case TLST:
302: if (t->t_dcar) {
303: t->t_dcar->t_dflg |= t->t_dflg & FINT;
304: execute(t->t_dcar, wanttty);
305: /*
306: * In strange case of A&B make a new job after A
307: */
308: if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
309: (t->t_dcdr->t_dflg&FAND) == 0)
310: pendjob();
311: }
312: if (t->t_dcdr) {
313: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
314: execute(t->t_dcdr, wanttty);
315: }
316: break;
317:
318: case TOR:
319: case TAND:
320: if (t->t_dcar) {
321: t->t_dcar->t_dflg |= t->t_dflg & FINT;
322: execute(t->t_dcar, wanttty);
323: if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
324: return;
325: }
326: if (t->t_dcdr) {
327: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
328: execute(t->t_dcdr, wanttty);
329: }
330: break;
331: }
332: /*
333: * Fall through for all breaks from switch
334: *
335: * If there will be no more executions of this
336: * command, flush all file descriptors.
337: * Places that turn on the FREDO bit are responsible
338: * for doing donefds after the last re-execution
339: */
340: if (didfds && !(t->t_dflg & FREDO))
341: donefds();
342: }
343:
344: #ifdef VFORK
345: vffree()
346: {
347: register char **v;
348:
349: if (v = gargv)
350: gargv = 0, xfree((char *)v);
351: if (v = pargv)
352: pargv = 0, xfree((char *)v);
353: _exit(1);
354: }
355: #endif
356:
357: /*
358: * Perform io redirection.
359: * We may or maynot be forked here.
360: */
361: doio(t, pipein, pipeout)
362: register struct command *t;
363: int *pipein, *pipeout;
364: {
365: register char *cp;
366: register int flags = t->t_dflg;
367:
368: if (didfds || (flags & FREDO))
369: return;
370: if ((flags & FHERE) == 0) { /* FHERE already done */
371: (void) close(0);
372: if (cp = t->t_dlef) {
373: cp = globone(Dfix1(cp));
374: xfree(cp);
375: if (open(cp, 0) < 0)
376: Perror(cp);
377: } else if (flags & FPIN) {
378: (void) dup(pipein[0]);
379: (void) close(pipein[0]);
380: (void) close(pipein[1]);
381: } else if ((flags & FINT) && tpgrp == -1) {
382: (void) close(0);
383: (void) open(_PATH_DEVNULL, 0);
384: } else
385: (void) dup(OLDSTD);
386: }
387: (void) close(1);
388: if (cp = t->t_drit) {
389: cp = globone(Dfix1(cp));
390: xfree(cp);
391: if (!(flags & FCAT) || open(cp, O_WRONLY|O_APPEND, 0) < 0) {
392: if (!(flags & FANY) && adrof("noclobber")) {
393: if (flags & FCAT)
394: Perror(cp);
395: chkclob(cp);
396: }
397: if (creat(cp, 0666) < 0)
398: Perror(cp);
399: }
400: } else if (flags & FPOU)
401: (void) dup(pipeout[1]);
402: else
403: (void) dup(SHOUT);
404:
405: (void) close(2);
406: if (flags & FDIAG)
407: (void) dup(1);
408: else
409: (void) dup(SHDIAG);
410: didfds = 1;
411: }
412:
413: mypipe(pv)
414: register int *pv;
415: {
416:
417: if (pipe(pv) < 0)
418: goto oops;
419: pv[0] = dmove(pv[0], -1);
420: pv[1] = dmove(pv[1], -1);
421: if (pv[0] >= 0 && pv[1] >= 0)
422: return;
423: oops:
424: error("Can't make pipe");
425: }
426:
427: chkclob(cp)
428: register char *cp;
429: {
430: struct stat stb;
431:
432: if (stat(cp, &stb) < 0)
433: return;
434: if ((stb.st_mode & S_IFMT) == S_IFCHR)
435: return;
436: error("%s: File exists", cp);
437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.