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