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