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 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 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 * 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 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 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 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