Mercurial > gftp.yaz
diff lib/pty.c @ 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 | 8d933999bba6 |
children | b8d14c2c3097 |
line wrap: on
line diff
--- 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); + } +} +