1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley Software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 #pragma ident "%Z%%M% %I% %E% SMI" 16 17 #include <unistd.h> 18 #include <fcntl.h> 19 #include "sh.h" 20 #include "sh.proc.h" 21 #include "sh.tconst.h" 22 23 /* 24 * C shell 25 */ 26 27 void doio(struct command *, int *, int *); 28 void mypipe(int *); 29 void chkclob(tchar *); 30 31 /* 32 * Return true if there is a back-quote (`) anywhere in the argument list. 33 * Its presence would cause glob() to be invoked in the child process 34 * and this would cause chaos if the child is created with vfork(). 35 */ 36 static bool 37 AnyBquote(struct command *t) 38 { 39 tchar **pp; 40 tchar *p; 41 42 if (noexec) 43 return (0); 44 for (pp = t->t_dcom; p = *pp++;) { 45 if (any('`', p)) 46 return (1); 47 } 48 return (0); 49 } 50 51 /*VARARGS 1*/ 52 void 53 execute(t, wanttty, pipein, pipeout) 54 struct command *t; 55 int wanttty, *pipein, *pipeout; 56 { 57 bool forked = 0; 58 struct biltins *bifunc; 59 int pid = 0; 60 int pv[2]; 61 extern int globcnt; 62 #ifdef TRACE 63 tprintf("TRACE- execute()\n"); 64 #endif 65 66 if (t == 0) 67 return; 68 if ((t->t_dflg & FAND) && wanttty > 0) 69 wanttty = 0; 70 switch (t->t_dtyp) { 71 72 case TCOM: 73 if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0]) 74 (void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1); 75 if ((t->t_dflg & FREDO) == 0) 76 Dfix(t); /* $ " ' \ */ 77 if (t->t_dcom[0] == 0) 78 return; 79 /* fall into... */ 80 81 case TPAR: 82 if (t->t_dflg & FPOU) 83 mypipe(pipeout); 84 /* 85 * Must do << early so parent will know 86 * where input pointer should be. 87 * If noexec then this is all we do. 88 */ 89 if (t->t_dflg & FHERE) { 90 (void) close(0); 91 unsetfd(0); 92 heredoc(t->t_dlef); 93 if (noexec) { 94 (void) close(0); 95 unsetfd(0); 96 } 97 } 98 if (noexec) 99 break; 100 101 set(S_status, S_0); 102 103 /* 104 * This mess is the necessary kludge to handle the prefix 105 * builtins: nice, nohup, time. These commands can also 106 * be used by themselves, and this is not handled here. 107 * This will also work when loops are parsed. 108 */ 109 while (t->t_dtyp == TCOM) 110 if (eq(t->t_dcom[0], S_nice /*"nice"*/)) 111 if (t->t_dcom[1]) 112 /*if (any(t->t_dcom[1][0], "+-"))*/ 113 if (t->t_dcom[1][0] == '+' || 114 t->t_dcom[1][0] == '-') 115 if (t->t_dcom[2]) { 116 setname(S_nice /*"nice"*/); 117 t->t_nice = getn(t->t_dcom[1]); 118 lshift(t->t_dcom, 2); 119 t->t_dflg |= FNICE; 120 } else 121 break; 122 else { 123 t->t_nice = 4; 124 lshift(t->t_dcom, 1); 125 t->t_dflg |= FNICE; 126 } 127 else 128 break; 129 else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/)) 130 if (t->t_dcom[1]) { 131 t->t_dflg |= FNOHUP; 132 lshift(t->t_dcom, 1); 133 } else 134 break; 135 else if (eq(t->t_dcom[0], S_time /*"time"*/)) 136 if (t->t_dcom[1]) { 137 t->t_dflg |= FTIME; 138 lshift(t->t_dcom, 1); 139 } else 140 break; 141 else 142 break; 143 /* 144 * Check if we have a builtin function and remember which one. 145 */ 146 bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0; 147 148 /* 149 * We fork only if we are timed, or are not the end of 150 * a parenthesized list and not a simple builtin function. 151 * Simple meaning one that is not pipedout, niced, nohupped, 152 * or &'d. 153 * It would be nice(?) to not fork in some of these cases. 154 */ 155 if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 && 156 (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP)))) 157 #ifdef VFORK 158 if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || 159 bifunc || AnyBquote(t)) 160 #endif 161 { forked++; pid = pfork(t, wanttty); } 162 #ifdef VFORK 163 else { 164 void vffree(); 165 struct sv { 166 int mask, child, setintr, haderr, didfds; 167 int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp; 168 struct sigvec sigv; 169 } sv; 170 171 /* 172 * Prepare for the vfork by saving everything 173 * that the child corrupts before it exec's. 174 * Note that in some signal implementations 175 * which keep the signal info in user space 176 * (e.g. Sun's) it will also be necessary to 177 * save and restore the current sigvec's for 178 * the signals the child touches before it 179 * exec's. 180 */ 181 sv.mask = sigblock(sigmask(SIGCHLD)); 182 sv.child = child; sv.setintr = setintr; 183 sv.haderr = haderr; sv.didfds = didfds; 184 sv.SHIN = SHIN; sv.SHOUT = SHOUT; 185 sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD; 186 sv.tpgrp = tpgrp; 187 Vsav = Vdp = 0; Vav = 0; 188 (void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv); 189 pid = vfork(); 190 if (pid < 0) { 191 (void) sigsetmask(sv.mask); 192 error("Vfork failed"); 193 } 194 forked++; 195 if (pid) { /* parent */ 196 int ppid; 197 closelog(); 198 child = sv.child; setintr = sv.setintr; 199 haderr = sv.haderr; didfds = sv.didfds; 200 SHIN = sv.SHIN; 201 SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG; 202 OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp; 203 xfree(Vsav); Vsav = 0; 204 xfree(Vdp); Vdp = 0; 205 xfree( (tchar *)Vav); Vav = 0; 206 /* this is from pfork() */ 207 ppid = pcurrjob ? pcurrjob->p_jobid : pid; 208 if (wanttty >= 0 && tpgrp >= 0) 209 setpgid (ppid, ppid); 210 palloc(pid, t); 211 /* 212 * Restore SIGINT handler. 213 */ 214 (void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0); 215 (void) sigsetmask(sv.mask); 216 } else { /* child */ 217 /* this is from pfork() */ 218 int pgrp; 219 bool ignint = 0; 220 int sigttou; 221 if (setintr) 222 ignint = 223 (tpgrp == -1 && (t->t_dflg&FINT)) 224 || gointr 225 && eq(gointr, S_MINUS/*"-"*/); 226 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 227 child++; 228 if (setintr) { 229 setintr = 0; 230 #ifdef notdef 231 (void) signal(SIGCHLD, SIG_DFL); 232 #endif 233 (void) signal(SIGINT, ignint ? 234 SIG_IGN : vffree); 235 (void) signal(SIGQUIT, ignint ? 236 SIG_IGN : SIG_DFL); 237 if (wanttty >= 0) { 238 (void) signal(SIGTSTP, SIG_DFL); 239 (void) signal(SIGTTIN, SIG_DFL); 240 (void) signal(SIGTTOU, SIG_DFL); 241 } 242 (void) signal(SIGTERM, parterm); 243 } else if (tpgrp == -1 && (t->t_dflg&FINT)) { 244 (void) signal(SIGINT, SIG_IGN); 245 (void) signal(SIGQUIT, SIG_IGN); 246 } 247 if (wanttty >= 0 && tpgrp >= 0) 248 (void) setpgid(0, pgrp); 249 if (wanttty > 0) { 250 sigttou = sigblock ( 251 sigmask(SIGTTOU) | 252 sigmask(SIGTTIN) | 253 sigmask(SIGTSTP)); 254 (void) ioctl(FSHTTY, TIOCSPGRP, 255 (tchar *)&pgrp); 256 sigsetmask (sigttou); 257 } 258 if (tpgrp > 0) 259 tpgrp = 0; 260 if (t->t_dflg & FNOHUP) 261 (void) signal(SIGHUP, SIG_IGN); 262 if (t->t_dflg & FNICE) 263 (void) setpriority(PRIO_PROCESS, 264 0, t->t_nice); 265 } 266 267 } 268 #endif 269 if (pid != 0) { 270 /* 271 * It would be better if we could wait for the 272 * whole job when we knew the last process 273 * had been started. Pwait, in fact, does 274 * wait for the whole job anyway, but this test 275 * doesn't really express our intentions. 276 */ 277 if (didfds==0 && t->t_dflg&FPIN) { 278 (void) close(pipein[0]); 279 unsetfd(pipein[0]); 280 (void) close(pipein[1]); 281 unsetfd(pipein[1]); 282 } 283 if ((t->t_dflg & (FPOU|FAND)) == 0) 284 pwait(); 285 break; 286 } 287 doio(t, pipein, pipeout); 288 if (t->t_dflg & FPOU) { 289 (void) close(pipeout[0]); 290 (void) unsetfd(pipeout[0]); 291 (void) close(pipeout[1]); 292 (void) unsetfd(pipeout[1]); 293 } 294 295 /* 296 * Perform a builtin function. 297 * If we are not forked, arrange for possible stopping 298 */ 299 if (bifunc) { 300 func(t, bifunc); 301 if (forked) 302 exitstat(); 303 break; 304 } 305 if (t->t_dtyp != TPAR) { 306 doexec(t); 307 /*NOTREACHED*/ 308 } 309 /* 310 * For () commands must put new 0,1,2 in FSH* and recurse 311 */ 312 OLDSTD = dcopy(0, FOLDSTD); 313 SHOUT = dcopy(1, FSHOUT); 314 SHDIAG = dcopy(2, FSHDIAG); 315 (void) close(SHIN); 316 (void) unsetfd(SHIN); 317 SHIN = -1; 318 didfds = 0; 319 wanttty = -1; 320 t->t_dspr->t_dflg |= t->t_dflg & FINT; 321 execute(t->t_dspr, wanttty); 322 exitstat(); 323 324 case TFIL: 325 t->t_dcar->t_dflg |= FPOU | 326 (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); 327 execute(t->t_dcar, wanttty, pipein, pv); 328 t->t_dcdr->t_dflg |= FPIN | 329 (t->t_dflg & (FPOU|FAND|FPAR|FINT)); 330 if (wanttty > 0) 331 wanttty = 0; /* got tty already */ 332 execute(t->t_dcdr, wanttty, pv, pipeout); 333 break; 334 335 case TLST: 336 if (t->t_dcar) { 337 t->t_dcar->t_dflg |= t->t_dflg & FINT; 338 execute(t->t_dcar, wanttty); 339 /* 340 * In strange case of A&B make a new job after A 341 */ 342 if (t->t_dcar->t_dflg&FAND && t->t_dcdr && 343 (t->t_dcdr->t_dflg&FAND) == 0) 344 pendjob(); 345 } 346 if (t->t_dcdr) { 347 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); 348 execute(t->t_dcdr, wanttty); 349 } 350 break; 351 352 case TOR: 353 case TAND: 354 if (t->t_dcar) { 355 t->t_dcar->t_dflg |= t->t_dflg & FINT; 356 execute(t->t_dcar, wanttty); 357 if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND)) 358 return; 359 } 360 if (t->t_dcdr) { 361 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); 362 execute(t->t_dcdr, wanttty); 363 } 364 break; 365 } 366 /* 367 * Fall through for all breaks from switch 368 * 369 * If there will be no more executions of this 370 * command, flush all file descriptors. 371 * Places that turn on the FREDO bit are responsible 372 * for doing donefds after the last re-execution 373 */ 374 if (didfds && !(t->t_dflg & FREDO)) 375 donefds(); 376 377 /* 378 * If glob() was called and arguments list is not yet 379 * free'ed, free them here. 380 */ 381 if (gargv) { 382 blkfree(gargv); 383 gargv = 0; 384 globcnt = 0; 385 } 386 } 387 388 #ifdef VFORK 389 void 390 vffree(void) 391 { 392 tchar **v; 393 394 #ifdef TRACE 395 tprintf("TRACE- vffree()\n"); 396 #endif 397 if (v = gargv) 398 gargv = 0, xfree( (tchar *)v); 399 if (v = pargv) 400 pargv = 0, xfree( (tchar *)v); 401 _exit(1); 402 } 403 #endif 404 405 /* 406 * Perform io redirection. 407 * We may or maynot be forked here. 408 */ 409 void 410 doio(struct command *t, int *pipein, int *pipeout) 411 { 412 tchar *cp, *dp; 413 int flags = t->t_dflg; 414 int fd; 415 416 #ifdef TRACE 417 tprintf("TRACE- doio()\n"); 418 #endif 419 if (didfds || (flags & FREDO)) 420 return; 421 if ((flags & FHERE) == 0) { /* FHERE already done */ 422 (void) close(0); 423 (void) unsetfd(0); 424 if (cp = t->t_dlef) { 425 dp = Dfix1(cp); 426 cp = globone(dp); 427 xfree(dp); 428 xfree(cp); 429 if (open_(cp, 0) < 0) 430 Perror(cp); 431 } else if (flags & FPIN) { 432 fd = dup(pipein[0]); 433 if (fd != -1) 434 setfd(fd); 435 (void) close(pipein[0]); 436 (void) unsetfd(pipein[0]); 437 (void) close(pipein[1]); 438 (void) unsetfd(pipein[1]); 439 } else if ((flags & FINT) && tpgrp == -1) { 440 (void) close(0); /* no need for unsetfd */ 441 (void) open("/dev/null", 0); /* no need for setfd */ 442 } else { 443 fd = dup(OLDSTD); 444 if (fd != -1) 445 setfd(fd); 446 } 447 } 448 (void) close(1); 449 (void) unsetfd(1); 450 if (cp = t->t_drit) { 451 dp = Dfix1(cp); 452 cp = globone(dp); 453 xfree(dp); 454 if ((flags & FCAT) && open_(cp, 1) >= 0) 455 (void) lseek(1, (off_t)0, 2); 456 else { 457 if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) { 458 if (flags & FCAT) 459 Perror(cp); 460 chkclob(cp); 461 } 462 if (creat_(cp, 0666) < 0) 463 Perror(cp); 464 } 465 xfree(cp); 466 } else if (flags & FPOU) { 467 fd = dup(pipeout[1]); 468 if (fd != -1) 469 setfd (fd); 470 } 471 else { 472 fd = dup(SHOUT); 473 if (fd != -1) 474 setfd(fd); 475 } 476 477 (void) close(2); 478 (void) unsetfd(2); 479 if (flags & FDIAG) { 480 fd = dup(1); 481 if (fd != -1) 482 setfd(fd); 483 } 484 else { 485 fd = dup(SHDIAG); 486 if (fd != -1) 487 setfd(fd); 488 } 489 didfds = 1; 490 } 491 492 void 493 mypipe(int *pv) 494 { 495 496 #ifdef TRACE 497 tprintf("TRACE- mypipe()\n"); 498 #endif 499 if (pipe(pv) < 0) 500 goto oops; 501 setfd(pv[0]); 502 setfd(pv[1]); 503 504 pv[0] = dmove(pv[0], -1); 505 pv[1] = dmove(pv[1], -1); 506 if (pv[0] >= 0 && pv[1] >= 0) 507 return; 508 oops: 509 error("Can't make pipe"); 510 } 511 512 void 513 chkclob(tchar *cp) 514 { 515 struct stat stb; 516 unsigned short type; 517 518 #ifdef TRACE 519 tprintf("TRACE- chkclob()\n"); 520 #endif 521 if (stat_(cp, &stb) < 0) 522 return; 523 type = stb.st_mode & S_IFMT; 524 if (type == S_IFCHR || type == S_IFIFO) 525 return; 526 error("%t: File exists", cp); 527 } 528