1 /*-
2 * Copyright (c) 1980, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)sem.c 5.17 (Berkeley) 6/17/91";
36 #endif /* not lint */
37
38 #include <sys/param.h>
39 #include <sys/ioctl.h>
40 #include <sys/stat.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #if __STDC__
47 # include <stdarg.h>
48 #else
49 # include <varargs.h>
50 #endif
51
52 #include "csh.h"
53 #include "proc.h"
54 #include "extern.h"
55
56 static void vffree __P((int));
57 static void doio __P((struct command *t, int *, int *));
58 static void chkclob __P((char *));
59
60 void
execute(t,wanttty,pipein,pipeout)61 execute(t, wanttty, pipein, pipeout)
62 register struct command *t;
63 int wanttty, *pipein, *pipeout;
64 {
65 bool forked = 0;
66 struct biltins *bifunc;
67 int pid = 0;
68 int pv[2];
69
70 static sigset_t csigmask;
71
72 static sigset_t ocsigmask;
73 static int onosigchld = 0;
74 static int nosigchld = 0;
75
76 if (t == 0)
77 return;
78
79 if (t->t_dflg & F_AMPERSAND)
80 wanttty = 0;
81 switch (t->t_dtyp) {
82
83 case NODE_COMMAND:
84 if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
85 (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
86 if ((t->t_dflg & F_REPEAT) == 0)
87 Dfix(t); /* $ " ' \ */
88 if (t->t_dcom[0] == 0)
89 return;
90 /* fall into... */
91
92 case NODE_PAREN:
93 if (t->t_dflg & F_PIPEOUT)
94 mypipe(pipeout);
95 /*
96 * Must do << early so parent will know where input pointer should be.
97 * If noexec then this is all we do.
98 */
99 if (t->t_dflg & F_READ) {
100 (void) close(0);
101 heredoc(t->t_dlef);
102 if (noexec)
103 (void) close(0);
104 }
105 if (noexec)
106 break;
107
108 set(STRstatus, Strsave(STR0));
109
110 /*
111 * This mess is the necessary kludge to handle the prefix builtins:
112 * nice, nohup, time. These commands can also be used by themselves,
113 * and this is not handled here. This will also work when loops are
114 * parsed.
115 */
116 while (t->t_dtyp == NODE_COMMAND)
117 if (eq(t->t_dcom[0], STRnice))
118 if (t->t_dcom[1])
119 if (strchr("+-", t->t_dcom[1][0]))
120 if (t->t_dcom[2]) {
121 setname("nice");
122 t->t_nice =
123 getn(t->t_dcom[1]);
124 lshift(t->t_dcom, 2);
125 t->t_dflg |= F_NICE;
126 }
127 else
128 break;
129 else {
130 t->t_nice = 4;
131 lshift(t->t_dcom, 1);
132 t->t_dflg |= F_NICE;
133 }
134 else
135 break;
136 else if (eq(t->t_dcom[0], STRnohup))
137 if (t->t_dcom[1]) {
138 t->t_dflg |= F_NOHUP;
139 lshift(t->t_dcom, 1);
140 }
141 else
142 break;
143 else if (eq(t->t_dcom[0], STRtime))
144 if (t->t_dcom[1]) {
145 t->t_dflg |= F_TIME;
146 lshift(t->t_dcom, 1);
147 }
148 else
149 break;
150 else
151 break;
152
153 /* is t a command */
154 if (t->t_dtyp == NODE_COMMAND) {
155 /*
156 * Check if we have a builtin function and remember which one.
157 */
158 bifunc = isbfunc(t);
159 }
160 else { /* not a command */
161 bifunc = NULL;
162 }
163
164 /*
165 * We fork only if we are timed, or are not the end of a parenthesized
166 * list and not a simple builtin function. Simple meaning one that is
167 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
168 * fork in some of these cases.
169 */
170 /*
171 * Prevent forking cd, pushd, popd, chdir cause this will cause the
172 * shell not to change dir!
173 */
174 if (bifunc && (bifunc->bfunct == dochngd ||
175 bifunc->bfunct == dopushd ||
176 bifunc->bfunct == dopopd))
177 t->t_dflg &= ~(F_NICE);
178 if (((t->t_dflg & F_TIME) || (t->t_dflg & F_NOFORK) == 0 &&
179 (!bifunc || t->t_dflg &
180 (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP))) ||
181 /*
182 * We have to fork for eval too.
183 */
184 (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
185 bifunc->bfunct == doeval))
186 if (t->t_dtyp == NODE_PAREN ||
187 t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) {
188 forked++;
189 /*
190 * We need to block SIGCHLD here, so that if the process does
191 * not die before we can set the process group
192 */
193 if (wanttty >= 0 && !nosigchld) {
194 csigmask = sigblock(sigmask(SIGCHLD));
195 nosigchld = 1;
196 }
197
198 pid = pfork(t, wanttty);
199 if (pid == 0 && nosigchld) {
200 (void) sigsetmask(csigmask);
201 nosigchld = 0;
202 }
203 }
204 else {
205 int ochild, osetintr, ohaderr, odidfds;
206 int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
207 sigset_t omask;
208
209 /*
210 * Prepare for the vfork by saving everything that the child
211 * corrupts before it exec's. Note that in some signal
212 * implementations which keep the signal info in user space
213 * (e.g. Sun's) it will also be necessary to save and restore
214 * the current sigvec's for the signals the child touches
215 * before it exec's.
216 */
217 if (wanttty >= 0 && !nosigchld && !noexec) {
218 csigmask = sigblock(sigmask(SIGCHLD));
219 nosigchld = 1;
220 }
221 omask = sigblock(sigmask(SIGCHLD) | sigmask(SIGINT));
222 ochild = child;
223 osetintr = setintr;
224 ohaderr = haderr;
225 odidfds = didfds;
226 oSHIN = SHIN;
227 oSHOUT = SHOUT;
228 oSHDIAG = SHDIAG;
229 oOLDSTD = OLDSTD;
230 otpgrp = tpgrp;
231 ocsigmask = csigmask;
232 onosigchld = nosigchld;
233 Vsav = Vdp = 0;
234 Vexpath = 0;
235 Vt = 0;
236 pid = vfork();
237
238 if (pid < 0) {
239 (void) sigsetmask(omask);
240 stderror(ERR_NOPROC);
241 }
242 forked++;
243 if (pid) { /* parent */
244 child = ochild;
245 setintr = osetintr;
246 haderr = ohaderr;
247 didfds = odidfds;
248 SHIN = oSHIN;
249 SHOUT = oSHOUT;
250 SHDIAG = oSHDIAG;
251 OLDSTD = oOLDSTD;
252 tpgrp = otpgrp;
253 csigmask = ocsigmask;
254 nosigchld = onosigchld;
255
256 xfree((ptr_t) Vsav);
257 Vsav = 0;
258 xfree((ptr_t) Vdp);
259 Vdp = 0;
260 xfree((ptr_t) Vexpath);
261 Vexpath = 0;
262 blkfree((Char **) Vt);
263 Vt = 0;
264 /* this is from pfork() */
265 palloc(pid, t);
266 (void) sigsetmask(omask);
267 }
268 else { /* child */
269 /* this is from pfork() */
270 int pgrp;
271 bool ignint = 0;
272
273 if (nosigchld) {
274 (void) sigsetmask(csigmask);
275 nosigchld = 0;
276 }
277
278 if (setintr)
279 ignint =
280 (tpgrp == -1 &&
281 (t->t_dflg & F_NOINTERRUPT))
282 || gointr && eq(gointr, STRminus);
283 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
284 child++;
285 if (setintr) {
286 setintr = 0;
287 if (ignint) {
288 (void) signal(SIGINT, SIG_IGN);
289 (void) signal(SIGQUIT, SIG_IGN);
290 }
291 else {
292 (void) signal(SIGINT, vffree);
293 (void) signal(SIGQUIT, SIG_DFL);
294 }
295
296 if (wanttty >= 0) {
297 (void) signal(SIGTSTP, SIG_DFL);
298 (void) signal(SIGTTIN, SIG_DFL);
299 (void) signal(SIGTTOU, SIG_DFL);
300 }
301
302 (void) signal(SIGTERM, parterm);
303 }
304 else if (tpgrp == -1 &&
305 (t->t_dflg & F_NOINTERRUPT)) {
306 (void) signal(SIGINT, SIG_IGN);
307 (void) signal(SIGQUIT, SIG_IGN);
308 }
309
310 pgetty(wanttty, pgrp);
311 if (t->t_dflg & F_NOHUP)
312 (void) signal(SIGHUP, SIG_IGN);
313 if (t->t_dflg & F_NICE)
314 (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
315 }
316
317 }
318 if (pid != 0) {
319 /*
320 * It would be better if we could wait for the whole job when we
321 * knew the last process had been started. Pwait, in fact, does
322 * wait for the whole job anyway, but this test doesn't really
323 * express our intentions.
324 */
325 if (didfds == 0 && t->t_dflg & F_PIPEIN) {
326 (void) close(pipein[0]);
327 (void) close(pipein[1]);
328 }
329 if ((t->t_dflg & F_PIPEOUT) == 0) {
330 if (nosigchld) {
331 (void) sigsetmask(csigmask);
332 nosigchld = 0;
333 }
334 if ((t->t_dflg & F_AMPERSAND) == 0)
335 pwait();
336 }
337 break;
338 }
339 doio(t, pipein, pipeout);
340 if (t->t_dflg & F_PIPEOUT) {
341 (void) close(pipeout[0]);
342 (void) close(pipeout[1]);
343 }
344 /*
345 * Perform a builtin function. If we are not forked, arrange for
346 * possible stopping
347 */
348 if (bifunc) {
349 func(t, bifunc);
350 if (forked)
351 exitstat();
352 break;
353 }
354 if (t->t_dtyp != NODE_PAREN) {
355 doexec(t);
356 /* NOTREACHED */
357 }
358 /*
359 * For () commands must put new 0,1,2 in FSH* and recurse
360 */
361 OLDSTD = dcopy(0, FOLDSTD);
362 SHOUT = dcopy(1, FSHOUT);
363 SHDIAG = dcopy(2, FSHDIAG);
364 (void) close(SHIN);
365 SHIN = -1;
366 didfds = 0;
367 wanttty = -1;
368 t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
369 execute(t->t_dspr, wanttty, NULL, NULL);
370 exitstat();
371
372 case NODE_PIPE:
373 t->t_dcar->t_dflg |= F_PIPEOUT |
374 (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
375 execute(t->t_dcar, wanttty, pipein, pv);
376 t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
377 (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
378 if (wanttty > 0)
379 wanttty = 0; /* got tty already */
380 execute(t->t_dcdr, wanttty, pv, pipeout);
381 break;
382
383 case NODE_LIST:
384 if (t->t_dcar) {
385 t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
386 execute(t->t_dcar, wanttty, NULL, NULL);
387 /*
388 * In strange case of A&B make a new job after A
389 */
390 if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
391 (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
392 pendjob();
393 }
394 if (t->t_dcdr) {
395 t->t_dcdr->t_dflg |= t->t_dflg &
396 (F_NOFORK | F_NOINTERRUPT);
397 execute(t->t_dcdr, wanttty, NULL, NULL);
398 }
399 break;
400
401 case NODE_OR:
402 case NODE_AND:
403 if (t->t_dcar) {
404 t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
405 execute(t->t_dcar, wanttty, NULL, NULL);
406 if ((getn(value(STRstatus)) == 0) !=
407 (t->t_dtyp == NODE_AND))
408 return;
409 }
410 if (t->t_dcdr) {
411 t->t_dcdr->t_dflg |= t->t_dflg &
412 (F_NOFORK | F_NOINTERRUPT);
413 execute(t->t_dcdr, wanttty, NULL, NULL);
414 }
415 break;
416 }
417 /*
418 * Fall through for all breaks from switch
419 *
420 * If there will be no more executions of this command, flush all file
421 * descriptors. Places that turn on the F_REPEAT bit are responsible for
422 * doing donefds after the last re-execution
423 */
424 if (didfds && !(t->t_dflg & F_REPEAT))
425 donefds();
426 }
427
428 static void
vffree(i)429 vffree(i)
430 int i;
431 {
432 register Char **v;
433
434 if (v = gargv) {
435 gargv = 0;
436 xfree((ptr_t) v);
437 }
438 if (v = pargv) {
439 pargv = 0;
440 xfree((ptr_t) v);
441 }
442 _exit(i);
443 }
444
445 /*
446 * Perform io redirection.
447 * We may or maynot be forked here.
448 */
449 static void
doio(t,pipein,pipeout)450 doio(t, pipein, pipeout)
451 register struct command *t;
452 int *pipein, *pipeout;
453 {
454 register int fd;
455 register Char *cp;
456 register int flags = t->t_dflg;
457
458 if (didfds || (flags & F_REPEAT))
459 return;
460 if ((flags & F_READ) == 0) {/* F_READ already done */
461 if (cp = t->t_dlef) {
462 char tmp[PATH_MAX+1];
463
464 /*
465 * so < /dev/std{in,out,err} work
466 */
467 (void) dcopy(SHIN, 0);
468 (void) dcopy(SHOUT, 1);
469 (void) dcopy(SHDIAG, 2);
470 cp = globone(Dfix1(cp), G_IGNORE);
471 (void) strncpy(tmp, short2str(cp), PATH_MAX);
472 tmp[PATH_MAX] = '\0';
473 xfree((ptr_t) cp);
474 if ((fd = open(tmp, O_RDONLY)) < 0)
475 stderror(ERR_SYSTEM, tmp, strerror(errno));
476 (void) dmove(fd, 0);
477 }
478 else if (flags & F_PIPEIN) {
479 (void) close(0);
480 (void) dup(pipein[0]);
481 (void) close(pipein[0]);
482 (void) close(pipein[1]);
483 }
484 else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
485 (void) close(0);
486 (void) open(_PATH_DEVNULL, O_RDONLY);
487 }
488 else {
489 (void) close(0);
490 (void) dup(OLDSTD);
491 (void) ioctl(0, FIONCLEX, NULL);
492 }
493 }
494 if (cp = t->t_drit) {
495 char tmp[PATH_MAX+1];
496
497 cp = globone(Dfix1(cp), G_IGNORE);
498 (void) strncpy(tmp, short2str(cp), PATH_MAX);
499 tmp[PATH_MAX] = '\0';
500 xfree((ptr_t) cp);
501 /*
502 * so > /dev/std{out,err} work
503 */
504 (void) dcopy(SHOUT, 1);
505 (void) dcopy(SHDIAG, 2);
506 if ((flags & F_APPEND) &&
507 #ifdef O_APPEND
508 (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
509 #else
510 (fd = open(tmp, O_WRONLY)) >= 0)
511 (void) lseek(1, (off_t) 0, L_XTND);
512 #endif
513 else {
514 if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
515 if (flags & F_APPEND)
516 stderror(ERR_SYSTEM, tmp, strerror(errno));
517 chkclob(tmp);
518 }
519 if ((fd = creat(tmp, 0666)) < 0)
520 stderror(ERR_SYSTEM, tmp, strerror(errno));
521 }
522 (void) dmove(fd, 1);
523 }
524 else if (flags & F_PIPEOUT) {
525 (void) close(1);
526 (void) dup(pipeout[1]);
527 }
528 else {
529 (void) close(1);
530 (void) dup(SHOUT);
531 (void) ioctl(1, FIONCLEX, NULL);
532 }
533
534 (void) close(2);
535 if (flags & F_STDERR) {
536 (void) dup(1);
537 }
538 else {
539 (void) dup(SHDIAG);
540 (void) ioctl(2, FIONCLEX, NULL);
541 }
542 didfds = 1;
543 }
544
545 void
mypipe(pv)546 mypipe(pv)
547 register int *pv;
548 {
549
550 if (pipe(pv) < 0)
551 goto oops;
552 pv[0] = dmove(pv[0], -1);
553 pv[1] = dmove(pv[1], -1);
554 if (pv[0] >= 0 && pv[1] >= 0)
555 return;
556 oops:
557 stderror(ERR_PIPE);
558 }
559
560 static void
chkclob(cp)561 chkclob(cp)
562 register char *cp;
563 {
564 struct stat stb;
565
566 if (stat(cp, &stb) < 0)
567 return;
568 if ((stb.st_mode & S_IFMT) == S_IFCHR)
569 return;
570 stderror(ERR_EXISTS, cp);
571 }
572