Exemplo n.º 1
0
/*ARGSUSED*/
void
dowhich(Char **v, struct command *c)
{
    struct wordent lexw[3];
    struct varent *vp;

    lexw[0].next = &lexw[1];
    lexw[1].next = &lexw[2];
    lexw[2].next = &lexw[0];

    lexw[0].prev = &lexw[2];
    lexw[1].prev = &lexw[0];
    lexw[2].prev = &lexw[1];

    lexw[0].word = STRNULL;
    lexw[2].word = STRret;

    while (*++v) {
	if ((vp = adrof1(*v, &aliases)) != NULL) {
	    (void)fprintf(cshout, "%s: \t aliased to ", vis_str(*v));
	    blkpr(cshout, vp->vec);
	    (void)fputc('\n', cshout);
	    set(STRstatus, Strsave(STR0));
	}
	else {
	    lexw[1].word = *v;
	    set(STRstatus, Strsave(tellmewhat(lexw, NULL) ? STR0 : STR1));
	}
    }
}
Exemplo n.º 2
0
/*
 * dfollow - change to arg directory; fall back on cdpath if not valid
 */
static Char *
dfollow(Char *cp)
{
    Char *dp;
    struct varent *c;
    char    ebuf[PATH_MAX];
    int serrno;

    cp = globone(cp, G_ERROR);
    /*
     * if we are ignoring symlinks, try to fix relatives now.
     */
    dp = dnormalize(cp);
    if (chdir(short2str(dp)) >= 0) {
	free(cp);
	return dgoto(dp);
    }
    else {
	free(dp);
	if (chdir(short2str(cp)) >= 0)
	    return dgoto(cp);
	serrno = errno;
    }

    if (cp[0] != '/' && !prefix(STRdotsl, cp) && !prefix(STRdotdotsl, cp)
	&& (c = adrof(STRcdpath))) {
	Char  **cdp;
	Char *p;
	Char    buf[PATH_MAX];

	for (cdp = c->vec; *cdp; cdp++) {
	    for (dp = buf, p = *cdp; (*dp++ = *p++) != '\0';)
		continue;
	    dp[-1] = '/';
	    for (p = cp; (*dp++ = *p++) != '\0';)
		continue;
	    if (chdir(short2str(buf)) >= 0) {
		printd = 1;
		free(cp);
		cp = Strsave(buf);
		return dgoto(cp);
	    }
	}
    }
    dp = value(cp);
    if ((dp[0] == '/' || dp[0] == '.') && chdir(short2str(dp)) >= 0) {
	free(cp);
	cp = Strsave(dp);
	printd = 1;
	return dgoto(cp);
    }
    (void) strlcpy(ebuf, short2str(cp), sizeof ebuf);
    free(cp);
    stderror(ERR_SYSTEM, ebuf, strerror(serrno));
    return (NULL);
}
Exemplo n.º 3
0
Char   *
globone(Char *str, int action)
{
    Char   *v[2], **vl, **vo;
    int gflg, noglob;

    noglob = adrof(STRnoglob) != 0;
    v[0] = str;
    v[1] = 0;
    gflg = tglob(v);
    if (gflg == G_NONE)
	return (strip(Strsave(str)));

    if (gflg & G_CSH) {
	/*
	 * Expand back-quote, tilde and brace
	 */
	vo = globexpand(v, noglob);
	if (noglob || (gflg & G_GLOB) == 0) {
	    vl = vo;
	    goto result;
	}
	cleanup_push(vo, blk_cleanup);
    }
    else if (noglob || (gflg & G_GLOB) == 0)
	return (strip(Strsave(str)));
    else
	vo = v;

    vl = libglob(vo);
    if (gflg & G_CSH) {
    	if (vl != vo)
	    cleanup_until(vo);
	else
	    cleanup_ignore(vo);
    }
    if (vl == NULL) {
	setname(short2str(str));
	stderror(ERR_NAME | ERR_NOMATCH);
    }
 result:
    if (vl && vl[0] == NULL) {
	xfree(vl);
	return (Strsave(STRNULL));
    }
    if (vl && vl[1]) 
	return (handleone(str, vl, action));
    else {
	str = strip(*vl);
	xfree(vl);
	return (str);
    }
}
Exemplo n.º 4
0
Arquivo: set.c Projeto: Open343/bitrig
void
setq(Char *name, Char **vec, struct varent *p)
{
    struct varent *c;
    int f;

    f = 0;			/* tree hangs off the header's left link */
    while ((c = p->v_link[f]) != NULL) {
	if ((f = *name - *c->v_name) == 0 &&
	    (f = Strcmp(name, c->v_name)) == 0) {
	    blkfree(c->vec);
	    goto found;
	}
	p = c;
	f = f > 0;
    }
    p->v_link[f] = c = (struct varent *) xmalloc((size_t) sizeof(struct varent));
    c->v_name = Strsave(name);
    c->v_bal = 0;
    c->v_left = c->v_right = 0;
    c->v_parent = p;
    balance(p, f, 0);
found:
    trim(c->vec = vec);
}
Exemplo n.º 5
0
static Char *
globtilde(Char *s)
{
    Char *name, *u, *home, *res;

    u = s;
    for (s++; *s && *s != '/' && *s != ':'; s++)
	continue;
    name = Strnsave(u + 1, s - (u + 1));
    cleanup_push(name, xfree);
    home = gethdir(name);
    if (home == NULL) {
	if (adrof(STRnonomatch)) {
	    cleanup_until(name);
	    return u;
	}
	if (*name)
	    stderror(ERR_UNKUSER, short2str(name));
	else
	    stderror(ERR_NOHOME);
    }
    cleanup_until(name);
    if (home[0] == '/' && home[1] == '\0' && s[0] == '/')
	res = Strsave(s);
    else
	res = Strspl(home, s);
    xfree(home);
    xfree(u);
    return res;
}
Exemplo n.º 6
0
void
setq(const Char *name, Char **vec, struct varent *p, int flags)
{
    struct varent *c;
    int f;

    f = 0;			/* tree hangs off the header's left link */
    while ((c = p->v_link[f]) != 0) {
	if ((f = *name - *c->v_name) == 0 &&
	    (f = Strcmp(name, c->v_name)) == 0) {
	    if (c->v_flags & VAR_READONLY)
		stderror(ERR_READONLY|ERR_NAME, c->v_name);
	    blkfree(c->vec);
	    c->v_flags = flags;
	    trim(c->vec = vec);
	    return;
	}
	p = c;
	f = f > 0;
    }
    p->v_link[f] = c = xmalloc(sizeof(struct varent));
    c->v_name = Strsave(name);
    c->v_flags = flags;
    c->v_bal = 0;
    c->v_left = c->v_right = 0;
    c->v_parent = p;
    balance(p, f, 0);
    trim(c->vec = vec);
}
Exemplo n.º 7
0
static Char *
handleone(Char *str, Char **vl, int action)
{
    size_t chars;
    Char **t, *p, *strp;

    switch (action) {
    case G_ERROR:
	setname(short2str(str));
	blkfree(vl);
	stderror(ERR_NAME | ERR_AMBIG);
	break;
    case G_APPEND:
	chars = 0;
	for (t = vl; (p = *t++) != NULL; chars++)
	    chars += Strlen(p);
	str = xmalloc(chars * sizeof(Char));
	for (t = vl, strp = str; (p = *t++) != '\0'; chars++) {
	    while (*p)
		 *strp++ = *p++ & TRIM;
	    *strp++ = ' ';
	}
	*--strp = '\0';
	blkfree(vl);
	break;
    case G_IGNORE:
	str = Strsave(strip(*vl));
	blkfree(vl);
	break;
    default:
	break;
    }
    return (str);
}
Exemplo n.º 8
0
void
importpath(Char *cp)
{
    Char *dp, **pv;
    int c, i;

    i = 0;
    for (dp = cp; *dp; dp++)
	if (*dp == ':')
	    i++;
    /*
     * i+2 where i is the number of colons in the path. There are i+1
     * directories in the path plus we need room for a zero terminator.
     */
    pv = (Char **)xcalloc((size_t) (i + 2), sizeof(Char **));
    dp = cp;
    i = 0;
    if (*dp)
	for (;;) {
	    if ((c = *dp) == ':' || c == 0) {
		*dp = 0;
		pv[i++] = Strsave(*cp ? cp : STRdot);
		if (c) {
		    cp = dp + 1;
		    *dp = ':';
		}
		else
		    break;
	    }
	    dp++;
	}
    pv[i] = 0;
    setq(STRpath, pv, &shvhed);
}
Exemplo n.º 9
0
Arquivo: sh.dir.c Projeto: lukem/tcsh
void
dsetstack(void)
{
    Char **cp;
    struct varent *vp;
    struct directory *dn, *dp;

    if ((vp = adrof(STRdirstack)) == NULL || vp->vec == NULL)
	return;

    /* Free the whole stack */
    while ((dn = dhead.di_prev) != &dhead) {
	dn->di_next->di_prev = dn->di_prev;
	dn->di_prev->di_next = dn->di_next;
	if (dn != dcwd)
	    dfree(dn);
    }

    /* thread the current working directory */
    dhead.di_prev = dhead.di_next = dcwd;
    dcwd->di_next = dcwd->di_prev = &dhead;

    /* put back the stack */
    for (cp = vp->vec; cp && *cp && **cp; cp++) {
	dp = xcalloc(sizeof(struct directory), 1);
	dp->di_name = Strsave(*cp);
	dp->di_count = 0;
	dp->di_prev = dcwd;
	dp->di_next = dcwd->di_next;
	dcwd->di_next = dp;
	dp->di_next->di_prev = dp;
    }
    dgetstack();	/* Make $dirstack reflect the current state */
}
Exemplo n.º 10
0
void
setcopy(const Char *var, const Char *val, int flags)
{
    Char *copy;

    copy = Strsave(val);
    cleanup_push(copy, xfree);
    setv(var, copy, flags);
    cleanup_ignore(copy);
    cleanup_until(copy);
}
Exemplo n.º 11
0
static Char *
xset(Char *cp, Char ***vp)
{
    Char *dp;

    if (*cp) {
	dp = Strsave(cp);
	--(*vp);
	xfree(** vp);
	**vp = dp;
    }
    return (putn(expr(vp)));
}
Exemplo n.º 12
0
Arquivo: sh.set.c Projeto: aosm/tcsh
Char   *
putn(int n)
{
    Char nbuf[(CHAR_BIT * sizeof (n) + 2) / 3 + 2]; /* Enough even for octal */

    putp = nbuf;
    if (n < 0) {
	n = -n;
	*putp++ = '-';
    }
    putn1(n);
    *putp = 0;
    return (Strsave(nbuf));
}
Exemplo n.º 13
0
Arquivo: sh.dir.c Projeto: lukem/tcsh
/*ARGSUSED*/
void
dochngd(Char **v, struct command *c)
{
    Char *cp;
    struct directory *dp;
    int dflag = skipargs(&v, "plvn", "[-|<dir>]");

    USE(c);
    printd = 0;
    cp = (dflag & DIR_OLD) ? varval(STRowd) : *v;

    if (cp == NULL) {
	if (!cdtohome)
	    stderror(ERR_NAME | ERR_TOOFEW);
	else if ((cp = varval(STRhome)) == STRNULL || *cp == 0)
	    stderror(ERR_NAME | ERR_NOHOMEDIR);
	if (chdir(short2str(cp)) < 0)
	    stderror(ERR_NAME | ERR_CANTCHANGE);
	cp = Strsave(cp);
    }
    else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) {
	stderror(ERR_NAME | ERR_TOOMANY);
	/* NOTREACHED */
	return;
    }
    else if ((dp = dfind(cp)) != 0) {
	char   *tmp;

	printd = 1;
	if (chdir(tmp = short2str(dp->di_name)) < 0)
	    stderror(ERR_SYSTEM, tmp, strerror(errno));
	dcwd->di_prev->di_next = dcwd->di_next;
	dcwd->di_next->di_prev = dcwd->di_prev;
	dfree(dcwd);
	dnewcwd(dp, dflag);
	return;
    }
    else
	if ((cp = dfollow(cp, dflag & DIR_OLD)) == NULL)
	    return;
    dp = xcalloc(sizeof(struct directory), 1);
    dp->di_name = cp;
    dp->di_count = 0;
    dp->di_next = dcwd->di_next;
    dp->di_prev = dcwd->di_prev;
    dp->di_prev->di_next = dp;
    dp->di_next->di_prev = dp;
    dfree(dcwd);
    dnewcwd(dp, dflag);
}
Exemplo n.º 14
0
static void
dset(Char *dp)
{
    /*
     * Don't call set() directly cause if the directory contains ` or
     * other junk characters glob will fail.
     */
    Char **vec = xreallocarray(NULL, 2, sizeof(*vec));

    vec[0] = Strsave(dp);
    vec[1] = 0;
    setq(STRcwd, vec, &shvhed);
    Setenv(STRPWD, dp);
}
Exemplo n.º 15
0
static void
dset(Char *dp)
{
    /*
     * Don't call set() directly cause if the directory contains ` or
     * other junk characters glob will fail.
     */
    Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));

    vec[0] = Strsave(dp);
    vec[1] = 0;
    setq(STRcwd, vec, &shvhed);
    Setenv(STRPWD, dp);
}
Exemplo n.º 16
0
Char *
putn(tcsh_number_t n)
{
    Char nbuf[1024]; /* Enough even for octal */

    putp = nbuf;
    if (n < 0) {
	n = -n;
	*putp++ = '-';
    }
    putn1(n);
    *putp = 0;
    return (Strsave(nbuf));
}
Exemplo n.º 17
0
/*
 * dochngd - implement chdir command.
 */
void
/*ARGSUSED*/
dochngd(Char **v, struct command *t)
{
    Char *cp;
    struct directory *dp;

    skipargs(&v, " [<dir>]");
    printd = 0;
    if (*v == NULL) {
	if ((cp = value(STRhome)) == NULL || *cp == 0)
	    stderror(ERR_NAME | ERR_NOHOMEDIR);
	if (chdir(short2str(cp)) < 0)
	    stderror(ERR_NAME | ERR_CANTCHANGE);
	cp = Strsave(cp);
    }
    else if (v[1] != NULL) {
	stderror(ERR_NAME | ERR_TOOMANY);
	/* NOTREACHED */
	return;
    }
    else if ((dp = dfind(*v)) != 0) {
	char   *tmp;

	printd = 1;
	if (chdir(tmp = short2str(dp->di_name)) < 0)
	    stderror(ERR_SYSTEM, tmp, strerror(errno));
	dcwd->di_prev->di_next = dcwd->di_next;
	dcwd->di_next->di_prev = dcwd->di_prev;
	dfree(dcwd);
	dnewcwd(dp);
	return;
    }
    else
	cp = dfollow(*v);
    dp = xcalloc(1, sizeof(struct directory));
    dp->di_name = cp;
    dp->di_count = 0;
    dp->di_next = dcwd->di_next;
    dp->di_prev = dcwd->di_prev;
    dp->di_prev->di_next = dp;
    dp->di_next->di_prev = dp;
    dfree(dcwd);
    dnewcwd(dp);
}
Exemplo n.º 18
0
/*
 * $ substitute one word, for i/o redirection
 */
Char   *
Dfix1(Char *cp)
{
    Char   *Dv[2];

    if (noexec)
	return (0);
    Dv[0] = cp;
    Dv[1] = NULL;
    Dfix2(Dv);
    if (gargc != 1) {
	setname(vis_str(cp));
	stderror(ERR_NAME | ERR_AMBIG);
    }
    cp = Strsave(gargv[0]);
    blkfree(gargv), gargv = 0;
    return (cp);
}
Exemplo n.º 19
0
/*
 * $ substitute one word, for i/o redirection
 */
Char   *
Dfix1(Char *cp)
{
    Char *Dv[2], **expanded;

    if (noexec)
	return (0);
    Dv[0] = cp;
    Dv[1] = NULL;
    expanded = Dfix2(Dv);
    if (expanded[0] == NULL || expanded[1] != NULL) {
	blkfree(expanded);
	setname(short2str(cp));
	stderror(ERR_NAME | ERR_AMBIG);
    }
    cp = Strsave(expanded[0]);
    blkfree(expanded);
    return (cp);
}
Exemplo n.º 20
0
int
Gnmatch(const Char *string, const Char *pattern, const Char **endstr)
{
    Char ***fblk, **p;
    const Char *tstring = string;
    int	   gpol = 1, gres = 0;

    if (*pattern == '^') {
	gpol = 0;
	pattern++;
    }

    fblk = xmalloc(sizeof(Char ***));
    *fblk = xmalloc(GLOBSPACE * sizeof(Char *));
    (*fblk)[0] = Strsave(pattern);
    (*fblk)[1] = NULL;

    cleanup_push(fblk, blk_indirect_cleanup);
    expbrace(fblk, NULL, GLOBSPACE);

    if (endstr == NULL)
	/* Exact matches only */
	for (p = *fblk; *p; p++) 
	    gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0;
    else {
	const Char *end;

	/* partial matches */
        end = Strend(string);
	for (p = *fblk; *p; p++)
	    if (t_pmatch(string, *p, &tstring, 1) != 0) {
		gres |= 1;
		if (end > tstring)
		    end = tstring;
	    }
	*endstr = end;
    }

    cleanup_until(fblk);
    return(gres == gpol);
} 
Exemplo n.º 21
0
Arquivo: sh.dir.c Projeto: lukem/tcsh
static void
dgetstack(void)
{
    int i = 0;
    Char **dblk, **dbp;
    struct directory *dn;

    if (adrof(STRdirstack) == NULL) 
    	return;

    for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev, i++)
	continue;
    dbp = dblk = xmalloc((i + 1) * sizeof(Char *));
    for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev, dbp++)
	 *dbp = Strsave(dn->di_name);
    *dbp = NULL;
    cleanup_push(dblk, blk_cleanup);
    setq(STRdirstack, dblk, &shvhed, VAR_READWRITE);
    cleanup_ignore(dblk);
    cleanup_until(dblk);
}
Exemplo n.º 22
0
/*ARGSUSED*/
void
dolist(Char **v, struct command *c)
{
    Char **globbed;
    int     i, k, ret = 0;
    struct stat st;

    USE(c);
    if (*++v == NULL) {
	struct Strbuf word = Strbuf_INIT;

	Strbuf_terminate(&word);
	cleanup_push(&word, Strbuf_cleanup);
	(void) t_search(&word, LIST, TW_ZERO, 0, STRNULL, 0);
	cleanup_until(&word);
	return;
    }
    v = glob_all_or_error(v);
    globbed = v;
    cleanup_push(globbed, blk_cleanup);
    for (k = 0; v[k] != NULL && v[k][0] != '-'; k++)
	continue;
    if (v[k]) {
	/*
	 * We cannot process a flag therefore we let ls do it right.
	 */
	Char *lspath;
	struct command *t;
	struct wordent cmd, *nextword, *lastword;
	Char   *cp;
	struct varent *vp;

	if (setintr) {
	    pintr_disabled++;
	    cleanup_push(&pintr_disabled, disabled_cleanup);
	}
	if (seterr) {
	    xfree(seterr);
	    seterr = NULL;
	}

	lspath = STRls;
	STRmCF[1] = 'C';
	STRmCF[3] = '\0';
	/* Look at listflags, to add -A to the flags, to get a path
	   of ls if necessary */
	if ((vp = adrof(STRlistflags)) != NULL && vp->vec != NULL &&
	    vp->vec[0] != STRNULL) {
	    if (vp->vec[1] != NULL && vp->vec[1][0] != '\0')
		lspath = vp->vec[1];
	    for (cp = vp->vec[0]; *cp; cp++)
		switch (*cp) {
		case 'x':
		    STRmCF[1] = 'x';
		    break;
		case 'a':
		    STRmCF[3] = 'a';
		    break;
		case 'A':
		    STRmCF[3] = 'A';
		    break;
		default:
		    break;
		}
	}

	cmd.word = STRNULL;
	lastword = &cmd;
	nextword = xcalloc(1, sizeof cmd);
	nextword->word = Strsave(lspath);
	lastword->next = nextword;
	nextword->prev = lastword;
	lastword = nextword;
	nextword = xcalloc(1, sizeof cmd);
	nextword->word = Strsave(STRmCF);
	lastword->next = nextword;
	nextword->prev = lastword;
#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
	if (dspmbyte_ls) {
	    lastword = nextword;
	    nextword = xcalloc(1, sizeof cmd);
	    nextword->word = Strsave(STRmmliteral);
	    lastword->next = nextword;
	    nextword->prev = lastword;
	}
#endif
#ifdef COLOR_LS_F
	if (color_context_ls) {
	    lastword = nextword;
	    nextword = xcalloc(1, sizeof cmd);
	    nextword->word = Strsave(STRmmcolormauto);
	    lastword->next = nextword;
	    nextword->prev = lastword;
	}
#endif /* COLOR_LS_F */
	lastword = nextword;
	for (cp = *v; cp; cp = *++v) {
	    nextword = xcalloc(1, sizeof cmd);
	    nextword->word = quote(Strsave(cp));
	    lastword->next = nextword;
	    nextword->prev = lastword;
	    lastword = nextword;
	}
	lastword->next = &cmd;
	cmd.prev = lastword;
	cleanup_push(&cmd, lex_cleanup);

	/* build a syntax tree for the command. */
	t = syntax(cmd.next, &cmd, 0);
	cleanup_push(t, syntax_cleanup);
	if (seterr)
	    stderror(ERR_OLD);
	/* expand aliases like process() does */
	/* alias(&cmd); */
	/* execute the parse tree. */
	execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL, FALSE);
	/* done. free the lex list and parse tree. */
	cleanup_until(&cmd);
	if (setintr)
	    cleanup_until(&pintr_disabled);
    }
    else {
	Char   *dp, *tmp;
	struct Strbuf buf = Strbuf_INIT;

	cleanup_push(&buf, Strbuf_cleanup);
	for (k = 0, i = 0; v[k] != NULL; k++) {
	    tmp = dnormalize(v[k], symlinks == SYM_IGNORE);
	    cleanup_push(tmp, xfree);
	    dp = Strend(tmp) - 1;
	    if (*dp == '/' && dp != tmp)
#ifdef apollo
		if (dp != &tmp[1])
#endif /* apollo */
		*dp = '\0';
	    if (stat(short2str(tmp), &st) == -1) {
		int err;

		err = errno;
		if (k != i) {
		    if (i != 0)
			xputchar('\n');
		    print_by_column(STRNULL, &v[i], k - i, FALSE);
		}
		haderr = 1;
		xprintf("%S: %s.\n", tmp, strerror(err));
		haderr = 0;
		i = k + 1;
		ret = 1;
	    }
	    else if (S_ISDIR(st.st_mode)) {
		Char   *cp;

		if (k != i) {
		    if (i != 0)
			xputchar('\n');
		    print_by_column(STRNULL, &v[i], k - i, FALSE);
		}
		if (k != 0 && v[1] != NULL)
		    xputchar('\n');
		xprintf("%S:\n", tmp);
		buf.len = 0;
		for (cp = tmp; *cp; cp++)
		    Strbuf_append1(&buf, (*cp | QUOTE));
		Strbuf_terminate(&buf);
		dp = &buf.s[buf.len - 1];
		if (
#ifdef WINNT_NATIVE
		    (*dp != (Char) (':' | QUOTE)) &&
#endif /* WINNT_NATIVE */
		    (*dp != (Char) ('/' | QUOTE))) {
		    Strbuf_append1(&buf, '/');
		    Strbuf_terminate(&buf);
		} else 
		    *dp &= TRIM;
		(void) t_search(&buf, LIST, TW_ZERO, 0, STRNULL, 0);
		i = k + 1;
	    }
	    cleanup_until(tmp);
	}
	cleanup_until(&buf);
	if (k != i) {
	    if (i != 0)
		xputchar('\n');
	    print_by_column(STRNULL, &v[i], k - i, FALSE);
	}
	if (ret)
	    stderror(ERR_SILENT);
    }

    cleanup_until(globbed);
}
Exemplo n.º 23
0
/*
 * Execute command f, arg list t.
 * Record error message if not found.
 * Also do shell scripts here.
 */
static void
texec(Char *sf, Char **st)
{
    struct varent *v;
    Char *lastsh[2], **vp, *st0, **ost;
    char *f, **t;
    int fd;
    unsigned char c = '\0';

    /* The order for the conversions is significant */
    t = short2blk(st);
    f = short2str(sf);
    Vt = t;
    errno = 0;			/* don't use a previous error */
    (void)execve(f, t, environ);
    Vt = 0;
    blkfree((Char **)t);
    switch (errno) {

    case ENOEXEC:
	/*
	 * From: [email protected] (Casper H.S. Dik) If we could not execute
	 * it, don't feed it to the shell if it looks like a binary!
	 */
	if ((fd = open(f, O_RDONLY)) != -1) {
	    if (read(fd, (char *)&c, 1) == 1) {
		if (!Isprint(c) && (c != '\n' && c != '\t')) {
		    (void)close(fd);
		    /*
		     * We *know* what ENOEXEC means.
		     */
		    stderror(ERR_ARCH, f, strerror(errno));
		}
	    }
#ifdef _PATH_BSHELL
	    else
		c = '#';
#endif
	    (void)close(fd);
	}
	/*
	 * If there is an alias for shell, then put the words of the alias in
	 * front of the argument list replacing the command name. Note no
	 * interpretation of the words at this point.
	 */
	v = adrof1(STRshell, &aliases);
	if (v == 0) {
	    vp = lastsh;
	    vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH;
	    vp[1] = NULL;
#ifdef _PATH_BSHELL
	    if (fd != -1 && c != '#')
		vp[0] = STR_BSHELL;
#endif
	}
	else
	    vp = v->vec;
	st0 = st[0];
	st[0] = sf;
	ost = st;
	st = blkspl(vp, st);	/* Splice up the new arglst */
	ost[0] = st0;
	sf = *st;
	/* The order for the conversions is significant */
	t = short2blk(st);
	f = short2str(sf);
	free(st);
	Vt = t;
	(void)execve(f, t, environ);
	Vt = 0;
	blkfree((Char **)t);
	/* FALLTHROUGH */

    case ENOMEM:
	stderror(ERR_SYSTEM, f, strerror(errno));
	/* NOTREACHED */

    case ENOENT:
	break;

    default:
	if (exerr == 0) {
	    exerr = strerror(errno);
	    if (expath)
		free(expath);
	    expath = Strsave(sf);
	    Vexpath = expath;
	}
    }
}
Exemplo n.º 24
0
void
/*ARGSUSED*/
doexec(Char **v, struct command *t)
{
    struct varent *pathv;
    Char *blk[2], **av, *dp, **pv, *sav;
    int i, hashval, hashval1;
    sigset_t nsigset;
    int slash;

    hashval = 0;
    /*
     * Glob the command name. We will search $path even if this does something,
     * as in sh but not in csh.  One special case: if there is no PATH, then we
     * execute only commands which start with '/'.
     */
    blk[0] = t->t_dcom[0];
    blk[1] = 0;
    gflag = 0, tglob(blk);
    if (gflag) {
	pv = globall(blk);
	if (pv == 0) {
	    setname(vis_str(blk[0]));
	    stderror(ERR_NAME | ERR_NOMATCH);
	}
	gargv = 0;
    }
    else
	pv = saveblk(blk);

    trim(pv);

    exerr = 0;
    expath = Strsave(pv[0]);
    Vexpath = expath;

    pathv = adrof(STRpath);
    if (pathv == 0 && expath[0] != '/') {
	blkfree(pv);
	pexerr();
    }
    slash = any(short2str(expath), '/');

    /*
     * Glob the argument list, if necessary. Otherwise trim off the quote bits.
     */
    gflag = 0;
    av = &t->t_dcom[1];
    tglob(av);
    if (gflag) {
	av = globall(av);
	if (av == 0) {
	    blkfree(pv);
	    setname(vis_str(expath));
	    stderror(ERR_NAME | ERR_NOMATCH);
	}
	gargv = 0;
    }
    else
	av = saveblk(av);

    blkfree(t->t_dcom);
    t->t_dcom = blkspl(pv, av);
    free(pv);
    free(av);
    av = t->t_dcom;
    trim(av);

    if (*av == NULL || **av == '\0')
	pexerr();

    xechoit(av);		/* Echo command if -x */
    /*
     * Since all internal file descriptors are set to close on exec, we don't
     * need to close them explicitly here.  Just reorient ourselves for error
     * messages.
     */
    SHIN = 0;
    SHOUT = 1;
    SHERR = 2;
    OLDSTD = 0;
    /*
     * We must do this AFTER any possible forking (like `foo` in glob) so that
     * this shell can still do subprocesses.
     */
    sigemptyset(&nsigset);
    (void)sigprocmask(SIG_SETMASK, &nsigset, NULL);
    /*
     * If no path, no words in path, or a / in the filename then restrict the
     * command search.
     */
    if (pathv == 0 || pathv->vec[0] == 0 || slash)
	pv = justabs;
    else
	pv = pathv->vec;
    sav = Strspl(STRslash, *av); 	/* / command name for postpending */
    Vsav = sav;
    if (havhash)
	hashval = hashname(*av);
    i = 0;
    hits++;
    do {
	/*
	 * Try to save time by looking at the hash table for where this command
	 * could be.  If we are doing delayed hashing, then we put the names in
	 * one at a time, as the user enters them.  This is kinda like Korn
	 * Shell's "tracked aliases".
	 */
	if (!slash && pv[0][0] == '/' && havhash) {
	    hashval1 = hash(hashval, i);
	    if (!bit(xhash, hashval1))
		goto cont;
	}
	if (pv[0][0] == 0 || eq(pv[0], STRdot))	/* don't make ./xxx */
	    texec(*av, av);
	else {
	    dp = Strspl(*pv, sav);
	    Vdp = dp;
	    texec(dp, av);
	    Vdp = 0;
	    free(dp);
	}
	misses++;
cont:
	pv++;
	i++;
    } while (*pv);
    hits--;
    Vsav = 0;
    free(sav);
    pexerr();
    /* NOTREACHED */
}
Exemplo n.º 25
0
static void
update_vars(Char *vp)
{
    if (eq(vp, STRpath)) {
	struct varent *p = adrof(STRpath); 
	if (p == NULL)
	    stderror(ERR_NAME | ERR_UNDVAR);
	else {
	    exportpath(p->vec);
	    dohash(NULL, NULL);
	}
    }
    else if (eq(vp, STRnoclobber)) {
	struct varent *p = adrof(STRnoclobber);
	if (p == NULL)
	    stderror(ERR_NAME | ERR_UNDVAR);
	else
	    no_clobber = set_noclobber(p->vec);
    }
    else if (eq(vp, STRhistchars)) {
	Char *pn = varval(vp);

	HIST = *pn++;
	if (HIST)
	    HISTSUB = *pn;
	else
	    HISTSUB = HIST;
    }
    else if (eq(vp, STRpromptchars)) {
	Char *pn = varval(vp);

	PRCH = *pn++;
	if (PRCH)
	    PRCHROOT = *pn;
	else
	    PRCHROOT = PRCH;
    }
    else if (eq(vp, STRhistlit)) {
	HistLit = 1;
    }
    else if (eq(vp, STRuser)) {
	tsetenv(STRKUSER, varval(vp));
	tsetenv(STRLOGNAME, varval(vp));
    }
    else if (eq(vp, STRgroup)) {
	tsetenv(STRKGROUP, varval(vp));
    }
    else if (eq(vp, STRwordchars)) {
	word_chars = varval(vp);
    }
    else if (eq(vp, STRloginsh)) {
	loginsh = 1;
    }
    else if (eq(vp, STRanyerror)) {
	anyerror = 1;
    }
    else if (eq(vp, STRsymlinks)) {
	Char *pn = varval(vp);

	if (eq(pn, STRignore))
	    symlinks = SYM_IGNORE;
	else if (eq(pn, STRexpand))
	    symlinks = SYM_EXPAND;
	else if (eq(pn, STRchase))
	    symlinks = SYM_CHASE;
	else
	    symlinks = 0;
    }
    else if (eq(vp, STRterm)) {
	Char *cp = varval(vp);
	tsetenv(STRKTERM, cp);
#ifdef DOESNT_WORK_RIGHT
	cp = getenv("TERMCAP");
	if (cp && (*cp != '/'))	/* if TERMCAP and not a path */
	    Unsetenv(STRTERMCAP);
#endif /* DOESNT_WORK_RIGHT */
	GotTermCaps = 0;
	if (noediting && Strcmp(cp, STRnetwork) != 0 &&
	    Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
	    editing = 1;
	    noediting = 0;
	    setNS(STRedit);
	}
	ed_Init();		/* reset the editor */
    }
    else if (eq(vp, STRhome)) {
	Char *cp, *canon;

	cp = Strsave(varval(vp));	/* get the old value back */
	cleanup_push(cp, xfree);

	/*
	 * convert to cononical pathname (possibly resolving symlinks)
	 */
	canon = dcanon(cp, cp);
	cleanup_ignore(cp);
	cleanup_until(cp);
	cleanup_push(canon, xfree);

	setcopy(vp, canon, VAR_READWRITE);	/* have to save the new val */

	/* and now mirror home with HOME */
	tsetenv(STRKHOME, canon);
	/* fix directory stack for new tilde home */
	dtilde();
	cleanup_until(canon);
    }
    else if (eq(vp, STRedit)) {
	editing = 1;
	noediting = 0;
	/* PWP: add more stuff in here later */
    }
    else if (eq(vp, STRvimode)) {
	VImode = 1;
	update_wordchars();
    }
    else if (eq(vp, STRshlvl)) {
	tsetenv(STRKSHLVL, varval(vp));
    }
    else if (eq(vp, STRignoreeof)) {
	Char *cp;
	numeof = 0;
    	for ((cp = varval(STRignoreeof)); cp && *cp; cp++) {
	    if (!Isdigit(*cp)) {
		numeof = 0;
		break;
	    }
	    numeof = numeof * 10 + *cp - '0';
	}
	if (numeof <= 0) numeof = 26;	/* Sanity check */
    } 
    else if (eq(vp, STRbackslash_quote)) {
	bslash_quote = 1;
    }
    else if (eq(vp, STRcompat_expr)) {
	compat_expr = 1;
    }
    else if (eq(vp, STRdirstack)) {
	dsetstack();
    }
    else if (eq(vp, STRrecognize_only_executables)) {
	tw_cmd_free();
    }
    else if (eq(vp, STRkillring)) {
	SetKillRing((int)getn(varval(vp)));
    }
    else if (eq(vp, STRhistory)) {
	sethistory((int)getn(varval(vp)));
    }
#ifndef HAVENOUTMP
    else if (eq(vp, STRwatch)) {
	resetwatch();
    }
#endif /* HAVENOUTMP */
    else if (eq(vp, STRimplicitcd)) {
	implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
    }
    else if (eq(vp, STRcdtohome)) {
	cdtohome = 1;
    }
#ifdef COLOR_LS_F
    else if (eq(vp, STRcolor)) {
	set_color_context();
    }
#endif /* COLOR_LS_F */
#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
    else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
	update_dspmbyte_vars();
    }
#endif
#ifdef NLS_CATALOGS
    else if (eq(vp, STRcatalog)) {
	nlsclose();
	nlsinit();
    }
#if defined(FILEC) && defined(TIOCSTI)
    else if (eq(vp, STRfilec))
	filec = 1;
#endif
#endif /* NLS_CATALOGS */
}
Exemplo n.º 26
0
/*ARGSUSED*/
void
dolet(Char **v, struct command *dummy)
{
    Char *p;
    Char   *vp, c, op;
    int    hadsub;
    int     subscr;

    USE(dummy);
    v++;
    p = *v++;
    if (p == 0) {
	prvars();
	return;
    }
    do {
	hadsub = 0;
	vp = p;
	if (letter(*p))
	    for (; alnum(*p); p++)
		continue;
	if (vp == p || !letter(*vp))
	    stderror(ERR_NAME | ERR_VARBEGIN);
	if (*p == '[') {
	    hadsub++;
	    p = getinx(p, &subscr);
	}
	if (*p == 0 && *v)
	    p = *v++;
	if ((op = *p) != 0)
	    *p++ = 0;
	else
	    stderror(ERR_NAME | ERR_ASSIGN);

	/*
	 * if there is no expression after the '=' then print a "Syntax Error"
	 * message - strike
	 */
	if (*p == '\0' && *v == NULL)
	    stderror(ERR_NAME | ERR_ASSIGN);

	vp = Strsave(vp);
	cleanup_push(vp, xfree);
	if (op == '=') {
	    c = '=';
	    p = xset(p, &v);
	}
	else {
	    c = *p++;
	    if (any("+-", c)) {
		if (c != op || *p)
		    stderror(ERR_NAME | ERR_UNKNOWNOP);
		p = Strsave(STR1);
	    }
	    else {
		if (any("<>", op)) {
		    if (c != op)
			stderror(ERR_NAME | ERR_UNKNOWNOP);
		    stderror(ERR_NAME | ERR_SYNTAX);
		}
		if (c != '=')
		    stderror(ERR_NAME | ERR_UNKNOWNOP);
		p = xset(p, &v);
	    }
	}
	cleanup_push(p, xfree);
	if (op == '=') {
	    if (hadsub)
		asx(vp, subscr, p);
	    else
		setv(vp, p, VAR_READWRITE);
	    cleanup_ignore(p);
	}
	else if (hadsub) {
	    struct varent *gv = getvx(vp, subscr);
	    Char *val;

	    val = operate(op, gv->vec[subscr - 1], p);
	    cleanup_push(val, xfree);
	    asx(vp, subscr, val);
	    cleanup_ignore(val);
	    cleanup_until(val);
	}
	else {
	    Char *val;

	    val = operate(op, varval(vp), p);
	    cleanup_push(val, xfree);
	    setv(vp, val, VAR_READWRITE);
	    cleanup_ignore(val);
	    cleanup_until(val);
	}
	update_vars(vp);
	cleanup_until(vp);
    } while ((p = *v++) != NULL);
}
Exemplo n.º 27
0
/*ARGSUSED*/
void
doset(Char **v, struct command *c)
{
    Char *p;
    Char   *vp;
    Char  **vecp;
    int    hadsub;
    int     subscr;
    int	    flags = VAR_READWRITE;
    int    first_match = 0;
    int    last_match = 0;
    int    changed = 0;

    USE(c);
    v++;
    do {
	changed = 0;
	/*
	 * Readonly addition From: Tim P. Starrin <*****@*****.**>
	 */
	if (*v && eq(*v, STRmr)) {
	    flags = VAR_READONLY;
	    v++;
	    changed = 1;
	}
	if (*v && eq(*v, STRmf) && !last_match) {
	    first_match = 1;
	    v++;
	    changed = 1;
	}
	if (*v && eq(*v, STRml) && !first_match) {
	    last_match = 1;
	    v++;
	    changed = 1;
	}
    } while(changed);
    p = *v++;
    if (p == 0) {
	plist(&shvhed, flags);
	return;
    }
    do {
	hadsub = 0;
	vp = p;
	if (!letter(*p))
	    stderror(ERR_NAME | ERR_VARBEGIN);
	do {
	    p++;
	} while (alnum(*p));
	if (*p == '[') {
	    hadsub++;
	    p = getinx(p, &subscr);
	}
	if (*p != '\0' && *p != '=')
	    stderror(ERR_NAME | ERR_VARALNUM);
	if (*p == '=') {
	    *p++ = '\0';
	    if (*p == '\0' && *v != NULL && **v == '(')
		p = *v++;
	}
	else if (*v && eq(*v, STRequal)) {
	    if (*++v != NULL)
		p = *v++;
	}
	if (eq(p, STRLparen)) {
	    Char **e = v;

	    if (hadsub)
		stderror(ERR_NAME | ERR_SYNTAX);
	    for (;;) {
		if (!*e)
		    stderror(ERR_NAME | ERR_MISSING, ')');
		if (**e == ')')
		    break;
		e++;
	    }
	    p = *e;
	    *e = 0;
	    vecp = saveblk(v);
	    if (first_match)
	       flags |= VAR_FIRST;
	    else if (last_match)
	       flags |= VAR_LAST;

	    set1(vp, vecp, &shvhed, flags);
	    *e = p;
	    v = e + 1;
	}
	else if (hadsub) {
	    Char *copy;

	    copy = Strsave(p);
	    cleanup_push(copy, xfree);
	    asx(vp, subscr, copy);
	    cleanup_ignore(copy);
	    cleanup_until(copy);
	}
	else
	    setv(vp, Strsave(p), flags);
	update_vars(vp);
    } while ((p = *v++) != NULL);
}
Exemplo n.º 28
0
/*
 * Print the error with the given id.
 *
 * Special ids:
 *	ERR_SILENT: Print nothing.
 *	ERR_OLD: Print the previously set error if one was there.
 *	         otherwise return.
 *	ERR_NAME: If this bit is set, print the name of the function
 *		  in bname
 *
 * This routine always resets or exits.  The flag haderr
 * is set so the routine who catches the unwind can propogate
 * it if they want.
 *
 * Note that any open files at the point of error will eventually
 * be closed in the routine process in sh.c which is the only
 * place error unwinds are ever caught.
 */
void
stderror(int id, ...)
{
    va_list va;
    Char **v;
    int flags;

    flags = id & ERR_FLAGS;
    id &= ~ERR_FLAGS;

    if ((flags & ERR_OLD) && seterr == NULL)
	abort();

    if (id < 0 || id > (int)(sizeof(errorlist) / sizeof(errorlist[0])))
	id = ERR_INVALID;

    (void)fflush(cshout);
    (void)fflush(csherr);
    haderr = 1;			/* Now to diagnostic output */
    timflg = 0;			/* This isn't otherwise reset */


    if (!(flags & ERR_SILENT)) {
	if (flags & ERR_NAME)
	    (void)fprintf(csherr, "%s: ", bname);
	if ((flags & ERR_OLD))
	    /* Old error. */
	    (void)fprintf(csherr, "%s.\n", seterr);
	else {
	    va_start(va, id);
	    (void)vfprintf(csherr, errorlist[id], va);
	    va_end(va);
	    (void)fprintf(csherr, ".\n");
	}
    }

    if (seterr) {
	xfree((ptr_t) seterr);
	seterr = NULL;
    }

    if ((v = pargv) != NULL)
	pargv = 0, blkfree(v);
    if ((v = gargv) != NULL)
	gargv = 0, blkfree(v);

    (void)fflush(cshout);
    (void)fflush(csherr);
    didfds = 0;			/* Forget about 0,1,2 */
    /*
     * Go away if -e or we are a child shell
     */
    if (exiterr || child)
	xexit(1);

    /*
     * Reset the state of the input. This buffered seek to end of file will
     * also clear the while/foreach stack.
     */
    btoeof();

    set(STRstatus, Strsave(STR1));
    if (tpgrp > 0)
	(void)tcsetpgrp(FSHTTY, tpgrp);
    reset();			/* Unwind */
}
Exemplo n.º 29
0
/*
 * Karl Kleinpaste, 21oct1983.
 * Set up a one-word alias command, for use for special things.
 * This code is based on the mainline of process().
 */
void
aliasrun(int cnt, Char *s1, Char *s2)
{
    struct wordent w, *new1, *new2;	/* for holding alias name */
    struct command *t = NULL;
    jmp_buf_t osetexit;
    int status;
    size_t omark;

    getexit(osetexit);
    if (seterr) {
	xfree(seterr);
	seterr = NULL;	/* don't repeatedly print err msg. */
    }
    w.word = STRNULL;
    new1 = xcalloc(1, sizeof w);
    new1->word = Strsave(s1);
    if (cnt == 1) {
	/* build a lex list with one word. */
	w.next = w.prev = new1;
	new1->next = new1->prev = &w;
    }
    else {
	/* build a lex list with two words. */
	new2 = xcalloc(1, sizeof w);
	new2->word = Strsave(s2);
	w.next = new2->prev = new1;
	new1->next = w.prev = new2;
	new1->prev = new2->next = &w;
    }
    cleanup_push(&w, lex_cleanup);

    /* Save the old status */
    status = getn(varval(STRstatus));

    /* expand aliases like process() does. */
    alias(&w);
    /* build a syntax tree for the command. */
    t = syntax(w.next, &w, 0);
    cleanup_push(t, syntax_cleanup);
    if (seterr)
	stderror(ERR_OLD);

    psavejob();
    cleanup_push(&cnt, psavejob_cleanup); /* cnt is used only as a marker */

    /* catch any errors here */
    omark = cleanup_push_mark();
    if (setexit() == 0)
	/* execute the parse tree. */
	/*
	 * From: Michael Schroeder <*****@*****.**>
	 * was execute(t, tpgrp);
	 */
	execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL, TRUE);
    /* reset the error catcher to the old place */
    cleanup_pop_mark(omark);
    resexit(osetexit);
    if (haderr) {
	haderr = 0;
	/*
	 * Either precmd, or cwdcmd, or periodic had an error. Call it again so
	 * that it is removed
	 */
	if (precmd_active)
	    precmd();
	if (postcmd_active)
	    postcmd();
#ifdef notdef
	/*
	 * XXX: On the other hand, just interrupting them causes an error too.
	 * So if we hit ^C in the middle of cwdcmd or periodic the alias gets
	 * removed. We don't want that. Note that we want to remove precmd
	 * though, cause that could lead into an infinite loop. This should be
	 * fixed correctly, but then haderr should give us the whole exit
	 * status not just true or false.
	 */
	else if (cwdcmd_active)
	    cwd_cmd();
	else if (beepcmd_active)
	    beep_cmd();
	else if (periodic_active)
	    period_cmd();
#endif /* notdef */
    }
    cleanup_until(&w);
    pendjob();
    /* Restore status */
    setv(STRstatus, putn((tcsh_number_t)status), VAR_READWRITE);
}
Exemplo n.º 30
0
void
execute(struct command *t, int wtty, int *pipein, int *pipeout)
{
    static sigset_t csigset, ocsigset; 
    static int nosigchld = 0, onosigchld = 0;
    volatile int wanttty = wtty;
    struct biltins * volatile bifunc;
    int pv[2], pid;
    sigset_t nsigset;
    int forked;

    UNREGISTER(forked);
    UNREGISTER(bifunc);
    UNREGISTER(wanttty);

    forked = 0;
    pid = 0;

    if (t == 0)
	return;

    if (t->t_dflg & F_AMPERSAND)
	wanttty = 0;
    switch (t->t_dtyp) {
    case NODE_COMMAND:
	if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
	    (void)Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
	if ((t->t_dflg & F_REPEAT) == 0)
	    Dfix(t);		/* $ " ' \ */
	if (t->t_dcom[0] == 0)
	    return;
	/* FALLTHROUGH */
    case NODE_PAREN:
	if (t->t_dflg & F_PIPEOUT)
	    mypipe(pipeout);
	/*
	 * Must do << early so parent will know where input pointer should be.
	 * If noexec then this is all we do.
	 */
	if (t->t_dflg & F_READ) {
	    (void)close(0);
	    heredoc(t->t_dlef);
	    if (noexec)
		(void)close(0);
	}

	set(STRstatus, Strsave(STR0));

	/*
	 * 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 == NODE_COMMAND)
	    if (eq(t->t_dcom[0], STRnice)) {
		if (t->t_dcom[1]) {
		    if (strchr("+-", t->t_dcom[1][0])) {
			if (t->t_dcom[2]) {
			    setname("nice");
			    t->t_nice =
				getn(t->t_dcom[1]);
			    lshift(t->t_dcom, 2);
			    t->t_dflg |= F_NICE;
			}
			else
			    break;
		    } else {
			t->t_nice = 4;
			lshift(t->t_dcom, 1);
			t->t_dflg |= F_NICE;
		    }
		} else
		    break;
	    } else if (eq(t->t_dcom[0], STRnohup)) {
		if (t->t_dcom[1]) {
		    t->t_dflg |= F_NOHUP;
		    lshift(t->t_dcom, 1);
		}
		else
		    break;
	    } else if (eq(t->t_dcom[0], STRtime)) {
		if (t->t_dcom[1]) {
		    t->t_dflg |= F_TIME;
		    lshift(t->t_dcom, 1);
		}
		else
		    break;
	    } else
		break;

	/* is it a command */
	if (t->t_dtyp == NODE_COMMAND) {
	    /*
	     * Check if we have a builtin function and remember which one.
	     */
	    bifunc = isbfunc(t);
 	    if (noexec && bifunc != NULL) {
		/*
		 * Continue for builtins that are part of the scripting language
		 */
		if (bifunc->bfunct != dobreak   && bifunc->bfunct != docontin &&
		    bifunc->bfunct != doelse    && bifunc->bfunct != doend    &&
		    bifunc->bfunct != doforeach && bifunc->bfunct != dogoto   &&
		    bifunc->bfunct != doif      && bifunc->bfunct != dorepeat &&
		    bifunc->bfunct != doswbrk   && bifunc->bfunct != doswitch &&
		    bifunc->bfunct != dowhile   && bifunc->bfunct != dozip)
		    break;
	    }
	}
	else {			/* not a command */
	    bifunc = NULL;
	    if (noexec)
		break;
	}

	/*
	 * 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.
	 */
	/*
	 * Prevent forking cd, pushd, popd, chdir cause this will cause the
	 * shell not to change dir!
	 */
	if (bifunc && (bifunc->bfunct == dochngd ||
		       bifunc->bfunct == dopushd ||
		       bifunc->bfunct == dopopd))
	    t->t_dflg &= ~(F_NICE);
	if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
	     (!bifunc || t->t_dflg &
	      (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) ||
	/*
	 * We have to fork for eval too.
	 */
	    (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 &&
	     bifunc->bfunct == doeval)) {
	    if (t->t_dtyp == NODE_PAREN ||
		t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) {
		forked++;
		/*
		 * We need to block SIGCHLD here, so that if the process does
		 * not die before we can set the process group
		 */
		if (wanttty >= 0 && !nosigchld) {
		    sigemptyset(&nsigset);
		    (void)sigaddset(&nsigset, SIGCHLD);
		    (void)sigprocmask(SIG_BLOCK, &nsigset, &csigset);
		    nosigchld = 1;
		}

		pid = pfork(t, wanttty);
		if (pid == 0 && nosigchld) {
		    (void)sigprocmask(SIG_SETMASK, &csigset, NULL);
		    nosigchld = 0;
		}
		else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
		    backpid = pid;

	    }
	    else {
		int ochild, osetintr, ohaderr, odidfds;
		int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp;
		sigset_t osigset;

		/*
		 * 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 sigaction's for the signals the child touches
		 * before it exec's.
		 */
		if (wanttty >= 0 && !nosigchld && !noexec) {
		    sigemptyset(&nsigset);
		    (void)sigaddset(&nsigset, SIGCHLD);
		    (void)sigprocmask(SIG_BLOCK, &nsigset, &csigset);
		    nosigchld = 1;
		}
		sigemptyset(&nsigset);
		(void)sigaddset(&nsigset, SIGCHLD);
		(void)sigaddset(&nsigset, SIGINT);
		(void)sigprocmask(SIG_BLOCK, &nsigset, &osigset);
		ochild = child;
		osetintr = setintr;
		ohaderr = haderr;
		odidfds = didfds;
		oSHIN = SHIN;
		oSHOUT = SHOUT;
		oSHERR = SHERR;
		oOLDSTD = OLDSTD;
		otpgrp = tpgrp;
		ocsigset = csigset;
		onosigchld = nosigchld;
		Vsav = Vdp = 0;
		Vexpath = 0;
		Vt = 0;
		pid = vfork();

		if (pid < 0) {
		    (void)sigprocmask(SIG_SETMASK, &osigset, NULL);
		    stderror(ERR_NOPROC);
		}
		forked++;
		if (pid) {	/* parent */
		    child = ochild;
		    setintr = osetintr;
		    haderr = ohaderr;
		    didfds = odidfds;
		    SHIN = oSHIN;
		    SHOUT = oSHOUT;
		    SHERR = oSHERR;
		    OLDSTD = oOLDSTD;
		    tpgrp = otpgrp;
		    csigset = ocsigset;
		    nosigchld = onosigchld;

		    xfree((ptr_t) Vsav);
		    Vsav = 0;
		    xfree((ptr_t) Vdp);
		    Vdp = 0;
		    xfree((ptr_t) Vexpath);
		    Vexpath = 0;
		    blkfree((Char **) Vt);
		    Vt = 0;
		    /* this is from pfork() */
		    palloc(pid, t);
		    (void)sigprocmask(SIG_SETMASK, &osigset, NULL);
		}
		else {		/* child */
		    /* this is from pfork() */
		    int pgrp;
		    int ignint = 0;

		    if (nosigchld) {
		        (void)sigprocmask(SIG_SETMASK, &csigset, NULL);
			nosigchld = 0;
		    }

		    if (setintr)
			ignint =
			    (tpgrp == -1 &&
			     (t->t_dflg & F_NOINTERRUPT))
			    || (gointr && eq(gointr, STRminus));
		    pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
		    child++;
		    if (setintr) {
			setintr = 0;
			if (ignint) {
			    (void)signal(SIGINT, SIG_IGN);
			    (void)signal(SIGQUIT, SIG_IGN);
			}
			else {
			    (void)signal(SIGINT, vffree);
			    (void)signal(SIGQUIT, SIG_DFL);
			}

			if (wanttty >= 0) {
			    (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 & F_NOINTERRUPT)) {
			(void)signal(SIGINT, SIG_IGN);
			(void)signal(SIGQUIT, SIG_IGN);
		    }

		    pgetty(wanttty, pgrp);
		    if (t->t_dflg & F_NOHUP)
			(void)signal(SIGHUP, SIG_IGN);
		    if (t->t_dflg & F_NICE)
			(void)setpriority(PRIO_PROCESS, 0, t->t_nice);
		}

	    }
	}
	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.
	     */
	    if (didfds == 0 && t->t_dflg & F_PIPEIN) {
		(void)close(pipein[0]);
		(void)close(pipein[1]);
	    }
	    if ((t->t_dflg & F_PIPEOUT) == 0) {
		if (nosigchld) {
		    (void)sigprocmask(SIG_SETMASK, &csigset, NULL);
		    nosigchld = 0;
		}
		if ((t->t_dflg & F_AMPERSAND) == 0)
		    pwait();
	    }
	    break;
	}
	doio(t, pipein, pipeout);
	if (t->t_dflg & F_PIPEOUT) {
	    (void)close(pipeout[0]);
	    (void)close(pipeout[1]);
	}
	/*
	 * Perform a builtin function. If we are not forked, arrange for
	 * possible stopping
	 */
	if (bifunc) {
	    func(t, bifunc);
	    if (forked)
		exitstat();
	    break;
	}
	if (t->t_dtyp != NODE_PAREN)
	    doexec(NULL, t);
	/*
	 * For () commands must put new 0,1,2 in FSH* and recurse
	 */
	(void) ioctl(OLDSTD = dcopy(0, FOLDSTD), FIOCLEX, NULL);
	(void) ioctl(SHOUT = dcopy(1, FSHOUT), FIOCLEX, NULL);
	(void) ioctl(SHERR = dcopy(2, FSHERR), FIOCLEX, NULL);
	(void) close(SHIN);

	SHIN = -1;
	didfds = 0;
	wanttty = -1;
	t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
	execute(t->t_dspr, wanttty, NULL, NULL);
	exitstat();
	/* NOTREACHED */
    case NODE_PIPE:
	t->t_dcar->t_dflg |= F_PIPEOUT |
	    (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
	execute(t->t_dcar, wanttty, pipein, pv);
	t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
			(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
	if (wanttty > 0)
	    wanttty = 0;	/* got tty already */
	execute(t->t_dcdr, wanttty, pv, pipeout);
	break;
    case NODE_LIST:
	if (t->t_dcar) {
	    t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
	    execute(t->t_dcar, wanttty, NULL, NULL);
	    /*
	     * In strange case of A&B make a new job after A
	     */
	    if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
		(t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
		pendjob();
	}
	if (t->t_dcdr) {
	    t->t_dcdr->t_dflg |= t->t_dflg &
		(F_NOFORK | F_NOINTERRUPT);
	    execute(t->t_dcdr, wanttty, NULL, NULL);
	}
	break;
    case NODE_OR:
    case NODE_AND:
	if (t->t_dcar) {
	    t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
	    execute(t->t_dcar, wanttty, NULL, NULL);
	    if ((getn(value(STRstatus)) == 0) !=
		(t->t_dtyp == NODE_AND))
		return;
	}
	if (t->t_dcdr) {
	    t->t_dcdr->t_dflg |= t->t_dflg &
		(F_NOFORK | F_NOINTERRUPT);
	    execute(t->t_dcdr, wanttty, NULL, NULL);
	}
	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 F_REPEAT bit are responsible for
     * doing donefds after the last re-execution
     */
    if (didfds && !(t->t_dflg & F_REPEAT))
	donefds();
}