1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley Software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char *sccsid = "@(#)sem.c 5.9 (Berkeley) 03/14/91"; 9 #endif 10 11 #include "sh.h" 12 #include "sh.proc.h" 13 #include <sys/file.h> 14 #include <sys/ioctl.h> 15 #include "pathnames.h" 16 17 /* 18 * C shell 19 */ 20 21 static int nosigchld = 0, osigmask; 22 static int onosigchld = 0, oosigmask; 23 /*VARARGS 1*/ 24 execute(t, wanttty, pipein, pipeout) 25 register struct command *t; 26 int wanttty, *pipein, *pipeout; 27 { 28 bool forked = 0; 29 struct biltins *bifunc; 30 int pid = 0; 31 int pv[2]; 32 33 if (t == 0) 34 return; 35 if ((t->t_dflg & FAND) && wanttty > 0) 36 wanttty = 0; 37 switch (t->t_dtyp) { 38 39 case TCOM: 40 if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE) 41 (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1); 42 if ((t->t_dflg & FREDO) == 0) 43 Dfix(t); /* $ " ' \ */ 44 if (t->t_dcom[0] == 0) 45 return; 46 /* fall into... */ 47 48 case TPAR: 49 if (t->t_dflg & FPOU) 50 mypipe(pipeout); 51 /* 52 * Must do << early so parent will know 53 * where input pointer should be. 54 * If noexec then this is all we do. 55 */ 56 if (t->t_dflg & FHERE) { 57 (void) close(0); 58 heredoc(t->t_dlef); 59 if (noexec) 60 (void) close(0); 61 } 62 if (noexec) 63 break; 64 65 set("status", "0"); 66 67 /* 68 * This mess is the necessary kludge to handle the prefix 69 * builtins: nice, nohup, time. These commands can also 70 * be used by themselves, and this is not handled here. 71 * This will also work when loops are parsed. 72 */ 73 while (t->t_dtyp == TCOM) 74 if (eq(t->t_dcom[0], "nice")) 75 if (t->t_dcom[1]) 76 if (index("+-", t->t_dcom[1][0])) 77 if (t->t_dcom[2]) { 78 setname("nice"); 79 t->t_nice = getn(t->t_dcom[1]); 80 lshift(t->t_dcom, 2); 81 t->t_dflg |= FNICE; 82 } else 83 break; 84 else { 85 t->t_nice = 4; 86 lshift(t->t_dcom, 1); 87 t->t_dflg |= FNICE; 88 } 89 else 90 break; 91 else if (eq(t->t_dcom[0], "nohup")) 92 if (t->t_dcom[1]) { 93 t->t_dflg |= FNOHUP; 94 lshift(t->t_dcom, 1); 95 } else 96 break; 97 else if (eq(t->t_dcom[0], "time")) 98 if (t->t_dcom[1]) { 99 t->t_dflg |= FTIME; 100 lshift(t->t_dcom, 1); 101 } else 102 break; 103 else 104 break; 105 /* 106 * Check if we have a builtin function and remember which one. 107 */ 108 bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0; 109 110 /* 111 * We fork only if we are timed, or are not the end of 112 * a parenthesized list and not a simple builtin function. 113 * Simple meaning one that is not pipedout, niced, nohupped, 114 * or &'d. 115 * It would be nice(?) to not fork in some of these cases. 116 */ 117 if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 && 118 (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP)))) 119 #ifdef VFORK 120 if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc) 121 #endif 122 { forked++; 123 if (wanttty >= 0 && !nosigchld) { 124 osigmask = sigblock(sigmask(SIGCHLD)); 125 nosigchld = 1; 126 } 127 128 pid = pfork(t, wanttty); 129 if (pid == 0 && nosigchld) { 130 sigsetmask(osigmask); 131 nosigchld = 0; 132 } 133 } 134 #ifdef VFORK 135 else { 136 sig_t vffree; 137 int ochild, osetintr, ohaderr, odidfds; 138 int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; 139 long omask; 140 141 /* 142 * Prepare for the vfork by saving everything 143 * that the child corrupts before it exec's. 144 * Note that in some signal implementations 145 * which keep the signal info in user space 146 * (e.g. Sun's) it will also be necessary to 147 * save and restore the current sigvec's for 148 * the signals the child touches before it 149 * exec's. 150 */ 151 if (wanttty >= 0 && !nosigchld && !noexec) { 152 osigmask = sigblock(sigmask(SIGCHLD)); 153 nosigchld = 1; 154 } 155 omask = sigblock(sigmask(SIGCHLD)); 156 ochild = child; osetintr = setintr; 157 ohaderr = haderr; odidfds = didfds; 158 oSHIN = SHIN; oSHOUT = SHOUT; 159 oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp; 160 oosigmask = osigmask; onosigchld = nosigchld; 161 Vsav = Vdp = 0; Vav = 0; 162 pid = vfork(); 163 if (pid < 0) { 164 (void) sigsetmask(omask); 165 error("No more processes"); 166 } 167 forked++; 168 if (pid) { /* parent */ 169 child = ochild; setintr = osetintr; 170 haderr = ohaderr; didfds = odidfds; 171 SHIN = oSHIN; 172 SHOUT = oSHOUT; SHDIAG = oSHDIAG; 173 OLDSTD = oOLDSTD; tpgrp = otpgrp; 174 osigmask = oosigmask; nosigchld = onosigchld; 175 xfree(Vsav); Vsav = 0; 176 xfree(Vdp); Vdp = 0; 177 xfree((char *)Vav); Vav = 0; 178 /* this is from pfork() */ 179 palloc(pid, t); 180 (void) sigsetmask(omask); 181 } else { /* child */ 182 /* this is from pfork() */ 183 int pgrp; 184 bool ignint = 0; 185 186 if (nosigchld) { 187 sigsetmask(osigmask); 188 nosigchld = 0; 189 } 190 if (setintr) 191 ignint = 192 (tpgrp == -1 && (t->t_dflg&FINT)) 193 || gointr && eq(gointr, "-"); 194 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 195 child++; 196 if (setintr) { 197 setintr = 0; 198 #ifdef notdef 199 (void) signal(SIGCHLD, SIG_DFL); 200 #endif 201 (void) signal(SIGINT, ignint ? 202 SIG_IGN : vffree); 203 (void) signal(SIGQUIT, ignint ? 204 SIG_IGN : SIG_DFL); 205 if (wanttty >= 0) { 206 (void) signal(SIGTSTP, SIG_DFL); 207 (void) signal(SIGTTIN, SIG_DFL); 208 (void) signal(SIGTTOU, SIG_DFL); 209 } 210 (void) signal(SIGTERM, parterm); 211 } else if (tpgrp == -1 && (t->t_dflg&FINT)) { 212 (void) signal(SIGINT, SIG_IGN); 213 (void) signal(SIGQUIT, SIG_IGN); 214 } 215 if (wanttty >= 0 && tpgrp >= 0) 216 (void) setpgrp(0, pgrp); 217 if (wanttty > 0) 218 (void) ioctl(FSHTTY, TIOCSPGRP, 219 (char *)&pgrp); 220 if (tpgrp > 0) 221 tpgrp = 0; 222 if (t->t_dflg & FNOHUP) 223 (void) signal(SIGHUP, SIG_IGN); 224 if (t->t_dflg & FNICE) 225 (void) setpriority(PRIO_PROCESS, 226 0, t->t_nice); 227 } 228 229 } 230 #endif 231 if (pid != 0) { 232 /* 233 * It would be better if we could wait for the 234 * whole job when we knew the last process 235 * had been started. Pwait, in fact, does 236 * wait for the whole job anyway, but this test 237 * doesn't really express our intentions. 238 */ 239 if (didfds==0 && t->t_dflg&FPIN) { 240 (void) close(pipein[0]); 241 (void) close(pipein[1]); 242 } 243 if ((t->t_dflg & FPOU) == 0) { 244 if (nosigchld) { 245 #ifdef foobarbaz 246 printf("DID\n"); 247 #endif 248 sigsetmask(osigmask); 249 nosigchld = 0; 250 } 251 if ((t->t_dflg & FAND) == 0) 252 pwait(); 253 } 254 break; 255 } 256 doio(t, pipein, pipeout); 257 if (t->t_dflg & FPOU) { 258 (void) close(pipeout[0]); 259 (void) close(pipeout[1]); 260 } 261 262 /* 263 * Perform a builtin function. 264 * If we are not forked, arrange for possible stopping 265 */ 266 if (bifunc) { 267 func(t, bifunc); 268 if (forked) 269 exitstat(); 270 break; 271 } 272 if (t->t_dtyp != TPAR) { 273 doexec(t); 274 /*NOTREACHED*/ 275 } 276 /* 277 * For () commands must put new 0,1,2 in FSH* and recurse 278 */ 279 OLDSTD = dcopy(0, FOLDSTD); 280 SHOUT = dcopy(1, FSHOUT); 281 SHDIAG = dcopy(2, FSHDIAG); 282 (void) close(SHIN); 283 SHIN = -1; 284 didfds = 0; 285 wanttty = -1; 286 t->t_dspr->t_dflg |= t->t_dflg & FINT; 287 execute(t->t_dspr, wanttty); 288 exitstat(); 289 290 case TFIL: 291 t->t_dcar->t_dflg |= FPOU | 292 (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); 293 execute(t->t_dcar, wanttty, pipein, pv); 294 t->t_dcdr->t_dflg |= FPIN | 295 (t->t_dflg & (FPOU|FAND|FPAR|FINT)); 296 if (wanttty > 0) 297 wanttty = 0; /* got tty already */ 298 execute(t->t_dcdr, wanttty, pv, pipeout); 299 break; 300 301 case TLST: 302 if (t->t_dcar) { 303 t->t_dcar->t_dflg |= t->t_dflg & FINT; 304 execute(t->t_dcar, wanttty); 305 /* 306 * In strange case of A&B make a new job after A 307 */ 308 if (t->t_dcar->t_dflg&FAND && t->t_dcdr && 309 (t->t_dcdr->t_dflg&FAND) == 0) 310 pendjob(); 311 } 312 if (t->t_dcdr) { 313 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); 314 execute(t->t_dcdr, wanttty); 315 } 316 break; 317 318 case TOR: 319 case TAND: 320 if (t->t_dcar) { 321 t->t_dcar->t_dflg |= t->t_dflg & FINT; 322 execute(t->t_dcar, wanttty); 323 if ((getn(value("status")) == 0) != (t->t_dtyp == TAND)) 324 return; 325 } 326 if (t->t_dcdr) { 327 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); 328 execute(t->t_dcdr, wanttty); 329 } 330 break; 331 } 332 /* 333 * Fall through for all breaks from switch 334 * 335 * If there will be no more executions of this 336 * command, flush all file descriptors. 337 * Places that turn on the FREDO bit are responsible 338 * for doing donefds after the last re-execution 339 */ 340 if (didfds && !(t->t_dflg & FREDO)) 341 donefds(); 342 } 343 344 #ifdef VFORK 345 vffree() 346 { 347 register char **v; 348 349 if (v = gargv) 350 gargv = 0, xfree((char *)v); 351 if (v = pargv) 352 pargv = 0, xfree((char *)v); 353 _exit(1); 354 } 355 #endif 356 357 /* 358 * Perform io redirection. 359 * We may or maynot be forked here. 360 */ 361 doio(t, pipein, pipeout) 362 register struct command *t; 363 int *pipein, *pipeout; 364 { 365 register char *cp; 366 register int flags = t->t_dflg; 367 368 if (didfds || (flags & FREDO)) 369 return; 370 if ((flags & FHERE) == 0) { /* FHERE already done */ 371 (void) close(0); 372 if (cp = t->t_dlef) { 373 cp = globone(Dfix1(cp)); 374 xfree(cp); 375 if (open(cp, 0) < 0) 376 Perror(cp); 377 } else if (flags & FPIN) { 378 (void) dup(pipein[0]); 379 (void) close(pipein[0]); 380 (void) close(pipein[1]); 381 } else if ((flags & FINT) && tpgrp == -1) { 382 (void) close(0); 383 (void) open(_PATH_DEVNULL, 0); 384 } else 385 (void) dup(OLDSTD); 386 } 387 (void) close(1); 388 if (cp = t->t_drit) { 389 cp = globone(Dfix1(cp)); 390 xfree(cp); 391 if (!(flags & FCAT) || open(cp, O_WRONLY|O_APPEND, 0) < 0) { 392 if (!(flags & FANY) && adrof("noclobber")) { 393 if (flags & FCAT) 394 Perror(cp); 395 chkclob(cp); 396 } 397 if (creat(cp, 0666) < 0) 398 Perror(cp); 399 } 400 } else if (flags & FPOU) 401 (void) dup(pipeout[1]); 402 else 403 (void) dup(SHOUT); 404 405 (void) close(2); 406 if (flags & FDIAG) 407 (void) dup(1); 408 else 409 (void) dup(SHDIAG); 410 didfds = 1; 411 } 412 413 mypipe(pv) 414 register int *pv; 415 { 416 417 if (pipe(pv) < 0) 418 goto oops; 419 pv[0] = dmove(pv[0], -1); 420 pv[1] = dmove(pv[1], -1); 421 if (pv[0] >= 0 && pv[1] >= 0) 422 return; 423 oops: 424 error("Can't make pipe"); 425 } 426 427 chkclob(cp) 428 register char *cp; 429 { 430 struct stat stb; 431 432 if (stat(cp, &stb) < 0) 433 return; 434 if ((stb.st_mode & S_IFMT) == S_IFCHR) 435 return; 436 error("%s: File exists", cp); 437 } 438