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