17c478bd9Sstevel@tonic-gate /* 2*6c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include <unistd.h> 187c478bd9Sstevel@tonic-gate #include <fcntl.h> 197c478bd9Sstevel@tonic-gate #include "sh.h" 207c478bd9Sstevel@tonic-gate #include "sh.proc.h" 217c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * C shell 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*6c02b4a4Smuffin void doio(struct command *, int *, int *); 28*6c02b4a4Smuffin void mypipe(int *); 29*6c02b4a4Smuffin void chkclob(tchar *); 30*6c02b4a4Smuffin 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Return true if there is a back-quote (`) anywhere in the argument list. 337c478bd9Sstevel@tonic-gate * Its presence would cause glob() to be invoked in the child process 347c478bd9Sstevel@tonic-gate * and this would cause chaos if the child is created with vfork(). 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate static bool 377c478bd9Sstevel@tonic-gate AnyBquote(struct command *t) 387c478bd9Sstevel@tonic-gate { 397c478bd9Sstevel@tonic-gate tchar **pp; 407c478bd9Sstevel@tonic-gate tchar *p; 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate if (noexec) 437c478bd9Sstevel@tonic-gate return (0); 447c478bd9Sstevel@tonic-gate for (pp = t->t_dcom; p = *pp++;) { 457c478bd9Sstevel@tonic-gate if (any('`', p)) 467c478bd9Sstevel@tonic-gate return (1); 477c478bd9Sstevel@tonic-gate } 487c478bd9Sstevel@tonic-gate return (0); 497c478bd9Sstevel@tonic-gate } 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /*VARARGS 1*/ 52*6c02b4a4Smuffin void 537c478bd9Sstevel@tonic-gate execute(t, wanttty, pipein, pipeout) 54*6c02b4a4Smuffin struct command *t; 557c478bd9Sstevel@tonic-gate int wanttty, *pipein, *pipeout; 567c478bd9Sstevel@tonic-gate { 577c478bd9Sstevel@tonic-gate bool forked = 0; 587c478bd9Sstevel@tonic-gate struct biltins *bifunc; 597c478bd9Sstevel@tonic-gate int pid = 0; 607c478bd9Sstevel@tonic-gate int pv[2]; 617c478bd9Sstevel@tonic-gate extern int globcnt; 627c478bd9Sstevel@tonic-gate #ifdef TRACE 637c478bd9Sstevel@tonic-gate tprintf("TRACE- execute()\n"); 647c478bd9Sstevel@tonic-gate #endif 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate if (t == 0) 677c478bd9Sstevel@tonic-gate return; 687c478bd9Sstevel@tonic-gate if ((t->t_dflg & FAND) && wanttty > 0) 697c478bd9Sstevel@tonic-gate wanttty = 0; 707c478bd9Sstevel@tonic-gate switch (t->t_dtyp) { 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate case TCOM: 737c478bd9Sstevel@tonic-gate if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0]) 747c478bd9Sstevel@tonic-gate (void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1); 757c478bd9Sstevel@tonic-gate if ((t->t_dflg & FREDO) == 0) 767c478bd9Sstevel@tonic-gate Dfix(t); /* $ " ' \ */ 777c478bd9Sstevel@tonic-gate if (t->t_dcom[0] == 0) 787c478bd9Sstevel@tonic-gate return; 797c478bd9Sstevel@tonic-gate /* fall into... */ 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate case TPAR: 827c478bd9Sstevel@tonic-gate if (t->t_dflg & FPOU) 837c478bd9Sstevel@tonic-gate mypipe(pipeout); 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * Must do << early so parent will know 867c478bd9Sstevel@tonic-gate * where input pointer should be. 877c478bd9Sstevel@tonic-gate * If noexec then this is all we do. 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate if (t->t_dflg & FHERE) { 907c478bd9Sstevel@tonic-gate (void) close(0); 917c478bd9Sstevel@tonic-gate unsetfd(0); 927c478bd9Sstevel@tonic-gate heredoc(t->t_dlef); 937c478bd9Sstevel@tonic-gate if (noexec) { 947c478bd9Sstevel@tonic-gate (void) close(0); 957c478bd9Sstevel@tonic-gate unsetfd(0); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate if (noexec) 997c478bd9Sstevel@tonic-gate break; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate set(S_status, S_0); 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * This mess is the necessary kludge to handle the prefix 1057c478bd9Sstevel@tonic-gate * builtins: nice, nohup, time. These commands can also 1067c478bd9Sstevel@tonic-gate * be used by themselves, and this is not handled here. 1077c478bd9Sstevel@tonic-gate * This will also work when loops are parsed. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate while (t->t_dtyp == TCOM) 1107c478bd9Sstevel@tonic-gate if (eq(t->t_dcom[0], S_nice /*"nice"*/)) 1117c478bd9Sstevel@tonic-gate if (t->t_dcom[1]) 1127c478bd9Sstevel@tonic-gate /*if (any(t->t_dcom[1][0], "+-"))*/ 1137c478bd9Sstevel@tonic-gate if (t->t_dcom[1][0] == '+' || 1147c478bd9Sstevel@tonic-gate t->t_dcom[1][0] == '-') 1157c478bd9Sstevel@tonic-gate if (t->t_dcom[2]) { 1167c478bd9Sstevel@tonic-gate setname(S_nice /*"nice"*/); 1177c478bd9Sstevel@tonic-gate t->t_nice = getn(t->t_dcom[1]); 1187c478bd9Sstevel@tonic-gate lshift(t->t_dcom, 2); 1197c478bd9Sstevel@tonic-gate t->t_dflg |= FNICE; 1207c478bd9Sstevel@tonic-gate } else 1217c478bd9Sstevel@tonic-gate break; 1227c478bd9Sstevel@tonic-gate else { 1237c478bd9Sstevel@tonic-gate t->t_nice = 4; 1247c478bd9Sstevel@tonic-gate lshift(t->t_dcom, 1); 1257c478bd9Sstevel@tonic-gate t->t_dflg |= FNICE; 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate else 1287c478bd9Sstevel@tonic-gate break; 1297c478bd9Sstevel@tonic-gate else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/)) 1307c478bd9Sstevel@tonic-gate if (t->t_dcom[1]) { 1317c478bd9Sstevel@tonic-gate t->t_dflg |= FNOHUP; 1327c478bd9Sstevel@tonic-gate lshift(t->t_dcom, 1); 1337c478bd9Sstevel@tonic-gate } else 1347c478bd9Sstevel@tonic-gate break; 1357c478bd9Sstevel@tonic-gate else if (eq(t->t_dcom[0], S_time /*"time"*/)) 1367c478bd9Sstevel@tonic-gate if (t->t_dcom[1]) { 1377c478bd9Sstevel@tonic-gate t->t_dflg |= FTIME; 1387c478bd9Sstevel@tonic-gate lshift(t->t_dcom, 1); 1397c478bd9Sstevel@tonic-gate } else 1407c478bd9Sstevel@tonic-gate break; 1417c478bd9Sstevel@tonic-gate else 1427c478bd9Sstevel@tonic-gate break; 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * Check if we have a builtin function and remember which one. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * We fork only if we are timed, or are not the end of 1507c478bd9Sstevel@tonic-gate * a parenthesized list and not a simple builtin function. 1517c478bd9Sstevel@tonic-gate * Simple meaning one that is not pipedout, niced, nohupped, 1527c478bd9Sstevel@tonic-gate * or &'d. 1537c478bd9Sstevel@tonic-gate * It would be nice(?) to not fork in some of these cases. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 && 1567c478bd9Sstevel@tonic-gate (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP)))) 1577c478bd9Sstevel@tonic-gate #ifdef VFORK 1587c478bd9Sstevel@tonic-gate if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || 1597c478bd9Sstevel@tonic-gate bifunc || AnyBquote(t)) 1607c478bd9Sstevel@tonic-gate #endif 1617c478bd9Sstevel@tonic-gate { forked++; pid = pfork(t, wanttty); } 1627c478bd9Sstevel@tonic-gate #ifdef VFORK 1637c478bd9Sstevel@tonic-gate else { 1647c478bd9Sstevel@tonic-gate void vffree(); 1657c478bd9Sstevel@tonic-gate struct sv { 1667c478bd9Sstevel@tonic-gate int mask, child, setintr, haderr, didfds; 1677c478bd9Sstevel@tonic-gate int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp; 1687c478bd9Sstevel@tonic-gate struct sigvec sigv; 1697c478bd9Sstevel@tonic-gate } sv; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * Prepare for the vfork by saving everything 1737c478bd9Sstevel@tonic-gate * that the child corrupts before it exec's. 1747c478bd9Sstevel@tonic-gate * Note that in some signal implementations 1757c478bd9Sstevel@tonic-gate * which keep the signal info in user space 1767c478bd9Sstevel@tonic-gate * (e.g. Sun's) it will also be necessary to 1777c478bd9Sstevel@tonic-gate * save and restore the current sigvec's for 1787c478bd9Sstevel@tonic-gate * the signals the child touches before it 1797c478bd9Sstevel@tonic-gate * exec's. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate sv.mask = sigblock(sigmask(SIGCHLD)); 1827c478bd9Sstevel@tonic-gate sv.child = child; sv.setintr = setintr; 1837c478bd9Sstevel@tonic-gate sv.haderr = haderr; sv.didfds = didfds; 1847c478bd9Sstevel@tonic-gate sv.SHIN = SHIN; sv.SHOUT = SHOUT; 1857c478bd9Sstevel@tonic-gate sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD; 1867c478bd9Sstevel@tonic-gate sv.tpgrp = tpgrp; 1877c478bd9Sstevel@tonic-gate Vsav = Vdp = 0; Vav = 0; 1887c478bd9Sstevel@tonic-gate (void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv); 1897c478bd9Sstevel@tonic-gate pid = vfork(); 1907c478bd9Sstevel@tonic-gate if (pid < 0) { 1917c478bd9Sstevel@tonic-gate (void) sigsetmask(sv.mask); 1927c478bd9Sstevel@tonic-gate error("Vfork failed"); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate forked++; 1957c478bd9Sstevel@tonic-gate if (pid) { /* parent */ 1967c478bd9Sstevel@tonic-gate int ppid; 1977c478bd9Sstevel@tonic-gate closelog(); 1987c478bd9Sstevel@tonic-gate child = sv.child; setintr = sv.setintr; 1997c478bd9Sstevel@tonic-gate haderr = sv.haderr; didfds = sv.didfds; 2007c478bd9Sstevel@tonic-gate SHIN = sv.SHIN; 2017c478bd9Sstevel@tonic-gate SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG; 2027c478bd9Sstevel@tonic-gate OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp; 2037c478bd9Sstevel@tonic-gate xfree(Vsav); Vsav = 0; 2047c478bd9Sstevel@tonic-gate xfree(Vdp); Vdp = 0; 2057c478bd9Sstevel@tonic-gate xfree( (tchar *)Vav); Vav = 0; 2067c478bd9Sstevel@tonic-gate /* this is from pfork() */ 2077c478bd9Sstevel@tonic-gate ppid = pcurrjob ? pcurrjob->p_jobid : pid; 2087c478bd9Sstevel@tonic-gate if (wanttty >= 0 && tpgrp >= 0) 2097c478bd9Sstevel@tonic-gate setpgid (ppid, ppid); 2107c478bd9Sstevel@tonic-gate palloc(pid, t); 2117c478bd9Sstevel@tonic-gate /* 2127c478bd9Sstevel@tonic-gate * Restore SIGINT handler. 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate (void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0); 2157c478bd9Sstevel@tonic-gate (void) sigsetmask(sv.mask); 2167c478bd9Sstevel@tonic-gate } else { /* child */ 2177c478bd9Sstevel@tonic-gate /* this is from pfork() */ 2187c478bd9Sstevel@tonic-gate int pgrp; 2197c478bd9Sstevel@tonic-gate bool ignint = 0; 2207c478bd9Sstevel@tonic-gate int sigttou; 2217c478bd9Sstevel@tonic-gate if (setintr) 2227c478bd9Sstevel@tonic-gate ignint = 2237c478bd9Sstevel@tonic-gate (tpgrp == -1 && (t->t_dflg&FINT)) 2247c478bd9Sstevel@tonic-gate || gointr 2257c478bd9Sstevel@tonic-gate && eq(gointr, S_MINUS/*"-"*/); 2267c478bd9Sstevel@tonic-gate pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 2277c478bd9Sstevel@tonic-gate child++; 2287c478bd9Sstevel@tonic-gate if (setintr) { 2297c478bd9Sstevel@tonic-gate setintr = 0; 2307c478bd9Sstevel@tonic-gate #ifdef notdef 2317c478bd9Sstevel@tonic-gate (void) signal(SIGCHLD, SIG_DFL); 2327c478bd9Sstevel@tonic-gate #endif 2337c478bd9Sstevel@tonic-gate (void) signal(SIGINT, ignint ? 2347c478bd9Sstevel@tonic-gate SIG_IGN : vffree); 2357c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, ignint ? 2367c478bd9Sstevel@tonic-gate SIG_IGN : SIG_DFL); 2377c478bd9Sstevel@tonic-gate if (wanttty >= 0) { 2387c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL); 2397c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_DFL); 2407c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_DFL); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); 2437c478bd9Sstevel@tonic-gate } else if (tpgrp == -1 && (t->t_dflg&FINT)) { 2447c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 2457c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate if (wanttty >= 0 && tpgrp >= 0) 2487c478bd9Sstevel@tonic-gate (void) setpgid(0, pgrp); 2497c478bd9Sstevel@tonic-gate if (wanttty > 0) { 2507c478bd9Sstevel@tonic-gate sigttou = sigblock ( 2517c478bd9Sstevel@tonic-gate sigmask(SIGTTOU) | 2527c478bd9Sstevel@tonic-gate sigmask(SIGTTIN) | 2537c478bd9Sstevel@tonic-gate sigmask(SIGTSTP)); 2547c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, 2557c478bd9Sstevel@tonic-gate (tchar *)&pgrp); 2567c478bd9Sstevel@tonic-gate sigsetmask (sigttou); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate if (tpgrp > 0) 2597c478bd9Sstevel@tonic-gate tpgrp = 0; 2607c478bd9Sstevel@tonic-gate if (t->t_dflg & FNOHUP) 2617c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN); 2627c478bd9Sstevel@tonic-gate if (t->t_dflg & FNICE) 2637c478bd9Sstevel@tonic-gate (void) setpriority(PRIO_PROCESS, 2647c478bd9Sstevel@tonic-gate 0, t->t_nice); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate #endif 2697c478bd9Sstevel@tonic-gate if (pid != 0) { 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * It would be better if we could wait for the 2727c478bd9Sstevel@tonic-gate * whole job when we knew the last process 2737c478bd9Sstevel@tonic-gate * had been started. Pwait, in fact, does 2747c478bd9Sstevel@tonic-gate * wait for the whole job anyway, but this test 2757c478bd9Sstevel@tonic-gate * doesn't really express our intentions. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate if (didfds==0 && t->t_dflg&FPIN) { 2787c478bd9Sstevel@tonic-gate (void) close(pipein[0]); 2797c478bd9Sstevel@tonic-gate unsetfd(pipein[0]); 2807c478bd9Sstevel@tonic-gate (void) close(pipein[1]); 2817c478bd9Sstevel@tonic-gate unsetfd(pipein[1]); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate if ((t->t_dflg & (FPOU|FAND)) == 0) 2847c478bd9Sstevel@tonic-gate pwait(); 2857c478bd9Sstevel@tonic-gate break; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate doio(t, pipein, pipeout); 2887c478bd9Sstevel@tonic-gate if (t->t_dflg & FPOU) { 2897c478bd9Sstevel@tonic-gate (void) close(pipeout[0]); 2907c478bd9Sstevel@tonic-gate (void) unsetfd(pipeout[0]); 2917c478bd9Sstevel@tonic-gate (void) close(pipeout[1]); 2927c478bd9Sstevel@tonic-gate (void) unsetfd(pipeout[1]); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Perform a builtin function. 2977c478bd9Sstevel@tonic-gate * If we are not forked, arrange for possible stopping 2987c478bd9Sstevel@tonic-gate */ 2997c478bd9Sstevel@tonic-gate if (bifunc) { 3007c478bd9Sstevel@tonic-gate func(t, bifunc); 3017c478bd9Sstevel@tonic-gate if (forked) 3027c478bd9Sstevel@tonic-gate exitstat(); 3037c478bd9Sstevel@tonic-gate break; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate if (t->t_dtyp != TPAR) { 3067c478bd9Sstevel@tonic-gate doexec(t); 3077c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * For () commands must put new 0,1,2 in FSH* and recurse 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate OLDSTD = dcopy(0, FOLDSTD); 3137c478bd9Sstevel@tonic-gate SHOUT = dcopy(1, FSHOUT); 3147c478bd9Sstevel@tonic-gate SHDIAG = dcopy(2, FSHDIAG); 3157c478bd9Sstevel@tonic-gate (void) close(SHIN); 3167c478bd9Sstevel@tonic-gate (void) unsetfd(SHIN); 3177c478bd9Sstevel@tonic-gate SHIN = -1; 3187c478bd9Sstevel@tonic-gate didfds = 0; 3197c478bd9Sstevel@tonic-gate wanttty = -1; 3207c478bd9Sstevel@tonic-gate t->t_dspr->t_dflg |= t->t_dflg & FINT; 3217c478bd9Sstevel@tonic-gate execute(t->t_dspr, wanttty); 3227c478bd9Sstevel@tonic-gate exitstat(); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate case TFIL: 3257c478bd9Sstevel@tonic-gate t->t_dcar->t_dflg |= FPOU | 3267c478bd9Sstevel@tonic-gate (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); 3277c478bd9Sstevel@tonic-gate execute(t->t_dcar, wanttty, pipein, pv); 3287c478bd9Sstevel@tonic-gate t->t_dcdr->t_dflg |= FPIN | 3297c478bd9Sstevel@tonic-gate (t->t_dflg & (FPOU|FAND|FPAR|FINT)); 3307c478bd9Sstevel@tonic-gate if (wanttty > 0) 3317c478bd9Sstevel@tonic-gate wanttty = 0; /* got tty already */ 3327c478bd9Sstevel@tonic-gate execute(t->t_dcdr, wanttty, pv, pipeout); 3337c478bd9Sstevel@tonic-gate break; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate case TLST: 3367c478bd9Sstevel@tonic-gate if (t->t_dcar) { 3377c478bd9Sstevel@tonic-gate t->t_dcar->t_dflg |= t->t_dflg & FINT; 3387c478bd9Sstevel@tonic-gate execute(t->t_dcar, wanttty); 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * In strange case of A&B make a new job after A 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate if (t->t_dcar->t_dflg&FAND && t->t_dcdr && 3437c478bd9Sstevel@tonic-gate (t->t_dcdr->t_dflg&FAND) == 0) 3447c478bd9Sstevel@tonic-gate pendjob(); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate if (t->t_dcdr) { 3477c478bd9Sstevel@tonic-gate t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); 3487c478bd9Sstevel@tonic-gate execute(t->t_dcdr, wanttty); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate break; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate case TOR: 3537c478bd9Sstevel@tonic-gate case TAND: 3547c478bd9Sstevel@tonic-gate if (t->t_dcar) { 3557c478bd9Sstevel@tonic-gate t->t_dcar->t_dflg |= t->t_dflg & FINT; 3567c478bd9Sstevel@tonic-gate execute(t->t_dcar, wanttty); 3577c478bd9Sstevel@tonic-gate if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND)) 3587c478bd9Sstevel@tonic-gate return; 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate if (t->t_dcdr) { 3617c478bd9Sstevel@tonic-gate t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); 3627c478bd9Sstevel@tonic-gate execute(t->t_dcdr, wanttty); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate break; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * Fall through for all breaks from switch 3687c478bd9Sstevel@tonic-gate * 3697c478bd9Sstevel@tonic-gate * If there will be no more executions of this 3707c478bd9Sstevel@tonic-gate * command, flush all file descriptors. 3717c478bd9Sstevel@tonic-gate * Places that turn on the FREDO bit are responsible 3727c478bd9Sstevel@tonic-gate * for doing donefds after the last re-execution 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate if (didfds && !(t->t_dflg & FREDO)) 3757c478bd9Sstevel@tonic-gate donefds(); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * If glob() was called and arguments list is not yet 3797c478bd9Sstevel@tonic-gate * free'ed, free them here. 3807c478bd9Sstevel@tonic-gate */ 3817c478bd9Sstevel@tonic-gate if (gargv) { 3827c478bd9Sstevel@tonic-gate blkfree(gargv); 3837c478bd9Sstevel@tonic-gate gargv = 0; 3847c478bd9Sstevel@tonic-gate globcnt = 0; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate #ifdef VFORK 3897c478bd9Sstevel@tonic-gate void 390*6c02b4a4Smuffin vffree(void) 3917c478bd9Sstevel@tonic-gate { 392*6c02b4a4Smuffin tchar **v; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate #ifdef TRACE 3957c478bd9Sstevel@tonic-gate tprintf("TRACE- vffree()\n"); 3967c478bd9Sstevel@tonic-gate #endif 3977c478bd9Sstevel@tonic-gate if (v = gargv) 3987c478bd9Sstevel@tonic-gate gargv = 0, xfree( (tchar *)v); 3997c478bd9Sstevel@tonic-gate if (v = pargv) 4007c478bd9Sstevel@tonic-gate pargv = 0, xfree( (tchar *)v); 4017c478bd9Sstevel@tonic-gate _exit(1); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate #endif 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * Perform io redirection. 4077c478bd9Sstevel@tonic-gate * We may or maynot be forked here. 4087c478bd9Sstevel@tonic-gate */ 409*6c02b4a4Smuffin void 410*6c02b4a4Smuffin doio(struct command *t, int *pipein, int *pipeout) 4117c478bd9Sstevel@tonic-gate { 412*6c02b4a4Smuffin tchar *cp, *dp; 413*6c02b4a4Smuffin int flags = t->t_dflg; 4147c478bd9Sstevel@tonic-gate int fd; 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate #ifdef TRACE 4177c478bd9Sstevel@tonic-gate tprintf("TRACE- doio()\n"); 4187c478bd9Sstevel@tonic-gate #endif 4197c478bd9Sstevel@tonic-gate if (didfds || (flags & FREDO)) 4207c478bd9Sstevel@tonic-gate return; 4217c478bd9Sstevel@tonic-gate if ((flags & FHERE) == 0) { /* FHERE already done */ 4227c478bd9Sstevel@tonic-gate (void) close(0); 4237c478bd9Sstevel@tonic-gate (void) unsetfd(0); 4247c478bd9Sstevel@tonic-gate if (cp = t->t_dlef) { 4257c478bd9Sstevel@tonic-gate dp = Dfix1(cp); 4267c478bd9Sstevel@tonic-gate cp = globone(dp); 4277c478bd9Sstevel@tonic-gate xfree(dp); 4287c478bd9Sstevel@tonic-gate xfree(cp); 4297c478bd9Sstevel@tonic-gate if (open_(cp, 0) < 0) 4307c478bd9Sstevel@tonic-gate Perror(cp); 4317c478bd9Sstevel@tonic-gate } else if (flags & FPIN) { 4327c478bd9Sstevel@tonic-gate fd = dup(pipein[0]); 4337c478bd9Sstevel@tonic-gate if (fd != -1) 4347c478bd9Sstevel@tonic-gate setfd(fd); 4357c478bd9Sstevel@tonic-gate (void) close(pipein[0]); 4367c478bd9Sstevel@tonic-gate (void) unsetfd(pipein[0]); 4377c478bd9Sstevel@tonic-gate (void) close(pipein[1]); 4387c478bd9Sstevel@tonic-gate (void) unsetfd(pipein[1]); 4397c478bd9Sstevel@tonic-gate } else if ((flags & FINT) && tpgrp == -1) { 4407c478bd9Sstevel@tonic-gate (void) close(0); /* no need for unsetfd */ 4417c478bd9Sstevel@tonic-gate (void) open("/dev/null", 0); /* no need for setfd */ 4427c478bd9Sstevel@tonic-gate } else { 4437c478bd9Sstevel@tonic-gate fd = dup(OLDSTD); 4447c478bd9Sstevel@tonic-gate if (fd != -1) 4457c478bd9Sstevel@tonic-gate setfd(fd); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate (void) close(1); 4497c478bd9Sstevel@tonic-gate (void) unsetfd(1); 4507c478bd9Sstevel@tonic-gate if (cp = t->t_drit) { 4517c478bd9Sstevel@tonic-gate dp = Dfix1(cp); 4527c478bd9Sstevel@tonic-gate cp = globone(dp); 4537c478bd9Sstevel@tonic-gate xfree(dp); 4547c478bd9Sstevel@tonic-gate if ((flags & FCAT) && open_(cp, 1) >= 0) 4557c478bd9Sstevel@tonic-gate (void) lseek(1, (off_t)0, 2); 4567c478bd9Sstevel@tonic-gate else { 4577c478bd9Sstevel@tonic-gate if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) { 4587c478bd9Sstevel@tonic-gate if (flags & FCAT) 4597c478bd9Sstevel@tonic-gate Perror(cp); 4607c478bd9Sstevel@tonic-gate chkclob(cp); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate if (creat_(cp, 0666) < 0) 4637c478bd9Sstevel@tonic-gate Perror(cp); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate xfree(cp); 4667c478bd9Sstevel@tonic-gate } else if (flags & FPOU) { 4677c478bd9Sstevel@tonic-gate fd = dup(pipeout[1]); 4687c478bd9Sstevel@tonic-gate if (fd != -1) 4697c478bd9Sstevel@tonic-gate setfd (fd); 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate else { 4727c478bd9Sstevel@tonic-gate fd = dup(SHOUT); 4737c478bd9Sstevel@tonic-gate if (fd != -1) 4747c478bd9Sstevel@tonic-gate setfd(fd); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate (void) close(2); 4787c478bd9Sstevel@tonic-gate (void) unsetfd(2); 4797c478bd9Sstevel@tonic-gate if (flags & FDIAG) { 4807c478bd9Sstevel@tonic-gate fd = dup(1); 4817c478bd9Sstevel@tonic-gate if (fd != -1) 4827c478bd9Sstevel@tonic-gate setfd(fd); 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate else { 4857c478bd9Sstevel@tonic-gate fd = dup(SHDIAG); 4867c478bd9Sstevel@tonic-gate if (fd != -1) 4877c478bd9Sstevel@tonic-gate setfd(fd); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate didfds = 1; 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 492*6c02b4a4Smuffin void 493*6c02b4a4Smuffin mypipe(int *pv) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate #ifdef TRACE 4977c478bd9Sstevel@tonic-gate tprintf("TRACE- mypipe()\n"); 4987c478bd9Sstevel@tonic-gate #endif 4997c478bd9Sstevel@tonic-gate if (pipe(pv) < 0) 5007c478bd9Sstevel@tonic-gate goto oops; 5017c478bd9Sstevel@tonic-gate setfd(pv[0]); 5027c478bd9Sstevel@tonic-gate setfd(pv[1]); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate pv[0] = dmove(pv[0], -1); 5057c478bd9Sstevel@tonic-gate pv[1] = dmove(pv[1], -1); 5067c478bd9Sstevel@tonic-gate if (pv[0] >= 0 && pv[1] >= 0) 5077c478bd9Sstevel@tonic-gate return; 5087c478bd9Sstevel@tonic-gate oops: 5097c478bd9Sstevel@tonic-gate error("Can't make pipe"); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 512*6c02b4a4Smuffin void 513*6c02b4a4Smuffin chkclob(tchar *cp) 5147c478bd9Sstevel@tonic-gate { 5157c478bd9Sstevel@tonic-gate struct stat stb; 5167c478bd9Sstevel@tonic-gate unsigned short type; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate #ifdef TRACE 5197c478bd9Sstevel@tonic-gate tprintf("TRACE- chkclob()\n"); 5207c478bd9Sstevel@tonic-gate #endif 5217c478bd9Sstevel@tonic-gate if (stat_(cp, &stb) < 0) 5227c478bd9Sstevel@tonic-gate return; 5237c478bd9Sstevel@tonic-gate type = stb.st_mode & S_IFMT; 5247c478bd9Sstevel@tonic-gate if (type == S_IFCHR || type == S_IFIFO) 5257c478bd9Sstevel@tonic-gate return; 5267c478bd9Sstevel@tonic-gate error("%t: File exists", cp); 5277c478bd9Sstevel@tonic-gate } 528