Commit | Line | Data |
---|---|---|
b79f4fa9 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
094e80ed | 3 | * All rights reserved. The Berkeley Software License Agreement |
b79f4fa9 DF |
4 | * specifies the terms and conditions for redistribution. |
5 | */ | |
6 | ||
35371dec | 7 | #ifndef lint |
1ab62557 | 8 | static char *sccsid = "@(#)sem.c 5.3 (Berkeley) %G%"; |
094e80ed | 9 | #endif |
e0cb907a BJ |
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) | |
35371dec | 37 | (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1); |
e0cb907a BJ |
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) { | |
35371dec | 53 | (void) close(0); |
e0cb907a BJ |
54 | heredoc(t->t_dlef); |
55 | if (noexec) | |
35371dec | 56 | (void) close(0); |
e0cb907a BJ |
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(); | |
35371dec | 122 | int ochild, osetintr, ohaderr, odidfds; |
e0cb907a | 123 | int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; |
d33af40e | 124 | int omask; |
e0cb907a | 125 | |
d33af40e | 126 | omask = sigblock(sigmask(SIGCHLD)); |
e0cb907a | 127 | ochild = child; osetintr = setintr; |
35371dec | 128 | ohaderr = haderr; odidfds = didfds; |
e0cb907a BJ |
129 | oSHIN = SHIN; oSHOUT = SHOUT; |
130 | oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp; | |
131 | Vsav = Vdp = 0; Vav = 0; | |
132 | pid = vfork(); | |
133 | if (pid < 0) { | |
35371dec | 134 | (void) sigsetmask(omask); |
e0cb907a BJ |
135 | error("No more processes"); |
136 | } | |
137 | forked++; | |
138 | if (pid) { | |
139 | child = ochild; setintr = osetintr; | |
140 | haderr = ohaderr; didfds = odidfds; | |
35371dec | 141 | SHIN = oSHIN; |
e0cb907a BJ |
142 | SHOUT = oSHOUT; SHDIAG = oSHDIAG; |
143 | OLDSTD = oOLDSTD; tpgrp = otpgrp; | |
144 | xfree(Vsav); Vsav = 0; | |
145 | xfree(Vdp); Vdp = 0; | |
35371dec | 146 | xfree((char *)Vav); Vav = 0; |
e0cb907a BJ |
147 | /* this is from pfork() */ |
148 | palloc(pid, t); | |
35371dec | 149 | (void) sigsetmask(omask); |
e0cb907a BJ |
150 | } else { |
151 | /* this is from pfork() */ | |
152 | int pgrp; | |
153 | bool ignint = 0; | |
154 | ||
155 | if (setintr) | |
156 | ignint = | |
157 | (tpgrp == -1 && (t->t_dflg&FINT)) | |
158 | || gointr && eq(gointr, "-"); | |
159 | pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); | |
160 | child++; | |
161 | if (setintr) { | |
162 | setintr = 0; | |
ec1a81af | 163 | #ifdef notdef |
35371dec | 164 | (void) signal(SIGCHLD, SIG_DFL); |
ec1a81af | 165 | #endif |
35371dec | 166 | (void) signal(SIGINT, ignint ? |
d33af40e | 167 | SIG_IGN : vffree); |
35371dec | 168 | (void) signal(SIGQUIT, ignint ? |
d33af40e | 169 | SIG_IGN : SIG_DFL); |
e0cb907a | 170 | if (wanttty >= 0) { |
35371dec EW |
171 | (void) signal(SIGTSTP, SIG_DFL); |
172 | (void) signal(SIGTTIN, SIG_DFL); | |
173 | (void) signal(SIGTTOU, SIG_DFL); | |
e0cb907a | 174 | } |
35371dec | 175 | (void) signal(SIGTERM, parterm); |
e0cb907a | 176 | } else if (tpgrp == -1 && (t->t_dflg&FINT)) { |
35371dec EW |
177 | (void) signal(SIGINT, SIG_IGN); |
178 | (void) signal(SIGQUIT, SIG_IGN); | |
e0cb907a BJ |
179 | } |
180 | if (wanttty > 0) | |
35371dec EW |
181 | (void) ioctl(FSHTTY, TIOCSPGRP, |
182 | (char *)&pgrp); | |
e0cb907a | 183 | if (wanttty >= 0 && tpgrp >= 0) |
35371dec | 184 | (void) setpgrp(0, pgrp); |
e0cb907a BJ |
185 | if (tpgrp > 0) |
186 | tpgrp = 0; | |
187 | if (t->t_dflg & FNOHUP) | |
35371dec | 188 | (void) signal(SIGHUP, SIG_IGN); |
e0cb907a | 189 | if (t->t_dflg & FNICE) |
1ab62557 JL |
190 | (void) setpriority(PRIO_PROCESS, 0, |
191 | getpriority(PRIO_PROCESS, 0) | |
192 | + t->t_nice); | |
e0cb907a BJ |
193 | } |
194 | ||
d33af40e | 195 | } |
e0cb907a BJ |
196 | #endif |
197 | if (pid != 0) { | |
198 | /* | |
199 | * It would be better if we could wait for the | |
200 | * whole job when we knew the last process | |
201 | * had been started. Pwait, in fact, does | |
202 | * wait for the whole job anyway, but this test | |
203 | * doesn't really express our intentions. | |
204 | */ | |
35371dec EW |
205 | if (didfds==0 && t->t_dflg&FPIN) { |
206 | (void) close(pipein[0]); | |
207 | (void) close(pipein[1]); | |
208 | } | |
e0cb907a BJ |
209 | if ((t->t_dflg & (FPOU|FAND)) == 0) |
210 | pwait(); | |
211 | break; | |
212 | } | |
213 | doio(t, pipein, pipeout); | |
35371dec EW |
214 | if (t->t_dflg & FPOU) { |
215 | (void) close(pipeout[0]); | |
216 | (void) close(pipeout[1]); | |
217 | } | |
e0cb907a BJ |
218 | |
219 | /* | |
220 | * Perform a builtin function. | |
221 | * If we are not forked, arrange for possible stopping | |
222 | */ | |
223 | if (bifunc) { | |
224 | func(t, bifunc); | |
225 | if (forked) | |
226 | exitstat(); | |
227 | break; | |
228 | } | |
229 | if (t->t_dtyp != TPAR) { | |
230 | doexec(t); | |
231 | /*NOTREACHED*/ | |
232 | } | |
233 | /* | |
234 | * For () commands must put new 0,1,2 in FSH* and recurse | |
235 | */ | |
236 | OLDSTD = dcopy(0, FOLDSTD); | |
237 | SHOUT = dcopy(1, FSHOUT); | |
238 | SHDIAG = dcopy(2, FSHDIAG); | |
35371dec EW |
239 | (void) close(SHIN); |
240 | SHIN = -1; | |
241 | didfds = 0; | |
e0cb907a BJ |
242 | wanttty = -1; |
243 | t->t_dspr->t_dflg |= t->t_dflg & FINT; | |
244 | execute(t->t_dspr, wanttty); | |
245 | exitstat(); | |
246 | ||
247 | case TFIL: | |
248 | t->t_dcar->t_dflg |= FPOU | | |
249 | (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); | |
250 | execute(t->t_dcar, wanttty, pipein, pv); | |
251 | t->t_dcdr->t_dflg |= FPIN | | |
252 | (t->t_dflg & (FPOU|FAND|FPAR|FINT)); | |
253 | if (wanttty > 0) | |
254 | wanttty = 0; /* got tty already */ | |
255 | execute(t->t_dcdr, wanttty, pv, pipeout); | |
256 | break; | |
257 | ||
258 | case TLST: | |
259 | if (t->t_dcar) { | |
260 | t->t_dcar->t_dflg |= t->t_dflg & FINT; | |
261 | execute(t->t_dcar, wanttty); | |
262 | /* | |
263 | * In strange case of A&B make a new job after A | |
264 | */ | |
265 | if (t->t_dcar->t_dflg&FAND && t->t_dcdr && | |
266 | (t->t_dcdr->t_dflg&FAND) == 0) | |
267 | pendjob(); | |
268 | } | |
269 | if (t->t_dcdr) { | |
270 | t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); | |
271 | execute(t->t_dcdr, wanttty); | |
272 | } | |
273 | break; | |
274 | ||
275 | case TOR: | |
276 | case TAND: | |
277 | if (t->t_dcar) { | |
278 | t->t_dcar->t_dflg |= t->t_dflg & FINT; | |
279 | execute(t->t_dcar, wanttty); | |
280 | if ((getn(value("status")) == 0) != (t->t_dtyp == TAND)) | |
281 | return; | |
282 | } | |
283 | if (t->t_dcdr) { | |
284 | t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); | |
285 | execute(t->t_dcdr, wanttty); | |
286 | } | |
287 | break; | |
288 | } | |
289 | /* | |
290 | * Fall through for all breaks from switch | |
291 | * | |
292 | * If there will be no more executions of this | |
293 | * command, flush all file descriptors. | |
294 | * Places that turn on the FREDO bit are responsible | |
295 | * for doing donefds after the last re-execution | |
296 | */ | |
297 | if (didfds && !(t->t_dflg & FREDO)) | |
298 | donefds(); | |
299 | } | |
300 | ||
301 | #ifdef VFORK | |
302 | vffree() | |
303 | { | |
304 | register char **v; | |
305 | ||
306 | if (v = gargv) | |
35371dec | 307 | gargv = 0, xfree((char *)v); |
e0cb907a | 308 | if (v = pargv) |
35371dec | 309 | pargv = 0, xfree((char *)v); |
e0cb907a BJ |
310 | _exit(1); |
311 | } | |
312 | #endif | |
313 | ||
314 | /* | |
315 | * Perform io redirection. | |
316 | * We may or maynot be forked here. | |
317 | */ | |
318 | doio(t, pipein, pipeout) | |
319 | register struct command *t; | |
320 | int *pipein, *pipeout; | |
321 | { | |
322 | register char *cp; | |
323 | register int flags = t->t_dflg; | |
324 | ||
325 | if (didfds || (flags & FREDO)) | |
326 | return; | |
327 | if ((flags & FHERE) == 0) { /* FHERE already done */ | |
35371dec | 328 | (void) close(0); |
e0cb907a BJ |
329 | if (cp = t->t_dlef) { |
330 | cp = globone(Dfix1(cp)); | |
331 | xfree(cp); | |
332 | if (open(cp, 0) < 0) | |
333 | Perror(cp); | |
35371dec EW |
334 | } else if (flags & FPIN) { |
335 | (void) dup(pipein[0]); | |
336 | (void) close(pipein[0]); | |
337 | (void) close(pipein[1]); | |
338 | } else if ((flags & FINT) && tpgrp == -1) { | |
339 | (void) close(0); | |
340 | (void) open("/dev/null", 0); | |
341 | } else | |
d671c35e | 342 | (void) dup(OLDSTD); |
e0cb907a | 343 | } |
35371dec | 344 | (void) close(1); |
e0cb907a BJ |
345 | if (cp = t->t_drit) { |
346 | cp = globone(Dfix1(cp)); | |
347 | xfree(cp); | |
348 | if ((flags & FCAT) && open(cp, 1) >= 0) | |
35371dec | 349 | (void) lseek(1, (off_t)0, 2); |
e0cb907a BJ |
350 | else { |
351 | if (!(flags & FANY) && adrof("noclobber")) { | |
352 | if (flags & FCAT) | |
353 | Perror(cp); | |
354 | chkclob(cp); | |
355 | } | |
356 | if (creat(cp, 0666) < 0) | |
357 | Perror(cp); | |
358 | } | |
359 | } else if (flags & FPOU) | |
35371dec | 360 | (void) dup(pipeout[1]); |
e0cb907a | 361 | else |
d671c35e | 362 | (void) dup(SHOUT); |
e0cb907a | 363 | |
35371dec EW |
364 | (void) close(2); |
365 | if (flags & FDIAG) | |
366 | (void) dup(1); | |
367 | else | |
d671c35e | 368 | (void) dup(SHDIAG); |
e0cb907a BJ |
369 | didfds = 1; |
370 | } | |
371 | ||
372 | mypipe(pv) | |
373 | register int *pv; | |
374 | { | |
375 | ||
376 | if (pipe(pv) < 0) | |
377 | goto oops; | |
378 | pv[0] = dmove(pv[0], -1); | |
379 | pv[1] = dmove(pv[1], -1); | |
380 | if (pv[0] >= 0 && pv[1] >= 0) | |
381 | return; | |
382 | oops: | |
383 | error("Can't make pipe"); | |
384 | } | |
385 | ||
386 | chkclob(cp) | |
387 | register char *cp; | |
388 | { | |
389 | struct stat stb; | |
390 | ||
391 | if (stat(cp, &stb) < 0) | |
392 | return; | |
393 | if ((stb.st_mode & S_IFMT) == S_IFCHR) | |
394 | return; | |
395 | error("%s: File exists", cp); | |
396 | } |