Exemple #1
0
Fichier : init.c Projet : Lujaw/zsh
enum loop_return
loop(int toplevel, int justonce)
{
    Eprog prog;
    int err, non_empty = 0;

    pushheap();
    if (!toplevel)
	lexsave();
    for (;;) {
	freeheap();
	if (stophist == 3)	/* re-entry via preprompt() */
	    hend(NULL);
	hbegin(1);		/* init history mech        */
	if (isset(SHINSTDIN)) {
	    setblock_stdin();
	    if (interact && toplevel) {
	        int hstop = stophist;
		stophist = 3;
		preprompt();
		if (stophist != 3)
		    hbegin(1);
		else
		    stophist = hstop;
		errflag = 0;
	    }
	}
	use_exit_printed = 0;
	intr();			/* interrupts on            */
	lexinit();              /* initialize lexical state */
	if (!(prog = parse_event())) {	/* if we couldn't parse a list */
	    hend(NULL);
	    if ((tok == ENDINPUT && !errflag) ||
		(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
		justonce)
		break;
	    if (exit_pending) {
		/*
		 * Something down there (a ZLE function?) decided
		 * to exit when there was stuff to clear up.
		 * Handle that now.
		 */
		stopmsg = 1;
		zexit(exit_pending >> 1, 0);
	    }
	    if (tok == LEXERR && !lastval)
		lastval = 1;
	    continue;
	}
	if (hend(prog)) {
	    int toksav = tok;

	    non_empty = 1;
	    if (toplevel &&
		(getshfunc("preexec") ||
		 paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) {
		LinkList args;
		char *cmdstr;

		/*
		 * As we're about to freeheap() or popheap()
		 * anyway, there's no gain in using permanent
		 * storage here.
		 */
		args = newlinklist();
		addlinknode(args, "preexec");
		/* If curline got dumped from the history, we don't know
		 * what the user typed. */
		if (hist_ring && curline.histnum == curhist)
		    addlinknode(args, hist_ring->node.nam);
		else
		    addlinknode(args, "");
		addlinknode(args, dupstring(getjobtext(prog, NULL)));
		addlinknode(args, cmdstr = getpermtext(prog, NULL, 0));

		callhookfunc("preexec", args, 1, NULL);

		/* The only permanent storage is from getpermtext() */
		zsfree(cmdstr);
		errflag = 0;
	    }
	    if (stopmsg)	/* unset 'you have stopped jobs' flag */
		stopmsg--;
	    execode(prog, 0, 0, toplevel ? "toplevel" : "file");
	    tok = toksav;
	    if (toplevel)
		noexitct = 0;
	}
	if (ferror(stderr)) {
	    zerr("write error");
	    clearerr(stderr);
	}
	if (subsh)		/* how'd we get this far in a subshell? */
	    exit(lastval);
	if (((!interact || sourcelevel) && errflag) || retflag)
	    break;
	if (isset(SINGLECOMMAND) && toplevel) {
	    if (sigtrapped[SIGEXIT])
		dotrap(SIGEXIT);
	    exit(lastval);
	}
	if (justonce)
	    break;
    }
Exemple #2
0
enum loop_return
loop(int toplevel, int justonce)
{
    Eprog prog;
    int err, non_empty = 0;

    queue_signals();
    pushheap();
    if (!toplevel)
	zcontext_save();
    for (;;) {
	freeheap();
	if (stophist == 3)	/* re-entry via preprompt() */
	    hend(NULL);
	hbegin(1);		/* init history mech        */
	if (isset(SHINSTDIN)) {
	    setblock_stdin();
	    if (interact && toplevel) {
	        int hstop = stophist;
		stophist = 3;
		/*
		 * Reset all errors including the interrupt error status
		 * immediately, so preprompt runs regardless of what
		 * just happened.  We'll reset again below as a
		 * precaution to ensure we get back to the command line
		 * no matter what.
		 */
		errflag = 0;
		preprompt();
		if (stophist != 3)
		    hbegin(1);
		else
		    stophist = hstop;
		/*
		 * Reset all errors, including user interupts.
		 * This is what allows ^C in an interactive shell
		 * to return us to the command line.
		 */
		errflag = 0;
	    }
	}
	use_exit_printed = 0;
	intr();			/* interrupts on            */
	lexinit();              /* initialize lexical state */
	if (!(prog = parse_event(ENDINPUT))) {
	    /* if we couldn't parse a list */
	    hend(NULL);
	    if ((tok == ENDINPUT && !errflag) ||
		(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
		justonce)
		break;
	    if (exit_pending) {
		/*
		 * Something down there (a ZLE function?) decided
		 * to exit when there was stuff to clear up.
		 * Handle that now.
		 */
		stopmsg = 1;
		zexit(exit_pending >> 1, 0);
	    }
	    if (tok == LEXERR && !lastval)
		lastval = 1;
	    continue;
	}
	if (hend(prog)) {
	    enum lextok toksav = tok;

	    non_empty = 1;
	    if (toplevel &&
		(getshfunc("preexec") ||
		 paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) {
		LinkList args;
		char *cmdstr;

		/*
		 * As we're about to freeheap() or popheap()
		 * anyway, there's no gain in using permanent
		 * storage here.
		 */
		args = newlinklist();
		addlinknode(args, "preexec");
		/* If curline got dumped from the history, we don't know
		 * what the user typed. */
		if (hist_ring && curline.histnum == curhist)
		    addlinknode(args, hist_ring->node.nam);
		else
		    addlinknode(args, "");
		addlinknode(args, dupstring(getjobtext(prog, NULL)));
		addlinknode(args, cmdstr = getpermtext(prog, NULL, 0));

		callhookfunc("preexec", args, 1, NULL);

		/* The only permanent storage is from getpermtext() */
		zsfree(cmdstr);
		/*
		 * Note this does *not* remove a user interrupt error
		 * condition, even though we're at the top level loop:
		 * that would be inconsistent with the case where
		 * we didn't execute a preexec function.  This is
		 * an implementation detail that an interrupting user
		 * does't care about.
		 */
		errflag &= ~ERRFLAG_ERROR;
	    }
	    if (stopmsg)	/* unset 'you have stopped jobs' flag */
		stopmsg--;
	    execode(prog, 0, 0, toplevel ? "toplevel" : "file");
	    tok = toksav;
	    if (toplevel)
		noexitct = 0;
	}
	if (ferror(stderr)) {
	    zerr("write error");
	    clearerr(stderr);
	}
	if (subsh)		/* how'd we get this far in a subshell? */
	    exit(lastval);
	if (((!interact || sourcelevel) && errflag) || retflag)
	    break;
	if (isset(SINGLECOMMAND) && toplevel) {
	    dont_queue_signals();
	    if (sigtrapped[SIGEXIT])
		dotrap(SIGEXIT);
	    exit(lastval);
	}
	if (justonce)
	    break;
    }
Exemple #3
0
static int
newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
{
    Ptycmd p;
    int master, slave, pid, oineval = ineval, ret;
    char *oscriptname = scriptname, syncch;
    Eprog prog;

    /* code borrowed from bin_eval() */
    ineval = !isset(EVALLINENO);
    if (!ineval)
	scriptname = "(zpty)";

    prog = parse_string(zjoin(args, ' ', 1), 0);
    if (!prog) {
	errflag &= ~ERRFLAG_ERROR;
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    }

    if (get_pty(1, &master)) {
	zwarnnam(nam, "can't open pseudo terminal: %e", errno);
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    }
    if ((pid = fork()) == -1) {
	zwarnnam(nam, "can't create pty command %s: %e", pname, errno);
	close(master);
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    } else if (!pid) {
	/* This code copied from the clone module, except for getting *
	 * the descriptor from get_pty() and duplicating it to 0/1/2. */

	deletehookfunc("exit", ptyhook);
	clearjobtab(0);
	ppid = getppid();
	mypid = getpid();
#ifdef HAVE_SETSID
	if (setsid() != mypid) {
	    zwarnnam(nam, "failed to create new session: %e", errno);
#endif
#ifdef TIOCNOTTY
	    if (ioctl(SHTTY, TIOCNOTTY, 0))
		zwarnnam(nam, "%e", errno);
	    setpgrp(0L, mypid);
#endif
#ifdef HAVE_SETSID
	}
#endif

	if (get_pty(0, &slave))
	    exit(1);
	SHTTY = slave;
	attachtty(mypid);
#ifdef TIOCGWINSZ
	/* Set the window size before associating with the terminal *
	 * so that we don't get hit with a SIGWINCH.  I'm paranoid. */
	if (interact) {
	    struct ttyinfo info;

	    if (ioctl(slave, TIOCGWINSZ, (char *) &info.winsize) == 0) {
		info.winsize.ws_row = zterm_lines;
		info.winsize.ws_col = zterm_columns;
		ioctl(slave, TIOCSWINSZ, (char *) &info.winsize);
	    }
	}
#endif /* TIOCGWINSZ */

	if (!echo) {
	    struct ttyinfo info;

	    if (!ptygettyinfo(slave, &info)) {
#ifdef HAVE_TERMIOS_H
		info.tio.c_lflag &= ~ECHO;
#else
#ifdef HAVE_TERMIO_H
		info.tio.c_lflag &= ~ECHO;
#else
		info.tio.lmodes &= ~ECHO; /**** dunno if this is right */
#endif
#endif
		ptysettyinfo(slave, &info);
	    }
	}

#ifdef TIOCSCTTY
	ioctl(slave, TIOCSCTTY, 0);
#endif

	close(0);
	close(1);
	close(2);

	dup2(slave, 0);
	dup2(slave, 1);
	dup2(slave, 2);

	closem(FDT_UNUSED, 0);
	close(slave);
	close(master);
	close(coprocin);
	close(coprocout);
	init_io(NULL);
	setsparam("TTY", ztrdup(ttystrname));

	opts[INTERACTIVE] = 0;

	syncch = 0;
	do {
	    ret = write(1, &syncch, 1);
	} while (ret != 1 && (
#ifdef EWOULDBLOCK
	    errno == EWOULDBLOCK ||
#else
#ifdef EAGAIN
	    errno == EAGAIN ||
#endif
#endif
	    errno == EINTR));

	execode(prog, 1, 0, "zpty");
	stopmsg = 2;
	mypid = 0; /* trick to ensure we _exit() */
	zexit(lastval, 0);
    }
    master = movefd(master);
    if (master == -1) {
	zerrnam(nam, "cannot duplicate fd %d: %e", master, errno);
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    }

    p = (Ptycmd) zalloc(sizeof(*p));

    p->name = ztrdup(pname);
    p->args = zarrdup(args);
    p->fd = master;
    p->pid = pid;
    p->echo = echo;
    p->nblock = nblock;
    p->fin = 0;
    p->read = -1;
    p->old = NULL;
    p->olen = 0;

    p->next = ptycmds;
    ptycmds = p;

    if (nblock)
	ptynonblock(master);

    scriptname = oscriptname;
    ineval = oineval;

    do {
	ret = read(master, &syncch, 1);
    } while (ret != 1 && (
#ifdef EWOULDBLOCK
	    errno == EWOULDBLOCK ||
#else
#ifdef EAGAIN
	    errno == EAGAIN ||
#endif
#endif
	    errno == EINTR));

    setiparam_no_convert("REPLY", (zlong)master);

    return 0;
}