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.
20 /* Unfortunate namespace collision */
22 #endif /* HAVE_PTY_H */
27 /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
28 #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
36 /* Allocates and opens a pty. Returns 0 if no pty could be allocated,
37 or nonzero if a pty was successfully allocated. On success, open file
38 descriptors for the pty and tty sides and the name of the tty side are
39 returned (the buffer must be able to hold at least 64 characters). */
41 int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
45 /* openpty(3) exists in OSF/1 and some other os'es */
49 i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
53 error("openpty: %.100s", strerror(errno));
59 #else /* HAVE_OPENPTY */
62 /* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
63 pty's automagically when needed */
67 slave = _getpty(ptyfd, O_RDWR, 0622, 0);
70 error("_getpty: %.100s", strerror(errno));
73 strcpy(namebuf, slave);
74 /* Open the slave side. */
75 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
78 error("%.200s: %.100s", namebuf, strerror(errno));
84 #else /* HAVE__GETPTY */
86 /* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 also has
87 bsd-style ptys, but they simply do not work.) */
92 ptm = open("/dev/ptmx", O_RDWR|O_NOCTTY);
95 error("/dev/ptmx: %.100s", strerror(errno));
100 error("grantpt: %.100s", strerror(errno));
103 if (unlockpt(ptm) < 0)
105 error("unlockpt: %.100s", strerror(errno));
110 error("Slave pty side name could not be obtained.");
111 strcpy(namebuf, pts);
114 /* Open the slave side. */
115 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
118 error("%.100s: %.100s", namebuf, strerror(errno));
122 /* Push the appropriate streams modules, as described in Solaris pts(7). */
123 if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
124 error("ioctl I_PUSH ptem: %.100s", strerror(errno));
125 if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
126 error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
127 if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
128 error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
131 #else /* HAVE_DEV_PTMX */
132 #ifdef HAVE_DEV_PTS_AND_PTC
134 /* AIX-style pty code. */
138 *ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
141 error("Could not open /dev/ptc: %.100s", strerror(errno));
144 name = ttyname(*ptyfd);
146 fatal("Open of /dev/ptc returns device for which ttyname fails.");
147 strcpy(namebuf, name);
148 *ttyfd = open(name, O_RDWR|O_NOCTTY);
151 error("Could not open pty slave side %.100s: %.100s",
152 name, strerror(errno));
158 #else /* HAVE_DEV_PTS_AND_PTC */
159 /* BSD-style pty code. */
163 const char *ptymajors =
164 "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
165 const char *ptyminors = "0123456789abcdef";
166 int num_minors = strlen(ptyminors);
167 int num_ptys = strlen(ptymajors) * num_minors;
169 for (i = 0; i < num_ptys; i++)
171 snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
172 ptyminors[i % num_minors]);
173 *ptyfd = open(buf, O_RDWR|O_NOCTTY);
176 snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
177 ptyminors[i % num_minors]);
179 /* Open the slave side. */
180 *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
183 error("%.100s: %.100s", namebuf, strerror(errno));
190 #endif /* HAVE_DEV_PTS_AND_PTC */
191 #endif /* HAVE_DEV_PTMX */
192 #endif /* HAVE__GETPTY */
193 #endif /* HAVE_OPENPTY */
196 /* Releases the tty. Its ownership is returned to root, and permissions to
199 void pty_release(const char *ttyname)
201 if (chown(ttyname, (uid_t)0, (gid_t)0) < 0)
202 debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
203 if (chmod(ttyname, (mode_t)0666) < 0)
204 debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
207 /* Makes the tty the processes controlling tty and sets it to sane modes. */
209 void pty_make_controlling_tty(int *ttyfd, const char *ttyname)
213 /* First disconnect from the old controlling tty. */
215 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
218 (void)ioctl(fd, TIOCNOTTY, NULL);
221 #endif /* TIOCNOTTY */
223 error("setsid: %.100s", strerror(errno));
225 /* Verify that we are successfully disconnected from the controlling tty. */
226 fd = open("/dev/tty", O_RDWR|O_NOCTTY);
229 error("Failed to disconnect from controlling tty.");
233 /* Make it our controlling tty. */
235 debug("Setting controlling tty using TIOCSCTTY.");
236 /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
237 EINVAL with these arguments, and there is absolutely no documentation. */
238 ioctl(*ttyfd, TIOCSCTTY, NULL);
239 #endif /* TIOCSCTTY */
240 fd = open(ttyname, O_RDWR);
242 error("%.100s: %.100s", ttyname, strerror(errno));
246 /* Verify that we now have a controlling tty. */
247 fd = open("/dev/tty", O_WRONLY);
249 error("open /dev/tty failed - could not set controlling tty: %.100s",
257 /* Changes the window size associated with the pty. */
259 void pty_change_window_size(int ptyfd, int row, int col,
260 int xpixel, int ypixel)
265 w.ws_xpixel = xpixel;
266 w.ws_ypixel = ypixel;
267 (void)ioctl(ptyfd, TIOCSWINSZ, &w);