1 /*-
2 * Copyright (c) 1980, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)sem.c 8.3 (Berkeley) 04/29/95";
10 #endif /* not lint */
11
12 #include <sys/param.h>
13 #include <sys/ioctl.h>
14 #include <sys/stat.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #if __STDC__
21 # include <stdarg.h>
22 #else
23 # include <varargs.h>
24 #endif
25
26 #include "csh.h"
27 #include "proc.h"
28 #include "extern.h"
29
30 static void vffree __P((int));
31 static Char *splicepipe __P((struct command *t, Char *));
32 static void doio __P((struct command *t, int *, int *));
33 static void chkclob __P((char *));
34
35 void
execute(t,wanttty,pipein,pipeout)36 execute(t, wanttty, pipein, pipeout)
37 register struct command *t;
38 int wanttty, *pipein, *pipeout;
39 {
40 bool forked = 0;
41 struct biltins *bifunc;
42 int pid = 0;
43 int pv[2];
44 sigset_t sigset;
45
46 static sigset_t csigset;
47
48 static sigset_t ocsigset;
49 static int onosigchld = 0;
50 static int nosigchld = 0;
51
52 UNREGISTER(forked);
53 UNREGISTER(bifunc);
54 UNREGISTER(wanttty);
55
56 if (t == 0)
57 return;
58
59 if (t->t_dflg & F_AMPERSAND)
60 wanttty = 0;
61 switch (t->t_dtyp) {
62
63 case NODE_COMMAND:
64 if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
65 (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
66 if ((t->t_dflg & F_REPEAT) == 0)
67 Dfix(t); /* $ " ' \ */
68 if (t->t_dcom[0] == 0)
69 return;
70 /* fall into... */
71
72 case NODE_PAREN:
73 if (t->t_dflg & F_PIPEOUT)
74 mypipe(pipeout);
75 /*
76 * Must do << early so parent will know where input pointer should be.
77 * If noexec then this is all we do.
78 */
79 if (t->t_dflg & F_READ) {
80 (void) close(0);
81 heredoc(t->t_dlef);
82 if (noexec)
83 (void) close(0);
84 }
85
86 set(STRstatus, Strsave(STR0));
87
88 /*
89 * This mess is the necessary kludge to handle the prefix builtins:
90 * nice, nohup, time. These commands can also be used by themselves,
91 * and this is not handled here. This will also work when loops are
92 * parsed.
93 */
94 while (t->t_dtyp == NODE_COMMAND)
95 if (eq(t->t_dcom[0], STRnice))
96 if (t->t_dcom[1])
97 if (strchr("+-", t->t_dcom[1][0]))
98 if (t->t_dcom[2]) {
99 setname("nice");
100 t->t_nice =
101 getn(t->t_dcom[1]);
102 lshift(t->t_dcom, 2);
103 t->t_dflg |= F_NICE;
104 }
105 else
106 break;
107 else {
108 t->t_nice = 4;
109 lshift(t->t_dcom, 1);
110 t->t_dflg |= F_NICE;
111 }
112 else
113 break;
114 else if (eq(t->t_dcom[0], STRnohup))
115 if (t->t_dcom[1]) {
116 t->t_dflg |= F_NOHUP;
117 lshift(t->t_dcom, 1);
118 }
119 else
120 break;
121 else if (eq(t->t_dcom[0], STRtime))
122 if (t->t_dcom[1]) {
123 t->t_dflg |= F_TIME;
124 lshift(t->t_dcom, 1);
125 }
126 else
127 break;
128 else
129 break;
130
131 /* is it a command */
132 if (t->t_dtyp == NODE_COMMAND) {
133 /*
134 * Check if we have a builtin function and remember which one.
135 */
136 bifunc = isbfunc(t);
137 if (noexec) {
138 /*
139 * Continue for builtins that are part of the scripting language
140 */
141 if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin &&
142 bifunc->bfunct != doelse && bifunc->bfunct != doend &&
143 bifunc->bfunct != doforeach && bifunc->bfunct != dogoto &&
144 bifunc->bfunct != doif && bifunc->bfunct != dorepeat &&
145 bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch &&
146 bifunc->bfunct != dowhile && bifunc->bfunct != dozip)
147 break;
148 }
149 }
150 else { /* not a command */
151 bifunc = NULL;
152 if (noexec)
153 break;
154 }
155
156 /*
157 * We fork only if we are timed, or are not the end of a parenthesized
158 * list and not a simple builtin function. Simple meaning one that is
159 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
160 * fork in some of these cases.
161 */
162 /*
163 * Prevent forking cd, pushd, popd, chdir cause this will cause the
164 * shell not to change dir!
165 */
166 if (bifunc && (bifunc->bfunct == dochngd ||
167 bifunc->bfunct == dopushd ||
168 bifunc->bfunct == dopopd))
169 t->t_dflg &= ~(F_NICE);
170 if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
171 (!bifunc || t->t_dflg &
172 (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) ||
173 /*
174 * We have to fork for eval too.
175 */
176 (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 &&
177 bifunc->bfunct == doeval))
178 if (t->t_dtyp == NODE_PAREN ||
179 t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) {
180 forked++;
181 /*
182 * We need to block SIGCHLD here, so that if the process does
183 * not die before we can set the process group
184 */
185 if (wanttty >= 0 && !nosigchld) {
186 sigemptyset(&sigset);
187 sigaddset(&sigset, SIGCHLD);
188 sigprocmask(SIG_BLOCK, &sigset, &csigset);
189 nosigchld = 1;
190 }
191
192 pid = pfork(t, wanttty);
193 if (pid == 0 && nosigchld) {
194 sigprocmask(SIG_SETMASK, &csigset, NULL);
195 nosigchld = 0;
196 }
197 else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
198 backpid = pid;
199
200 }
201 else {
202 int ochild, osetintr, ohaderr, odidfds;
203 int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp;
204 sigset_t osigset;
205
206 /*
207 * Prepare for the vfork by saving everything that the child
208 * corrupts before it exec's. Note that in some signal
209 * implementations which keep the signal info in user space
210 * (e.g. Sun's) it will also be necessary to save and restore
211 * the current sigaction's for the signals the child touches
212 * before it exec's.
213 */
214 if (wanttty >= 0 && !nosigchld && !noexec) {
215 sigemptyset(&sigset);
216 sigaddset(&sigset, SIGCHLD);
217 sigprocmask(SIG_BLOCK, &sigset, &csigset);
218 nosigchld = 1;
219 }
220 sigemptyset(&sigset);
221 sigaddset(&sigset, SIGCHLD);
222 sigaddset(&sigset, SIGINT);
223 sigprocmask(SIG_BLOCK, &sigset, &osigset);
224 ochild = child;
225 osetintr = setintr;
226 ohaderr = haderr;
227 odidfds = didfds;
228 oSHIN = SHIN;
229 oSHOUT = SHOUT;
230 oSHERR = SHERR;
231 oOLDSTD = OLDSTD;
232 otpgrp = tpgrp;
233 ocsigset = csigset;
234 onosigchld = nosigchld;
235 Vsav = Vdp = 0;
236 Vexpath = 0;
237 Vt = 0;
238 pid = vfork();
239
240 if (pid < 0) {
241 sigprocmask(SIG_SETMASK, &osigset, NULL);
242 stderror(ERR_NOPROC);
243 }
244 forked++;
245 if (pid) { /* parent */
246 child = ochild;
247 setintr = osetintr;
248 haderr = ohaderr;
249 didfds = odidfds;
250 SHIN = oSHIN;
251 SHOUT = oSHOUT;
252 SHERR = oSHERR;
253 OLDSTD = oOLDSTD;
254 tpgrp = otpgrp;
255 csigset = ocsigset;
256 nosigchld = onosigchld;
257
258 xfree((ptr_t) Vsav);
259 Vsav = 0;
260 xfree((ptr_t) Vdp);
261 Vdp = 0;
262 xfree((ptr_t) Vexpath);
263 Vexpath = 0;
264 blkfree((Char **) Vt);
265 Vt = 0;
266 /* this is from pfork() */
267 palloc(pid, t);
268 sigprocmask(SIG_SETMASK, &osigset, NULL);
269 }
270 else { /* child */
271 /* this is from pfork() */
272 int pgrp;
273 bool ignint = 0;
274
275 if (nosigchld) {
276 sigprocmask(SIG_SETMASK, &csigset, NULL);
277 nosigchld = 0;
278 }
279
280 if (setintr)
281 ignint =
282 (tpgrp == -1 &&
283 (t->t_dflg & F_NOINTERRUPT))
284 || (gointr && eq(gointr, STRminus));
285 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
286 child++;
287 if (setintr) {
288 setintr = 0;
289 if (ignint) {
290 (void) signal(SIGINT, SIG_IGN);
291 (void) signal(SIGQUIT, SIG_IGN);
292 }
293 else {
294 (void) signal(SIGINT, vffree);
295 (void) signal(SIGQUIT, SIG_DFL);
296 }
297
298 if (wanttty >= 0) {
299 (void) signal(SIGTSTP, SIG_DFL);
300 (void) signal(SIGTTIN, SIG_DFL);
301 (void) signal(SIGTTOU, SIG_DFL);
302 }
303
304 (void) signal(SIGTERM, parterm);
305 }
306 else if (tpgrp == -1 &&
307 (t->t_dflg & F_NOINTERRUPT)) {
308 (void) signal(SIGINT, SIG_IGN);
309 (void) signal(SIGQUIT, SIG_IGN);
310 }
311
312 pgetty(wanttty, pgrp);
313 if (t->t_dflg & F_NOHUP)
314 (void) signal(SIGHUP, SIG_IGN);
315 if (t->t_dflg & F_NICE)
316 (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
317 }
318
319 }
320 if (pid != 0) {
321 /*
322 * It would be better if we could wait for the whole job when we
323 * knew the last process had been started. Pwait, in fact, does
324 * wait for the whole job anyway, but this test doesn't really
325 * express our intentions.
326 */
327 if (didfds == 0 && t->t_dflg & F_PIPEIN) {
328 (void) close(pipein[0]);
329 (void) close(pipein[1]);
330 }
331 if ((t->t_dflg & F_PIPEOUT) == 0) {
332 if (nosigchld) {
333 sigprocmask(SIG_SETMASK, &csigset, NULL);
334 nosigchld = 0;
335 }
336 if ((t->t_dflg & F_AMPERSAND) == 0)
337 pwait();
338 }
339 break;
340 }
341 doio(t, pipein, pipeout);
342 if (t->t_dflg & F_PIPEOUT) {
343 (void) close(pipeout[0]);
344 (void) close(pipeout[1]);
345 }
346 /*
347 * Perform a builtin function. If we are not forked, arrange for
348 * possible stopping
349 */
350 if (bifunc) {
351 func(t, bifunc);
352 if (forked)
353 exitstat();
354 break;
355 }
356 if (t->t_dtyp != NODE_PAREN) {
357 doexec(NULL, t);
358 /* NOTREACHED */
359 }
360 /*
361 * For () commands must put new 0,1,2 in FSH* and recurse
362 */
363 OLDSTD = dcopy(0, FOLDSTD);
364 SHOUT = dcopy(1, FSHOUT);
365 SHERR = dcopy(2, FSHERR);
366 (void) close(SHIN);
367 SHIN = -1;
368 didfds = 0;
369 wanttty = -1;
370 t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
371 execute(t->t_dspr, wanttty, NULL, NULL);
372 exitstat();
373
374 case NODE_PIPE:
375 t->t_dcar->t_dflg |= F_PIPEOUT |
376 (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
377 execute(t->t_dcar, wanttty, pipein, pv);
378 t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
379 (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
380 if (wanttty > 0)
381 wanttty = 0; /* got tty already */
382 execute(t->t_dcdr, wanttty, pv, pipeout);
383 break;
384
385 case NODE_LIST:
386 if (t->t_dcar) {
387 t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
388 execute(t->t_dcar, wanttty, NULL, NULL);
389 /*
390 * In strange case of A&B make a new job after A
391 */
392 if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
393 (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
394 pendjob();
395 }
396 if (t->t_dcdr) {
397 t->t_dcdr->t_dflg |= t->t_dflg &
398 (F_NOFORK | F_NOINTERRUPT);
399 execute(t->t_dcdr, wanttty, NULL, NULL);
400 }
401 break;
402
403 case NODE_OR:
404 case NODE_AND:
405 if (t->t_dcar) {
406 t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
407 execute(t->t_dcar, wanttty, NULL, NULL);
408 if ((getn(value(STRstatus)) == 0) !=
409 (t->t_dtyp == NODE_AND))
410 return;
411 }
412 if (t->t_dcdr) {
413 t->t_dcdr->t_dflg |= t->t_dflg &
414 (F_NOFORK | F_NOINTERRUPT);
415 execute(t->t_dcdr, wanttty, NULL, NULL);
416 }
417 break;
418 }
419 /*
420 * Fall through for all breaks from switch
421 *
422 * If there will be no more executions of this command, flush all file
423 * descriptors. Places that turn on the F_REPEAT bit are responsible for
424 * doing donefds after the last re-execution
425 */
426 if (didfds && !(t->t_dflg & F_REPEAT))
427 donefds();
428 }
429
430 static void
vffree(i)431 vffree(i)
432 int i;
433 {
434 register Char **v;
435
436 if ((v = gargv) != NULL) {
437 gargv = 0;
438 xfree((ptr_t) v);
439 }
440 if ((v = pargv) != NULL) {
441 pargv = 0;
442 xfree((ptr_t) v);
443 }
444 _exit(i);
445 }
446
447 /*
448 * Expand and glob the words after an i/o redirection.
449 * If more than one word is generated, then update the command vector.
450 *
451 * This is done differently in all the shells:
452 * 1. in the bourne shell and ksh globbing is not performed
453 * 2. Bash/csh say ambiguous
454 * 3. zsh does i/o to/from all the files
455 * 4. itcsh concatenates the words.
456 *
457 * I don't know what is best to do. I think that Ambiguous is better
458 * than restructuring the command vector, because the user can get
459 * unexpected results. In any case, the command vector restructuring
460 * code is present and the user can choose it by setting noambiguous
461 */
462 static Char *
splicepipe(t,cp)463 splicepipe(t, cp)
464 register struct command *t;
465 Char *cp; /* word after < or > */
466 {
467 Char *blk[2];
468
469 if (adrof(STRnoambiguous)) {
470 Char **pv;
471
472 blk[0] = Dfix1(cp); /* expand $ */
473 blk[1] = NULL;
474
475 gflag = 0, tglob(blk);
476 if (gflag) {
477 pv = globall(blk);
478 if (pv == NULL) {
479 setname(vis_str(blk[0]));
480 xfree((ptr_t) blk[0]);
481 stderror(ERR_NAME | ERR_NOMATCH);
482 }
483 gargv = NULL;
484 if (pv[1] != NULL) { /* we need to fix the command vector */
485 Char **av = blkspl(t->t_dcom, &pv[1]);
486 xfree((ptr_t) t->t_dcom);
487 t->t_dcom = av;
488 }
489 xfree((ptr_t) blk[0]);
490 blk[0] = pv[0];
491 xfree((ptr_t) pv);
492 }
493 }
494 else {
495 blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR);
496 xfree((ptr_t) blk[1]);
497 }
498 return(blk[0]);
499 }
500
501 /*
502 * Perform io redirection.
503 * We may or maynot be forked here.
504 */
505 static void
doio(t,pipein,pipeout)506 doio(t, pipein, pipeout)
507 register struct command *t;
508 int *pipein, *pipeout;
509 {
510 register int fd;
511 register Char *cp;
512 register int flags = t->t_dflg;
513
514 if (didfds || (flags & F_REPEAT))
515 return;
516 if ((flags & F_READ) == 0) {/* F_READ already done */
517 if (t->t_dlef) {
518 char tmp[MAXPATHLEN+1];
519
520 /*
521 * so < /dev/std{in,out,err} work
522 */
523 (void) dcopy(SHIN, 0);
524 (void) dcopy(SHOUT, 1);
525 (void) dcopy(SHERR, 2);
526 cp = splicepipe(t, t->t_dlef);
527 (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
528 tmp[MAXPATHLEN] = '\0';
529 xfree((ptr_t) cp);
530 if ((fd = open(tmp, O_RDONLY)) < 0)
531 stderror(ERR_SYSTEM, tmp, strerror(errno));
532 (void) dmove(fd, 0);
533 }
534 else if (flags & F_PIPEIN) {
535 (void) close(0);
536 (void) dup(pipein[0]);
537 (void) close(pipein[0]);
538 (void) close(pipein[1]);
539 }
540 else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
541 (void) close(0);
542 (void) open(_PATH_DEVNULL, O_RDONLY);
543 }
544 else {
545 (void) close(0);
546 (void) dup(OLDSTD);
547 (void) ioctl(0, FIONCLEX, NULL);
548 }
549 }
550 if (t->t_drit) {
551 char tmp[MAXPATHLEN+1];
552
553 cp = splicepipe(t, t->t_drit);
554 (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
555 tmp[MAXPATHLEN] = '\0';
556 xfree((ptr_t) cp);
557 /*
558 * so > /dev/std{out,err} work
559 */
560 (void) dcopy(SHOUT, 1);
561 (void) dcopy(SHERR, 2);
562 if ((flags & F_APPEND) &&
563 #ifdef O_APPEND
564 (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
565 #else
566 (fd = open(tmp, O_WRONLY)) >= 0)
567 (void) lseek(1, (off_t) 0, L_XTND);
568 #endif
569 else {
570 if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
571 if (flags & F_APPEND)
572 stderror(ERR_SYSTEM, tmp, strerror(errno));
573 chkclob(tmp);
574 }
575 if ((fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
576 stderror(ERR_SYSTEM, tmp, strerror(errno));
577 }
578 (void) dmove(fd, 1);
579 }
580 else if (flags & F_PIPEOUT) {
581 (void) close(1);
582 (void) dup(pipeout[1]);
583 }
584 else {
585 (void) close(1);
586 (void) dup(SHOUT);
587 (void) ioctl(1, FIONCLEX, NULL);
588 }
589
590 (void) close(2);
591 if (flags & F_STDERR) {
592 (void) dup(1);
593 }
594 else {
595 (void) dup(SHERR);
596 (void) ioctl(2, FIONCLEX, NULL);
597 }
598 didfds = 1;
599 }
600
601 void
mypipe(pv)602 mypipe(pv)
603 register int *pv;
604 {
605
606 if (pipe(pv) < 0)
607 goto oops;
608 pv[0] = dmove(pv[0], -1);
609 pv[1] = dmove(pv[1], -1);
610 if (pv[0] >= 0 && pv[1] >= 0)
611 return;
612 oops:
613 stderror(ERR_PIPE);
614 }
615
616 static void
chkclob(cp)617 chkclob(cp)
618 register char *cp;
619 {
620 struct stat stb;
621
622 if (stat(cp, &stb) < 0)
623 return;
624 if (S_ISCHR(stb.st_mode))
625 return;
626 stderror(ERR_EXISTS, cp);
627 }
628