Annotation of src/usr.bin/ssh/pty.c, Revision 1.9
1.1 deraadt 1: /*
1.7 deraadt 2: *
3: * pty.c
4: *
5: * Author: Tatu Ylonen <ylo@cs.hut.fi>
6: *
7: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: * All rights reserved
9: *
10: * Created: Fri Mar 17 04:37:25 1995 ylo
11: *
12: * Allocating a pseudo-terminal, and making it the controlling tty.
13: *
14: */
1.1 deraadt 15:
16: #include "includes.h"
1.9 ! deraadt 17: RCSID("$Id: pty.c,v 1.8 1999/11/24 19:53:48 markus Exp $");
1.1 deraadt 18:
19: #include "pty.h"
20: #include "ssh.h"
21:
22: /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
23: #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
24: #undef HAVE_DEV_PTMX
25: #endif
26:
27: #ifndef O_NOCTTY
28: #define O_NOCTTY 0
29: #endif
30:
1.8 markus 31: /*
32: * Allocates and opens a pty. Returns 0 if no pty could be allocated, or
33: * nonzero if a pty was successfully allocated. On success, open file
34: * descriptors for the pty and tty sides and the name of the tty side are
35: * returned (the buffer must be able to hold at least 64 characters).
36: */
1.1 deraadt 37:
1.6 markus 38: int
1.9 ! deraadt 39: pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
1.1 deraadt 40: {
1.9 ! deraadt 41: #if defined(HAVE_OPENPTY) || defined(BSD4_4)
1.6 markus 42: /* openpty(3) exists in OSF/1 and some other os'es */
1.9 ! deraadt 43: char buf[64];
1.6 markus 44: int i;
1.1 deraadt 45:
1.9 ! deraadt 46: i = openpty(ptyfd, ttyfd, buf, NULL, NULL);
1.6 markus 47: if (i < 0) {
48: error("openpty: %.100s", strerror(errno));
49: return 0;
50: }
1.9 ! deraadt 51: strlcpy(namebuf, buf, namebuflen); /* possible truncation */
1.6 markus 52: return 1;
1.1 deraadt 53: #else /* HAVE_OPENPTY */
54: #ifdef HAVE__GETPTY
1.8 markus 55: /*
56: * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
57: * pty's automagically when needed
58: */
1.6 markus 59: char *slave;
60:
61: slave = _getpty(ptyfd, O_RDWR, 0622, 0);
62: if (slave == NULL) {
63: error("_getpty: %.100s", strerror(errno));
64: return 0;
65: }
1.9 ! deraadt 66: strlcpy(namebuf, slave, namebuflen);
1.6 markus 67: /* Open the slave side. */
68: *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
69: if (*ttyfd < 0) {
70: error("%.200s: %.100s", namebuf, strerror(errno));
71: close(*ptyfd);
72: return 0;
73: }
74: return 1;
1.1 deraadt 75: #else /* HAVE__GETPTY */
76: #ifdef HAVE_DEV_PTMX
1.8 markus 77: /*
78: * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
79: * also has bsd-style ptys, but they simply do not work.)
80: */
1.6 markus 81: int ptm;
82: char *pts;
83:
84: ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
85: if (ptm < 0) {
86: error("/dev/ptmx: %.100s", strerror(errno));
87: return 0;
88: }
89: if (grantpt(ptm) < 0) {
90: error("grantpt: %.100s", strerror(errno));
91: return 0;
92: }
93: if (unlockpt(ptm) < 0) {
94: error("unlockpt: %.100s", strerror(errno));
95: return 0;
96: }
97: pts = ptsname(ptm);
98: if (pts == NULL)
99: error("Slave pty side name could not be obtained.");
1.9 ! deraadt 100: strlcpy(namebuf, pts, namebuflen);
1.6 markus 101: *ptyfd = ptm;
102:
103: /* Open the slave side. */
104: *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
105: if (*ttyfd < 0) {
106: error("%.100s: %.100s", namebuf, strerror(errno));
107: close(*ptyfd);
108: return 0;
109: }
1.8 markus 110: /* Push the appropriate streams modules, as described in Solaris pts(7). */
1.6 markus 111: if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
112: error("ioctl I_PUSH ptem: %.100s", strerror(errno));
113: if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
114: error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
115: if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
116: error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
117: return 1;
1.1 deraadt 118: #else /* HAVE_DEV_PTMX */
119: #ifdef HAVE_DEV_PTS_AND_PTC
1.6 markus 120: /* AIX-style pty code. */
121: const char *name;
1.1 deraadt 122:
1.6 markus 123: *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
124: if (*ptyfd < 0) {
125: error("Could not open /dev/ptc: %.100s", strerror(errno));
126: return 0;
127: }
128: name = ttyname(*ptyfd);
129: if (!name)
130: fatal("Open of /dev/ptc returns device for which ttyname fails.");
1.9 ! deraadt 131: strlcpy(namebuf, name, namebuflen);
1.6 markus 132: *ttyfd = open(name, O_RDWR | O_NOCTTY);
133: if (*ttyfd < 0) {
134: error("Could not open pty slave side %.100s: %.100s",
135: name, strerror(errno));
136: close(*ptyfd);
137: return 0;
138: }
139: return 1;
1.1 deraadt 140: #else /* HAVE_DEV_PTS_AND_PTC */
1.6 markus 141: /* BSD-style pty code. */
142: char buf[64];
143: int i;
1.8 markus 144: const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
1.6 markus 145: const char *ptyminors = "0123456789abcdef";
146: int num_minors = strlen(ptyminors);
147: int num_ptys = strlen(ptymajors) * num_minors;
148:
149: for (i = 0; i < num_ptys; i++) {
150: snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
151: ptyminors[i % num_minors]);
152: *ptyfd = open(buf, O_RDWR | O_NOCTTY);
153: if (*ptyfd < 0)
154: continue;
1.9 ! deraadt 155: snprintf(namebuf, sizeof namebuflen, "/dev/tty%c%c",
! 156: ptymajors[i / num_minors], ptyminors[i % num_minors]);
1.6 markus 157:
158: /* Open the slave side. */
159: *ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
160: if (*ttyfd < 0) {
161: error("%.100s: %.100s", namebuf, strerror(errno));
162: close(*ptyfd);
163: return 0;
164: }
165: return 1;
166: }
167: return 0;
1.1 deraadt 168: #endif /* HAVE_DEV_PTS_AND_PTC */
169: #endif /* HAVE_DEV_PTMX */
170: #endif /* HAVE__GETPTY */
171: #endif /* HAVE_OPENPTY */
172: }
173:
1.6 markus 174: /* Releases the tty. Its ownership is returned to root, and permissions to 0666. */
1.1 deraadt 175:
1.6 markus 176: void
177: pty_release(const char *ttyname)
1.1 deraadt 178: {
1.6 markus 179: if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0)
180: debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
181: if (chmod(ttyname, (mode_t) 0666) < 0)
182: debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
1.1 deraadt 183: }
184:
185: /* Makes the tty the processes controlling tty and sets it to sane modes. */
186:
1.6 markus 187: void
188: pty_make_controlling_tty(int *ttyfd, const char *ttyname)
1.1 deraadt 189: {
1.6 markus 190: int fd;
1.1 deraadt 191:
1.6 markus 192: /* First disconnect from the old controlling tty. */
1.1 deraadt 193: #ifdef TIOCNOTTY
1.6 markus 194: fd = open("/dev/tty", O_RDWR | O_NOCTTY);
195: if (fd >= 0) {
196: (void) ioctl(fd, TIOCNOTTY, NULL);
197: close(fd);
198: }
1.1 deraadt 199: #endif /* TIOCNOTTY */
1.6 markus 200: if (setsid() < 0)
201: error("setsid: %.100s", strerror(errno));
1.1 deraadt 202:
1.8 markus 203: /*
204: * Verify that we are successfully disconnected from the controlling
205: * tty.
206: */
1.6 markus 207: fd = open("/dev/tty", O_RDWR | O_NOCTTY);
208: if (fd >= 0) {
209: error("Failed to disconnect from controlling tty.");
210: close(fd);
211: }
212: /* Make it our controlling tty. */
1.1 deraadt 213: #ifdef TIOCSCTTY
1.6 markus 214: debug("Setting controlling tty using TIOCSCTTY.");
1.8 markus 215: /*
216: * We ignore errors from this, because HPSUX defines TIOCSCTTY, but
217: * returns EINVAL with these arguments, and there is absolutely no
218: * documentation.
219: */
1.6 markus 220: ioctl(*ttyfd, TIOCSCTTY, NULL);
1.1 deraadt 221: #endif /* TIOCSCTTY */
1.6 markus 222: fd = open(ttyname, O_RDWR);
223: if (fd < 0)
224: error("%.100s: %.100s", ttyname, strerror(errno));
225: else
226: close(fd);
227:
228: /* Verify that we now have a controlling tty. */
229: fd = open("/dev/tty", O_WRONLY);
230: if (fd < 0)
231: error("open /dev/tty failed - could not set controlling tty: %.100s",
232: strerror(errno));
233: else {
234: close(fd);
235: }
1.1 deraadt 236: }
237:
238: /* Changes the window size associated with the pty. */
239:
1.6 markus 240: void
241: pty_change_window_size(int ptyfd, int row, int col,
242: int xpixel, int ypixel)
1.1 deraadt 243: {
1.6 markus 244: struct winsize w;
245: w.ws_row = row;
246: w.ws_col = col;
247: w.ws_xpixel = xpixel;
248: w.ws_ypixel = ypixel;
249: (void) ioctl(ptyfd, TIOCSWINSZ, &w);
1.1 deraadt 250: }