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