示例#1
0
/*
 * sscr_check_input -
 *	Check whether any input from shell or passed set.
 *
 * PUBLIC: int sscr_check_input __P((SCR *sp, fd_set *rdfd, int maxfd));
 */
int
sscr_check_input(SCR *sp, fd_set *fdset, int maxfd)
{
	fd_set rdfd;
	SCR *tsp;
	WIN *wp;

	wp = sp->wp;

loop:	memcpy(&rdfd, fdset, sizeof(fd_set));

	TAILQ_FOREACH(tsp, &wp->scrq, q)
		if (F_ISSET(sp, SC_SCRIPT)) {
			FD_SET(sp->script->sh_master, &rdfd);
			if (sp->script->sh_master > maxfd)
				maxfd = sp->script->sh_master;
		}
	switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
	case 0:
		abort();
	case -1:
		return 1;
	default:
		break;
	}
	TAILQ_FOREACH(tsp, &wp->scrq, q)
		if (F_ISSET(sp, SC_SCRIPT) &&
		    FD_ISSET(sp->script->sh_master, &rdfd)) {
			if (sscr_input(sp))
				return 1;
			goto loop;
		}
	return 0;
}
示例#2
0
文件: cl_read.c 项目: coyizumi/cs111
/*
 * cl_read --
 *	Read characters from the input.
 */
static input_t
cl_read(SCR *sp, u_int32_t flags, char *bp, size_t blen, int *nrp, struct timeval *tp)
{
    struct termios term1, term2;
    CL_PRIVATE *clp;
    GS *gp;
    fd_set rdfd;
    input_t rval;
    int maxfd, nr, term_reset;

    gp = sp->gp;
    clp = CLP(sp);
    term_reset = 0;

    /*
     * 1: A read from a file or a pipe.  In this case, the reads
     *    never timeout regardless.  This means that we can hang
     *    when trying to complete a map, but we're going to hang
     *    on the next read anyway.
     */
    if (!F_ISSET(clp, CL_STDIN_TTY)) {
        switch (nr = read(STDIN_FILENO, bp, blen)) {
        case 0:
            return (INP_EOF);
        case -1:
            goto err;
        default:
            *nrp = nr;
            return (INP_OK);
        }
        /* NOTREACHED */
    }

    /*
     * 2: A read with an associated timeout, e.g., trying to complete
     *    a map sequence.  If input exists, we fall into #3.
     */
    if (tp != NULL) {
        FD_ZERO(&rdfd);
        FD_SET(STDIN_FILENO, &rdfd);
        switch (select(STDIN_FILENO + 1, &rdfd, NULL, NULL, tp)) {
        case 0:
            return (INP_TIMEOUT);
        case -1:
            goto err;
        default:
            break;
        }
    }

    /*
     * The user can enter a key in the editor to quote a character.  If we
     * get here and the next key is supposed to be quoted, do what we can.
     * Reset the tty so that the user can enter a ^C, ^Q, ^S.  There's an
     * obvious race here, when the key has already been entered, but there's
     * nothing that we can do to fix that problem.
     *
     * The editor can ask for the next literal character even thought it's
     * generally running in line-at-a-time mode.  Do what we can.
     */
    if (LF_ISSET(EC_QUOTED | EC_RAW) && !tcgetattr(STDIN_FILENO, &term1)) {
        term_reset = 1;
        if (LF_ISSET(EC_QUOTED)) {
            term2 = term1;
            term2.c_lflag &= ~ISIG;
            term2.c_iflag &= ~(IXON | IXOFF);
            (void)tcsetattr(STDIN_FILENO,
                            TCSASOFT | TCSADRAIN, &term2);
        } else
            (void)tcsetattr(STDIN_FILENO,
                            TCSASOFT | TCSADRAIN, &clp->vi_enter);
    }

    /*
     * 3: Wait for input.
     *
     * Select on the command input and scripting window file descriptors.
     * It's ugly that we wait on scripting file descriptors here, but it's
     * the only way to keep from locking out scripting windows.
     */
    if (F_ISSET(gp, G_SCRWIN)) {
loop:
        FD_ZERO(&rdfd);
        FD_SET(STDIN_FILENO, &rdfd);
        maxfd = STDIN_FILENO;
        if (F_ISSET(sp, SC_SCRIPT)) {
            FD_SET(sp->script->sh_master, &rdfd);
            if (sp->script->sh_master > maxfd)
                maxfd = sp->script->sh_master;
        }
        switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
        case 0:
            abort();
        case -1:
            goto err;
        default:
            break;
        }
        if (!FD_ISSET(STDIN_FILENO, &rdfd)) {
            if (sscr_input(sp))
                return (INP_ERR);
            goto loop;
        }
    }

    /*
     * 4: Read the input.
     *
     * !!!
     * What's going on here is some scary stuff.  Ex runs the terminal in
     * canonical mode.  So, the <newline> character terminating a line of
     * input is returned in the buffer, but a trailing <EOF> character is
     * not similarly included.  As ex uses 0<EOF> and ^<EOF> as autoindent
     * commands, it has to see the trailing <EOF> characters to determine
     * the difference between the user entering "0ab" and "0<EOF>ab".  We
     * leave an extra slot in the buffer, so that we can add a trailing
     * <EOF> character if the buffer isn't terminated by a <newline>.  We
     * lose if the buffer is too small for the line and exactly N characters
     * are entered followed by an <EOF> character.
     */
#define	ONE_FOR_EOF	1
    switch (nr = read(STDIN_FILENO, bp, blen - ONE_FOR_EOF)) {
    case  0:				/* EOF. */
        /*
         * ^D in canonical mode returns a read of 0, i.e. EOF.  EOF is
         * a valid command, but we don't want to loop forever because
         * the terminal driver is returning EOF because the user has
         * disconnected. The editor will almost certainly try to write
         * something before this fires, which should kill us, but You
         * Never Know.
         */
        if (++clp->eof_count < 50) {
            bp[0] = clp->orig.c_cc[VEOF];
            *nrp = 1;
            rval = INP_OK;

        } else
            rval = INP_EOF;
        break;
    case -1:				/* Error or interrupt. */
err:
        if (errno == EINTR)
            rval = INP_INTR;
        else {
            rval = INP_ERR;
            msgq(sp, M_SYSERR, "input");
        }
        break;
    default:				/* Input characters. */
        if (F_ISSET(sp, SC_EX) && bp[nr - 1] != '\n')
            bp[nr++] = clp->orig.c_cc[VEOF];
        *nrp = nr;
        clp->eof_count = 0;
        rval = INP_OK;
        break;
    }

    /* Restore the terminal state if it was modified. */
    if (term_reset)
        (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &term1);
    return (rval);
}