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