From 81908f2ff28c6e131bfd81ff3c5d1b9ee93ef038 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 17 Mar 2021 21:46:27 -0700 Subject: telnetd: don't exit if waitpid() returns 0. Noticed while using telnetd to manually test some telnet fixes: telnetd would sometimes exit when I'd disconnect because it couldn't find pid 0 on its list of sessions. I've not seen obscure exits because select() times out, but I've also changed that `return` to an error_exit() so we'll at least know what's happened if that ever occurs. Also use rather than manually #define'ing its constants, use the FLAG() macro throughout, and xsetsockopt(). Don't pointlessly set errno to 0 at the start of main and then never look at it again. --- toys/pending/telnetd.c | 56 ++++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) (limited to 'toys') diff --git a/toys/pending/telnetd.c b/toys/pending/telnetd.c index bb08e785..c82ff61e 100644 --- a/toys/pending/telnetd.c +++ b/toys/pending/telnetd.c @@ -24,7 +24,9 @@ config TELNETD #define FOR_telnetd #include "toys.h" +#include #include + GLOBALS( char *login_path; char *issue_path; @@ -36,20 +38,6 @@ GLOBALS( pid_t fork_pid; ) - -# define IAC 255 /* interpret as command: */ -# define DONT 254 /* you are not to use option */ -# define DO 253 /* please, you use option */ -# define WONT 252 /* I won't use option */ -# define WILL 251 /* I will use option */ -# define SB 250 /* interpret as subnegotiation */ -# define SE 240 /* end sub negotiation */ -# define NOP 241 /* No Operation */ -# define TELOPT_ECHO 1 /* echo */ -# define TELOPT_SGA 3 /* suppress go ahead */ -# define TELOPT_TTYPE 24 /* terminal type */ -# define TELOPT_NAWS 31 /* window size */ - #define BUFSIZE 4*1024 struct term_session { int new_fd, pty_fd; @@ -132,7 +120,7 @@ static int listen_socket(void) char buf[sizeof(struct sockaddr_storage)]; memset(buf, 0, sizeof(buf)); - if (toys.optflags & FLAG_b) { + if (FLAG(b)) { get_sockaddr(TT.host_addr, buf); af = ((struct sockaddr *)buf)->sa_family; } else { @@ -140,8 +128,7 @@ static int listen_socket(void) ((struct sockaddr_in*)buf)->sin_family = af; } s = xsocket(af, SOCK_STREAM, 0); - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) == -1) - perror_exit("setsockopt"); + xsetsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); xbind(s, (struct sockaddr *)buf, ((af == AF_INET)? (sizeof(struct sockaddr_in)):(sizeof(struct sockaddr_in6)))); @@ -187,9 +174,9 @@ static int new_session(int sockfd) setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i)); flags = fcntl(sockfd, F_GETFL); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - if (toys.optflags & FLAG_i) fcntl((sockfd + 1), F_SETFL, flags | O_NONBLOCK); + if (FLAG(i)) fcntl((sockfd + 1), F_SETFL, flags | O_NONBLOCK); - writeall((toys.optflags & FLAG_i)?1:sockfd, intial_iacs, sizeof(intial_iacs)); + 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); @@ -300,21 +287,19 @@ static int dup_iacs(char *start, int fd, int len) void telnetd_main(void) { - errno = 0; fd_set rd, wr; struct term_session *tm = NULL; struct timeval tv, *tv_ptr = NULL; int pty_fd, new_fd, c = 0, w, master_fd = 0; - int inetd_m = toys.optflags & FLAG_i; - if (!(toys.optflags & FLAG_l)) TT.login_path = "/bin/login"; - if (!(toys.optflags & FLAG_f)) TT.issue_path = "/etc/issue.net"; - if (toys.optflags & FLAG_w) toys.optflags |= FLAG_F; - if (!inetd_m) { + if (!FLAG(l)) TT.login_path = "/bin/login"; + if (!FLAG(f)) TT.issue_path = "/etc/issue.net"; + if (FLAG(w)) toys.optflags |= FLAG_F; + if (!FLAG(i)) { master_fd = listen_socket(); fcntl(master_fd, F_SETFD, FD_CLOEXEC); if (master_fd > TT.gmax_fd) TT.gmax_fd = master_fd; - if (!(toys.optflags & FLAG_F)) daemon(0, 0); + if (!FLAG(F)) daemon(0, 0); } else { pty_fd = new_session(master_fd); //master_fd = 0 if (pty_fd > TT.gmax_fd) TT.gmax_fd = pty_fd; @@ -328,7 +313,7 @@ void telnetd_main(void) } else session_list = tm; } - if ((toys.optflags & FLAG_w) && !session_list) { + if (FLAG(w) && !session_list) { tv.tv_sec = TT.w_sec; tv.tv_usec = 0; tv_ptr = &tv; @@ -338,7 +323,7 @@ void telnetd_main(void) for (;;) { FD_ZERO(&rd); FD_ZERO(&wr); - if (!inetd_m) FD_SET(master_fd, &rd); + if (!FLAG(i)) FD_SET(master_fd, &rd); tm = session_list; while (tm) { @@ -354,10 +339,10 @@ void telnetd_main(void) int r = select(TT.gmax_fd + 1, &rd, &wr, NULL, tv_ptr); - if (!r) return; //timeout + if (!r) error_exit("select timed out"); if (r < -1) continue; - if (!inetd_m && FD_ISSET(master_fd, &rd)) { //accept new connection + if (!FLAG(i) && FD_ISSET(master_fd, &rd)) { //accept new connection new_fd = accept(master_fd, NULL, NULL); if (new_fd < 0) continue; tv_ptr = NULL; @@ -382,7 +367,7 @@ void telnetd_main(void) if ((c = read(tm->pty_fd, tm->buff1 + tm->buff1_avail, BUFSIZE-tm->buff1_avail)) <= 0) break; tm->buff1_avail += c; - if ((w = dup_iacs(tm->buff1 + tm->buff1_written, tm->new_fd + inetd_m, + if ((w = dup_iacs(tm->buff1 + tm->buff1_written, tm->new_fd + FLAG(i), tm->buff1_avail - tm->buff1_written)) < 0) break; tm->buff1_written += w; } @@ -401,7 +386,7 @@ void telnetd_main(void) tm->buff2_written += w; } if (FD_ISSET(tm->new_fd, &wr)) { - if ((w = dup_iacs(tm->buff1 + tm->buff1_written, tm->new_fd + inetd_m, + if ((w = dup_iacs(tm->buff1 + tm->buff1_written, tm->new_fd + FLAG(i), tm->buff1_avail - tm->buff1_written)) < 0) break; tm->buff1_written += w; } @@ -421,17 +406,16 @@ void telnetd_main(void) // funny little dance to avoid race conditions. toys.signal = 0; pid = waitpid(-1, &status, WNOHANG); - if (pid < 0) break; + if (pid <= 0) break; toys.signal++; - for (tm = session_list; tm; tm = tm->next) { if (tm->child_pid == pid) break; prev = tm; } - if (!tm) return; // reparented child we don't care about + if (!tm) error_exit("unexpected reparenting of %d", pid); - if (toys.optflags & FLAG_i) exit(EXIT_SUCCESS); + if (FLAG(i)) exit(EXIT_SUCCESS); if (!prev) session_list = session_list->next; else prev->next = tm->next; utmp_entry(); -- cgit v1.2.3