|
|
1.1 root 1: static char *sccsid = "@(#)sh.sem.c 4.1 10/9/80";
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: sigsys(SIGCHLD, SIG_DFL);
155: sigsys(SIGINT, ignint ? SIG_IGN : vffree);
156: sigsys(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
157: if (wanttty >= 0) {
158: sigsys(SIGTSTP, SIG_DFL);
159: sigsys(SIGTTIN, SIG_DFL);
160: sigsys(SIGTTOU, SIG_DFL);
161: }
162: sigsys(SIGTERM, parterm);
163: } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
164: sigsys(SIGINT, SIG_IGN);
165: sigsys(SIGQUIT, SIG_IGN);
166: }
167: if (wanttty > 0)
168: ioctl(FSHTTY, TIOCSPGRP, &pgrp);
169: if (wanttty >= 0 && tpgrp >= 0)
170: setpgrp(0, pgrp);
171: if (tpgrp > 0)
172: tpgrp = 0;
173: if (t->t_dflg & FNOHUP)
174: sigsys(SIGHUP, SIG_IGN);
175: if (t->t_dflg & FNICE)
176: nice(t->t_nice);
177: }
178:
179: }
180: #endif
181: if (pid != 0) {
182: /*
183: * It would be better if we could wait for the
184: * whole job when we knew the last process
185: * had been started. Pwait, in fact, does
186: * wait for the whole job anyway, but this test
187: * doesn't really express our intentions.
188: */
189: if (didfds==0 && t->t_dflg&FPIN)
190: close(pipein[0]), close(pipein[1]);
191: if ((t->t_dflg & (FPOU|FAND)) == 0)
192: pwait();
193: break;
194: }
195: doio(t, pipein, pipeout);
196: if (t->t_dflg & FPOU)
197: close(pipeout[0]), close(pipeout[1]);
198:
199: /*
200: * Perform a builtin function.
201: * If we are not forked, arrange for possible stopping
202: */
203: if (bifunc) {
204: func(t, bifunc);
205: if (forked)
206: exitstat();
207: break;
208: }
209: if (t->t_dtyp != TPAR) {
210: doexec(t);
211: /*NOTREACHED*/
212: }
213: /*
214: * For () commands must put new 0,1,2 in FSH* and recurse
215: */
216: OLDSTD = dcopy(0, FOLDSTD);
217: SHOUT = dcopy(1, FSHOUT);
218: SHDIAG = dcopy(2, FSHDIAG);
219: close(SHIN), SHIN = -1;
220: didcch = 0, didfds = 0;
221: wanttty = -1;
222: t->t_dspr->t_dflg |= t->t_dflg & FINT;
223: execute(t->t_dspr, wanttty);
224: exitstat();
225:
226: case TFIL:
227: t->t_dcar->t_dflg |= FPOU |
228: (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
229: execute(t->t_dcar, wanttty, pipein, pv);
230: t->t_dcdr->t_dflg |= FPIN |
231: (t->t_dflg & (FPOU|FAND|FPAR|FINT));
232: if (wanttty > 0)
233: wanttty = 0; /* got tty already */
234: execute(t->t_dcdr, wanttty, pv, pipeout);
235: break;
236:
237: case TLST:
238: if (t->t_dcar) {
239: t->t_dcar->t_dflg |= t->t_dflg & FINT;
240: execute(t->t_dcar, wanttty);
241: /*
242: * In strange case of A&B make a new job after A
243: */
244: if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
245: (t->t_dcdr->t_dflg&FAND) == 0)
246: pendjob();
247: }
248: if (t->t_dcdr) {
249: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
250: execute(t->t_dcdr, wanttty);
251: }
252: break;
253:
254: case TOR:
255: case TAND:
256: if (t->t_dcar) {
257: t->t_dcar->t_dflg |= t->t_dflg & FINT;
258: execute(t->t_dcar, wanttty);
259: if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
260: return;
261: }
262: if (t->t_dcdr) {
263: t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
264: execute(t->t_dcdr, wanttty);
265: }
266: break;
267: }
268: /*
269: * Fall through for all breaks from switch
270: *
271: * If there will be no more executions of this
272: * command, flush all file descriptors.
273: * Places that turn on the FREDO bit are responsible
274: * for doing donefds after the last re-execution
275: */
276: if (didfds && !(t->t_dflg & FREDO))
277: donefds();
278: }
279:
280: #ifdef VFORK
281: vffree()
282: {
283: register char **v;
284:
285: if (v = gargv)
286: gargv = 0, xfree(gargv);
287: if (v = pargv)
288: pargv = 0, xfree(pargv);
289: _exit(1);
290: }
291: #endif
292:
293: /*
294: * Perform io redirection.
295: * We may or maynot be forked here.
296: */
297: doio(t, pipein, pipeout)
298: register struct command *t;
299: int *pipein, *pipeout;
300: {
301: register char *cp;
302: register int flags = t->t_dflg;
303:
304: if (didfds || (flags & FREDO))
305: return;
306: if ((flags & FHERE) == 0) { /* FHERE already done */
307: close(0);
308: if (cp = t->t_dlef) {
309: cp = globone(Dfix1(cp));
310: xfree(cp);
311: if (open(cp, 0) < 0)
312: Perror(cp);
313: } else if (flags & FPIN)
314: dup(pipein[0]), close(pipein[0]), close(pipein[1]);
315: else if ((flags & FINT) && tpgrp == -1)
316: close(0), open("/dev/null", 0);
317: else
318: dup(OLDSTD);
319: }
320: close(1);
321: if (cp = t->t_drit) {
322: cp = globone(Dfix1(cp));
323: xfree(cp);
324: if ((flags & FCAT) && open(cp, 1) >= 0)
325: lseek(1, 0l, 2);
326: else {
327: if (!(flags & FANY) && adrof("noclobber")) {
328: if (flags & FCAT)
329: Perror(cp);
330: chkclob(cp);
331: }
332: if (creat(cp, 0666) < 0)
333: Perror(cp);
334: }
335: } else if (flags & FPOU)
336: dup(pipeout[1]);
337: else
338: dup(SHOUT);
339:
340: close(2);
341: dup((flags & FDIAG) ? 1 : SHDIAG);
342: didfds = 1;
343: }
344:
345: mypipe(pv)
346: register int *pv;
347: {
348:
349: if (pipe(pv) < 0)
350: goto oops;
351: pv[0] = dmove(pv[0], -1);
352: pv[1] = dmove(pv[1], -1);
353: if (pv[0] >= 0 && pv[1] >= 0)
354: return;
355: oops:
356: error("Can't make pipe");
357: }
358:
359: chkclob(cp)
360: register char *cp;
361: {
362: struct stat stb;
363:
364: if (stat(cp, &stb) < 0)
365: return;
366: if ((stb.st_mode & S_IFMT) == S_IFCHR)
367: return;
368: error("%s: File exists", cp);
369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.