Blob Blame History Raw
diff -up netkit-rsh-0.17/rlogind/rlogind.c.rh947213 netkit-rsh-0.17/rlogind/rlogind.c
--- netkit-rsh-0.17/rlogind/rlogind.c.rh947213	2013-04-11 14:18:47.481715853 +0200
+++ netkit-rsh-0.17/rlogind/rlogind.c	2013-04-11 14:32:50.807780164 +0200
@@ -67,12 +67,13 @@ char rcsid[] =
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <pty.h>
+#include <utmp.h>
 
 #include "pathnames.h"
 #include "logwtmp.h"
 #include "rlogind.h"
 
-pid_t forkpty(int *, char *, struct termios *, struct winsize *);
 int logout(const char *);
 
 #ifndef TIOCPKT_WINDOW
@@ -389,7 +390,7 @@ static void getstr(char *buf, int cnt, c
 }
 
 static void doit(int netfd) {
-    int master, pid, on = 1;
+    int master, slave, r, pid, on = 1;
     int authenticated = 0;
     char *hname;
     int hostok;
@@ -421,12 +422,34 @@ static void doit(int netfd) {
 	write(netfd, "rlogind: Host address mismatch.\r\n", 33);
     }
 
-    pid = forkpty(&master, line, NULL, &win);
-    if (pid < 0) {
+    /*  We can no longer call forkpty here (a convenience routine that combines
+        openpty, fork, and login_tty) because, with forkpty, the slave end of
+        the pty is open only in the child process. The child process execs
+        /bin/login which now closes all open file descriptors before doing a
+        vhangup (see lkml.org/lkml/2012/6/5/145), and this resets packet mode
+        on the pty, undoing the effect of the ioctl(master, TIOCPKT, &on) call
+        made by the parent.
+
+        Instead, we call openpty, fork, and login_tty individually, so that we
+        can keep a file descriptor to the slave open in the parent process,
+        thereby retaining packet mode even when the child closes file descriptors
+        to call vhangup. */
+    r = openpty(&master, &slave, line, NULL, &win);
+    if (r < 0) {
 	if (errno == ENOENT) fatal(netfd, "Out of ptys", 0);
-	fatal(netfd, "Forkpty", 1);
+	fatal(netfd, "Openpty", 1);
+    }
+
+    signal(SIGHUP, SIG_IGN);
+
+    pid = fork();
+    if (pid < 0) {
+        fatal(netfd, "Fork", 1);
     }
+
     if (pid == 0) {
+	close(master);
+	login_tty(slave);
 	/* netfd should always be 0, but... */ 
 	if (netfd > 2) close(netfd);
 	child(hname, termtype, lusername, authenticated, rusername);