1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.sem.c,v 3.90 2015/10/31 18:54:42 christos Exp $ */ 2 /* 3 * sh.sem.c: I/O redirections and job forking. A touchy issue! 4 * Most stuff with builtins is incorrect 5 */ 6 /*- 7 * Copyright (c) 1980, 1991 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 #include "sh.h" 35 36 RCSID("$tcsh: sh.sem.c,v 3.90 2015/10/31 18:54:42 christos Exp $") 37 38 #include "tc.h" 39 #include "tw.h" 40 #ifdef WINNT_NATIVE 41 #include "nt.const.h" 42 #endif /*WINNT_NATIVE*/ 43 44 #ifdef CLOSE_ON_EXEC 45 # ifndef SUNOS4 46 # ifndef CLEX_DUPS 47 # define CLEX_DUPS 48 # endif /* CLEX_DUPS */ 49 # endif /* !SUNOS4 */ 50 #endif /* CLOSE_ON_EXEC */ 51 52 #if defined(__sparc__) || defined(sparc) 53 # if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(__linux__) && !defined(__GNU__) && !defined(__GLIBC__) 54 # include <vfork.h> 55 # endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !glibc */ 56 #endif /* __sparc__ || sparc */ 57 58 #ifdef VFORK 59 static void vffree (int); 60 #endif 61 static Char *splicepipe (struct command *, Char *); 62 static void doio (struct command *, int *, int *); 63 static void chkclob (const char *); 64 65 /* 66 * C shell 67 */ 68 69 /* 70 * For SVR4, there are problems with pipelines having the first process as 71 * the group leader. The problem occurs when the first process exits before 72 * the others have a chance to setpgid(). This is because in SVR4 you can't 73 * have a zombie as a group leader. The solution I have used is to reverse 74 * the order in which pipelines are started, making the last process the 75 * group leader. (Note I am not using 'pipeline' in the generic sense -- I 76 * mean processes connected by '|'.) I don't know yet if this causes other 77 * problems. 78 * 79 * All the changes for this are in execute(), and are enclosed in 80 * '#ifdef BACKPIPE' 81 * 82 * David Dawes (dawes@physics.su.oz.au) Oct 1991 83 */ 84 85 /*VARARGS 1*/ 86 void 87 execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, 88 int do_glob) 89 { 90 int forked = 0; 91 const struct biltins * volatile bifunc; 92 pid_t pid = 0; 93 int pv[2]; 94 sigset_t set; 95 static sigset_t csigset; 96 #ifdef VFORK 97 static int onosigchld = 0; 98 #endif /* VFORK */ 99 static int nosigchld = 0; 100 101 (void) &wanttty; 102 (void) &forked; 103 (void) &bifunc; 104 105 if (t == 0) 106 return; 107 108 #ifdef WINNT_NATIVE 109 { 110 if ((varval(STRNTslowexec) == STRNULL) && 111 !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds && 112 (intty || intact) && (t->t_dtyp == NODE_COMMAND) && 113 !isbfunc(t)) { 114 if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 115 (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 116 Dfix(t); 117 if (nt_try_fast_exec(t) == 0) 118 return; 119 } 120 } 121 #endif /* WINNT_NATIVE */ 122 123 /* 124 * Ed hutchins@sgi.com & Dominic dbg@sgi.com 125 * Sat Feb 25 03:13:11 PST 1995 126 * try implicit cd if we have a 1 word command 127 */ 128 if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] && 129 t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) { 130 Char *sCName; 131 struct stat stbuf; 132 char *pathname; 133 134 sCName = dollar(t->t_dcom[0]); 135 if (sCName != NULL && sCName[0] == '~') { 136 struct Strbuf buf = Strbuf_INIT; 137 const Char *name_end; 138 139 for (name_end = sCName + 1; *name_end != '\0' && *name_end != '/'; 140 name_end++) 141 continue; 142 if (name_end != sCName + 1) { 143 Char *name, *home; 144 145 name = Strnsave(sCName + 1, name_end - (sCName + 1)); 146 home = gethdir(name); 147 if (home != NULL) { 148 Strbuf_append(&buf, home); 149 xfree(home); 150 } else 151 Strbuf_append(&buf, name); 152 xfree(name); 153 } else 154 Strbuf_append(&buf, varval(STRhome)); 155 Strbuf_append(&buf, name_end); 156 xfree(sCName); 157 sCName = Strbuf_finish(&buf); 158 } 159 160 pathname = short2str(sCName); 161 xfree(sCName); 162 /* if this is a dir, tack a "cd" on as the first arg */ 163 if (pathname != NULL && 164 ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode)) 165 #ifdef WINNT_NATIVE 166 || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0') 167 #endif /* WINNT_NATIVE */ 168 )) { 169 Char *vCD[2]; 170 Char **ot_dcom = t->t_dcom; 171 172 vCD[0] = Strsave(STRcd); 173 vCD[1] = NULL; 174 t->t_dcom = blkspl(vCD, ot_dcom); 175 xfree(ot_dcom); 176 if (implicit_cd > 1) { 177 blkpr(t->t_dcom); 178 xputchar( '\n' ); 179 } 180 } 181 } 182 183 /* 184 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 185 * Don't check for wantty > 0... 186 */ 187 if (t->t_dflg & F_AMPERSAND) 188 wanttty = 0; 189 switch (t->t_dtyp) { 190 191 case NODE_COMMAND: 192 if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) 193 memmove(t->t_dcom[0], t->t_dcom[0] + 1, 194 (Strlen(t->t_dcom[0] + 1) + 1) * sizeof (*t->t_dcom[0])); 195 if ((t->t_dflg & F_REPEAT) == 0) 196 Dfix(t); /* $ " ' \ */ 197 if (t->t_dcom[0] == 0) { 198 return; 199 } 200 /*FALLTHROUGH*/ 201 202 case NODE_PAREN: 203 #ifdef BACKPIPE 204 if (t->t_dflg & F_PIPEIN) 205 mypipe(pipein); 206 #else /* !BACKPIPE */ 207 if (t->t_dflg & F_PIPEOUT) 208 mypipe(pipeout); 209 #endif /* BACKPIPE */ 210 /* 211 * Must do << early so parent will know where input pointer should be. 212 * If noexec then this is all we do. 213 */ 214 if (t->t_dflg & F_READ) { 215 int old_pintr_disabled; 216 217 xclose(0); 218 if (setintr) 219 pintr_push_enable(&old_pintr_disabled); 220 heredoc(t->t_dlef); 221 if (setintr) 222 cleanup_until(&old_pintr_disabled); 223 if (noexec) 224 xclose(0); 225 } 226 227 setcopy(STRstatus, STR0, VAR_READWRITE); 228 229 /* 230 * This mess is the necessary kludge to handle the prefix builtins: 231 * nice, nohup, time. These commands can also be used by themselves, 232 * and this is not handled here. This will also work when loops are 233 * parsed. 234 */ 235 while (t->t_dtyp == NODE_COMMAND) 236 if (eq(t->t_dcom[0], STRnice)) { 237 if (t->t_dcom[1]) { 238 if (strchr("+-", t->t_dcom[1][0])) { 239 if (t->t_dcom[2]) { 240 setname("nice"); 241 t->t_nice = (unsigned char)getn(t->t_dcom[1]); 242 lshift(t->t_dcom, 2); 243 t->t_dflg |= F_NICE; 244 } 245 else 246 break; 247 } 248 else { 249 t->t_nice = 4; 250 lshift(t->t_dcom, 1); 251 t->t_dflg |= F_NICE; 252 } 253 } 254 else 255 break; 256 } 257 else if (eq(t->t_dcom[0], STRnohup)) { 258 if (t->t_dcom[1]) { 259 t->t_dflg |= F_NOHUP; 260 lshift(t->t_dcom, 1); 261 } 262 else 263 break; 264 } 265 else if (eq(t->t_dcom[0], STRhup)) { 266 if (t->t_dcom[1]) { 267 t->t_dflg |= F_HUP; 268 lshift(t->t_dcom, 1); 269 } 270 else 271 break; 272 } 273 else if (eq(t->t_dcom[0], STRtime)) { 274 if (t->t_dcom[1]) { 275 t->t_dflg |= F_TIME; 276 lshift(t->t_dcom, 1); 277 } 278 else 279 break; 280 } 281 #ifdef F_VER 282 else if (eq(t->t_dcom[0], STRver)) 283 if (t->t_dcom[1] && t->t_dcom[2]) { 284 setname("ver"); 285 t->t_systype = getv(t->t_dcom[1]); 286 lshift(t->t_dcom, 2); 287 t->t_dflg |= F_VER; 288 } 289 else 290 break; 291 #endif /* F_VER */ 292 else 293 break; 294 295 /* is it a command */ 296 if (t->t_dtyp == NODE_COMMAND) { 297 /* 298 * Check if we have a builtin function and remember which one. 299 */ 300 bifunc = isbfunc(t); 301 if (noexec) { 302 /* 303 * Continue for builtins that are part of the scripting language 304 */ 305 if (bifunc == NULL) 306 break; 307 if (bifunc->bfunct != (bfunc_t)dobreak && 308 bifunc->bfunct != (bfunc_t)docontin && 309 bifunc->bfunct != (bfunc_t)doelse && 310 bifunc->bfunct != (bfunc_t)doend && 311 bifunc->bfunct != (bfunc_t)doforeach&& 312 bifunc->bfunct != (bfunc_t)dogoto && 313 bifunc->bfunct != (bfunc_t)doif && 314 bifunc->bfunct != (bfunc_t)dorepeat && 315 bifunc->bfunct != (bfunc_t)doswbrk && 316 bifunc->bfunct != (bfunc_t)doswitch && 317 bifunc->bfunct != (bfunc_t)dowhile && 318 bifunc->bfunct != (bfunc_t)dozip) 319 break; 320 } 321 } 322 else { /* not a command */ 323 bifunc = NULL; 324 if (noexec) 325 break; 326 } 327 328 /* 329 * GrP Executing a command - run jobcmd hook 330 * Don't run for builtins 331 * Don't run if we're not in a tty 332 * Don't run if we're not really executing 333 */ 334 /* 335 * CR - Charles Ross Aug 2005 336 * added "isoutatty". 337 * The new behavior is that the jobcmd won't be executed 338 * if stdout (SHOUT) isnt attached to a tty.. IE when 339 * redirecting, or using backquotes etc.. 340 */ 341 if (t->t_dtyp == NODE_COMMAND && !bifunc && !noexec && intty && isoutatty) { 342 Char *cmd = unparse(t); 343 344 cleanup_push(cmd, xfree); 345 job_cmd(cmd); 346 cleanup_until(cmd); 347 } 348 349 /* 350 * We fork only if we are timed, or are not the end of a parenthesized 351 * list and not a simple builtin function. Simple meaning one that is 352 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not 353 * fork in some of these cases. 354 */ 355 #ifdef BACKPIPE 356 /* 357 * Can't have NOFORK for the tail of a pipe - because it is not the 358 * last command spawned (even if it is at the end of a parenthesised 359 * list). 360 */ 361 if (t->t_dflg & F_PIPEIN) 362 t->t_dflg &= ~(F_NOFORK); 363 #else 364 /* 365 * "command | builtin" may cause major misbehaviour as noted in 366 * in the BUGS file entry 367 * Subject: Redirected input to built-in functions misbehaves badly 368 * forking when the builtin is the end of the pipe corrects the 369 * problem. 370 */ 371 if (bifunc && (t->t_dflg & F_PIPEIN)) 372 t->t_dflg &= ~(F_NOFORK); 373 #endif /* BACKPIPE */ 374 /* 375 * Prevent forking cd, pushd, popd, chdir cause this will cause the 376 * shell not to change dir! (XXX: but only for nice?) 377 */ 378 if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd || 379 bifunc->bfunct == (bfunc_t)dopushd || 380 bifunc->bfunct == (bfunc_t)dopopd)) 381 t->t_dflg &= ~(F_NICE); 382 383 if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && 384 (!bifunc || t->t_dflg & 385 (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) || 386 /* 387 * We have to fork for eval too. 388 */ 389 (bifunc && (t->t_dflg & F_PIPEIN) != 0 && 390 bifunc->bfunct == (bfunc_t)doeval)) { 391 #ifdef VFORK 392 if (t->t_dtyp == NODE_PAREN || 393 t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) 394 #endif /* VFORK */ 395 { 396 forked++; 397 /* 398 * We need to block SIGCHLD here, so that if the process does 399 * not die before we can set the process group 400 */ 401 if (wanttty >= 0 && !nosigchld) { 402 sigemptyset(&set); 403 sigaddset(&set, SIGCHLD); 404 (void)sigprocmask(SIG_BLOCK, &set, &csigset); 405 406 nosigchld = 1; 407 } 408 409 pid = pfork(t, wanttty); 410 if (pid == 0 && nosigchld) { 411 sigprocmask(SIG_SETMASK, &csigset, NULL); 412 nosigchld = 0; 413 } 414 else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) 415 backpid = pid; 416 } 417 418 #ifdef VFORK 419 else { 420 int ochild, osetintr, ohaderr, odidfds; 421 int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; 422 int oisoutatty, oisdiagatty; 423 sigset_t oset, ocsigset; 424 # ifndef CLOSE_ON_EXEC 425 int odidcch; 426 # endif /* !CLOSE_ON_EXEC */ 427 428 /* 429 * Prepare for the vfork by saving everything that the child 430 * corrupts before it exec's. Note that in some signal 431 * implementations which keep the signal info in user space 432 * (e.g. Sun's) it will also be necessary to save and restore 433 * the current sigvec's for the signals the child touches 434 * before it exec's. 435 */ 436 437 /* 438 * Sooooo true... If this is a Sun, save the sigvec's. (Skip 439 * Gilbrech - 11/22/87) 440 */ 441 # ifdef SAVESIGVEC 442 struct sigaction savesv[NSIGSAVED]; 443 sigset_t savesm; 444 445 # endif /* SAVESIGVEC */ 446 if (wanttty >= 0 && !nosigchld && !noexec) { 447 sigemptyset(&set); 448 sigaddset(&set, SIGCHLD); 449 (void)sigprocmask(SIG_BLOCK, &set, &csigset); 450 nosigchld = 1; 451 } 452 sigemptyset(&set); 453 sigaddset(&set, SIGCHLD); 454 sigaddset(&set, SIGINT); 455 (void)sigprocmask(SIG_BLOCK, &set, &oset); 456 ochild = child; 457 osetintr = setintr; 458 ohaderr = haderr; 459 odidfds = didfds; 460 # ifndef CLOSE_ON_EXEC 461 odidcch = didcch; 462 # endif /* !CLOSE_ON_EXEC */ 463 oSHIN = SHIN; 464 oSHOUT = SHOUT; 465 oSHDIAG = SHDIAG; 466 oOLDSTD = OLDSTD; 467 otpgrp = tpgrp; 468 oisoutatty = isoutatty; 469 oisdiagatty = isdiagatty; 470 ocsigset = csigset; 471 onosigchld = nosigchld; 472 Vsav = Vdp = 0; 473 Vexpath = 0; 474 Vt = 0; 475 # ifdef SAVESIGVEC 476 savesigvec(savesv, savesm); 477 # endif /* SAVESIGVEC */ 478 if (use_fork) 479 pid = fork(); 480 else 481 pid = vfork(); 482 483 if (pid < 0) { 484 # ifdef SAVESIGVEC 485 restoresigvec(savesv, savesm); 486 # endif /* SAVESIGVEC */ 487 sigprocmask(SIG_SETMASK, &oset, NULL); 488 stderror(ERR_NOPROC); 489 } 490 forked++; 491 if (pid) { /* parent */ 492 # ifdef SAVESIGVEC 493 restoresigvec(savesv, savesm); 494 # endif /* SAVESIGVEC */ 495 child = ochild; 496 setintr = osetintr; 497 haderr = ohaderr; 498 didfds = odidfds; 499 SHIN = oSHIN; 500 # ifndef CLOSE_ON_EXEC 501 didcch = odidcch; 502 # endif /* !CLOSE_ON_EXEC */ 503 SHOUT = oSHOUT; 504 SHDIAG = oSHDIAG; 505 OLDSTD = oOLDSTD; 506 tpgrp = otpgrp; 507 isoutatty = oisoutatty; 508 isdiagatty = oisdiagatty; 509 csigset = ocsigset; 510 nosigchld = onosigchld; 511 512 xfree(Vsav); 513 Vsav = 0; 514 xfree(Vdp); 515 Vdp = 0; 516 xfree(Vexpath); 517 Vexpath = 0; 518 blk_cleanup(Vt); 519 Vt = 0; 520 /* this is from pfork() */ 521 palloc(pid, t); 522 sigprocmask(SIG_SETMASK, &oset, NULL); 523 } 524 else { /* child */ 525 /* this is from pfork() */ 526 pid_t pgrp; 527 int ignint = 0; 528 if (nosigchld) { 529 sigprocmask(SIG_SETMASK, &csigset, NULL); 530 nosigchld = 0; 531 } 532 533 if (setintr) 534 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 535 || (gointr && eq(gointr, STRminus)); 536 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 537 child++; 538 if (setintr) { 539 setintr = 0; 540 /* 541 * casts made right for SunOS 4.0 by Douglas C. Schmidt 542 * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU> 543 * (thanks! -- PWP) 544 * 545 * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET> 546 * (thanks again) 547 */ 548 if (ignint) { 549 (void) signal(SIGINT, SIG_IGN); 550 (void) signal(SIGQUIT, SIG_IGN); 551 } 552 else { 553 (void) signal(SIGINT, vffree); 554 (void) signal(SIGQUIT, SIG_DFL); 555 } 556 # ifdef BSDJOBS 557 if (wanttty >= 0) { 558 (void) signal(SIGTSTP, SIG_DFL); 559 (void) signal(SIGTTIN, SIG_DFL); 560 (void) signal(SIGTTOU, SIG_DFL); 561 } 562 # endif /* BSDJOBS */ 563 564 sigaction(SIGTERM, &parterm, NULL); 565 } 566 else if (tpgrp == -1 && 567 (t->t_dflg & F_NOINTERRUPT)) { 568 (void) signal(SIGINT, SIG_IGN); 569 (void) signal(SIGQUIT, SIG_IGN); 570 } 571 572 pgetty(wanttty, pgrp); 573 574 if (t->t_dflg & F_NOHUP) 575 (void) signal(SIGHUP, SIG_IGN); 576 if (t->t_dflg & F_HUP) 577 (void) signal(SIGHUP, SIG_DFL); 578 if (t->t_dflg & F_NICE) { 579 int nval = SIGN_EXTEND_CHAR(t->t_nice); 580 # if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) 581 if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno) 582 stderror(ERR_SYSTEM, "setpriority", 583 strerror(errno)); 584 # else /* !HAVE_SETPRIORITY || !PRIO_PROCESS */ 585 (void) nice(nval); 586 # endif /* HAVE_SETPRIORITY && PRIO_PROCESS */ 587 } 588 # ifdef F_VER 589 if (t->t_dflg & F_VER) { 590 tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 591 dohash(NULL, NULL); 592 } 593 # endif /* F_VER */ 594 } 595 596 } 597 #endif /* VFORK */ 598 } 599 if (pid != 0) { 600 /* 601 * It would be better if we could wait for the whole job when we 602 * knew the last process had been started. Pwait, in fact, does 603 * wait for the whole job anyway, but this test doesn't really 604 * express our intentions. 605 */ 606 #ifdef BACKPIPE 607 if (didfds == 0 && t->t_dflg & F_PIPEOUT) { 608 xclose(pipeout[0]); 609 xclose(pipeout[1]); 610 } 611 if ((t->t_dflg & F_PIPEIN) != 0) 612 break; 613 #else /* !BACKPIPE */ 614 if (didfds == 0 && t->t_dflg & F_PIPEIN) { 615 xclose(pipein[0]); 616 xclose(pipein[1]); 617 } 618 if ((t->t_dflg & F_PIPEOUT) != 0) 619 break; 620 #endif /* BACKPIPE */ 621 622 if (nosigchld) { 623 sigprocmask(SIG_SETMASK, &csigset, NULL); 624 nosigchld = 0; 625 } 626 if ((t->t_dflg & F_AMPERSAND) == 0) 627 pwait(); 628 break; 629 } 630 631 doio(t, pipein, pipeout); 632 #ifdef BACKPIPE 633 if (t->t_dflg & F_PIPEIN) { 634 xclose(pipein[0]); 635 xclose(pipein[1]); 636 } 637 #else /* !BACKPIPE */ 638 if (t->t_dflg & F_PIPEOUT) { 639 xclose(pipeout[0]); 640 xclose(pipeout[1]); 641 } 642 #endif /* BACKPIPE */ 643 /* 644 * Perform a builtin function. If we are not forked, arrange for 645 * possible stopping 646 */ 647 if (bifunc) { 648 if (forked) { 649 func(t, bifunc); 650 exitstat(); 651 } else { 652 jmp_buf_t oldexit; 653 int ohaderr = haderr; 654 655 getexit(oldexit); 656 if (setexit() == 0) 657 func(t, bifunc); 658 resexit(oldexit); 659 haderr = ohaderr; 660 661 if (adrof(STRprintexitvalue)) { 662 int rv = getn(varval(STRstatus)); 663 if (rv != 0) 664 xprintf(CGETS(17, 2, "Exit %d\n"), rv); 665 } 666 } 667 break; 668 } 669 if (t->t_dtyp != NODE_PAREN) { 670 doexec(t, do_glob); 671 /* NOTREACHED */ 672 } 673 /* 674 * For () commands must put new 0,1,2 in FSH* and recurse 675 */ 676 if ((OLDSTD = dcopy(0, FOLDSTD)) >= 0) 677 (void)close_on_exec(OLDSTD, 1); 678 if ((SHOUT = dcopy(1, FSHOUT)) >= 0) { 679 (void)close_on_exec(SHOUT, 1); 680 isoutatty = isatty(SHOUT); 681 } 682 if ((SHDIAG = dcopy(2, FSHDIAG)) >= 0) { 683 (void)close_on_exec(SHDIAG, 1); 684 isdiagatty = isatty(SHDIAG); 685 } 686 xclose(SHIN); 687 SHIN = -1; 688 #ifndef CLOSE_ON_EXEC 689 didcch = 0; 690 #else 691 (void) close_on_exec(FSHOUT, 1); 692 (void) close_on_exec(FSHDIAG, 1); 693 (void) close_on_exec(FOLDSTD, 1); 694 #endif /* !CLOSE_ON_EXEC */ 695 didfds = 0; 696 wanttty = -1; 697 t->t_dspr->t_dflg |= t->t_dflg & (F_NOINTERRUPT | F_BACKQ); 698 execute(t->t_dspr, wanttty, NULL, NULL, do_glob); 699 exitstat(); 700 701 case NODE_PIPE: 702 #ifdef BACKPIPE 703 t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 704 (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT | F_BACKQ)); 705 execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); 706 t->t_dcar->t_dflg |= F_PIPEOUT | (t->t_dflg & 707 (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT | F_BACKQ)); 708 execute(t->t_dcar, wanttty, pipein, pv, do_glob); 709 #else /* !BACKPIPE */ 710 t->t_dcar->t_dflg |= F_PIPEOUT | (t->t_dflg & 711 (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT | F_BACKQ)); 712 execute(t->t_dcar, wanttty, pipein, pv, do_glob); 713 t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & 714 (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT | F_BACKQ)); 715 execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); 716 #endif /* BACKPIPE */ 717 break; 718 719 case NODE_LIST: 720 if (t->t_dcar) { 721 t->t_dcar->t_dflg |= t->t_dflg & (F_NOINTERRUPT | F_BACKQ); 722 execute(t->t_dcar, wanttty, NULL, NULL, do_glob); 723 /* 724 * In strange case of A&B make a new job after A 725 */ 726 if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && 727 (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) 728 pendjob(); 729 } 730 if (t->t_dcdr) { 731 t->t_dcdr->t_dflg |= t->t_dflg & 732 (F_NOFORK | F_NOINTERRUPT | F_BACKQ); 733 execute(t->t_dcdr, wanttty, NULL, NULL, do_glob); 734 } 735 break; 736 737 case NODE_OR: 738 case NODE_AND: 739 if (t->t_dcar) { 740 t->t_dcar->t_dflg |= t->t_dflg & (F_NOINTERRUPT | F_BACKQ); 741 execute(t->t_dcar, wanttty, NULL, NULL, do_glob); 742 if ((getn(varval(STRstatus)) == 0) != 743 (t->t_dtyp == NODE_AND)) { 744 return; 745 } 746 } 747 if (t->t_dcdr) { 748 t->t_dcdr->t_dflg |= t->t_dflg & 749 (F_NOFORK | F_NOINTERRUPT | F_BACKQ); 750 execute(t->t_dcdr, wanttty, NULL, NULL, do_glob); 751 } 752 break; 753 754 default: 755 break; 756 } 757 /* 758 * Fall through for all breaks from switch 759 * 760 * If there will be no more executions of this command, flush all file 761 * descriptors. Places that turn on the F_REPEAT bit are responsible for 762 * doing donefds after the last re-execution 763 */ 764 if (didfds && !(t->t_dflg & F_REPEAT)) 765 donefds(); 766 } 767 768 #ifdef VFORK 769 static void 770 /*ARGSUSED*/ 771 vffree(int snum) 772 { 773 USE(snum); 774 775 _exit(1); 776 } 777 #endif /* VFORK */ 778 779 /* 780 * Expand and glob the words after an i/o redirection. 781 * If more than one word is generated, then update the command vector. 782 * 783 * This is done differently in all the shells: 784 * 1. in the bourne shell and ksh globbing is not performed 785 * 2. Bash/csh say ambiguous 786 * 3. zsh does i/o to/from all the files 787 * 4. itcsh concatenates the words. 788 * 789 * I don't know what is best to do. I think that Ambiguous is better 790 * than restructuring the command vector, because the user can get 791 * unexpected results. In any case, the command vector restructuring 792 * code is present and the user can choose it by setting noambiguous 793 */ 794 static Char * 795 splicepipe(struct command *t, Char *cp) 796 { 797 Char *blk[2]; 798 799 if (adrof(STRnoambiguous)) { 800 Char **pv; 801 int gflag; 802 803 blk[0] = Dfix1(cp); /* expand $ */ 804 blk[1] = NULL; 805 806 gflag = tglob(blk); 807 if (gflag) { 808 pv = globall(blk, gflag); 809 if (pv == NULL) { 810 setname(short2str(blk[0])); 811 xfree(blk[0]); 812 stderror(ERR_NAME | ERR_NOMATCH); 813 } 814 if (pv[1] != NULL) { /* we need to fix the command vector */ 815 Char **av = blkspl(t->t_dcom, &pv[1]); 816 xfree(t->t_dcom); 817 t->t_dcom = av; 818 } 819 xfree(blk[0]); 820 blk[0] = pv[0]; 821 xfree(pv); 822 } 823 } 824 else { 825 Char *buf; 826 827 buf = Dfix1(cp); 828 cleanup_push(buf, xfree); 829 blk[0] = globone(buf, G_ERROR); 830 cleanup_until(buf); 831 } 832 return(blk[0]); 833 } 834 835 /* 836 * Perform io redirection. 837 * We may or maynot be forked here. 838 */ 839 static void 840 doio(struct command *t, int *pipein, int *pipeout) 841 { 842 int fd; 843 Char *cp; 844 unsigned long flags = t->t_dflg; 845 846 if (didfds || (flags & F_REPEAT)) 847 return; 848 if ((flags & F_READ) == 0) {/* F_READ already done */ 849 if (t->t_dlef) { 850 char *tmp; 851 852 /* 853 * so < /dev/std{in,out,err} work 854 */ 855 (void) dcopy(SHIN, 0); 856 (void) dcopy(SHOUT, 1); 857 (void) dcopy(SHDIAG, 2); 858 cp = splicepipe(t, t->t_dlef); 859 tmp = strsave(short2str(cp)); 860 xfree(cp); 861 cleanup_push(tmp, xfree); 862 if ((fd = xopen(tmp, O_RDONLY|O_LARGEFILE)) < 0) 863 stderror(ERR_SYSTEM, tmp, strerror(errno)); 864 cleanup_until(tmp); 865 /* allow input files larger than 2Gb */ 866 #ifndef WINNT_NATIVE 867 (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); 868 #endif /*!WINNT_NATIVE*/ 869 (void) dmove(fd, 0); 870 } 871 else if (flags & F_PIPEIN) { 872 xclose(0); 873 TCSH_IGNORE(dup(pipein[0])); 874 xclose(pipein[0]); 875 xclose(pipein[1]); 876 } 877 else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { 878 xclose(0); 879 (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 880 } 881 else { 882 xclose(0); 883 TCSH_IGNORE(dup(OLDSTD)); 884 #if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 885 /* 886 * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved 887 * across dup()s, so we have to UNSET it here or else we get a 888 * command with NO stdin, stdout, or stderr at all (a bad thing 889 * indeed) 890 */ 891 (void) close_on_exec(0, 0); 892 #endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 893 } 894 } 895 if (t->t_drit) { 896 char *tmp; 897 898 cp = splicepipe(t, t->t_drit); 899 tmp = strsave(short2str(cp)); 900 xfree(cp); 901 cleanup_push(tmp, xfree); 902 /* 903 * so > /dev/std{out,err} work 904 */ 905 (void) dcopy(SHOUT, 1); 906 (void) dcopy(SHDIAG, 2); 907 if ((flags & F_APPEND) != 0) { 908 #ifdef O_APPEND 909 fd = xopen(tmp, O_WRONLY|O_APPEND|O_LARGEFILE); 910 #else /* !O_APPEND */ 911 fd = xopen(tmp, O_WRONLY|O_LARGEFILE); 912 (void) lseek(fd, (off_t) 0, L_XTND); 913 #endif /* O_APPEND */ 914 } 915 else 916 fd = 0; 917 if ((flags & F_APPEND) == 0 || fd == -1) { 918 if (!(flags & F_OVERWRITE) && no_clobber) { 919 if (flags & F_APPEND) 920 stderror(ERR_SYSTEM, tmp, strerror(errno)); 921 chkclob(tmp); 922 } 923 if ((fd = xcreat(tmp, 0666)) < 0) 924 stderror(ERR_SYSTEM, tmp, strerror(errno)); 925 /* allow input files larger than 2Gb */ 926 #ifndef WINNT_NATIVE 927 (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_LARGEFILE); 928 #endif /*!WINNT_NATIVE*/ 929 } 930 cleanup_until(tmp); 931 (void) dmove(fd, 1); 932 is1atty = isatty(1); 933 } 934 else if (flags & F_PIPEOUT) { 935 xclose(1); 936 TCSH_IGNORE(dup(pipeout[1])); 937 is1atty = 0; 938 } 939 else { 940 xclose(1); 941 TCSH_IGNORE(dup(SHOUT)); 942 is1atty = isoutatty; 943 # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 944 (void) close_on_exec(1, 0); 945 # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 946 } 947 948 xclose(2); 949 if (flags & F_STDERR) { 950 TCSH_IGNORE(dup(1)); 951 is2atty = is1atty; 952 } 953 else { 954 TCSH_IGNORE(dup(SHDIAG)); 955 is2atty = isdiagatty; 956 # if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS) 957 (void) close_on_exec(2, 0); 958 # endif /* CLOSE_ON_EXEC && CLEX_DUPS */ 959 } 960 didfds = 1; 961 } 962 963 void 964 mypipe(int *pv) 965 { 966 967 if (pipe(pv) < 0) 968 goto oops; 969 (void)close_on_exec(pv[0] = dmove(pv[0], -1), 1); 970 (void)close_on_exec(pv[1] = dmove(pv[1], -1), 1); 971 if (pv[0] >= 0 && pv[1] >= 0) 972 return; 973 if (pv[0] >= 0) 974 xclose(pv[0]); 975 if (pv[1] >= 0) 976 xclose(pv[1]); 977 oops: 978 stderror(ERR_PIPE); 979 } 980 981 static void 982 chkclob(const char *cp) 983 { 984 struct stat stb; 985 986 if (stat(cp, &stb) < 0) 987 return; 988 if (S_ISCHR(stb.st_mode)) 989 return; 990 if (no_clobber & NOCLOBBER_NOTEMPTY && stb.st_size == 0) 991 return; 992 if (no_clobber & NOCLOBBER_ASK) { 993 if (getYN(CGETS(22, 15, 994 "Do you really want to overwrite an existing file? [N/y] "))) 995 return; 996 } 997 998 stderror(ERR_EXISTS, cp); 999 } 1000