Fix client not to hang when EOF on stdin overtakes C_EXECUTE

Player input may overtake batch file contents (well-known protocol
flaw, see doc/clients-howto for details).  This includes EOF.  When
that happens, the client closes standard input, sends an EOF cookie,
and continues reading output until the server closes the connection.
When it gets C_EXECUTE, it redirects input to the batch file.  But it
then failed to read the batch file.  The server waited forever for the
execute's EOF cookie, the client waited forever for the server closing
the connection.

Fix by stopping only reading from standard input.  Broken in 8b7d0b91,
v4.3.11.

Note that the EOF cookie still overtakes the batch file contents,
which makes the server interpret the input between the execute command
and the EOF as batch file, and the batch file contents as ordinary
input.
This commit is contained in:
Markus Armbruster 2009-04-05 10:58:30 +02:00
parent 92ce7cf665
commit 2196ffd55c

View file

@ -473,10 +473,10 @@ play(int sock)
/*
* Want to read player input only when we don't need to send
* cookies, and we haven't hit EOF on fd 0, and INBUF can
* accept some.
* cookies, and INPUT_FD is still open, and INBUF can accept
* some.
*/
if (!send_intr && !send_eof && !eof_fd0 && ring_space(&inbuf))
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))
@ -503,7 +503,7 @@ play(int sock)
continue;
/* read player input */
if (FD_ISSET(input_fd, &rdfd)) {
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 */
@ -515,10 +515,11 @@ play(int sock)
if (input_fd) {
/* execute done, switch back to fd 0 */
close(input_fd);
input_fd = 0;
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);
}