#define O_NOCTTY 0
#endif
-int
-openpty(int *amaster, int *aslave, char *name, struct termios *termp,
+#if defined(HAVE_DEV_PTMX) && !defined(HAVE__GETPTY)
+static int
+openpty_streams(int *amaster, int *aslave, char *name, struct termios *termp,
struct winsize *winp)
{
-#if defined(HAVE__GETPTY)
- /*
- * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
- * pty's automagically when needed
- */
- char *slave;
-
- if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
- return (-1);
-
- /* Open the slave side. */
- if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
- close(*amaster);
- return (-1);
- }
- return (0);
-
-#elif defined(HAVE_DEV_PTMX)
/*
* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
* also has bsd-style ptys, but they simply do not work.)
# ifndef __hpux
ioctl(*aslave, I_PUSH, "ttcompat");
# endif /* __hpux */
+ return (0);
+}
+#endif
+
+int
+openpty(int *amaster, int *aslave, char *name, struct termios *termp,
+ struct winsize *winp)
+{
+#if defined(HAVE__GETPTY)
+ /*
+ * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
+ * pty's automagically when needed
+ */
+ char *slave;
+
+ if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
+ return (-1);
+ /* Open the slave side. */
+ if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
+ close(*amaster);
+ return (-1);
+ }
return (0);
+#elif defined(HAVE_DEV_PTMX)
+
+#ifdef SSHD_ACQUIRES_CTTY
+ /*
+ * On some (most? all?) SysV based systems with STREAMS based terminals,
+ * sshd will acquire a controlling terminal when it pushes the "ptem"
+ * module. On such platforms, first allocate a sacrificial pty so
+ * that sshd already has a controlling terminal before allocating the
+ * one that will be passed back to the user process. This ensures
+ * the second pty is not already the controlling terminal for a
+ * different session and is available to become controlling terminal
+ * for the client's subprocess. See bugzilla #245 for details.
+ */
+ static int junk_ptyfd = -1, junk_ttyfd;
+
+ if (junk_ptyfd == -1)
+ (void)openpty_streams(&junk_ptyfd, &junk_ttyfd, NULL, NULL,
+ NULL);
+#endif
+
+ return openpty_streams(amaster, aslave, name, termp, winp);
+
#elif defined(HAVE_DEV_PTS_AND_PTC)
/* AIX-style pty code. */
const char *ttname;
* setlogin() affects the entire process group. We don't
* want the child to be able to affect the parent.
*/
-#if !defined(SSHD_ACQUIRES_CTTY)
- /*
- * If setsid is called, on some platforms sshd will later acquire a
- * controlling terminal which will result in "could not set
- * controlling tty" errors.
- */
if (!debug_flag && !inetd_flag && setsid() == -1)
error("setsid: %.100s", strerror(errno));
-#endif
if (rexec_flag) {
debug("rexec start in %d out %d newsock %d pipe %d sock %d",