5 Author: Tatu Ylonen <ylo@cs.hut.fi>
7 Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
10 Created: Fri Mar 17 04:37:25 1995 ylo
12 Allocating a pseudo-terminal, and making it the controlling tty.
21 #endif /* HAVE_PTY_H */
26 /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
27 #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
35 /* Allocates and opens a pty. Returns 0 if no pty could be allocated,
36 or nonzero if a pty was successfully allocated. On success, open file
37 descriptors for the pty and tty sides and the name of the tty side are
38 returned (the buffer must be able to hold at least 64 characters). */
40 int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
44 /* openpty(3) exists in OSF/1 and some other os'es */
48 i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
52 error("openpty: %.100s", strerror(errno));
58 #else /* HAVE_OPENPTY */
61 /* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
62 pty's automagically when needed */
66 slave = _getpty(ptyfd, O_RDWR, 0622, 0);
69 error("_getpty: %.100s", strerror(errno));
72 strcpy(namebuf, slave);
73 /* Open the slave side. */
74 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
77 error("%.200s: %.100s", namebuf, strerror(errno));
83 #else /* HAVE__GETPTY */
85 /* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 also has
86 bsd-style ptys, but they simply do not work.) */
91 ptm = open("/dev/ptmx", O_RDWR|O_NOCTTY);
94 error("/dev/ptmx: %.100s", strerror(errno));
99 error("grantpt: %.100s", strerror(errno));
102 if (unlockpt(ptm) < 0)
104 error("unlockpt: %.100s", strerror(errno));
109 error("Slave pty side name could not be obtained.");
110 strcpy(namebuf, pts);
113 /* Open the slave side. */
114 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
117 error("%.100s: %.100s", namebuf, strerror(errno));
121 /* Push the appropriate streams modules, as described in Solaris pts(7). */
122 if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
123 error("ioctl I_PUSH ptem: %.100s", strerror(errno));
124 if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
125 error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
126 if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
127 error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
130 #else /* HAVE_DEV_PTMX */
131 #ifdef HAVE_DEV_PTS_AND_PTC
133 /* AIX-style pty code. */
137 *ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
140 error("Could not open /dev/ptc: %.100s", strerror(errno));
143 name = ttyname(*ptyfd);
145 fatal("Open of /dev/ptc returns device for which ttyname fails.");
146 strcpy(namebuf, name);
147 *ttyfd = open(name, O_RDWR|O_NOCTTY);
150 error("Could not open pty slave side %.100s: %.100s",
151 name, strerror(errno));
157 #else /* HAVE_DEV_PTS_AND_PTC */
158 /* BSD-style pty code. */
162 const char *ptymajors =
163 "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
164 const char *ptyminors = "0123456789abcdef";
165 int num_minors = strlen(ptyminors);
166 int num_ptys = strlen(ptymajors) * num_minors;
168 for (i = 0; i < num_ptys; i++)
170 snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
171 ptyminors[i % num_minors]);
172 *ptyfd = open(buf, O_RDWR|O_NOCTTY);
175 snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
176 ptyminors[i % num_minors]);
178 /* Open the slave side. */
179 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
182 error("%.100s: %.100s", namebuf, strerror(errno));
189 #endif /* HAVE_DEV_PTS_AND_PTC */
190 #endif /* HAVE_DEV_PTMX */
191 #endif /* HAVE__GETPTY */
192 #endif /* HAVE_OPENPTY */
195 /* Releases the tty. Its ownership is returned to root, and permissions to
198 void pty_release(const char *ttyname)
200 if (chown(ttyname, (uid_t)0, (gid_t)0) < 0)
201 debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
202 if (chmod(ttyname, (mode_t)0666) < 0)
203 debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
206 /* Makes the tty the processes controlling tty and sets it to sane modes. */
208 void pty_make_controlling_tty(int *ttyfd, const char *ttyname)
212 /* First disconnect from the old controlling tty. */
214 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
217 (void)ioctl(fd, TIOCNOTTY, NULL);
220 #endif /* TIOCNOTTY */
222 error("setsid: %.100s", strerror(errno));
224 /* Verify that we are successfully disconnected from the controlling tty. */
225 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
228 error("Failed to disconnect from controlling tty.");
232 /* Make it our controlling tty. */
234 debug("Setting controlling tty using TIOCSCTTY.");
235 /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
236 EINVAL with these arguments, and there is absolutely no documentation. */
237 ioctl(*ttyfd, TIOCSCTTY, NULL);
238 #endif /* TIOCSCTTY */
239 fd = open(ttyname, O_RDWR);
241 error("%.100s: %.100s", ttyname, strerror(errno));
245 /* Verify that we now have a controlling tty. */
246 fd = open("/dev/tty", O_WRONLY);
248 error("open /dev/tty failed - could not set controlling tty: %.100s",
256 /* Changes the window size associated with the pty. */
258 void pty_change_window_size(int ptyfd, int row, int col,
259 int xpixel, int ypixel)
264 w.ws_xpixel = xpixel;
265 w.ws_ypixel = ypixel;
266 (void)ioctl(ptyfd, TIOCSWINSZ, &w);