Exemplo n.º 1
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.º 2
0
static void
backeval(struct blk_buf *bb, struct Strbuf *word, Char *cp, int literal)
{
    ssize_t icnt;
    Char c, *ip;
    struct command faket;
    int    hadnl;
    int     pvec[2], quoted;
    Char   *fakecom[2], ibuf[BUFSIZE];
    char    tibuf[BUFSIZE];

    hadnl = 0;
    icnt = 0;
    quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
    faket.t_dtyp = NODE_COMMAND;
    faket.t_dflg = F_BACKQ;
    faket.t_dlef = 0;
    faket.t_drit = 0;
    faket.t_dspr = 0;
    faket.t_dcom = fakecom;
    fakecom[0] = STRfakecom1;
    fakecom[1] = 0;

    /*
     * We do the psave job to temporarily change the current job so that the
     * following fork is considered a separate job.  This is so that when
     * backquotes are used in a builtin function that calls glob the "current
     * job" is not corrupted.  We only need one level of pushed jobs as long as
     * we are sure to fork here.
     */
    psavejob();
    cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */

    /*
     * It would be nicer if we could integrate this redirection more with the
     * routines in sh.sem.c by doing a fake execute on a builtin function that
     * was piped out.
     */
    mypipe(pvec);
    cleanup_push(&pvec[0], open_cleanup);
    cleanup_push(&pvec[1], open_cleanup);
    if (pfork(&faket, -1) == 0) {
	jmp_buf_t osetexit;
	struct command *t;
	size_t omark;

	xclose(pvec[0]);
	(void) dmove(pvec[1], 1);
	(void) dmove(SHDIAG,  2);
	initdesc();
	closem();
	arginp = cp;
	for (arginp = cp; *cp; cp++) {
	    *cp &= TRIM;
	    if (is_set(STRcsubstnonl) && (*cp == '\n' || *cp == '\r'))
		*cp = ' ';
	}

        /*
	 * In the child ``forget'' everything about current aliases or
	 * eval vectors.
	 */
	alvec = NULL;
	evalvec = NULL;
	alvecp = NULL;
	evalp = NULL;

	omark = cleanup_push_mark();
	getexit(osetexit);
	for (;;) {
	    (void) setexit();
	    justpr = 0;
	    
	    if (haderr) {
		/* unwind */
		doneinp = 0;
		cleanup_pop_mark(omark);
		resexit(osetexit);
		reset();
	    }
	    if (seterr) {
		xfree(seterr);
		seterr = NULL;
	    }

	    (void) lex(&paraml);
	    cleanup_push(&paraml, lex_cleanup);
	    if (seterr)
		stderror(ERR_OLD);
	    alias(&paraml);
	    t = syntax(paraml.next, &paraml, 0);
	    if (t == NULL)
		return;
	    cleanup_push(t, syntax_cleanup);
	    /* The F_BACKQ flag must set so the job output is correct if
	     * printexitvalue is set.  If it's not set, the job output
	     * will have "Exit N" appended where N is the exit status. */
	    t->t_dflg = F_BACKQ|F_NOFORK;
	    if (seterr)
		stderror(ERR_OLD);
#ifdef SIGTSTP
	    signal(SIGTSTP, SIG_IGN);
#endif
#ifdef SIGTTIN
	    signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGTTOU
	    signal(SIGTTOU, SIG_IGN);
#endif
	    execute(t, -1, NULL, NULL, TRUE);

	    cleanup_until(&paraml);
	}
    }
    cleanup_until(&pvec[1]);
    c = 0;
    ip = NULL;
    do {
	ssize_t     cnt = 0;
	char   *tmp;

	tmp = tibuf;
	for (;;) {
	    while (icnt == 0) {
		int     i, eof;

		ip = ibuf;
		icnt = xread(pvec[0], tmp, tibuf + BUFSIZE - tmp);
		eof = 0;
		if (icnt <= 0) {
		    if (tmp == tibuf)
			goto eof;
		    icnt = 0;
		    eof = 1;
		}
		icnt += tmp - tibuf;
		i = 0;
		tmp = tibuf;
		while (tmp < tibuf + icnt) {
		    int len;

		    len = normal_mbtowc(&ip[i], tmp, tibuf + icnt - tmp);
		    if (len == -1) {
		        reset_mbtowc();
		        if (!eof && (size_t)(tibuf + icnt - tmp) < MB_CUR_MAX) {
			    break; /* Maybe a partial character */
			}
			ip[i] = (unsigned char) *tmp | INVALID_BYTE; /* Error */
		    }
		    if (len <= 0)
		        len = 1;
		    i++;
		    tmp += len;
		}
		if (tmp != tibuf)
		    memmove (tibuf, tmp, tibuf + icnt - tmp);
		tmp = tibuf + (tibuf + icnt - tmp);
		icnt = i;
	    }
	    if (hadnl)
		break;
	    --icnt;
	    c = (*ip++ & TRIM);
	    if (c == 0)
		break;
#if defined(WINNT_NATIVE) || defined(__CYGWIN__)
	    if (c == '\r')
	    	c = ' ';
#endif /* WINNT_NATIVE || __CYGWIN__ */
	    if (c == '\n') {
		/*
		 * Continue around the loop one more time, so that we can eat
		 * the last newline without terminating this word.
		 */
		hadnl = 1;
		continue;
	    }
	    if (!quoted && (c == ' ' || c == '\t'))
		break;
	    cnt++;
	    Strbuf_append1(word, c | quoted);
	}
	/*
	 * Unless at end-of-file, we will form a new word here if there were
	 * characters in the word, or in any case when we take text literally.
	 * If we didn't make empty words here when literal was set then we
	 * would lose blank lines.
	 */
	if (c != 0 && (cnt || literal))
	    pword(bb, word);
	hadnl = 0;
    } while (c > 0);
 eof:
    cleanup_until(&pvec[0]);
    pwait();
    cleanup_until(&faket); /* psavejob_cleanup(); */
}