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