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