Ejemplo n.º 1
0
/*
 * Read input from the user either stdin or from file.
 * For stdin, read from bounce_buf which filled by the stdin thread
 * otherwise use the regular ring_from_file.
 */
static int
w32_ring_from_file_or_bounce_buf(struct ring *r, int fd)
{
    int i, res;

    if (fd)
	return ring_from_file(r, fd);

    if (bounce_status < 0) {
	errno = bounce_error;
	res = bounce_status;
    } else {
	for (i = 0; i < bounce_status; i++) {
	    if (ring_putc(r, bounce_buf[i]) == EOF) {
		/* more work to do, hold on to bounce_buf */
		memmove(bounce_buf, bounce_buf + i, bounce_status - i);
		bounce_status -= i;
		return i;
	    }
	}
	res = i;
    }

    ResetEvent(bounce_full);
    SetEvent(bounce_empty);
    return res;
}
Ejemplo n.º 2
0
/*
 * Remember input @inp for a while.
 */
void
save_input(char inp)
{
    int eol;

    while (ring_putc(&recent_input, inp) < 0) {
	eol = ring_search(&recent_input, "\n", 0);
	assert(eol >= 0);
	ring_discard(&recent_input, eol + 1);
    }
}
Ejemplo n.º 3
0
/*
 * Receive command input from @fd into @inbuf.
 * Return 1 on receipt of input, zero on EOF, -1 on error.
 */
static int
recv_input(int fd, struct ring *inbuf)
{
    static struct lbuf cmdbuf;
    int n, i, ch;
    char *line;
    int res = 1;

    n = ring_from_file(inbuf, fd);
    if (n < 0)
	return -1;
    if (n == 0) {
	/* EOF on input */
	if (lbuf_len(&cmdbuf)) {
	    /* incomplete line */
	    ring_putc(inbuf, '\n');
	    n++;
	}
	/*
	 * Can't put EOF cookie into INBUF here, it may not fit.
	 * Leave it to caller.
	 */
	res = 0;
    }

    /* copy input to AUXFP etc. */
    for (i = -n; i < 0; i++) {
	ch = ring_peek(inbuf, i);
	assert(ch != EOF);
	if (ch != '\r' && lbuf_putc(&cmdbuf, ch) > 0) {
	    line = lbuf_line(&cmdbuf);
	    save_input(line);
	    lbuf_init(&cmdbuf);
	}
	if (auxfp)
	    putc(ch, auxfp);
    }

    return res;
}
Ejemplo n.º 4
0
/*
 * Play on @sock.
 * The session must be in the playing phase.
 * Return 0 when the session ended, -1 on error.
 */
int
play(int sock)
{
    /*
     * Player input flows from INPUT_FD through recv_input() into ring
     * buffer INBUF, which drains into SOCK.  This must not block.
     * Server output flows from SOCK into recv_output().  Reading SOCK
     * must not block.
     */
    struct sigaction sa;
    struct ring inbuf;		/* input buffer, draining to SOCK */
    int eof_fd0;		/* read fd 0 hit EOF? */
    int partial_line_sent;	/* partial input line sent? */
    fd_set rdfd, wrfd;
    int n;

    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = intr;
    sigaction(SIGINT, &sa, NULL);
    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, NULL);

    ring_init(&inbuf);
    eof_fd0 = partial_line_sent = send_eof = send_intr = 0;
    input_fd = 0;
    sysdep_stdin_init();

    for (;;) {
	FD_ZERO(&rdfd);
	FD_ZERO(&wrfd);

	/*
	 * Want to read player input only when we don't need to send
	 * cookies, and INPUT_FD is still open, and INBUF can accept
	 * some.
	 */
	if (!send_intr && !send_eof && input_fd >= 0 && ring_space(&inbuf))
	    FD_SET(input_fd, &rdfd);
	/* Want to send player input only when we have something */
	if (send_intr || send_eof || ring_len(&inbuf))
	    FD_SET(sock, &wrfd);
	/* Always want to read server output */
	FD_SET(sock, &rdfd);

	n = select(MAX(input_fd, sock) + 1, &rdfd, &wrfd, NULL, NULL);
	if (n < 0) {
	    if (errno != EINTR) {
		perror("select");
		return -1;
	    }
	}

	if ((send_eof || send_intr) && partial_line_sent
	    && ring_putc(&inbuf, '\n') != EOF)
	    partial_line_sent = 0;
	if (send_eof && !partial_line_sent
	    && ring_putm(&inbuf, EOF_COOKIE, sizeof(EOF_COOKIE) - 1) >= 0)
	    send_eof--;
	if (send_intr && !partial_line_sent
	    && ring_putm(&inbuf, INTR_COOKIE, sizeof(INTR_COOKIE) - 1) >= 0) {
	    send_intr = 0;
	    if (input_fd) {
		/* execute aborted, switch back to fd 0 */
		close(input_fd);
		input_fd = eof_fd0 ? -1 : 0;
	    }
	}

	if (n < 0)
	    continue;

	/* read player input */
	if (input_fd >= 0 && FD_ISSET(input_fd, &rdfd)) {
	    n = recv_input(input_fd, &inbuf);
	    if (n < 0) {
		perror("read stdin"); /* FIXME stdin misleading, could be execing */
		n = 0;
	    }
	    if (n == 0) {
		/* EOF on input */
		send_eof++;
		if (input_fd) {
		    /* execute done, switch back to fd 0 */
		    close(input_fd);
		    input_fd = eof_fd0 ? -1 : 0;
		} else {
		    /* stop reading input, drain socket ring buffers */
		    eof_fd0 = 1;
		    input_fd = -1;
		    sa.sa_handler = SIG_DFL;
		    sigaction(SIGINT, &sa, NULL);
		}
	    } else
		partial_line_sent = ring_peek(&inbuf, -1) != '\n';
	}

	/* send it to the server */
	if (FD_ISSET(sock, &wrfd)) {
	    n = ring_to_file(&inbuf, sock);
	    if (n < 0) {
		perror("write socket");
		return -1;
	    }
	}

	/* read server output and print it */
	if (FD_ISSET(sock, &rdfd)) {
	    n = recv_output(sock);
	    if (n < 0) {
		perror("read socket");
		return -1;
	    }
	    if (n == 0)
		return 0;
	}
    }
}