diff options
Diffstat (limited to 'toys/pending/telnetd.c')
-rw-r--r-- | toys/pending/telnetd.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/toys/pending/telnetd.c b/toys/pending/telnetd.c index 7bfbf316..032104f2 100644 --- a/toys/pending/telnetd.c +++ b/toys/pending/telnetd.c @@ -149,23 +149,16 @@ static int new_session(int sockfd) { char *argv_login[] = {NULL, "-h", NULL, NULL}; char tty_name[30]; //tty name length. - int fd, flags, i = 1; + int fd, i = 1; char intial_iacs[] = {IAC, DO, TELOPT_ECHO, IAC, DO, TELOPT_NAWS, IAC, WILL, TELOPT_ECHO, IAC, WILL, TELOPT_SGA }; struct sockaddr_storage sa; socklen_t sl = sizeof(sa); setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i)); - flags = fcntl(sockfd, F_GETFL); - fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - if (FLAG(i)) fcntl((sockfd + 1), F_SETFL, flags | O_NONBLOCK); writeall(FLAG(i)?1:sockfd, intial_iacs, sizeof(intial_iacs)); - if ((TT.fork_pid = forkpty(&fd, tty_name, NULL, NULL)) > 0) { - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - return fd; - } + if ((TT.fork_pid = forkpty(&fd, tty_name, NULL, NULL)) > 0) return fd; if (TT.fork_pid < 0) perror_exit("fork"); if (getpeername(sockfd, (void *)&sa, &sl)) perror_exit("getpeername"); @@ -362,7 +355,15 @@ void telnetd_main(void) } if (FD_ISSET(tm->new_fd, &rd)) { if ((c = read(tm->new_fd, tm->buff2+tm->buff2_avail, - BUFSIZE-tm->buff2_avail)) <= 0) break; + BUFSIZE-tm->buff2_avail)) <= 0) { + // The other side went away without a proper shutdown. Happens if + // you exit telnet via ^]^D, leaving the socket in TIME_WAIT. + xclose(tm->new_fd); + tm->new_fd = -1; + xclose(tm->pty_fd); + tm->pty_fd = -1; + break; + } c = handle_iacs(tm, c, tm->pty_fd); tm->buff2_avail += c; if ((w = write(tm->pty_fd, tm->buff2+ tm->buff2_written, @@ -405,6 +406,7 @@ void telnetd_main(void) if (!tm) error_exit("unexpected reparenting of %d", pid); if (FLAG(i)) exit(EXIT_SUCCESS); + if (!prev) session_list = session_list->next; else prev->next = tm->next; xclose(tm->pty_fd); |