changeset 210:82ebd1b05345

2003-7-6 Brian Masney <masneyb@gftp.org> * lib/pty.c lib/gftp.h - added gftp_exec_with_new_pty() and gftp_exec_without_new_pty() * lib/sshv2.c - use the 2 new functions above * lib/pty.c lib/gftp.h - split open_ptys() to _gftp_ptym_open() and _gftp_ptys_open() * lib/sslcommon.c - don't do thread setup if we are compiling against glib 1.2. I do not want to link against the pthread library because that would make the text port dependant on pthreads being installed on the box
author masneyb
date Sun, 06 Jul 2003 13:52:43 +0000
parents d79e2782eb1b
children 3f2203e70218
files ChangeLog lib/gftp.h lib/pty.c lib/sshv2.c lib/sslcommon.c
diffstat 5 files changed, 293 insertions(+), 136 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Jul 05 17:30:14 2003 +0000
+++ b/ChangeLog	Sun Jul 06 13:52:43 2003 +0000
@@ -1,3 +1,17 @@
+2003-7-6 Brian Masney <masneyb@gftp.org>
+	* lib/pty.c lib/gftp.h - added gftp_exec_with_new_pty() and
+	gftp_exec_without_new_pty()
+
+	* lib/sshv2.c - use the 2 new functions above
+
+	* lib/pty.c lib/gftp.h - split open_ptys() to _gftp_ptym_open()
+	and _gftp_ptys_open()
+
+	* lib/sslcommon.c - don't do thread setup if we are compiling against
+	glib 1.2. I do not want to link against the pthread library because 
+	that would make the text port dependant on pthreads being installed on
+	the box
+
 2003-7-5 Brian Masney <masneyb@gftp.org>
 	* lib/protocols.c (gftp_get_line) - fixed bug where the read function
 	was being called one extra time after the end of file was reached
@@ -1167,7 +1181,7 @@
 
 	* cvsclean - added this script
 
-	* *.[ch] - added $Id: ChangeLog,v 1.105 2003/07/05 17:30:13 masneyb Exp $ tags
+	* *.[ch] - added $Id: ChangeLog,v 1.106 2003/07/06 13:52:42 masneyb Exp $ tags
 
 	* debian/* - updated files from Debian maintainer
 
--- a/lib/gftp.h	Sat Jul 05 17:30:14 2003 +0000
+++ b/lib/gftp.h	Sun Jul 06 13:52:43 2003 +0000
@@ -90,10 +90,13 @@
 
 #ifdef HAVE_PTY_H
 #include <pty.h>
+#include <utmp.h> /* for login_tty */
 #elif HAVE_LIBUTIL_H
 #include <libutil.h>
+#include <utmp.h> /* for login_tty */
 #else
 extern int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize * winp);
+extern int login_tty(int fd);
 #endif
 
 #ifdef HAVE_GETADDRINFO
@@ -945,13 +948,15 @@
 					  mode_t perms );
 
 /* pty.c */
-char * get_pty_impl 			( void );
+char * gftp_get_pty_impl 		( void );
 
-int open_ptys 				( gftp_request * request, 
+pid_t gftp_exec_with_new_pty 		( gftp_request * request, 
 					  int *fdm, 
-					  int *fds );
+					  char **args );
 
-int tty_raw 				( int fd );
+pid_t gftp_exec_without_new_pty 	( gftp_request * request, 
+					  int *fdm, 
+					  char **args );
 
 #ifdef USE_SSL
 /* sslcommon.c */
--- a/lib/pty.c	Sat Jul 05 17:30:14 2003 +0000
+++ b/lib/pty.c	Sun Jul 06 13:52:43 2003 +0000
@@ -24,100 +24,134 @@
 #ifdef __sgi
 
 char *
-get_pty_impl (void)
+gftp_get_pty_impl (void)
 {
   return ("sgi");
 }
 
 
-int
-open_ptys (gftp_request * request, int *fdm, int *fds)
+static int
+_gftp_ptym_open (char *pts_name, size_t len, int *fds)
 {
-  char *pts_name;
+  char *new_pts_name;
+  int fdm;
 
-  if ((pts_name = _getpty (fdm, O_RDWR, 0600, 0)) == NULL)
+  if ((new_pts_name = _getpty (&fdm, O_RDWR, 0600, 0)) == NULL)
     return (GFTP_ERETRYABLE);
 
-  if ((*fds = open (pts_name, O_RDWR)) < 0)
+  strncpy (pts_name, new_pts_name, len);
+
+  return (fdm);
+}
+
+
+static int
+_gftp_ptys_open (int fdm, int fds, char *pts_name)
+{
+  int new_fds;
+
+  if ((new_fds = open (pts_name, O_RDWR)) < 0)
     {
-      close (*fdm);
-      return (GFTP_ERETRYABLE);
+      close (fdm);
+      return (-1);
     }
 
-  return (0);
+  return (new_fds);
 }
 
 #elif HAVE_GRANTPT
 
 char *
-get_pty_impl (void)
+gftp_get_pty_impl (void)
 {
   return ("unix98");
 }
 
 
-int
-open_ptys (gftp_request * request, int *fdm, int *fds)
+static int
+_gftp_ptym_open (char *pts_name, size_t len, int *fds)
 {
-  char *pts_name;
+  char *new_pts_name;
+  int fdm;
 
-  if ((*fdm = open ("/dev/ptmx", O_RDWR)) < 0)
+  if ((fdm = open ("/dev/ptmx", O_RDWR)) < 0)
     return (GFTP_ERETRYABLE);
 
-  if (grantpt (*fdm) < 0)
+  if (grantpt (fdm) < 0)
     {
-      close (*fdm);
+      close (fdm);
+      return (GFTP_ERETRYABLE);
+    }
+
+  if (unlockpt (fdm) < 0)
+    {
+      close (fdm);
       return (GFTP_ERETRYABLE);
     }
 
-  if (unlockpt (*fdm) < 0)
+  if ((new_pts_name = ptsname (fdm)) == NULL)
     {
-      close (*fdm);
+      close (fdm);
       return (GFTP_ERETRYABLE);
     }
 
-  if ((pts_name = ptsname (*fdm)) == NULL)
+  strncpy (pts_name, new_pts_name, len);
+
+  return (fdm);
+}
+
+
+static int
+_gftp_ptys_open (int fdm, int fds, char *pts_name)
+{
+  int new_fds;
+
+  if ((new_fds = open (pts_name, O_RDWR)) < 0)
     {
-      close (*fdm);
-      return (GFTP_ERETRYABLE);
-    }
-
-  if ((*fds = open (pts_name, O_RDWR)) < 0)
-    {
-      close (*fdm);
-      return (GFTP_ERETRYABLE);
+      close (fdm);
+      return (-1);
     }
 
 #ifdef SYSV
   /* I intentionally ignore these errors */
-  ioctl (*fds, I_PUSH, "ptem");
-  ioctl (*fds, I_PUSH, "ldterm");
-  ioctl (*fds, I_PUSH, "ttcompat");
+  ioctl (new_fds, I_PUSH, "ptem");
+  ioctl (new_fds, I_PUSH, "ldterm");
+  ioctl (new_fds, I_PUSH, "ttcompat");
 #endif
 
-  return (0);
+  return (new_fds);
 }
 
 #elif HAVE_OPENPTY
 
 char *
-get_pty_impl (void)
+gftp_get_pty_impl (void)
 {
   return ("openpty");
 }
 
 
-int
-open_ptys (gftp_request * request, int *fdm, int *fds)
+static int
+_gftp_ptym_open (char *pts_name, size_t len, int *fds)
 {
-  char *pts_name;
+  int fdm;
 
-  if (openpty (fdm, fds, &pts_name, NULL, NULL ) < 0)
+  if (openpty (&fdm, fds, pts_name, NULL, NULL) < 0)
     return (GFTP_ERETRYABLE);
 
   ioctl (*fds, TIOCSCTTY, NULL);
 
-  return (0);
+  return (fdm);
+}
+
+
+static int
+_gftp_ptys_open (int fdm, int fds, char *pts_name)
+{
+  if (login_tty (fds) < 0)
+    return (GFTP_EFATAL);
+
+  return (fds);
 }
 
 #else /* !HAVE_OPENPTY */
@@ -125,53 +159,65 @@
 /* Fall back to *BSD... */
 
 char *
-get_pty_impl (void)
+gftp_get_pty_impl (void)
 {
   return ("bsd");
 }
 
 
-int
-open_ptys (gftp_request * request, int *fdm, int *fds)
+static int
+_gftp_ptym_open (char *pts_name, size_t len, int *fds)
 {
-  char pts_name[20], *pos1, *pos2;
+  char *pos1, *pos2;
+  int fdm;
 
-  strncpy (pts_name, "/dev/ptyXY", sizeof (pts_name));
+  g_return_val_if_fail (len >= 10, GFTP_EFATAL);
+
+  strncpy (pts_name, "/dev/ptyXY", len);
   for (pos1 = "pqrstuvwxyzPQRST"; *pos1 != '\0'; pos1++) 
     {
       pts_name[8] = *pos1;
       for (pos2 = "0123456789abcdef"; *pos2 != '\0'; pos2++)
         {
           pts_name[9] = *pos2;
-          if ((*fdm = open (pts_name, O_RDWR)) < 0)
+          if ((fdm = open (pts_name, O_RDWR)) < 0)
             continue;
 
           pts_name[5] = 't';
           chmod (pts_name, S_IRUSR | S_IWUSR);
           chown (pts_name, getuid (), -1);
 
-          if ((*fds = open (pts_name, O_RDWR)) < 0)
-            {
-              pts_name[5] = 'p';
-              continue;
-            }
-
-#if defined(TIOCSCTTY) && !defined(CIBAUD)
-          ioctl (*fds, TIOCSCTTY, NULL);
-#endif
-
-          return (0);
+          return (fdm);
         }
     }
 
   return (GFTP_ERETRYABLE);
 }
 
+
+static int
+_gftp_ptys_open (int fdm, int fds, char *pts_name)
+{
+  int new_fds;
+
+  if ((new_fds = open (pts_name, O_RDWR)) < 0)
+    {
+      close (fdm);
+      return (-1);
+    }
+
+#if defined(TIOCSCTTY) && !defined(CIBAUD)
+  ioctl (new_fds, TIOCSCTTY, NULL);
+#endif
+
+  return (new_fds);
+}
+
 #endif /* __sgi */
 
 
-int
-tty_raw (int fd)
+static int
+_gftp_tty_raw (int fd)
 {
   struct termios buf;
 
@@ -195,3 +241,123 @@
 }
 
 
+static void
+_gftp_close_all_fds (void)
+{
+  int i, maxfds;
+
+#ifdef HAVE_GETDTABLESIZE
+  maxfds = getdtablesize () - 1;
+#elif defined (OPEN_MAX)
+  maxfds = OPEN_MAX;
+#else
+  maxfds = -1;
+#endif
+
+  for (i=3; i<maxfds; i++)
+    close (i);
+}
+
+
+pid_t
+gftp_exec_without_new_pty (gftp_request * request, int *fdm, char **args)
+{
+  pid_t child;
+  int s[2];
+
+  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0)
+    {
+      request->logging_function (gftp_logging_error, request,
+                                 _("Cannot create a socket pair: %s\n"),
+                                 g_strerror (errno));
+      return (-1);
+    }
+
+  if ((child = fork ()) == 0)
+    {
+      setsid ();
+
+      close (s[0]);
+
+      _gftp_tty_raw (s[1]);
+      dup2 (s[1], 0);
+      dup2 (s[1], 1);
+      dup2 (s[1], 2);
+      _gftp_close_all_fds ();
+
+      execvp (args[0], args);
+
+      printf (_("Error: Cannot execute ssh: %s\n"), g_strerror (errno));
+      exit (1);
+    }
+  else if (child > 0)
+    {
+      close (s[1]);
+      _gftp_tty_raw (s[0]);
+      *fdm = s[0];
+      return (child);
+    }
+  else
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Cannot fork another process: %s\n"),
+                                 g_strerror (errno));
+      return (-1);
+    }
+}
+
+
+pid_t
+gftp_exec_with_new_pty (gftp_request * request, int *fdm, char **args)
+{
+  char pts_name[64];
+  pid_t child;
+  int fds;
+
+  *pts_name = '\0';
+  if ((*fdm = _gftp_ptym_open (pts_name, sizeof (pts_name), &fds)) < 0)
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                _("Cannot open master pty %s: %s\n"), pts_name,
+                                g_strerror (errno));
+      return (-1);
+    }
+
+  if ((child = fork ()) == 0)
+    {
+      setsid ();
+
+      if ((fds = _gftp_ptys_open (*fdm, fds, pts_name)) < 0)
+        {
+          printf ("Cannot open slave pts %s: %s\n", pts_name, 
+                  g_strerror (errno));
+          return (-1);
+        }
+
+      close (*fdm);
+
+      _gftp_tty_raw (fds);
+      dup2 (fds, 0);
+      dup2 (fds, 1);
+      dup2 (fds, 2);
+      _gftp_close_all_fds ();
+
+      execvp (args[0], args);
+
+      printf (_("Error: Cannot execute ssh: %s\n"), g_strerror (errno));
+      exit (1);
+    }
+  else if (child > 0)
+    {
+      _gftp_tty_raw (*fdm);
+      return (child);
+    }
+  else
+    {
+      request->logging_function (gftp_logging_error, request->user_data,
+                                 _("Cannot fork another process: %s\n"),
+                                 g_strerror (errno));
+      return (-1);
+    }
+}
+
--- a/lib/sshv2.c	Sat Jul 05 17:30:14 2003 +0000
+++ b/lib/sshv2.c	Sun Jul 06 13:52:43 2003 +0000
@@ -813,7 +813,7 @@
 static int
 sshv2_connect (gftp_request * request)
 {
-  int version, s[2], ret, ssh_use_askpass, sshv2_use_sftp_subsys;
+  int version, ret, ssh_use_askpass, sshv2_use_sftp_subsys, fdm;
   char **args, *tempstr, *p1, p2, *exepath, *ssh2_sftp_path;
   struct servent serv_struct;
   sshv2_message message;
@@ -867,90 +867,56 @@
   args = sshv2_gen_exec_args (request, exepath, sshv2_use_sftp_subsys);
 
   if (ssh_use_askpass || sshv2_use_sftp_subsys)
-    {
-      if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0)
-        {
-          request->logging_function (gftp_logging_error, request,
-                                     _("Cannot create a socket pair: %s\n"),
-                                     g_strerror (errno));
-          return (GFTP_ERETRYABLE);
-        }
-    }
+    child = gftp_exec_without_new_pty (request, &fdm, args);
   else
-    {
-      if ((ret = open_ptys (request, &s[0], &s[1])) < 0)
-        return (ret);
-    }
- 
-  if ((child = fork ()) == 0)
+    child = gftp_exec_with_new_pty (request, &fdm, args);
+
+  if (child == 0)
+    exit (0);
+  else if (child < 0)
+    return (GFTP_ERETRYABLE);
+
+  if (!sshv2_use_sftp_subsys)
     {
-      setsid ();
-      close (s[0]);
-
-      tty_raw (s[1]);
-      dup2 (s[1], 0);
-      dup2 (s[1], 1);
-      dup2 (s[1], 2);
-      execvp (args[0], args);
-
-      printf (_("Error: Cannot execute ssh: %s\n"), g_strerror (errno));
-      exit (1);
-    }
-  else if (child > 0)
-    {
-      close (s[1]);
-      tty_raw (s[0]);
-
-      if (!sshv2_use_sftp_subsys)
+      tempstr = sshv2_start_login_sequence (request, fdm);
+      if (!tempstr || !(strlen (tempstr) > 4 && strcmp (tempstr + strlen (tempstr) - 5,
+                                                        "xsftp") == 0))
         {
-          tempstr = sshv2_start_login_sequence (request, s[0]);
-          if (!tempstr ||
-              !(strlen (tempstr) > 4 && strcmp (tempstr + strlen (tempstr) - 5,
-                                                "xsftp") == 0))
-            {
-              sshv2_free_args (args);
-              g_free (exepath);
-              return (GFTP_EFATAL);
-            }
-          g_free (tempstr);
+          sshv2_free_args (args);
+          g_free (exepath);
+          return (GFTP_EFATAL);
         }
-      sshv2_free_args (args);
-      g_free (exepath);
-
-      request->datafd = s[0];
+      g_free (tempstr);
+    }
 
-      version = htonl (SSH_MY_VERSION);
-      if ((ret = sshv2_send_command (request, SSH_FXP_INIT, (char *) 
-                                     &version, 4)) < 0)
-        return (ret);
+  sshv2_free_args (args);
+  g_free (exepath);
 
-      memset (&message, 0, sizeof (message));
-      if ((ret = sshv2_read_response (request, &message, -1)) != SSH_FXP_VERSION)
-        {
-          request->logging_function (gftp_logging_error, request,
-                   _("Received wrong response from server, disconnecting\n"));
-          sshv2_message_free (&message);
-          gftp_disconnect (request);
+  request->datafd = fdm;
 
-          if (ret < 0)
-            return (ret);
-          else
-            return (GFTP_ERETRYABLE);
-        }
-      sshv2_message_free (&message);
+  version = htonl (SSH_MY_VERSION);
+  if ((ret = sshv2_send_command (request, SSH_FXP_INIT, (char *) 
+                                 &version, 4)) < 0)
+    return (ret);
 
-      request->logging_function (gftp_logging_misc, request,
-			         _("Successfully logged into SSH server %s\n"),
-                                 request->hostname);
-    }
-  else
+  memset (&message, 0, sizeof (message));
+  if ((ret = sshv2_read_response (request, &message, -1)) != SSH_FXP_VERSION)
     {
       request->logging_function (gftp_logging_error, request,
-                                 _("Cannot fork another process: %s\n"),
-                                 g_strerror (errno));
-      g_free (args);
-      return (GFTP_ERETRYABLE);
+               _("Received wrong response from server, disconnecting\n"));
+      sshv2_message_free (&message);
+      gftp_disconnect (request);
+
+      if (ret < 0)
+        return (ret);
+      else
+        return (GFTP_ERETRYABLE);
     }
+  sshv2_message_free (&message);
+
+  request->logging_function (gftp_logging_misc, request,
+                             _("Successfully logged into SSH server %s\n"),
+                             request->hostname);
 
   if (sshv2_getcwd (request) < 0)
     {
--- a/lib/sslcommon.c	Sat Jul 05 17:30:14 2003 +0000
+++ b/lib/sslcommon.c	Sun Jul 06 13:52:43 2003 +0000
@@ -206,7 +206,8 @@
 #if GLIB_MAJOR_VERSION > 1
   return ((unsigned long) g_thread_self ());
 #else
-  /* FIXME _ call pthread version */
+  /* FIXME _ call pthread version. Once this is done, the #ifdef below can be
+     removed */
   return (0);
 #endif
 } 
@@ -248,6 +249,11 @@
 {
   int i;
 
+#ifdef G_MAJOR_VERSION == 1
+  /* Thread setup isn't supported in glib 1.2 yet */
+  return;
+#endif
+
   gftp_ssl_mutexes = g_malloc (CRYPTO_num_locks( ) * sizeof (*gftp_ssl_mutexes));
 
   for (i = 0; i < CRYPTO_num_locks ( ); i++)