147823Sbostic /*-
260765Sbostic * Copyright (c) 1980, 1991, 1993
360765Sbostic * The Regents of the University of California. All rights reserved.
447823Sbostic *
547823Sbostic * %sccs.include.redist.c%
621941Sdist */
721941Sdist
817512Sedward #ifndef lint
9*69126Schristos static char sccsid[] = "@(#)sem.c 8.3 (Berkeley) 04/29/95";
1047823Sbostic #endif /* not lint */
111304Sbill
1250028Sbostic #include <sys/param.h>
1350028Sbostic #include <sys/ioctl.h>
1450028Sbostic #include <sys/stat.h>
1550028Sbostic #include <errno.h>
1650028Sbostic #include <fcntl.h>
1750028Sbostic #include <stdlib.h>
1850028Sbostic #include <string.h>
1950028Sbostic #include <unistd.h>
2050033Schristos #if __STDC__
2150033Schristos # include <stdarg.h>
2250033Schristos #else
2350033Schristos # include <varargs.h>
2450033Schristos #endif
2550033Schristos
2650023Sbostic #include "csh.h"
2750023Sbostic #include "proc.h"
2850023Sbostic #include "extern.h"
291304Sbill
3051522Schristos static void vffree __P((int));
3151522Schristos static Char *splicepipe __P((struct command *t, Char *));
3251522Schristos static void doio __P((struct command *t, int *, int *));
3351522Schristos static void chkclob __P((char *));
3449992Sbostic
3549992Sbostic void
execute(t,wanttty,pipein,pipeout)361304Sbill execute(t, wanttty, pipein, pipeout)
3749992Sbostic register struct command *t;
3849992Sbostic int wanttty, *pipein, *pipeout;
391304Sbill {
4049992Sbostic bool forked = 0;
4149992Sbostic struct biltins *bifunc;
4249992Sbostic int pid = 0;
4349992Sbostic int pv[2];
4468576Schristos sigset_t sigset;
451304Sbill
4668576Schristos static sigset_t csigset;
471304Sbill
4868576Schristos static sigset_t ocsigset;
4949992Sbostic static int onosigchld = 0;
5049992Sbostic static int nosigchld = 0;
511304Sbill
5260237Schristos UNREGISTER(forked);
5360237Schristos UNREGISTER(bifunc);
5460237Schristos UNREGISTER(wanttty);
5560237Schristos
5649992Sbostic if (t == 0)
5749992Sbostic return;
581304Sbill
5949992Sbostic if (t->t_dflg & F_AMPERSAND)
6049992Sbostic wanttty = 0;
6149992Sbostic switch (t->t_dtyp) {
621304Sbill
6349992Sbostic case NODE_COMMAND:
6449992Sbostic if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
6549992Sbostic (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
6649992Sbostic if ((t->t_dflg & F_REPEAT) == 0)
6749992Sbostic Dfix(t); /* $ " ' \ */
6849992Sbostic if (t->t_dcom[0] == 0)
6949992Sbostic return;
7049992Sbostic /* fall into... */
7139545Smarc
7249992Sbostic case NODE_PAREN:
7349992Sbostic if (t->t_dflg & F_PIPEOUT)
7449992Sbostic mypipe(pipeout);
7549992Sbostic /*
7649992Sbostic * Must do << early so parent will know where input pointer should be.
7749992Sbostic * If noexec then this is all we do.
7849992Sbostic */
7949992Sbostic if (t->t_dflg & F_READ) {
8049992Sbostic (void) close(0);
8149992Sbostic heredoc(t->t_dlef);
8249992Sbostic if (noexec)
8349992Sbostic (void) close(0);
8449992Sbostic }
851304Sbill
8649992Sbostic set(STRstatus, Strsave(STR0));
871304Sbill
8849992Sbostic /*
8949992Sbostic * This mess is the necessary kludge to handle the prefix builtins:
9049992Sbostic * nice, nohup, time. These commands can also be used by themselves,
9149992Sbostic * and this is not handled here. This will also work when loops are
9249992Sbostic * parsed.
9349992Sbostic */
9449992Sbostic while (t->t_dtyp == NODE_COMMAND)
9549992Sbostic if (eq(t->t_dcom[0], STRnice))
9649992Sbostic if (t->t_dcom[1])
9749992Sbostic if (strchr("+-", t->t_dcom[1][0]))
9849992Sbostic if (t->t_dcom[2]) {
9949992Sbostic setname("nice");
10049992Sbostic t->t_nice =
10149992Sbostic getn(t->t_dcom[1]);
10249992Sbostic lshift(t->t_dcom, 2);
10349992Sbostic t->t_dflg |= F_NICE;
1041304Sbill }
10549992Sbostic else
10649992Sbostic break;
10749992Sbostic else {
10849992Sbostic t->t_nice = 4;
10949992Sbostic lshift(t->t_dcom, 1);
11049992Sbostic t->t_dflg |= F_NICE;
11117137Sralph }
11249992Sbostic else
11349992Sbostic break;
11449992Sbostic else if (eq(t->t_dcom[0], STRnohup))
11549992Sbostic if (t->t_dcom[1]) {
11649992Sbostic t->t_dflg |= F_NOHUP;
11749992Sbostic lshift(t->t_dcom, 1);
1181304Sbill }
11949992Sbostic else
12049992Sbostic break;
12149992Sbostic else if (eq(t->t_dcom[0], STRtime))
12249992Sbostic if (t->t_dcom[1]) {
12349992Sbostic t->t_dflg |= F_TIME;
12449992Sbostic lshift(t->t_dcom, 1);
12517512Sedward }
12649992Sbostic else
12749992Sbostic break;
12849992Sbostic else
12949992Sbostic break;
1301304Sbill
13150977Schristos /* is it a command */
13249992Sbostic if (t->t_dtyp == NODE_COMMAND) {
13349992Sbostic /*
13449992Sbostic * Check if we have a builtin function and remember which one.
13549992Sbostic */
13649992Sbostic bifunc = isbfunc(t);
13750977Schristos if (noexec) {
13850977Schristos /*
13950977Schristos * Continue for builtins that are part of the scripting language
14050977Schristos */
14150977Schristos if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin &&
14250977Schristos bifunc->bfunct != doelse && bifunc->bfunct != doend &&
14350977Schristos bifunc->bfunct != doforeach && bifunc->bfunct != dogoto &&
14450977Schristos bifunc->bfunct != doif && bifunc->bfunct != dorepeat &&
14550977Schristos bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch &&
14650977Schristos bifunc->bfunct != dowhile && bifunc->bfunct != dozip)
14750977Schristos break;
14850977Schristos }
14949992Sbostic }
15049992Sbostic else { /* not a command */
15150028Sbostic bifunc = NULL;
15250977Schristos if (noexec)
15350977Schristos break;
15449992Sbostic }
15549992Sbostic
15649992Sbostic /*
15749992Sbostic * We fork only if we are timed, or are not the end of a parenthesized
15849992Sbostic * list and not a simple builtin function. Simple meaning one that is
15949992Sbostic * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
16049992Sbostic * fork in some of these cases.
16149992Sbostic */
16249992Sbostic /*
16349992Sbostic * Prevent forking cd, pushd, popd, chdir cause this will cause the
16449992Sbostic * shell not to change dir!
16549992Sbostic */
16649992Sbostic if (bifunc && (bifunc->bfunct == dochngd ||
16749992Sbostic bifunc->bfunct == dopushd ||
16849992Sbostic bifunc->bfunct == dopopd))
16949992Sbostic t->t_dflg &= ~(F_NICE);
17060237Schristos if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
17149992Sbostic (!bifunc || t->t_dflg &
17260237Schristos (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) ||
17349992Sbostic /*
17449992Sbostic * We have to fork for eval too.
17549992Sbostic */
17650439Schristos (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 &&
17749992Sbostic bifunc->bfunct == doeval))
17849992Sbostic if (t->t_dtyp == NODE_PAREN ||
17950023Sbostic t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) {
18049992Sbostic forked++;
1811304Sbill /*
18249992Sbostic * We need to block SIGCHLD here, so that if the process does
18349992Sbostic * not die before we can set the process group
1841304Sbill */
18549992Sbostic if (wanttty >= 0 && !nosigchld) {
18668576Schristos sigemptyset(&sigset);
18768576Schristos sigaddset(&sigset, SIGCHLD);
18868576Schristos sigprocmask(SIG_BLOCK, &sigset, &csigset);
18949992Sbostic nosigchld = 1;
1901304Sbill }
19149992Sbostic
19249992Sbostic pid = pfork(t, wanttty);
19349992Sbostic if (pid == 0 && nosigchld) {
19468576Schristos sigprocmask(SIG_SETMASK, &csigset, NULL);
19549992Sbostic nosigchld = 0;
1961304Sbill }
19751522Schristos else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
19851522Schristos backpid = pid;
19951522Schristos
20049992Sbostic }
20149992Sbostic else {
20249992Sbostic int ochild, osetintr, ohaderr, odidfds;
20350439Schristos int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp;
20468576Schristos sigset_t osigset;
20549992Sbostic
2061304Sbill /*
20749992Sbostic * Prepare for the vfork by saving everything that the child
20849992Sbostic * corrupts before it exec's. Note that in some signal
20949992Sbostic * implementations which keep the signal info in user space
21049992Sbostic * (e.g. Sun's) it will also be necessary to save and restore
21168576Schristos * the current sigaction's for the signals the child touches
21249992Sbostic * before it exec's.
2131304Sbill */
21449992Sbostic if (wanttty >= 0 && !nosigchld && !noexec) {
21568576Schristos sigemptyset(&sigset);
21668576Schristos sigaddset(&sigset, SIGCHLD);
21768576Schristos sigprocmask(SIG_BLOCK, &sigset, &csigset);
21849992Sbostic nosigchld = 1;
21949992Sbostic }
22068576Schristos sigemptyset(&sigset);
22168576Schristos sigaddset(&sigset, SIGCHLD);
22268576Schristos sigaddset(&sigset, SIGINT);
22368576Schristos sigprocmask(SIG_BLOCK, &sigset, &osigset);
22449992Sbostic ochild = child;
22549992Sbostic osetintr = setintr;
22649992Sbostic ohaderr = haderr;
22749992Sbostic odidfds = didfds;
22849992Sbostic oSHIN = SHIN;
22949992Sbostic oSHOUT = SHOUT;
23050439Schristos oSHERR = SHERR;
23149992Sbostic oOLDSTD = OLDSTD;
23249992Sbostic otpgrp = tpgrp;
23368576Schristos ocsigset = csigset;
23449992Sbostic onosigchld = nosigchld;
23549992Sbostic Vsav = Vdp = 0;
23649992Sbostic Vexpath = 0;
23749992Sbostic Vt = 0;
23849992Sbostic pid = vfork();
2391304Sbill
24049992Sbostic if (pid < 0) {
24168576Schristos sigprocmask(SIG_SETMASK, &osigset, NULL);
24249992Sbostic stderror(ERR_NOPROC);
24349992Sbostic }
24449992Sbostic forked++;
24549992Sbostic if (pid) { /* parent */
24649992Sbostic child = ochild;
24749992Sbostic setintr = osetintr;
24849992Sbostic haderr = ohaderr;
24949992Sbostic didfds = odidfds;
25049992Sbostic SHIN = oSHIN;
25149992Sbostic SHOUT = oSHOUT;
25250439Schristos SHERR = oSHERR;
25349992Sbostic OLDSTD = oOLDSTD;
25449992Sbostic tpgrp = otpgrp;
25568576Schristos csigset = ocsigset;
25649992Sbostic nosigchld = onosigchld;
2571304Sbill
25849992Sbostic xfree((ptr_t) Vsav);
25949992Sbostic Vsav = 0;
26049992Sbostic xfree((ptr_t) Vdp);
26149992Sbostic Vdp = 0;
26249992Sbostic xfree((ptr_t) Vexpath);
26349992Sbostic Vexpath = 0;
26449992Sbostic blkfree((Char **) Vt);
26549992Sbostic Vt = 0;
26649992Sbostic /* this is from pfork() */
26749992Sbostic palloc(pid, t);
26868576Schristos sigprocmask(SIG_SETMASK, &osigset, NULL);
2691304Sbill }
27049992Sbostic else { /* child */
27149992Sbostic /* this is from pfork() */
27249992Sbostic int pgrp;
27349992Sbostic bool ignint = 0;
27449992Sbostic
27549992Sbostic if (nosigchld) {
27668576Schristos sigprocmask(SIG_SETMASK, &csigset, NULL);
27749992Sbostic nosigchld = 0;
27849992Sbostic }
27949992Sbostic
28049992Sbostic if (setintr)
28149992Sbostic ignint =
28249992Sbostic (tpgrp == -1 &&
28349992Sbostic (t->t_dflg & F_NOINTERRUPT))
28460237Schristos || (gointr && eq(gointr, STRminus));
28549992Sbostic pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
28649992Sbostic child++;
28749992Sbostic if (setintr) {
28849992Sbostic setintr = 0;
28949992Sbostic if (ignint) {
29049992Sbostic (void) signal(SIGINT, SIG_IGN);
29149992Sbostic (void) signal(SIGQUIT, SIG_IGN);
29249992Sbostic }
29349992Sbostic else {
29449992Sbostic (void) signal(SIGINT, vffree);
29549992Sbostic (void) signal(SIGQUIT, SIG_DFL);
29649992Sbostic }
29749992Sbostic
29849992Sbostic if (wanttty >= 0) {
29949992Sbostic (void) signal(SIGTSTP, SIG_DFL);
30049992Sbostic (void) signal(SIGTTIN, SIG_DFL);
30149992Sbostic (void) signal(SIGTTOU, SIG_DFL);
30249992Sbostic }
30349992Sbostic
30449992Sbostic (void) signal(SIGTERM, parterm);
30549992Sbostic }
30649992Sbostic else if (tpgrp == -1 &&
30749992Sbostic (t->t_dflg & F_NOINTERRUPT)) {
30849992Sbostic (void) signal(SIGINT, SIG_IGN);
30949992Sbostic (void) signal(SIGQUIT, SIG_IGN);
31049992Sbostic }
31149992Sbostic
31249992Sbostic pgetty(wanttty, pgrp);
31349992Sbostic if (t->t_dflg & F_NOHUP)
31449992Sbostic (void) signal(SIGHUP, SIG_IGN);
31549992Sbostic if (t->t_dflg & F_NICE)
31649992Sbostic (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
3171304Sbill }
3181304Sbill
31949992Sbostic }
32049992Sbostic if (pid != 0) {
32149992Sbostic /*
32249992Sbostic * It would be better if we could wait for the whole job when we
32349992Sbostic * knew the last process had been started. Pwait, in fact, does
32449992Sbostic * wait for the whole job anyway, but this test doesn't really
32549992Sbostic * express our intentions.
32649992Sbostic */
32749992Sbostic if (didfds == 0 && t->t_dflg & F_PIPEIN) {
32849992Sbostic (void) close(pipein[0]);
32949992Sbostic (void) close(pipein[1]);
33049992Sbostic }
33149992Sbostic if ((t->t_dflg & F_PIPEOUT) == 0) {
33249992Sbostic if (nosigchld) {
33368576Schristos sigprocmask(SIG_SETMASK, &csigset, NULL);
33449992Sbostic nosigchld = 0;
3351304Sbill }
33649992Sbostic if ((t->t_dflg & F_AMPERSAND) == 0)
33749992Sbostic pwait();
33849992Sbostic }
33949992Sbostic break;
3401304Sbill }
34149992Sbostic doio(t, pipein, pipeout);
34249992Sbostic if (t->t_dflg & F_PIPEOUT) {
34349992Sbostic (void) close(pipeout[0]);
34449992Sbostic (void) close(pipeout[1]);
34549992Sbostic }
3461304Sbill /*
34749992Sbostic * Perform a builtin function. If we are not forked, arrange for
34849992Sbostic * possible stopping
3491304Sbill */
35049992Sbostic if (bifunc) {
35149992Sbostic func(t, bifunc);
35249992Sbostic if (forked)
35349992Sbostic exitstat();
35449992Sbostic break;
35549992Sbostic }
35649992Sbostic if (t->t_dtyp != NODE_PAREN) {
35750439Schristos doexec(NULL, t);
35849992Sbostic /* NOTREACHED */
35949992Sbostic }
36049992Sbostic /*
36149992Sbostic * For () commands must put new 0,1,2 in FSH* and recurse
36249992Sbostic */
36349992Sbostic OLDSTD = dcopy(0, FOLDSTD);
36449992Sbostic SHOUT = dcopy(1, FSHOUT);
36550439Schristos SHERR = dcopy(2, FSHERR);
36649992Sbostic (void) close(SHIN);
36749992Sbostic SHIN = -1;
36849992Sbostic didfds = 0;
36949992Sbostic wanttty = -1;
37049992Sbostic t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
37149992Sbostic execute(t->t_dspr, wanttty, NULL, NULL);
37249992Sbostic exitstat();
37349992Sbostic
37449992Sbostic case NODE_PIPE:
37549992Sbostic t->t_dcar->t_dflg |= F_PIPEOUT |
37649992Sbostic (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
37749992Sbostic execute(t->t_dcar, wanttty, pipein, pv);
37849992Sbostic t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
37949992Sbostic (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
38049992Sbostic if (wanttty > 0)
38149992Sbostic wanttty = 0; /* got tty already */
38249992Sbostic execute(t->t_dcdr, wanttty, pv, pipeout);
38349992Sbostic break;
38449992Sbostic
38549992Sbostic case NODE_LIST:
38649992Sbostic if (t->t_dcar) {
38749992Sbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
38849992Sbostic execute(t->t_dcar, wanttty, NULL, NULL);
38949992Sbostic /*
39049992Sbostic * In strange case of A&B make a new job after A
39149992Sbostic */
39249992Sbostic if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
39349992Sbostic (t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
39449992Sbostic pendjob();
39549992Sbostic }
39649992Sbostic if (t->t_dcdr) {
39749992Sbostic t->t_dcdr->t_dflg |= t->t_dflg &
39849992Sbostic (F_NOFORK | F_NOINTERRUPT);
39949992Sbostic execute(t->t_dcdr, wanttty, NULL, NULL);
40049992Sbostic }
40149992Sbostic break;
40249992Sbostic
40349992Sbostic case NODE_OR:
40449992Sbostic case NODE_AND:
40549992Sbostic if (t->t_dcar) {
40649992Sbostic t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
40749992Sbostic execute(t->t_dcar, wanttty, NULL, NULL);
40849992Sbostic if ((getn(value(STRstatus)) == 0) !=
40949992Sbostic (t->t_dtyp == NODE_AND))
41049992Sbostic return;
41149992Sbostic }
41249992Sbostic if (t->t_dcdr) {
41349992Sbostic t->t_dcdr->t_dflg |= t->t_dflg &
41449992Sbostic (F_NOFORK | F_NOINTERRUPT);
41549992Sbostic execute(t->t_dcdr, wanttty, NULL, NULL);
41649992Sbostic }
41749992Sbostic break;
41849992Sbostic }
41949992Sbostic /*
42049992Sbostic * Fall through for all breaks from switch
42149992Sbostic *
42249992Sbostic * If there will be no more executions of this command, flush all file
42349992Sbostic * descriptors. Places that turn on the F_REPEAT bit are responsible for
42449992Sbostic * doing donefds after the last re-execution
42549992Sbostic */
42649992Sbostic if (didfds && !(t->t_dflg & F_REPEAT))
42749992Sbostic donefds();
4281304Sbill }
4291304Sbill
43049992Sbostic static void
vffree(i)43150024Schristos vffree(i)
43250024Schristos int i;
4331304Sbill {
43449992Sbostic register Char **v;
4351304Sbill
43660237Schristos if ((v = gargv) != NULL) {
43749992Sbostic gargv = 0;
43849992Sbostic xfree((ptr_t) v);
43949992Sbostic }
44060237Schristos if ((v = pargv) != NULL) {
44149992Sbostic pargv = 0;
44249992Sbostic xfree((ptr_t) v);
44349992Sbostic }
44450024Schristos _exit(i);
4451304Sbill }
44649992Sbostic
4471304Sbill /*
44851522Schristos * Expand and glob the words after an i/o redirection.
44951522Schristos * If more than one word is generated, then update the command vector.
45051522Schristos *
45151522Schristos * This is done differently in all the shells:
45251522Schristos * 1. in the bourne shell and ksh globbing is not performed
45351522Schristos * 2. Bash/csh say ambiguous
45451522Schristos * 3. zsh does i/o to/from all the files
45551522Schristos * 4. itcsh concatenates the words.
45651522Schristos *
45751522Schristos * I don't know what is best to do. I think that Ambiguous is better
45851522Schristos * than restructuring the command vector, because the user can get
45951522Schristos * unexpected results. In any case, the command vector restructuring
46051522Schristos * code is present and the user can choose it by setting noambiguous
46151522Schristos */
46251522Schristos static Char *
splicepipe(t,cp)46351522Schristos splicepipe(t, cp)
46451522Schristos register struct command *t;
46551522Schristos Char *cp; /* word after < or > */
46651522Schristos {
46751522Schristos Char *blk[2];
46851522Schristos
46951522Schristos if (adrof(STRnoambiguous)) {
47051522Schristos Char **pv;
47151522Schristos
47251522Schristos blk[0] = Dfix1(cp); /* expand $ */
47351522Schristos blk[1] = NULL;
47451522Schristos
47551522Schristos gflag = 0, tglob(blk);
47651522Schristos if (gflag) {
47751522Schristos pv = globall(blk);
47851522Schristos if (pv == NULL) {
47951589Schristos setname(vis_str(blk[0]));
48051522Schristos xfree((ptr_t) blk[0]);
48151522Schristos stderror(ERR_NAME | ERR_NOMATCH);
48251522Schristos }
48351522Schristos gargv = NULL;
48451522Schristos if (pv[1] != NULL) { /* we need to fix the command vector */
48551522Schristos Char **av = blkspl(t->t_dcom, &pv[1]);
48651522Schristos xfree((ptr_t) t->t_dcom);
48751522Schristos t->t_dcom = av;
48851522Schristos }
48951522Schristos xfree((ptr_t) blk[0]);
49051522Schristos blk[0] = pv[0];
49151522Schristos xfree((ptr_t) pv);
49251522Schristos }
49351522Schristos }
49451522Schristos else {
49551522Schristos blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR);
49651522Schristos xfree((ptr_t) blk[1]);
49751522Schristos }
49851522Schristos return(blk[0]);
49951522Schristos }
50051522Schristos
50151522Schristos /*
5021304Sbill * Perform io redirection.
5031304Sbill * We may or maynot be forked here.
5041304Sbill */
50549992Sbostic static void
doio(t,pipein,pipeout)5061304Sbill doio(t, pipein, pipeout)
50749992Sbostic register struct command *t;
50849992Sbostic int *pipein, *pipeout;
5091304Sbill {
51049992Sbostic register int fd;
51151522Schristos register Char *cp;
51249992Sbostic register int flags = t->t_dflg;
5131304Sbill
51449992Sbostic if (didfds || (flags & F_REPEAT))
51549992Sbostic return;
51649992Sbostic if ((flags & F_READ) == 0) {/* F_READ already done */
51751522Schristos if (t->t_dlef) {
51850074Schristos char tmp[MAXPATHLEN+1];
51949992Sbostic
52049992Sbostic /*
52149992Sbostic * so < /dev/std{in,out,err} work
52249992Sbostic */
52349992Sbostic (void) dcopy(SHIN, 0);
52449992Sbostic (void) dcopy(SHOUT, 1);
52550439Schristos (void) dcopy(SHERR, 2);
52651522Schristos cp = splicepipe(t, t->t_dlef);
52749992Sbostic (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
52850074Schristos tmp[MAXPATHLEN] = '\0';
52949992Sbostic xfree((ptr_t) cp);
53049992Sbostic if ((fd = open(tmp, O_RDONLY)) < 0)
53149992Sbostic stderror(ERR_SYSTEM, tmp, strerror(errno));
53249992Sbostic (void) dmove(fd, 0);
5331304Sbill }
53449992Sbostic else if (flags & F_PIPEIN) {
53549992Sbostic (void) close(0);
53649992Sbostic (void) dup(pipein[0]);
53749992Sbostic (void) close(pipein[0]);
53849992Sbostic (void) close(pipein[1]);
53949992Sbostic }
54049992Sbostic else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
54149992Sbostic (void) close(0);
54249992Sbostic (void) open(_PATH_DEVNULL, O_RDONLY);
54349992Sbostic }
54449992Sbostic else {
54549992Sbostic (void) close(0);
54649992Sbostic (void) dup(OLDSTD);
54750028Sbostic (void) ioctl(0, FIONCLEX, NULL);
54849992Sbostic }
54949992Sbostic }
55051522Schristos if (t->t_drit) {
55150074Schristos char tmp[MAXPATHLEN+1];
55249992Sbostic
55351522Schristos cp = splicepipe(t, t->t_drit);
55450074Schristos (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
55550074Schristos tmp[MAXPATHLEN] = '\0';
55649992Sbostic xfree((ptr_t) cp);
55749992Sbostic /*
55849992Sbostic * so > /dev/std{out,err} work
55949992Sbostic */
56049992Sbostic (void) dcopy(SHOUT, 1);
56150439Schristos (void) dcopy(SHERR, 2);
56249992Sbostic if ((flags & F_APPEND) &&
56349992Sbostic #ifdef O_APPEND
56450074Schristos (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0);
56549992Sbostic #else
56650074Schristos (fd = open(tmp, O_WRONLY)) >= 0)
56749992Sbostic (void) lseek(1, (off_t) 0, L_XTND);
56849992Sbostic #endif
56949992Sbostic else {
57049992Sbostic if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
57149992Sbostic if (flags & F_APPEND)
57250074Schristos stderror(ERR_SYSTEM, tmp, strerror(errno));
57349992Sbostic chkclob(tmp);
57449992Sbostic }
575*69126Schristos if ((fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
57650074Schristos stderror(ERR_SYSTEM, tmp, strerror(errno));
57749992Sbostic }
57849992Sbostic (void) dmove(fd, 1);
57949992Sbostic }
58049992Sbostic else if (flags & F_PIPEOUT) {
58117512Sedward (void) close(1);
58249992Sbostic (void) dup(pipeout[1]);
58349992Sbostic }
58449992Sbostic else {
58549992Sbostic (void) close(1);
58649992Sbostic (void) dup(SHOUT);
58750028Sbostic (void) ioctl(1, FIONCLEX, NULL);
58849992Sbostic }
5891304Sbill
59049992Sbostic (void) close(2);
59149992Sbostic if (flags & F_STDERR) {
59249992Sbostic (void) dup(1);
59349992Sbostic }
59449992Sbostic else {
59550439Schristos (void) dup(SHERR);
59650028Sbostic (void) ioctl(2, FIONCLEX, NULL);
59749992Sbostic }
59849992Sbostic didfds = 1;
5991304Sbill }
6001304Sbill
60149992Sbostic void
mypipe(pv)6021304Sbill mypipe(pv)
60349992Sbostic register int *pv;
6041304Sbill {
6051304Sbill
60649992Sbostic if (pipe(pv) < 0)
60749992Sbostic goto oops;
60849992Sbostic pv[0] = dmove(pv[0], -1);
60949992Sbostic pv[1] = dmove(pv[1], -1);
61049992Sbostic if (pv[0] >= 0 && pv[1] >= 0)
61149992Sbostic return;
6121304Sbill oops:
61349992Sbostic stderror(ERR_PIPE);
6141304Sbill }
6151304Sbill
61649992Sbostic static void
chkclob(cp)6171304Sbill chkclob(cp)
61850074Schristos register char *cp;
6191304Sbill {
62049992Sbostic struct stat stb;
6211304Sbill
62250074Schristos if (stat(cp, &stb) < 0)
62349992Sbostic return;
62451522Schristos if (S_ISCHR(stb.st_mode))
62549992Sbostic return;
62650074Schristos stderror(ERR_EXISTS, cp);
6271304Sbill }
628