[vinagre] Hold the slave PTY open, so that SSH does not fail



commit 9001d60fab1057057e995d323ef6fffcc9dfa082
Author: Tristan Schmelcher <tristan_schmelcher alumni uwaterloo ca>
Date:   Tue Oct 18 17:59:39 2011 +0200

    Hold the slave PTY open, so that SSH does not fail
    
    Optionally hold the slave PTY open in the parent. Needed to prevent EIO
    from read() on the master if exec'ing a program that enumerates and
    closes open fds before opening /dev/tty (ssh). Partially fixes bug
    644432.

 vinagre/pty_open.c    |   27 +++++++++++++++++++++++----
 vinagre/pty_open.h    |    3 ++-
 vinagre/vinagre-ssh.c |   12 +++++++++---
 3 files changed, 34 insertions(+), 8 deletions(-)
---
diff --git a/vinagre/pty_open.c b/vinagre/pty_open.c
index a535809..a299146 100644
--- a/vinagre/pty_open.c
+++ b/vinagre/pty_open.c
@@ -404,9 +404,10 @@ _pty_fork_on_pty_name(const char *path, int parent_fd, char **env_add,
 		      const char *directory,
 		      int columns, int rows, 
 		      int *stdin_fd, int *stdout_fd, int *stderr_fd, 
+		      int *held_fd,
 		      pid_t *child, gboolean reapchild, gboolean login)
 {
-	int fd, i;
+	int fd, hold_fd, i;
 	char c;
 	int ready_a[2] = { 0, 0 };
 	int ready_b[2] = { 0, 0 };
@@ -416,6 +417,17 @@ _pty_fork_on_pty_name(const char *path, int parent_fd, char **env_add,
 	int stdout_pipe[2];
 	int stderr_pipe[2];
 
+	/* Optionally hold the slave PTY open in the parent. Needed to prevent
+	 * EIO from read() on the master if exec'ing a program that enumerates
+	 * and closes open fds before opening /dev/tty (ssh). Partially fixes
+	 * bug 644432. */
+	if (held_fd) {
+		hold_fd = open(path, O_RDWR|O_NOCTTY);
+		if (hold_fd == -1) {
+			return -1;
+		}
+	}
+
 	/* Open pipes for synchronizing between parent and child. */
 	if (_pty_pipe_open_bi(&ready_a[0], &ready_a[1],
 			      &ready_b[0], &ready_b[1]) == -1) {
@@ -457,6 +469,7 @@ _pty_fork_on_pty_name(const char *path, int parent_fd, char **env_add,
 		close(stdin_pipe[1]);
 		close(stdout_pipe[0]);
 		close(stderr_pipe[0]);
+		if (held_fd) close(hold_fd);
 
 		if(reapchild) {
 			close(pid_pipe[0]);
@@ -575,6 +588,7 @@ _pty_fork_on_pty_name(const char *path, int parent_fd, char **env_add,
 		*stdin_fd = stdin_pipe[1];
 		*stdout_fd = stdout_pipe[0];
 		*stderr_fd = stderr_pipe[0];
+		if (held_fd) *held_fd = hold_fd;
 
 		return 0;
 		break;
@@ -603,6 +617,7 @@ _pty_fork_on_pty_name(const char *path, int parent_fd, char **env_add,
 	close(ready_b[1]);
  bail_ready:
 	*child = -1;
+	if (held_fd) close(hold_fd);
 	return -1;
 }
 
@@ -716,7 +731,8 @@ static int
 _pty_open_unix98(pid_t *child, guint flags, char **env_add,
 			   const char *command, char **argv,
 			   const char *directory, int columns, int rows,
-			   int *stdin_fd, int *stdout_fd, int *stderr_fd)
+			   int *stdin_fd, int *stdout_fd, int *stderr_fd,
+			   int *held_fd)
 {
 	int fd;
 	char *buf;
@@ -736,6 +752,7 @@ _pty_open_unix98(pid_t *child, guint flags, char **env_add,
 						  argv, directory,
 						  columns, rows,
 						  stdin_fd, stdout_fd, stderr_fd, 
+						  held_fd,
 						  child, 
 						  flags & PTY_REAP_CHILD, 
 						  flags & PTY_LOGIN_TTY) != 0) {
@@ -773,13 +790,15 @@ int
 pty_open(pid_t *child, guint flags, char **env_add, 
 	 const char *command, char **argv, const char *directory,
 	 int columns, int rows,
-	 int *stdin_fd, int *stdout_fd, int *stderr_fd)
+	 int *stdin_fd, int *stdout_fd, int *stderr_fd,
+	 int *held_fd)
 {
 	int ret = -1;
 	if (ret == -1) {
 		ret = _pty_open_unix98(child, flags, env_add, command, 
 						 argv, directory, columns, rows,
-						 stdin_fd, stdout_fd, stderr_fd);
+						 stdin_fd, stdout_fd, stderr_fd,
+						 held_fd);
 	}
 	return ret;
 }
diff --git a/vinagre/pty_open.h b/vinagre/pty_open.h
index 2e482e1..9a3e026 100644
--- a/vinagre/pty_open.h
+++ b/vinagre/pty_open.h
@@ -59,7 +59,8 @@ enum {
 int pty_open(pid_t *child, guint flags, char **env_add,
 	     const char *command, char **argv, const char *directory,
 	     int columns, int rows,
-	     int *stdin_fd, int *stdout_fd, int *stderr_fd);
+	     int *stdin_fd, int *stdout_fd, int *stderr_fd,
+	     int *held_fd);
 
 G_END_DECLS
 
diff --git a/vinagre/vinagre-ssh.c b/vinagre/vinagre-ssh.c
index c5b3427..8bfa507 100644
--- a/vinagre/vinagre-ssh.c
+++ b/vinagre/vinagre-ssh.c
@@ -173,13 +173,15 @@ spawn_ssh (char *args[],
            int *stdin_fd,
            int *stdout_fd,
            int *stderr_fd,
+           int *held_fd,
            GError **error)
 {
 #ifdef USE_PTY
   *tty_fd = pty_open(pid, PTY_REAP_CHILD, NULL,
 		     args[0], args, NULL,
 		     300, 300, 
-		     stdin_fd, stdout_fd, stderr_fd);
+		     stdin_fd, stdout_fd, stderr_fd,
+		     held_fd);
   if (*tty_fd == -1)
     {
       g_set_error_literal (error,
@@ -207,6 +209,7 @@ spawn_ssh (char *args[],
       return FALSE;
     }
   *pid = gpid;
+  if (held_fd) *held_fd = -1; /* Not applicable here. */
 #endif
   
   return TRUE;
@@ -728,7 +731,7 @@ vinagre_ssh_connect (GtkWindow *parent,
 		     gint *tty,
 		     GError **error)
 {
-  int tty_fd, stdin_fd, stdout_fd, stderr_fd;
+  int tty_fd, stdin_fd, stdout_fd, stderr_fd, held_fd;
   GPid pid;
   gchar *user, *host, **args;
   gboolean res;
@@ -758,7 +761,7 @@ vinagre_ssh_connect (GtkWindow *parent,
   args = setup_ssh_commandline (host, port, user, extra_arguments, command);
   if (!spawn_ssh (args,
 		  &pid,
-		  &tty_fd, &stdin_fd, &stdout_fd, &stderr_fd,
+		  &tty_fd, &stdin_fd, &stdout_fd, &stderr_fd, &held_fd,
 		  error))
     {
       g_strfreev (args);
@@ -772,6 +775,9 @@ vinagre_ssh_connect (GtkWindow *parent,
   else
     res = handle_login (parent, host, port, user, tty_fd, stdout_fd, stderr_fd, error);
 
+  /* ssh has opened the PTY slave by now, so we can close it */
+  if (held_fd != -1) close(held_fd);
+
   g_strfreev (args);
   g_free (user);
   g_free (host);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]