X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/1a2936c4eb2758a6459006897669d2b7b15b2170..1431a9004eca672916d485091f3db0a20954a9a0:/sshpty.c diff --git a/sshpty.c b/sshpty.c index 4af55e92..64ac4e59 100644 --- a/sshpty.c +++ b/sshpty.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshpty.c,v 1.1 2001/03/04 01:46:30 djm Exp $"); +RCSID("$OpenBSD: sshpty.c,v 1.7 2002/06/24 17:57:20 deraadt Exp $"); #ifdef HAVE_UTIL_H # include @@ -20,6 +20,7 @@ RCSID("$OpenBSD: sshpty.c,v 1.1 2001/03/04 01:46:30 djm Exp $"); #include "sshpty.h" #include "log.h" +#include "misc.h" /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */ #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY) @@ -93,16 +94,19 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) */ int ptm; char *pts; + mysig_t old_signal; ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); if (ptm < 0) { error("/dev/ptmx: %.100s", strerror(errno)); return 0; } + old_signal = mysignal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) { error("grantpt: %.100s", strerror(errno)); return 0; } + mysignal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) { error("unlockpt: %.100s", strerror(errno)); return 0; @@ -152,12 +156,42 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) *ttyfd = open(name, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { error("Could not open pty slave side %.100s: %.100s", - name, strerror(errno)); + name, strerror(errno)); close(*ptyfd); return 0; } return 1; #else /* HAVE_DEV_PTS_AND_PTC */ +#ifdef _CRAY + char buf[64]; + int i; + int highpty; + +#ifdef _SC_CRAY_NPTY + highpty = sysconf(_SC_CRAY_NPTY); + if (highpty == -1) + highpty = 128; +#else + highpty = 128; +#endif + + for (i = 0; i < highpty; i++) { + snprintf(buf, sizeof(buf), "/dev/pty/%03d", i); + *ptyfd = open(buf, O_RDWR|O_NOCTTY); + if (*ptyfd < 0) + continue; + snprintf(namebuf, namebuflen, "/dev/ttyp%03d", i); + /* Open the slave side. */ + *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); + if (*ttyfd < 0) { + error("%.100s: %.100s", namebuf, strerror(errno)); + close(*ptyfd); + return 0; + } + return 1; + } + return 0; +#else /* BSD-style pty code. */ char buf[64]; int i; @@ -165,6 +199,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; + struct termios tio; for (i = 0; i < num_ptys; i++) { snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], @@ -189,9 +224,23 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) close(*ptyfd); return 0; } + /* set tty modes to a sane state for broken clients */ + if (tcgetattr(*ptyfd, &tio) < 0) + log("Getting tty modes for pty failed: %.100s", strerror(errno)); + else { + tio.c_lflag |= (ECHO | ISIG | ICANON); + tio.c_oflag |= (OPOST | ONLCR); + tio.c_iflag |= ICRNL; + + /* Set the new modes for the terminal. */ + if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) + log("Setting tty modes for pty failed: %.100s", strerror(errno)); + } + return 1; } return 0; +#endif /* CRAY */ #endif /* HAVE_DEV_PTS_AND_PTC */ #endif /* HAVE_DEV_PTMX */ #endif /* HAVE__GETPTY */ @@ -219,6 +268,30 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname) void *old; #endif /* USE_VHANGUP */ +#ifdef _CRAY + if (setsid() < 0) + error("setsid: %.100s", strerror(errno)); + + fd = open(ttyname, O_RDWR|O_NOCTTY); + if (fd != -1) { + mysignal(SIGHUP, SIG_IGN); + ioctl(fd, TCVHUP, (char *)NULL); + mysignal(SIGHUP, SIG_DFL); + setpgid(0, 0); + close(fd); + } else { + error("Failed to disconnect from controlling tty."); + } + + debug("Setting controlling tty using TCSETCTTY."); + ioctl(*ttyfd, TCSETCTTY, NULL); + fd = open("/dev/tty", O_RDWR); + if (fd < 0) + error("%.100s: %.100s", ttyname, strerror(errno)); + close(*ttyfd); + *ttyfd = fd; +#else /* _CRAY */ + /* First disconnect from the old controlling tty. */ #ifdef TIOCNOTTY fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); @@ -250,9 +323,9 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname) error("SETPGRP %s",strerror(errno)); #endif /* HAVE_NEWS4 */ #ifdef USE_VHANGUP - old = signal(SIGHUP, SIG_IGN); + old = mysignal(SIGHUP, SIG_IGN); vhangup(); - signal(SIGHUP, old); + mysignal(SIGHUP, old); #endif /* USE_VHANGUP */ fd = open(ttyname, O_RDWR); if (fd < 0) { @@ -269,19 +342,20 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname) fd = open(_PATH_TTY, O_WRONLY); if (fd < 0) error("open /dev/tty failed - could not set controlling tty: %.100s", - strerror(errno)); - else { + strerror(errno)); + else close(fd); - } +#endif /* _CRAY */ } /* Changes the window size associated with the pty. */ void pty_change_window_size(int ptyfd, int row, int col, - int xpixel, int ypixel) + int xpixel, int ypixel) { struct winsize w; + w.ws_row = row; w.ws_col = col; w.ws_xpixel = xpixel; @@ -309,7 +383,8 @@ pty_setowner(struct passwd *pw, const char *ttyname) /* * Change owner and mode of the tty as required. - * Warn but continue if filesystem is read-only and the uids match. + * Warn but continue if filesystem is read-only and the uids match/ + * tty is owned by root. */ if (stat(ttyname, &st)) fatal("stat(%.100s) failed: %.100s", ttyname, @@ -317,14 +392,15 @@ pty_setowner(struct passwd *pw, const char *ttyname) if (st.st_uid != pw->pw_uid || st.st_gid != gid) { if (chown(ttyname, pw->pw_uid, gid) < 0) { - if (errno == EROFS && st.st_uid == pw->pw_uid) - error("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); + if (errno == EROFS && + (st.st_uid == pw->pw_uid || st.st_uid == 0)) + error("chown(%.100s, %u, %u) failed: %.100s", + ttyname, (u_int)pw->pw_uid, (u_int)gid, + strerror(errno)); else - fatal("chown(%.100s, %d, %d) failed: %.100s", - ttyname, pw->pw_uid, gid, - strerror(errno)); + fatal("chown(%.100s, %u, %u) failed: %.100s", + ttyname, (u_int)pw->pw_uid, (u_int)gid, + strerror(errno)); } } @@ -333,10 +409,10 @@ pty_setowner(struct passwd *pw, const char *ttyname) if (errno == EROFS && (st.st_mode & (S_IRGRP | S_IROTH)) == 0) error("chmod(%.100s, 0%o) failed: %.100s", - ttyname, mode, strerror(errno)); + ttyname, mode, strerror(errno)); else fatal("chmod(%.100s, 0%o) failed: %.100s", - ttyname, mode, strerror(errno)); + ttyname, mode, strerror(errno)); } } }