Annotation of src/usr.bin/ssh/pty.c, Revision 1.2
1.1 deraadt 1: /*
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: */
15:
16: #include "includes.h"
1.2 ! deraadt 17: RCSID("$Id: pty.c,v 1.1 1999/09/26 20:53:36 deraadt 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: #ifdef HAVE_DEV_PTMX
28: #include <sys/stream.h>
29: #include <stropts.h>
30: #include <sys/conf.h>
31: #endif /* HAVE_DEV_PTMX */
32:
33: #ifndef O_NOCTTY
34: #define O_NOCTTY 0
35: #endif
36:
37: /* Allocates and opens a pty. Returns 0 if no pty could be allocated,
38: or nonzero if a pty was successfully allocated. On success, open file
39: descriptors for the pty and tty sides and the name of the tty side are
40: returned (the buffer must be able to hold at least 64 characters). */
41:
42: int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
43: {
44: #ifdef HAVE_OPENPTY
45:
46: /* openpty(3) exists in OSF/1 and some other os'es */
47:
48: int i;
49:
50: i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
51:
52: if (i < 0)
53: {
54: error("openpty: %.100s", strerror(errno));
55: return 0;
56: }
57:
58: return 1;
59:
60: #else /* HAVE_OPENPTY */
61: #ifdef HAVE__GETPTY
62:
63: /* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
64: pty's automagically when needed */
65:
66: char *slave;
67:
68: slave = _getpty(ptyfd, O_RDWR, 0622, 0);
69: if (slave == NULL)
70: {
71: error("_getpty: %.100s", strerror(errno));
72: return 0;
73: }
74: strcpy(namebuf, slave);
75: /* Open the slave side. */
76: *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
77: if (*ttyfd < 0)
78: {
79: error("%.200s: %.100s", namebuf, strerror(errno));
80: close(*ptyfd);
81: return 0;
82: }
83: return 1;
84:
85: #else /* HAVE__GETPTY */
86: #ifdef HAVE_DEV_PTMX
87: /* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 also has
88: bsd-style ptys, but they simply do not work.) */
89:
90: int ptm;
91: char *pts;
92:
93: ptm = open("/dev/ptmx", O_RDWR|O_NOCTTY);
94: if (ptm < 0)
95: {
96: error("/dev/ptmx: %.100s", strerror(errno));
97: return 0;
98: }
99: if (grantpt(ptm) < 0)
100: {
101: error("grantpt: %.100s", strerror(errno));
102: return 0;
103: }
104: if (unlockpt(ptm) < 0)
105: {
106: error("unlockpt: %.100s", strerror(errno));
107: return 0;
108: }
109: pts = ptsname(ptm);
110: if (pts == NULL)
111: error("Slave pty side name could not be obtained.");
112: strcpy(namebuf, pts);
113: *ptyfd = ptm;
114:
115: /* Open the slave side. */
116: *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
117: if (*ttyfd < 0)
118: {
119: error("%.100s: %.100s", namebuf, strerror(errno));
120: close(*ptyfd);
121: return 0;
122: }
123: /* Push the appropriate streams modules, as described in Solaris pts(7). */
124: if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
125: error("ioctl I_PUSH ptem: %.100s", strerror(errno));
126: if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
127: error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
128: if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
129: error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
130: return 1;
131:
132: #else /* HAVE_DEV_PTMX */
133: #ifdef HAVE_DEV_PTS_AND_PTC
134:
135: /* AIX-style pty code. */
136:
137: const char *name;
138:
139: *ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
140: if (*ptyfd < 0)
141: {
142: error("Could not open /dev/ptc: %.100s", strerror(errno));
143: return 0;
144: }
145: name = ttyname(*ptyfd);
146: if (!name)
147: fatal("Open of /dev/ptc returns device for which ttyname fails.");
148: strcpy(namebuf, name);
149: *ttyfd = open(name, O_RDWR|O_NOCTTY);
150: if (*ttyfd < 0)
151: {
152: error("Could not open pty slave side %.100s: %.100s",
153: name, strerror(errno));
154: close(*ptyfd);
155: return 0;
156: }
157: return 1;
158:
159: #else /* HAVE_DEV_PTS_AND_PTC */
160: #ifdef CRAY
161: char buf[64];
162: int i;
163:
164: for (i = 0; i < 128; i++)
165: {
166: sprintf(buf, "/dev/pty/%03d", i);
167: *ptyfd = open(buf, O_RDWR|O_NOCTTY);
168: if (*ptyfd < 0)
169: continue;
170: sprintf(namebuf, "/dev/ttyp%03d", i);
171: /* Open the slave side. */
172: *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
173: if (*ttyfd < 0)
174: {
175: error("%.100s: %.100s", namebuf, strerror(errno));
176: close(*ptyfd);
177: return 0;
178: }
179: return 1;
180: }
181: return 0;
182:
183: #else /* CRAY */
184:
185: /* BSD-style pty code. */
186:
187: char buf[64];
188: int i;
189: const char *ptymajors =
190: "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
191: const char *ptyminors = "0123456789abcdef";
192: int num_minors = strlen(ptyminors);
193: int num_ptys = strlen(ptymajors) * num_minors;
194:
195: for (i = 0; i < num_ptys; i++)
196: {
197: sprintf(buf, "/dev/pty%c%c", ptymajors[i / num_minors],
198: ptyminors[i % num_minors]);
199: *ptyfd = open(buf, O_RDWR|O_NOCTTY);
200: if (*ptyfd < 0)
201: continue;
202: sprintf(namebuf, "/dev/tty%c%c", ptymajors[i / num_minors],
203: ptyminors[i % num_minors]);
204:
205: /* Open the slave side. */
206: *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
207: if (*ttyfd < 0)
208: {
209: error("%.100s: %.100s", namebuf, strerror(errno));
210: close(*ptyfd);
211: return 0;
212: }
213: return 1;
214: }
215: return 0;
216: #endif /* CRAY */
217: #endif /* HAVE_DEV_PTS_AND_PTC */
218: #endif /* HAVE_DEV_PTMX */
219: #endif /* HAVE__GETPTY */
220: #endif /* HAVE_OPENPTY */
221: }
222:
223: /* Releases the tty. Its ownership is returned to root, and permissions to
224: 0666. */
225:
226: void pty_release(const char *ttyname)
227: {
228: if (chown(ttyname, (uid_t)0, (gid_t)0) < 0)
229: debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
230: if (chmod(ttyname, (mode_t)0666) < 0)
231: debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
232: }
233:
234: /* Makes the tty the processes controlling tty and sets it to sane modes. */
235:
236: void pty_make_controlling_tty(int *ttyfd, const char *ttyname)
237: {
238: int fd;
239:
240: /* First disconnect from the old controlling tty. */
241: #ifdef TIOCNOTTY
242: fd = open("/dev/tty", O_RDWR|O_NOCTTY);
243: if (fd >= 0)
244: {
245: (void)ioctl(fd, TIOCNOTTY, NULL);
246: close(fd);
247: }
248: #endif /* TIOCNOTTY */
249: if (setsid() < 0)
250: error("setsid: %.100s", strerror(errno));
251:
252: /* Verify that we are successfully disconnected from the controlling tty. */
253: fd = open("/dev/tty", O_RDWR|O_NOCTTY);
254: if (fd >= 0)
255: {
256: error("Failed to disconnect from controlling tty.");
257: close(fd);
258: }
259:
260: /* Make it our controlling tty. */
261: #ifdef TIOCSCTTY
262: debug("Setting controlling tty using TIOCSCTTY.");
263: /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
264: EINVAL with these arguments, and there is absolutely no documentation. */
265: ioctl(*ttyfd, TIOCSCTTY, NULL);
266: #endif /* TIOCSCTTY */
267: fd = open(ttyname, O_RDWR);
268: if (fd < 0)
269: error("%.100s: %.100s", ttyname, strerror(errno));
270: else
271: close(fd);
272:
273: /* Verify that we now have a controlling tty. */
274: fd = open("/dev/tty", O_WRONLY);
275: if (fd < 0)
276: error("open /dev/tty failed - could not set controlling tty: %.100s",
277: strerror(errno));
278: else
279: {
280: close(fd);
281: #ifdef HAVE_VHANGUP
282: signal(SIGHUP, SIG_IGN);
283: vhangup();
284: signal(SIGHUP, SIG_DFL);
285: fd = open(ttyname, O_RDWR);
286: if (fd == -1)
287: error("pty_make_controlling_tty: reopening controlling tty after vhangup failed for %.100s",
288: ttyname);
289: close(*ttyfd);
290: *ttyfd = fd;
291: #endif /* HAVE_VHANGUP */
292: }
293: }
294:
295: /* Changes the window size associated with the pty. */
296:
297: void pty_change_window_size(int ptyfd, int row, int col,
298: int xpixel, int ypixel)
299: {
300: struct winsize w;
301: w.ws_row = row;
302: w.ws_col = col;
303: w.ws_xpixel = xpixel;
304: w.ws_ypixel = ypixel;
305: (void)ioctl(ptyfd, TIOCSWINSZ, &w);
306: }
307: