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