/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley Software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <fcntl.h>
#include "sh.h"
#include "sh.proc.h"
#include "sh.tconst.h"
/*
* C shell
*/
void mypipe(int *);
/*
* Return true if there is a back-quote (`) anywhere in the argument list.
* Its presence would cause glob() to be invoked in the child process
* and this would cause chaos if the child is created with vfork().
*/
static bool
{
tchar *p;
if (noexec)
return (0);
if (any('`', p))
return (1);
}
return (0);
}
/*VARARGS 1*/
void
struct command *t;
{
bool forked = 0;
int pid = 0;
extern int globcnt;
#ifdef TRACE
tprintf("TRACE- execute()\n");
#endif
if (t == 0)
return;
wanttty = 0;
switch (t->t_dtyp) {
case TCOM:
Dfix(t); /* $ " ' \ */
if (t->t_dcom[0] == 0)
return;
/* fall into... */
case TPAR:
/*
* Must do << early so parent will know
* where input pointer should be.
* If noexec then this is all we do.
*/
(void) close(0);
unsetfd(0);
if (noexec) {
(void) close(0);
unsetfd(0);
}
}
if (noexec)
break;
/*
* 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.
*/
if (t->t_dcom[1])
/*if (any(t->t_dcom[1][0], "+-"))*/
if (t->t_dcom[2]) {
} else
break;
else {
t->t_nice = 4;
}
else
break;
if (t->t_dcom[1]) {
} else
break;
if (t->t_dcom[1]) {
} else
break;
else
break;
/*
* Check if we have a builtin function and remember which one.
*/
/*
* 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,
* or &'d.
* It would be nice(?) to not fork in some of these cases.
*/
#ifdef VFORK
#endif
#ifdef VFORK
else {
void vffree();
struct sv {
} sv;
/*
* 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
* exec's.
*/
if (pid < 0) {
error("Vfork failed");
}
forked++;
if (pid) { /* parent */
int ppid;
closelog();
/* this is from pfork() */
/*
* Restore SIGINT handler.
*/
} else { /* child */
/* this is from pfork() */
int pgrp;
bool ignint = 0;
int sigttou;
if (setintr)
ignint =
|| gointr
child++;
if (setintr) {
setintr = 0;
#ifdef notdef
#endif
if (wanttty >= 0) {
}
}
if (wanttty > 0) {
}
if (tpgrp > 0)
tpgrp = 0;
(void) setpriority(PRIO_PROCESS,
0, t->t_nice);
}
}
#endif
if (pid != 0) {
/*
* 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.
*/
}
pwait();
break;
}
}
/*
* Perform a builtin function.
* If we are not forked, arrange for possible stopping
*/
if (bifunc) {
if (forked)
exitstat();
break;
}
doexec(t);
/*NOTREACHED*/
}
/*
* For () commands must put new 0,1,2 in FSH* and recurse
*/
SHIN = -1;
didfds = 0;
wanttty = -1;
exitstat();
case TFIL:
if (wanttty > 0)
wanttty = 0; /* got tty already */
break;
case TLST:
if (t->t_dcar) {
/*
* In strange case of A&B make a new job after A
*/
pendjob();
}
if (t->t_dcdr) {
}
break;
case TOR:
case TAND:
if (t->t_dcar) {
return;
}
if (t->t_dcdr) {
}
break;
}
/*
* 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
*/
donefds();
/*
* If glob() was called and arguments list is not yet
* free'ed, free them here.
*/
if (gargv) {
gargv = 0;
globcnt = 0;
}
}
#ifdef VFORK
void
vffree(void)
{
tchar **v;
#ifdef TRACE
tprintf("TRACE- vffree()\n");
#endif
if (v = gargv)
if (v = pargv)
_exit(1);
}
#endif
/*
* Perform io redirection.
* We may or maynot be forked here.
*/
void
{
int fd;
#ifdef TRACE
tprintf("TRACE- doio()\n");
#endif
return;
(void) close(0);
(void) unsetfd(0);
if (fd != -1)
(void) close(0); /* no need for unsetfd */
} else {
if (fd != -1)
}
}
(void) close(1);
(void) unsetfd(1);
else {
}
}
if (fd != -1)
}
else {
if (fd != -1)
}
(void) close(2);
(void) unsetfd(2);
if (fd != -1)
}
else {
if (fd != -1)
}
didfds = 1;
}
void
{
#ifdef TRACE
tprintf("TRACE- mypipe()\n");
#endif
goto oops;
return;
oops:
error("Can't make pipe");
}
void
{
unsigned short type;
#ifdef TRACE
tprintf("TRACE- chkclob()\n");
#endif
return;
return;
}