- Applied pty cleanup patch from markus.friedl@informatik.uni-erlangen.de
diff --git a/ChangeLog b/ChangeLog
index e118a33..12edfc4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,7 @@
    - Rewrote OpenSSL detection code. Now uses AC_TRY_RUN with a test program
      to detect library and header location _and_ ensure library has proper
      RSA support built in (this is a problem with OpenSSL 0.9.5).
+ - Applied pty cleanup patch from markus.friedl@informatik.uni-erlangen.de
 
 20000207
  - Removed SOCKS code. Will support through a ProxyCommand.
diff --git a/pty.c b/pty.c
index b3a0535..de6f751 100644
--- a/pty.c
+++ b/pty.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: pty.c,v 1.11 1999/12/21 00:18:08 damien Exp $");
+RCSID("$Id: pty.c,v 1.12 2000/03/02 12:30:53 damien Exp $");
 
 #ifdef HAVE_UTIL_H
 # include <util.h>
@@ -188,9 +188,9 @@
 pty_release(const char *ttyname)
 {
 	if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0)
-		debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
+		error("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
 	if (chmod(ttyname, (mode_t) 0666) < 0)
-		debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
+		error("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
 }
 
 /* Makes the tty the processes controlling tty and sets it to sane modes. */
@@ -259,3 +259,29 @@
 	w.ws_ypixel = ypixel;
 	(void) ioctl(ptyfd, TIOCSWINSZ, &w);
 }
+
+void
+pty_setowner(struct passwd *pw, const char *ttyname)
+{
+	struct group *grp;
+	gid_t gid;
+	mode_t mode;
+
+	/* Determine the group to make the owner of the tty. */
+	grp = getgrnam("tty");
+	if (grp) {
+		gid = grp->gr_gid;
+		mode = S_IRUSR | S_IWUSR | S_IWGRP;
+	} else {
+		gid = pw->pw_gid;
+		mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
+	}
+
+	/* Change ownership of the tty. */
+	if (chown(ttyname, pw->pw_uid, gid) < 0)
+		fatal("chown(%.100s, %d, %d) failed: %.100s",
+		    ttyname, pw->pw_uid, gid, strerror(errno));
+	if (chmod(ttyname, mode) < 0)
+		fatal("chmod(%.100s, 0%o) failed: %.100s",
+		    ttyname, mode, strerror(errno));
+}
diff --git a/pty.h b/pty.h
index 186cb3c..4d0e5f1 100644
--- a/pty.h
+++ b/pty.h
@@ -13,7 +13,7 @@
  * tty.
  */
 
-/* RCSID("$Id: pty.h,v 1.4 1999/12/07 04:38:32 damien Exp $"); */
+/* RCSID("$Id: pty.h,v 1.5 2000/03/02 12:30:53 damien Exp $"); */
 
 #ifndef PTY_H
 #define PTY_H
@@ -43,4 +43,6 @@
 pty_change_window_size(int ptyfd, int row, int col,
     int xpixel, int ypixel);
 
+void	pty_setowner(struct passwd *pw, const char *ttyname);
+
 #endif				/* PTY_H */
diff --git a/sshd.c b/sshd.c
index 0a6045e..f49b453 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1622,6 +1622,37 @@
 	}
 }
 
+struct pty_cleanup_context {
+	const char *ttyname;
+	int pid;
+};
+
+/*
+ * Function to perform cleanup if we get aborted abnormally (e.g., due to a
+ * dropped connection).
+ */
+void 
+pty_cleanup_proc(void *context)
+{
+	struct pty_cleanup_context *cu = context;
+
+	debug("pty_cleanup_proc called");
+
+	/* Record that the user has logged out. */
+	record_logout(cu->pid, cu->ttyname);
+
+	/* Release the pseudo-tty. */
+	pty_release(cu->ttyname);
+}
+
+/* simple cleanup: chown tty slave back to root */
+static void
+pty_release_proc(void *tty)
+{
+	char *ttyname = tty;
+	pty_release(ttyname);
+}
+
 /*
  * Prepares for an interactive session.  This is called after the user has
  * been successfully authenticated.  During this message exchange, pseudo
@@ -1636,11 +1667,7 @@
 	int have_pty = 0, ptyfd = -1, ttyfd = -1, xauthfd = -1;
 	int row, col, xpixel, ypixel, screen;
 	char ttyname[64];
-	char *command, *term = NULL, *display = NULL, *proto = NULL,
-	*data = NULL;
-	struct group *grp;
-	gid_t tty_gid;
-	mode_t tty_mode;
+	char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL;
 	int n_bytes;
 
 	/*
@@ -1698,33 +1725,20 @@
 				error("Failed to allocate pty.");
 				goto fail;
 			}
-			/* Determine the group to make the owner of the tty. */
-			grp = getgrnam("tty");
-			if (grp) {
-				tty_gid = grp->gr_gid;
-				tty_mode = S_IRUSR | S_IWUSR | S_IWGRP;
-			} else {
-				tty_gid = pw->pw_gid;
-				tty_mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
-			}
-
-			/* Change ownership of the tty. */
-			if (chown(ttyname, pw->pw_uid, tty_gid) < 0)
-				fatal("chown(%.100s, %d, %d) failed: %.100s",
-				      ttyname, pw->pw_uid, tty_gid, strerror(errno));
-			if (chmod(ttyname, tty_mode) < 0)
-				fatal("chmod(%.100s, 0%o) failed: %.100s",
-				      ttyname, tty_mode, strerror(errno));
+			fatal_add_cleanup(pty_release_proc, (void *)ttyname);
+			pty_setowner(pw, ttyname);
 
 			/* Get TERM from the packet.  Note that the value may be of arbitrary length. */
 			term = packet_get_string(&dlen);
 			packet_integrity_check(dlen, strlen(term), type);
-			/* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
+
 			/* Remaining bytes */
 			n_bytes = plen - (4 + dlen + 4 * 4);
 
-			if (strcmp(term, "") == 0)
+			if (strcmp(term, "") == 0) {
+				xfree(term);
 				term = NULL;
+			}
 
 			/* Get window size from the packet. */
 			row = packet_get_int();
@@ -1998,29 +2012,6 @@
 #endif /* USE_PIPES */
 }
 
-struct pty_cleanup_context {
-	const char *ttyname;
-	int pid;
-};
-
-/*
- * Function to perform cleanup if we get aborted abnormally (e.g., due to a
- * dropped connection).
- */
-void 
-pty_cleanup_proc(void *context)
-{
-	struct pty_cleanup_context *cu = context;
-
-	debug("pty_cleanup_proc called");
-
-	/* Record that the user has logged out. */
-	record_logout(cu->pid, cu->ttyname);
-
-	/* Release the pseudo-tty. */
-	pty_release(cu->ttyname);
-}
-
 /*
  * This is called to fork and execute a command when we have a tty.  This
  * will call do_child from the child, and server_loop from the parent after
@@ -2167,6 +2158,15 @@
 	close(ttyfd);
 
 	/*
+	 * Add a cleanup function to clear the utmp entry and record logout
+	 * time in case we call fatal() (e.g., the connection gets closed).
+	 */
+	cleanup_context.pid = pid;
+	cleanup_context.ttyname = ttyname;
+	fatal_add_cleanup(pty_cleanup_proc, (void *) &cleanup_context);
+	fatal_remove_cleanup(pty_release_proc, (void *) ttyname);
+
+	/*
 	 * Create another descriptor of the pty master side for use as the
 	 * standard input.  We could use the original descriptor, but this
 	 * simplifies code in server_loop.  The descriptor is bidirectional.
@@ -2175,14 +2175,6 @@
 	if (fdout < 0)
 		packet_disconnect("dup failed: %.100s", strerror(errno));
 
-	/*
-	 * Add a cleanup function to clear the utmp entry and record logout
-	 * time in case we call fatal() (e.g., the connection gets closed).
-	 */
-	cleanup_context.pid = pid;
-	cleanup_context.ttyname = ttyname;
-	fatal_add_cleanup(pty_cleanup_proc, (void *) &cleanup_context);
-
 	/* Enter interactive session. */
 	server_loop(pid, ptyfd, fdout, -1);
 	/* server_loop has not closed ptyfd and fdout. */