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