10Sstevel@tonic-gate /*
2*356Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
70Sstevel@tonic-gate /* All Rights Reserved */
80Sstevel@tonic-gate
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
110Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
120Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
130Sstevel@tonic-gate */
140Sstevel@tonic-gate
150Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
160Sstevel@tonic-gate
170Sstevel@tonic-gate #include <unistd.h>
180Sstevel@tonic-gate #include <fcntl.h>
190Sstevel@tonic-gate #include "sh.h"
200Sstevel@tonic-gate #include "sh.proc.h"
210Sstevel@tonic-gate #include "sh.tconst.h"
220Sstevel@tonic-gate
230Sstevel@tonic-gate /*
240Sstevel@tonic-gate * C shell
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
27*356Smuffin void doio(struct command *, int *, int *);
28*356Smuffin void mypipe(int *);
29*356Smuffin void chkclob(tchar *);
30*356Smuffin
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate * Return true if there is a back-quote (`) anywhere in the argument list.
330Sstevel@tonic-gate * Its presence would cause glob() to be invoked in the child process
340Sstevel@tonic-gate * and this would cause chaos if the child is created with vfork().
350Sstevel@tonic-gate */
360Sstevel@tonic-gate static bool
AnyBquote(struct command * t)370Sstevel@tonic-gate AnyBquote(struct command *t)
380Sstevel@tonic-gate {
390Sstevel@tonic-gate tchar **pp;
400Sstevel@tonic-gate tchar *p;
410Sstevel@tonic-gate
420Sstevel@tonic-gate if (noexec)
430Sstevel@tonic-gate return (0);
440Sstevel@tonic-gate for (pp = t->t_dcom; p = *pp++;) {
450Sstevel@tonic-gate if (any('`', p))
460Sstevel@tonic-gate return (1);
470Sstevel@tonic-gate }
480Sstevel@tonic-gate return (0);
490Sstevel@tonic-gate }
500Sstevel@tonic-gate
510Sstevel@tonic-gate /*VARARGS 1*/
52*356Smuffin void
execute(t,wanttty,pipein,pipeout)530Sstevel@tonic-gate execute(t, wanttty, pipein, pipeout)
54*356Smuffin struct command *t;
550Sstevel@tonic-gate int wanttty, *pipein, *pipeout;
560Sstevel@tonic-gate {
570Sstevel@tonic-gate bool forked = 0;
580Sstevel@tonic-gate struct biltins *bifunc;
590Sstevel@tonic-gate int pid = 0;
600Sstevel@tonic-gate int pv[2];
610Sstevel@tonic-gate extern int globcnt;
620Sstevel@tonic-gate #ifdef TRACE
630Sstevel@tonic-gate tprintf("TRACE- execute()\n");
640Sstevel@tonic-gate #endif
650Sstevel@tonic-gate
660Sstevel@tonic-gate if (t == 0)
670Sstevel@tonic-gate return;
680Sstevel@tonic-gate if ((t->t_dflg & FAND) && wanttty > 0)
690Sstevel@tonic-gate wanttty = 0;
700Sstevel@tonic-gate switch (t->t_dtyp) {
710Sstevel@tonic-gate
720Sstevel@tonic-gate case TCOM:
730Sstevel@tonic-gate if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0])
740Sstevel@tonic-gate (void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1);
750Sstevel@tonic-gate if ((t->t_dflg & FREDO) == 0)
760Sstevel@tonic-gate Dfix(t); /* $ " ' \ */
770Sstevel@tonic-gate if (t->t_dcom[0] == 0)
780Sstevel@tonic-gate return;
790Sstevel@tonic-gate /* fall into... */
800Sstevel@tonic-gate
810Sstevel@tonic-gate case TPAR:
820Sstevel@tonic-gate if (t->t_dflg & FPOU)
830Sstevel@tonic-gate mypipe(pipeout);
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate * Must do << early so parent will know
860Sstevel@tonic-gate * where input pointer should be.
870Sstevel@tonic-gate * If noexec then this is all we do.
880Sstevel@tonic-gate */
890Sstevel@tonic-gate if (t->t_dflg & FHERE) {
900Sstevel@tonic-gate (void) close(0);
910Sstevel@tonic-gate unsetfd(0);
920Sstevel@tonic-gate heredoc(t->t_dlef);
930Sstevel@tonic-gate if (noexec) {
940Sstevel@tonic-gate (void) close(0);
950Sstevel@tonic-gate unsetfd(0);
960Sstevel@tonic-gate }
970Sstevel@tonic-gate }
980Sstevel@tonic-gate if (noexec)
990Sstevel@tonic-gate break;
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate set(S_status, S_0);
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate /*
1040Sstevel@tonic-gate * This mess is the necessary kludge to handle the prefix
1050Sstevel@tonic-gate * builtins: nice, nohup, time. These commands can also
1060Sstevel@tonic-gate * be used by themselves, and this is not handled here.
1070Sstevel@tonic-gate * This will also work when loops are parsed.
1080Sstevel@tonic-gate */
1090Sstevel@tonic-gate while (t->t_dtyp == TCOM)
1100Sstevel@tonic-gate if (eq(t->t_dcom[0], S_nice /*"nice"*/))
1110Sstevel@tonic-gate if (t->t_dcom[1])
1120Sstevel@tonic-gate /*if (any(t->t_dcom[1][0], "+-"))*/
1130Sstevel@tonic-gate if (t->t_dcom[1][0] == '+' ||
1140Sstevel@tonic-gate t->t_dcom[1][0] == '-')
1150Sstevel@tonic-gate if (t->t_dcom[2]) {
1160Sstevel@tonic-gate setname(S_nice /*"nice"*/);
1170Sstevel@tonic-gate t->t_nice = getn(t->t_dcom[1]);
1180Sstevel@tonic-gate lshift(t->t_dcom, 2);
1190Sstevel@tonic-gate t->t_dflg |= FNICE;
1200Sstevel@tonic-gate } else
1210Sstevel@tonic-gate break;
1220Sstevel@tonic-gate else {
1230Sstevel@tonic-gate t->t_nice = 4;
1240Sstevel@tonic-gate lshift(t->t_dcom, 1);
1250Sstevel@tonic-gate t->t_dflg |= FNICE;
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate else
1280Sstevel@tonic-gate break;
1290Sstevel@tonic-gate else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/))
1300Sstevel@tonic-gate if (t->t_dcom[1]) {
1310Sstevel@tonic-gate t->t_dflg |= FNOHUP;
1320Sstevel@tonic-gate lshift(t->t_dcom, 1);
1330Sstevel@tonic-gate } else
1340Sstevel@tonic-gate break;
1350Sstevel@tonic-gate else if (eq(t->t_dcom[0], S_time /*"time"*/))
1360Sstevel@tonic-gate if (t->t_dcom[1]) {
1370Sstevel@tonic-gate t->t_dflg |= FTIME;
1380Sstevel@tonic-gate lshift(t->t_dcom, 1);
1390Sstevel@tonic-gate } else
1400Sstevel@tonic-gate break;
1410Sstevel@tonic-gate else
1420Sstevel@tonic-gate break;
1430Sstevel@tonic-gate /*
1440Sstevel@tonic-gate * Check if we have a builtin function and remember which one.
1450Sstevel@tonic-gate */
1460Sstevel@tonic-gate bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate * We fork only if we are timed, or are not the end of
1500Sstevel@tonic-gate * a parenthesized list and not a simple builtin function.
1510Sstevel@tonic-gate * Simple meaning one that is not pipedout, niced, nohupped,
1520Sstevel@tonic-gate * or &'d.
1530Sstevel@tonic-gate * It would be nice(?) to not fork in some of these cases.
1540Sstevel@tonic-gate */
1550Sstevel@tonic-gate if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
1560Sstevel@tonic-gate (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
1570Sstevel@tonic-gate #ifdef VFORK
1580Sstevel@tonic-gate if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) ||
1590Sstevel@tonic-gate bifunc || AnyBquote(t))
1600Sstevel@tonic-gate #endif
1610Sstevel@tonic-gate { forked++; pid = pfork(t, wanttty); }
1620Sstevel@tonic-gate #ifdef VFORK
1630Sstevel@tonic-gate else {
1640Sstevel@tonic-gate void vffree();
1650Sstevel@tonic-gate struct sv {
1660Sstevel@tonic-gate int mask, child, setintr, haderr, didfds;
1670Sstevel@tonic-gate int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp;
1680Sstevel@tonic-gate struct sigvec sigv;
1690Sstevel@tonic-gate } sv;
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /*
1720Sstevel@tonic-gate * Prepare for the vfork by saving everything
1730Sstevel@tonic-gate * that the child corrupts before it exec's.
1740Sstevel@tonic-gate * Note that in some signal implementations
1750Sstevel@tonic-gate * which keep the signal info in user space
1760Sstevel@tonic-gate * (e.g. Sun's) it will also be necessary to
1770Sstevel@tonic-gate * save and restore the current sigvec's for
1780Sstevel@tonic-gate * the signals the child touches before it
1790Sstevel@tonic-gate * exec's.
1800Sstevel@tonic-gate */
1810Sstevel@tonic-gate sv.mask = sigblock(sigmask(SIGCHLD));
1820Sstevel@tonic-gate sv.child = child; sv.setintr = setintr;
1830Sstevel@tonic-gate sv.haderr = haderr; sv.didfds = didfds;
1840Sstevel@tonic-gate sv.SHIN = SHIN; sv.SHOUT = SHOUT;
1850Sstevel@tonic-gate sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD;
1860Sstevel@tonic-gate sv.tpgrp = tpgrp;
1870Sstevel@tonic-gate Vsav = Vdp = 0; Vav = 0;
1880Sstevel@tonic-gate (void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv);
1890Sstevel@tonic-gate pid = vfork();
1900Sstevel@tonic-gate if (pid < 0) {
1910Sstevel@tonic-gate (void) sigsetmask(sv.mask);
1920Sstevel@tonic-gate error("Vfork failed");
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate forked++;
1950Sstevel@tonic-gate if (pid) { /* parent */
1960Sstevel@tonic-gate int ppid;
1970Sstevel@tonic-gate closelog();
1980Sstevel@tonic-gate child = sv.child; setintr = sv.setintr;
1990Sstevel@tonic-gate haderr = sv.haderr; didfds = sv.didfds;
2000Sstevel@tonic-gate SHIN = sv.SHIN;
2010Sstevel@tonic-gate SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG;
2020Sstevel@tonic-gate OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp;
2030Sstevel@tonic-gate xfree(Vsav); Vsav = 0;
2040Sstevel@tonic-gate xfree(Vdp); Vdp = 0;
2050Sstevel@tonic-gate xfree( (tchar *)Vav); Vav = 0;
2060Sstevel@tonic-gate /* this is from pfork() */
2070Sstevel@tonic-gate ppid = pcurrjob ? pcurrjob->p_jobid : pid;
2080Sstevel@tonic-gate if (wanttty >= 0 && tpgrp >= 0)
2090Sstevel@tonic-gate setpgid (ppid, ppid);
2100Sstevel@tonic-gate palloc(pid, t);
2110Sstevel@tonic-gate /*
2120Sstevel@tonic-gate * Restore SIGINT handler.
2130Sstevel@tonic-gate */
2140Sstevel@tonic-gate (void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0);
2150Sstevel@tonic-gate (void) sigsetmask(sv.mask);
2160Sstevel@tonic-gate } else { /* child */
2170Sstevel@tonic-gate /* this is from pfork() */
2180Sstevel@tonic-gate int pgrp;
2190Sstevel@tonic-gate bool ignint = 0;
2200Sstevel@tonic-gate int sigttou;
2210Sstevel@tonic-gate if (setintr)
2220Sstevel@tonic-gate ignint =
2230Sstevel@tonic-gate (tpgrp == -1 && (t->t_dflg&FINT))
2240Sstevel@tonic-gate || gointr
2250Sstevel@tonic-gate && eq(gointr, S_MINUS/*"-"*/);
2260Sstevel@tonic-gate pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
2270Sstevel@tonic-gate child++;
2280Sstevel@tonic-gate if (setintr) {
2290Sstevel@tonic-gate setintr = 0;
2300Sstevel@tonic-gate #ifdef notdef
2310Sstevel@tonic-gate (void) signal(SIGCHLD, SIG_DFL);
2320Sstevel@tonic-gate #endif
2330Sstevel@tonic-gate (void) signal(SIGINT, ignint ?
2340Sstevel@tonic-gate SIG_IGN : vffree);
2350Sstevel@tonic-gate (void) signal(SIGQUIT, ignint ?
2360Sstevel@tonic-gate SIG_IGN : SIG_DFL);
2370Sstevel@tonic-gate if (wanttty >= 0) {
2380Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL);
2390Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_DFL);
2400Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_DFL);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate (void) signal(SIGTERM, parterm);
2430Sstevel@tonic-gate } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
2440Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN);
2450Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate if (wanttty >= 0 && tpgrp >= 0)
2480Sstevel@tonic-gate (void) setpgid(0, pgrp);
2490Sstevel@tonic-gate if (wanttty > 0) {
2500Sstevel@tonic-gate sigttou = sigblock (
2510Sstevel@tonic-gate sigmask(SIGTTOU) |
2520Sstevel@tonic-gate sigmask(SIGTTIN) |
2530Sstevel@tonic-gate sigmask(SIGTSTP));
2540Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP,
2550Sstevel@tonic-gate (tchar *)&pgrp);
2560Sstevel@tonic-gate sigsetmask (sigttou);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate if (tpgrp > 0)
2590Sstevel@tonic-gate tpgrp = 0;
2600Sstevel@tonic-gate if (t->t_dflg & FNOHUP)
2610Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN);
2620Sstevel@tonic-gate if (t->t_dflg & FNICE)
2630Sstevel@tonic-gate (void) setpriority(PRIO_PROCESS,
2640Sstevel@tonic-gate 0, t->t_nice);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate #endif
2690Sstevel@tonic-gate if (pid != 0) {
2700Sstevel@tonic-gate /*
2710Sstevel@tonic-gate * It would be better if we could wait for the
2720Sstevel@tonic-gate * whole job when we knew the last process
2730Sstevel@tonic-gate * had been started. Pwait, in fact, does
2740Sstevel@tonic-gate * wait for the whole job anyway, but this test
2750Sstevel@tonic-gate * doesn't really express our intentions.
2760Sstevel@tonic-gate */
2770Sstevel@tonic-gate if (didfds==0 && t->t_dflg&FPIN) {
2780Sstevel@tonic-gate (void) close(pipein[0]);
2790Sstevel@tonic-gate unsetfd(pipein[0]);
2800Sstevel@tonic-gate (void) close(pipein[1]);
2810Sstevel@tonic-gate unsetfd(pipein[1]);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate if ((t->t_dflg & (FPOU|FAND)) == 0)
2840Sstevel@tonic-gate pwait();
2850Sstevel@tonic-gate break;
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate doio(t, pipein, pipeout);
2880Sstevel@tonic-gate if (t->t_dflg & FPOU) {
2890Sstevel@tonic-gate (void) close(pipeout[0]);
2900Sstevel@tonic-gate (void) unsetfd(pipeout[0]);
2910Sstevel@tonic-gate (void) close(pipeout[1]);
2920Sstevel@tonic-gate (void) unsetfd(pipeout[1]);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate * Perform a builtin function.
2970Sstevel@tonic-gate * If we are not forked, arrange for possible stopping
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate if (bifunc) {
3000Sstevel@tonic-gate func(t, bifunc);
3010Sstevel@tonic-gate if (forked)
3020Sstevel@tonic-gate exitstat();
3030Sstevel@tonic-gate break;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate if (t->t_dtyp != TPAR) {
3060Sstevel@tonic-gate doexec(t);
3070Sstevel@tonic-gate /*NOTREACHED*/
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate * For () commands must put new 0,1,2 in FSH* and recurse
3110Sstevel@tonic-gate */
3120Sstevel@tonic-gate OLDSTD = dcopy(0, FOLDSTD);
3130Sstevel@tonic-gate SHOUT = dcopy(1, FSHOUT);
3140Sstevel@tonic-gate SHDIAG = dcopy(2, FSHDIAG);
3150Sstevel@tonic-gate (void) close(SHIN);
3160Sstevel@tonic-gate (void) unsetfd(SHIN);
3170Sstevel@tonic-gate SHIN = -1;
3180Sstevel@tonic-gate didfds = 0;
3190Sstevel@tonic-gate wanttty = -1;
3200Sstevel@tonic-gate t->t_dspr->t_dflg |= t->t_dflg & FINT;
3210Sstevel@tonic-gate execute(t->t_dspr, wanttty);
3220Sstevel@tonic-gate exitstat();
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate case TFIL:
3250Sstevel@tonic-gate t->t_dcar->t_dflg |= FPOU |
3260Sstevel@tonic-gate (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
3270Sstevel@tonic-gate execute(t->t_dcar, wanttty, pipein, pv);
3280Sstevel@tonic-gate t->t_dcdr->t_dflg |= FPIN |
3290Sstevel@tonic-gate (t->t_dflg & (FPOU|FAND|FPAR|FINT));
3300Sstevel@tonic-gate if (wanttty > 0)
3310Sstevel@tonic-gate wanttty = 0; /* got tty already */
3320Sstevel@tonic-gate execute(t->t_dcdr, wanttty, pv, pipeout);
3330Sstevel@tonic-gate break;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate case TLST:
3360Sstevel@tonic-gate if (t->t_dcar) {
3370Sstevel@tonic-gate t->t_dcar->t_dflg |= t->t_dflg & FINT;
3380Sstevel@tonic-gate execute(t->t_dcar, wanttty);
3390Sstevel@tonic-gate /*
3400Sstevel@tonic-gate * In strange case of A&B make a new job after A
3410Sstevel@tonic-gate */
3420Sstevel@tonic-gate if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
3430Sstevel@tonic-gate (t->t_dcdr->t_dflg&FAND) == 0)
3440Sstevel@tonic-gate pendjob();
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate if (t->t_dcdr) {
3470Sstevel@tonic-gate t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
3480Sstevel@tonic-gate execute(t->t_dcdr, wanttty);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate break;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate case TOR:
3530Sstevel@tonic-gate case TAND:
3540Sstevel@tonic-gate if (t->t_dcar) {
3550Sstevel@tonic-gate t->t_dcar->t_dflg |= t->t_dflg & FINT;
3560Sstevel@tonic-gate execute(t->t_dcar, wanttty);
3570Sstevel@tonic-gate if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND))
3580Sstevel@tonic-gate return;
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate if (t->t_dcdr) {
3610Sstevel@tonic-gate t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
3620Sstevel@tonic-gate execute(t->t_dcdr, wanttty);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate break;
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate /*
3670Sstevel@tonic-gate * Fall through for all breaks from switch
3680Sstevel@tonic-gate *
3690Sstevel@tonic-gate * If there will be no more executions of this
3700Sstevel@tonic-gate * command, flush all file descriptors.
3710Sstevel@tonic-gate * Places that turn on the FREDO bit are responsible
3720Sstevel@tonic-gate * for doing donefds after the last re-execution
3730Sstevel@tonic-gate */
3740Sstevel@tonic-gate if (didfds && !(t->t_dflg & FREDO))
3750Sstevel@tonic-gate donefds();
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate * If glob() was called and arguments list is not yet
3790Sstevel@tonic-gate * free'ed, free them here.
3800Sstevel@tonic-gate */
3810Sstevel@tonic-gate if (gargv) {
3820Sstevel@tonic-gate blkfree(gargv);
3830Sstevel@tonic-gate gargv = 0;
3840Sstevel@tonic-gate globcnt = 0;
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate #ifdef VFORK
3890Sstevel@tonic-gate void
vffree(void)390*356Smuffin vffree(void)
3910Sstevel@tonic-gate {
392*356Smuffin tchar **v;
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate #ifdef TRACE
3950Sstevel@tonic-gate tprintf("TRACE- vffree()\n");
3960Sstevel@tonic-gate #endif
3970Sstevel@tonic-gate if (v = gargv)
3980Sstevel@tonic-gate gargv = 0, xfree( (tchar *)v);
3990Sstevel@tonic-gate if (v = pargv)
4000Sstevel@tonic-gate pargv = 0, xfree( (tchar *)v);
4010Sstevel@tonic-gate _exit(1);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate #endif
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * Perform io redirection.
4070Sstevel@tonic-gate * We may or maynot be forked here.
4080Sstevel@tonic-gate */
409*356Smuffin void
doio(struct command * t,int * pipein,int * pipeout)410*356Smuffin doio(struct command *t, int *pipein, int *pipeout)
4110Sstevel@tonic-gate {
412*356Smuffin tchar *cp, *dp;
413*356Smuffin int flags = t->t_dflg;
4140Sstevel@tonic-gate int fd;
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate #ifdef TRACE
4170Sstevel@tonic-gate tprintf("TRACE- doio()\n");
4180Sstevel@tonic-gate #endif
4190Sstevel@tonic-gate if (didfds || (flags & FREDO))
4200Sstevel@tonic-gate return;
4210Sstevel@tonic-gate if ((flags & FHERE) == 0) { /* FHERE already done */
4220Sstevel@tonic-gate (void) close(0);
4230Sstevel@tonic-gate (void) unsetfd(0);
4240Sstevel@tonic-gate if (cp = t->t_dlef) {
4250Sstevel@tonic-gate dp = Dfix1(cp);
4260Sstevel@tonic-gate cp = globone(dp);
4270Sstevel@tonic-gate xfree(dp);
4280Sstevel@tonic-gate xfree(cp);
4290Sstevel@tonic-gate if (open_(cp, 0) < 0)
4300Sstevel@tonic-gate Perror(cp);
4310Sstevel@tonic-gate } else if (flags & FPIN) {
4320Sstevel@tonic-gate fd = dup(pipein[0]);
4330Sstevel@tonic-gate if (fd != -1)
4340Sstevel@tonic-gate setfd(fd);
4350Sstevel@tonic-gate (void) close(pipein[0]);
4360Sstevel@tonic-gate (void) unsetfd(pipein[0]);
4370Sstevel@tonic-gate (void) close(pipein[1]);
4380Sstevel@tonic-gate (void) unsetfd(pipein[1]);
4390Sstevel@tonic-gate } else if ((flags & FINT) && tpgrp == -1) {
4400Sstevel@tonic-gate (void) close(0); /* no need for unsetfd */
4410Sstevel@tonic-gate (void) open("/dev/null", 0); /* no need for setfd */
4420Sstevel@tonic-gate } else {
4430Sstevel@tonic-gate fd = dup(OLDSTD);
4440Sstevel@tonic-gate if (fd != -1)
4450Sstevel@tonic-gate setfd(fd);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate (void) close(1);
4490Sstevel@tonic-gate (void) unsetfd(1);
4500Sstevel@tonic-gate if (cp = t->t_drit) {
4510Sstevel@tonic-gate dp = Dfix1(cp);
4520Sstevel@tonic-gate cp = globone(dp);
4530Sstevel@tonic-gate xfree(dp);
4540Sstevel@tonic-gate if ((flags & FCAT) && open_(cp, 1) >= 0)
4550Sstevel@tonic-gate (void) lseek(1, (off_t)0, 2);
4560Sstevel@tonic-gate else {
4570Sstevel@tonic-gate if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) {
4580Sstevel@tonic-gate if (flags & FCAT)
4590Sstevel@tonic-gate Perror(cp);
4600Sstevel@tonic-gate chkclob(cp);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate if (creat_(cp, 0666) < 0)
4630Sstevel@tonic-gate Perror(cp);
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate xfree(cp);
4660Sstevel@tonic-gate } else if (flags & FPOU) {
4670Sstevel@tonic-gate fd = dup(pipeout[1]);
4680Sstevel@tonic-gate if (fd != -1)
4690Sstevel@tonic-gate setfd (fd);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate else {
4720Sstevel@tonic-gate fd = dup(SHOUT);
4730Sstevel@tonic-gate if (fd != -1)
4740Sstevel@tonic-gate setfd(fd);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate (void) close(2);
4780Sstevel@tonic-gate (void) unsetfd(2);
4790Sstevel@tonic-gate if (flags & FDIAG) {
4800Sstevel@tonic-gate fd = dup(1);
4810Sstevel@tonic-gate if (fd != -1)
4820Sstevel@tonic-gate setfd(fd);
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate else {
4850Sstevel@tonic-gate fd = dup(SHDIAG);
4860Sstevel@tonic-gate if (fd != -1)
4870Sstevel@tonic-gate setfd(fd);
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate didfds = 1;
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate
492*356Smuffin void
mypipe(int * pv)493*356Smuffin mypipe(int *pv)
4940Sstevel@tonic-gate {
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate #ifdef TRACE
4970Sstevel@tonic-gate tprintf("TRACE- mypipe()\n");
4980Sstevel@tonic-gate #endif
4990Sstevel@tonic-gate if (pipe(pv) < 0)
5000Sstevel@tonic-gate goto oops;
5010Sstevel@tonic-gate setfd(pv[0]);
5020Sstevel@tonic-gate setfd(pv[1]);
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate pv[0] = dmove(pv[0], -1);
5050Sstevel@tonic-gate pv[1] = dmove(pv[1], -1);
5060Sstevel@tonic-gate if (pv[0] >= 0 && pv[1] >= 0)
5070Sstevel@tonic-gate return;
5080Sstevel@tonic-gate oops:
5090Sstevel@tonic-gate error("Can't make pipe");
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate
512*356Smuffin void
chkclob(tchar * cp)513*356Smuffin chkclob(tchar *cp)
5140Sstevel@tonic-gate {
5150Sstevel@tonic-gate struct stat stb;
5160Sstevel@tonic-gate unsigned short type;
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate #ifdef TRACE
5190Sstevel@tonic-gate tprintf("TRACE- chkclob()\n");
5200Sstevel@tonic-gate #endif
5210Sstevel@tonic-gate if (stat_(cp, &stb) < 0)
5220Sstevel@tonic-gate return;
5230Sstevel@tonic-gate type = stb.st_mode & S_IFMT;
5240Sstevel@tonic-gate if (type == S_IFCHR || type == S_IFIFO)
5250Sstevel@tonic-gate return;
5260Sstevel@tonic-gate error("%t: File exists", cp);
5270Sstevel@tonic-gate }
528