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