aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/telnetd.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/pending/telnetd.c')
-rw-r--r--toys/pending/telnetd.c54
1 files changed, 22 insertions, 32 deletions
diff --git a/toys/pending/telnetd.c b/toys/pending/telnetd.c
index c82ff61e..032104f2 100644
--- a/toys/pending/telnetd.c
+++ b/toys/pending/telnetd.c
@@ -25,7 +25,6 @@ config TELNETD
#define FOR_telnetd
#include "toys.h"
#include <arpa/telnet.h>
-#include <utmp.h>
GLOBALS(
char *login_path;
@@ -97,23 +96,6 @@ static void get_sockaddr(char *host, void *buf)
else ((struct sockaddr_in6*)buf)->sin6_port = port_num;
}
-static void utmp_entry(void)
-{
- struct utmp entry;
- struct utmp *utp_ptr;
- pid_t pid = getpid();
-
- utmpname(_PATH_UTMP);
- setutent(); //start from start
- while ((utp_ptr = getutent()) != NULL) {
- if (utp_ptr->ut_pid == pid && utp_ptr->ut_type >= INIT_PROCESS) break;
- }
- if (!utp_ptr) entry.ut_type = DEAD_PROCESS;
- entry.ut_time = time(0);
- setutent();
- pututline(&entry);
-}
-
static int listen_socket(void)
{
int s, af = AF_INET, yes = 1;
@@ -165,27 +147,27 @@ static void write_issue(char *tty)
static int new_session(int sockfd)
{
- char *argv_login[2]; //arguments for execvp cmd, NULL
+ 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");
+ if (getnameinfo((void *)&sa, sl, toybuf, sizeof(toybuf), NULL, 0, 0))
+ perror_exit("getnameinfo");
+
write_issue(tty_name);
- argv_login[0] = strdup(TT.login_path);
- argv_login[1] = NULL;
+ argv_login[0] = TT.login_path;
+ argv_login[2] = toybuf;
execvp(argv_login[0], argv_login);
exit(EXIT_FAILURE);
}
@@ -373,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,
@@ -416,9 +406,9 @@ 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;
- utmp_entry();
xclose(tm->pty_fd);
xclose(tm->new_fd);
free(tm);