* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley Software License Agreement
* specifies the terms and conditions for redistribution.
static char *sccsid
= "@(#)sem.c 5.4 (Berkeley) %G%";
execute(t
, wanttty
, pipein
, pipeout
)
register struct command
*t
;
int wanttty
, *pipein
, *pipeout
;
if ((t
->t_dflg
& FAND
) && wanttty
> 0)
if ((t
->t_dcom
[0][0] & (QUOTE
|TRIM
)) == QUOTE
)
(void) strcpy(t
->t_dcom
[0], t
->t_dcom
[0] + 1);
if ((t
->t_dflg
& FREDO
) == 0)
* Must do << early so parent will know
* where input pointer should be.
* If noexec then this is all we do.
* This mess is the necessary kludge to handle the prefix
* builtins: nice, nohup, time. These commands can also
* be used by themselves, and this is not handled here.
* This will also work when loops are parsed.
while (t
->t_dtyp
== TCOM
)
if (eq(t
->t_dcom
[0], "nice"))
if (any(t
->t_dcom
[1][0], "+-"))
t
->t_nice
= getn(t
->t_dcom
[1]);
else if (eq(t
->t_dcom
[0], "nohup"))
else if (eq(t
->t_dcom
[0], "time"))
* Check if we have a builtin function and remember which one.
bifunc
= t
->t_dtyp
== TCOM
? isbfunc(t
) : (struct biltins
*) 0;
* We fork only if we are timed, or are not the end of
* a parenthesized list and not a simple builtin function.
* Simple meaning one that is not pipedout, niced, nohupped,
* It would be nice(?) to not fork in some of these cases.
if (((t
->t_dflg
& FTIME
) || (t
->t_dflg
& FPAR
) == 0 &&
(!bifunc
|| t
->t_dflg
& (FPOU
|FAND
|FNICE
|FNOHUP
))))
if (t
->t_dtyp
== TPAR
|| t
->t_dflg
&(FREDO
|FAND
) || bifunc
)
{ forked
++; pid
= pfork(t
, wanttty
); }
int ochild
, osetintr
, ohaderr
, odidfds
;
int oSHIN
, oSHOUT
, oSHDIAG
, oOLDSTD
, otpgrp
;
* Prepare for the vfork by saving everything
* that the child corrupts before it exec's.
* Note that in some signal implementations
* which keep the signal info in user space
* (e.g. Sun's) it will also be necessary to
* save and restore the current sigvec's for
* the signals the child touches before it
omask
= sigblock(sigmask(SIGCHLD
));
ochild
= child
; osetintr
= setintr
;
ohaderr
= haderr
; odidfds
= didfds
;
oSHIN
= SHIN
; oSHOUT
= SHOUT
;
oSHDIAG
= SHDIAG
; oOLDSTD
= OLDSTD
; otpgrp
= tpgrp
;
(void) sigsetmask(omask
);
error("No more processes");
child
= ochild
; setintr
= osetintr
;
haderr
= ohaderr
; didfds
= odidfds
;
SHOUT
= oSHOUT
; SHDIAG
= oSHDIAG
;
OLDSTD
= oOLDSTD
; tpgrp
= otpgrp
;
xfree((char *)Vav
); Vav
= 0;
/* this is from pfork() */
(void) sigsetmask(omask
);
/* this is from pfork() */
(tpgrp
== -1 && (t
->t_dflg
&FINT
))
|| gointr
&& eq(gointr
, "-");
pgrp
= pcurrjob
? pcurrjob
->p_jobid
: getpid();
(void) signal(SIGCHLD
, SIG_DFL
);
(void) signal(SIGINT
, ignint
?
(void) signal(SIGQUIT
, ignint
?
(void) signal(SIGTSTP
, SIG_DFL
);
(void) signal(SIGTTIN
, SIG_DFL
);
(void) signal(SIGTTOU
, SIG_DFL
);
(void) signal(SIGTERM
, parterm
);
} else if (tpgrp
== -1 && (t
->t_dflg
&FINT
)) {
(void) signal(SIGINT
, SIG_IGN
);
(void) signal(SIGQUIT
, SIG_IGN
);
(void) ioctl(FSHTTY
, TIOCSPGRP
,
if (wanttty
>= 0 && tpgrp
>= 0)
(void) signal(SIGHUP
, SIG_IGN
);
(void) setpriority(PRIO_PROCESS
,
* It would be better if we could wait for the
* whole job when we knew the last process
* had been started. Pwait, in fact, does
* wait for the whole job anyway, but this test
* doesn't really express our intentions.
if (didfds
==0 && t
->t_dflg
&FPIN
) {
if ((t
->t_dflg
& (FPOU
|FAND
)) == 0)
doio(t
, pipein
, pipeout
);
(void) close(pipeout
[0]);
(void) close(pipeout
[1]);
* Perform a builtin function.
* If we are not forked, arrange for possible stopping
* For () commands must put new 0,1,2 in FSH* and recurse
OLDSTD
= dcopy(0, FOLDSTD
);
SHOUT
= dcopy(1, FSHOUT
);
SHDIAG
= dcopy(2, FSHDIAG
);
t
->t_dspr
->t_dflg
|= t
->t_dflg
& FINT
;
execute(t
->t_dspr
, wanttty
);
t
->t_dcar
->t_dflg
|= FPOU
|
(t
->t_dflg
& (FPIN
|FAND
|FDIAG
|FINT
));
execute(t
->t_dcar
, wanttty
, pipein
, pv
);
t
->t_dcdr
->t_dflg
|= FPIN
|
(t
->t_dflg
& (FPOU
|FAND
|FPAR
|FINT
));
wanttty
= 0; /* got tty already */
execute(t
->t_dcdr
, wanttty
, pv
, pipeout
);
t
->t_dcar
->t_dflg
|= t
->t_dflg
& FINT
;
execute(t
->t_dcar
, wanttty
);
* In strange case of A&B make a new job after A
if (t
->t_dcar
->t_dflg
&FAND
&& t
->t_dcdr
&&
(t
->t_dcdr
->t_dflg
&FAND
) == 0)
t
->t_dcdr
->t_dflg
|= t
->t_dflg
& (FPAR
|FINT
);
execute(t
->t_dcdr
, wanttty
);
t
->t_dcar
->t_dflg
|= t
->t_dflg
& FINT
;
execute(t
->t_dcar
, wanttty
);
if ((getn(value("status")) == 0) != (t
->t_dtyp
== TAND
))
t
->t_dcdr
->t_dflg
|= t
->t_dflg
& (FPAR
|FINT
);
execute(t
->t_dcdr
, wanttty
);
* Fall through for all breaks from switch
* If there will be no more executions of this
* command, flush all file descriptors.
* Places that turn on the FREDO bit are responsible
* for doing donefds after the last re-execution
if (didfds
&& !(t
->t_dflg
& FREDO
))
gargv
= 0, xfree((char *)v
);
pargv
= 0, xfree((char *)v
);
* Perform io redirection.
* We may or maynot be forked here.
register struct command
*t
;
register int flags
= t
->t_dflg
;
if (didfds
|| (flags
& FREDO
))
if ((flags
& FHERE
) == 0) { /* FHERE already done */
} else if (flags
& FPIN
) {
} else if ((flags
& FINT
) && tpgrp
== -1) {
(void) open("/dev/null", 0);
if ((flags
& FCAT
) && open(cp
, 1) >= 0)
(void) lseek(1, (off_t
)0, 2);
if (!(flags
& FANY
) && adrof("noclobber")) {
pv
[0] = dmove(pv
[0], -1);
pv
[1] = dmove(pv
[1], -1);
if (pv
[0] >= 0 && pv
[1] >= 0)
error("Can't make pipe");
if ((stb
.st_mode
& S_IFMT
) == S_IFCHR
)
error("%s: File exists", cp
);