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