aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/telnetd.c22
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);