diff options
author | Ben Lindstrom <mouring@eviladmin.org> | 2001-02-18 19:13:33 +0000 |
---|---|---|
committer | Ben Lindstrom <mouring@eviladmin.org> | 2001-02-18 19:13:33 +0000 |
commit | d95c09cc83ec07b42feb07c4ff71d23720b37e8e (patch) | |
tree | 73b15e75f83356fa59b0d17ffd88409d8f4fc5de /pty.c | |
parent | c32a5b1a1568258481df6316dc008fc7cd3825fd (diff) |
- (bal) Markus' blessing to rename login.[ch] -> sshlogin.[ch] and
pty.[ch] -> sshpty.[ch]
Diffstat (limited to 'pty.c')
-rw-r--r-- | pty.c | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/pty.c b/pty.c deleted file mode 100644 index 4b9370ce5..000000000 --- a/pty.c +++ /dev/null | |||
@@ -1,342 +0,0 @@ | |||
1 | /* | ||
2 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | ||
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
4 | * All rights reserved | ||
5 | * Allocating a pseudo-terminal, and making it the controlling tty. | ||
6 | * | ||
7 | * As far as I am concerned, the code I have written for this software | ||
8 | * can be used freely for any purpose. Any derived versions of this | ||
9 | * software must be clearly marked as such, and if the derived work is | ||
10 | * incompatible with the protocol description in the RFC file, it must be | ||
11 | * called by a name other than "ssh" or "Secure Shell". | ||
12 | */ | ||
13 | |||
14 | #include "includes.h" | ||
15 | RCSID("$OpenBSD: pty.c,v 1.22 2001/02/08 19:30:52 itojun Exp $"); | ||
16 | |||
17 | #ifdef HAVE_UTIL_H | ||
18 | # include <util.h> | ||
19 | #endif /* HAVE_UTIL_H */ | ||
20 | |||
21 | #include "pty.h" | ||
22 | #include "log.h" | ||
23 | |||
24 | /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */ | ||
25 | #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY) | ||
26 | #undef HAVE_DEV_PTMX | ||
27 | #endif | ||
28 | |||
29 | #ifdef HAVE_PTY_H | ||
30 | # include <pty.h> | ||
31 | #endif | ||
32 | #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) | ||
33 | # include <sys/stropts.h> | ||
34 | #endif | ||
35 | |||
36 | #ifndef O_NOCTTY | ||
37 | #define O_NOCTTY 0 | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | * Allocates and opens a pty. Returns 0 if no pty could be allocated, or | ||
42 | * nonzero if a pty was successfully allocated. On success, open file | ||
43 | * descriptors for the pty and tty sides and the name of the tty side are | ||
44 | * returned (the buffer must be able to hold at least 64 characters). | ||
45 | */ | ||
46 | |||
47 | int | ||
48 | pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) | ||
49 | { | ||
50 | #if defined(HAVE_OPENPTY) || defined(BSD4_4) | ||
51 | /* openpty(3) exists in OSF/1 and some other os'es */ | ||
52 | char *name; | ||
53 | int i; | ||
54 | |||
55 | i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); | ||
56 | if (i < 0) { | ||
57 | error("openpty: %.100s", strerror(errno)); | ||
58 | return 0; | ||
59 | } | ||
60 | name = ttyname(*ttyfd); | ||
61 | if (!name) | ||
62 | fatal("openpty returns device for which ttyname fails."); | ||
63 | |||
64 | strlcpy(namebuf, name, namebuflen); /* possible truncation */ | ||
65 | return 1; | ||
66 | #else /* HAVE_OPENPTY */ | ||
67 | #ifdef HAVE__GETPTY | ||
68 | /* | ||
69 | * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more | ||
70 | * pty's automagically when needed | ||
71 | */ | ||
72 | char *slave; | ||
73 | |||
74 | slave = _getpty(ptyfd, O_RDWR, 0622, 0); | ||
75 | if (slave == NULL) { | ||
76 | error("_getpty: %.100s", strerror(errno)); | ||
77 | return 0; | ||
78 | } | ||
79 | strlcpy(namebuf, slave, namebuflen); | ||
80 | /* Open the slave side. */ | ||
81 | *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); | ||
82 | if (*ttyfd < 0) { | ||
83 | error("%.200s: %.100s", namebuf, strerror(errno)); | ||
84 | close(*ptyfd); | ||
85 | return 0; | ||
86 | } | ||
87 | return 1; | ||
88 | #else /* HAVE__GETPTY */ | ||
89 | #if defined(HAVE_DEV_PTMX) | ||
90 | /* | ||
91 | * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 | ||
92 | * also has bsd-style ptys, but they simply do not work.) | ||
93 | */ | ||
94 | int ptm; | ||
95 | char *pts; | ||
96 | |||
97 | ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); | ||
98 | if (ptm < 0) { | ||
99 | error("/dev/ptmx: %.100s", strerror(errno)); | ||
100 | return 0; | ||
101 | } | ||
102 | if (grantpt(ptm) < 0) { | ||
103 | error("grantpt: %.100s", strerror(errno)); | ||
104 | return 0; | ||
105 | } | ||
106 | if (unlockpt(ptm) < 0) { | ||
107 | error("unlockpt: %.100s", strerror(errno)); | ||
108 | return 0; | ||
109 | } | ||
110 | pts = ptsname(ptm); | ||
111 | if (pts == NULL) | ||
112 | error("Slave pty side name could not be obtained."); | ||
113 | strlcpy(namebuf, pts, namebuflen); | ||
114 | *ptyfd = ptm; | ||
115 | |||
116 | /* Open the slave side. */ | ||
117 | *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); | ||
118 | if (*ttyfd < 0) { | ||
119 | error("%.100s: %.100s", namebuf, strerror(errno)); | ||
120 | close(*ptyfd); | ||
121 | return 0; | ||
122 | } | ||
123 | #ifndef HAVE_CYGWIN | ||
124 | /* | ||
125 | * Push the appropriate streams modules, as described in Solaris pts(7). | ||
126 | * HP-UX pts(7) doesn't have ttcompat module. | ||
127 | */ | ||
128 | if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) | ||
129 | error("ioctl I_PUSH ptem: %.100s", strerror(errno)); | ||
130 | if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) | ||
131 | error("ioctl I_PUSH ldterm: %.100s", strerror(errno)); | ||
132 | #ifndef __hpux | ||
133 | if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) | ||
134 | error("ioctl I_PUSH ttcompat: %.100s", strerror(errno)); | ||
135 | #endif | ||
136 | #endif | ||
137 | return 1; | ||
138 | #else /* HAVE_DEV_PTMX */ | ||
139 | #ifdef HAVE_DEV_PTS_AND_PTC | ||
140 | /* AIX-style pty code. */ | ||
141 | const char *name; | ||
142 | |||
143 | *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY); | ||
144 | if (*ptyfd < 0) { | ||
145 | error("Could not open /dev/ptc: %.100s", strerror(errno)); | ||
146 | return 0; | ||
147 | } | ||
148 | name = ttyname(*ptyfd); | ||
149 | if (!name) | ||
150 | fatal("Open of /dev/ptc returns device for which ttyname fails."); | ||
151 | strlcpy(namebuf, name, namebuflen); | ||
152 | *ttyfd = open(name, O_RDWR | O_NOCTTY); | ||
153 | if (*ttyfd < 0) { | ||
154 | error("Could not open pty slave side %.100s: %.100s", | ||
155 | name, strerror(errno)); | ||
156 | close(*ptyfd); | ||
157 | return 0; | ||
158 | } | ||
159 | return 1; | ||
160 | #else /* HAVE_DEV_PTS_AND_PTC */ | ||
161 | /* BSD-style pty code. */ | ||
162 | char buf[64]; | ||
163 | int i; | ||
164 | const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
165 | const char *ptyminors = "0123456789abcdef"; | ||
166 | int num_minors = strlen(ptyminors); | ||
167 | int num_ptys = strlen(ptymajors) * num_minors; | ||
168 | |||
169 | 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 | snprintf(namebuf, namebuflen, "/dev/tty%c%c", | ||
173 | ptymajors[i / num_minors], ptyminors[i % num_minors]); | ||
174 | |||
175 | *ptyfd = open(buf, O_RDWR | O_NOCTTY); | ||
176 | if (*ptyfd < 0) { | ||
177 | /* Try SCO style naming */ | ||
178 | snprintf(buf, sizeof buf, "/dev/ptyp%d", i); | ||
179 | snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); | ||
180 | *ptyfd = open(buf, O_RDWR | O_NOCTTY); | ||
181 | if (*ptyfd < 0) | ||
182 | continue; | ||
183 | } | ||
184 | |||
185 | /* Open the slave side. */ | ||
186 | *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); | ||
187 | if (*ttyfd < 0) { | ||
188 | error("%.100s: %.100s", namebuf, strerror(errno)); | ||
189 | close(*ptyfd); | ||
190 | return 0; | ||
191 | } | ||
192 | return 1; | ||
193 | } | ||
194 | return 0; | ||
195 | #endif /* HAVE_DEV_PTS_AND_PTC */ | ||
196 | #endif /* HAVE_DEV_PTMX */ | ||
197 | #endif /* HAVE__GETPTY */ | ||
198 | #endif /* HAVE_OPENPTY */ | ||
199 | } | ||
200 | |||
201 | /* Releases the tty. Its ownership is returned to root, and permissions to 0666. */ | ||
202 | |||
203 | void | ||
204 | pty_release(const char *ttyname) | ||
205 | { | ||
206 | if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0) | ||
207 | error("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno)); | ||
208 | if (chmod(ttyname, (mode_t) 0666) < 0) | ||
209 | error("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno)); | ||
210 | } | ||
211 | |||
212 | /* Makes the tty the processes controlling tty and sets it to sane modes. */ | ||
213 | |||
214 | void | ||
215 | pty_make_controlling_tty(int *ttyfd, const char *ttyname) | ||
216 | { | ||
217 | int fd; | ||
218 | #ifdef USE_VHANGUP | ||
219 | void *old; | ||
220 | #endif /* USE_VHANGUP */ | ||
221 | |||
222 | /* First disconnect from the old controlling tty. */ | ||
223 | #ifdef TIOCNOTTY | ||
224 | fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); | ||
225 | if (fd >= 0) { | ||
226 | (void) ioctl(fd, TIOCNOTTY, NULL); | ||
227 | close(fd); | ||
228 | } | ||
229 | #endif /* TIOCNOTTY */ | ||
230 | if (setsid() < 0) | ||
231 | error("setsid: %.100s", strerror(errno)); | ||
232 | |||
233 | /* | ||
234 | * Verify that we are successfully disconnected from the controlling | ||
235 | * tty. | ||
236 | */ | ||
237 | fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); | ||
238 | if (fd >= 0) { | ||
239 | error("Failed to disconnect from controlling tty."); | ||
240 | close(fd); | ||
241 | } | ||
242 | /* Make it our controlling tty. */ | ||
243 | #ifdef TIOCSCTTY | ||
244 | debug("Setting controlling tty using TIOCSCTTY."); | ||
245 | if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) | ||
246 | error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); | ||
247 | #endif /* TIOCSCTTY */ | ||
248 | #ifdef HAVE_NEWS4 | ||
249 | if (setpgrp(0,0) < 0) | ||
250 | error("SETPGRP %s",strerror(errno)); | ||
251 | #endif /* HAVE_NEWS4 */ | ||
252 | #ifdef USE_VHANGUP | ||
253 | old = signal(SIGHUP, SIG_IGN); | ||
254 | vhangup(); | ||
255 | signal(SIGHUP, old); | ||
256 | #endif /* USE_VHANGUP */ | ||
257 | fd = open(ttyname, O_RDWR); | ||
258 | if (fd < 0) { | ||
259 | error("%.100s: %.100s", ttyname, strerror(errno)); | ||
260 | } else { | ||
261 | #ifdef USE_VHANGUP | ||
262 | close(*ttyfd); | ||
263 | *ttyfd = fd; | ||
264 | #else /* USE_VHANGUP */ | ||
265 | close(fd); | ||
266 | #endif /* USE_VHANGUP */ | ||
267 | } | ||
268 | /* Verify that we now have a controlling tty. */ | ||
269 | fd = open(_PATH_TTY, O_WRONLY); | ||
270 | if (fd < 0) | ||
271 | error("open /dev/tty failed - could not set controlling tty: %.100s", | ||
272 | strerror(errno)); | ||
273 | else { | ||
274 | close(fd); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | /* Changes the window size associated with the pty. */ | ||
279 | |||
280 | void | ||
281 | pty_change_window_size(int ptyfd, int row, int col, | ||
282 | int xpixel, int ypixel) | ||
283 | { | ||
284 | struct winsize w; | ||
285 | w.ws_row = row; | ||
286 | w.ws_col = col; | ||
287 | w.ws_xpixel = xpixel; | ||
288 | w.ws_ypixel = ypixel; | ||
289 | (void) ioctl(ptyfd, TIOCSWINSZ, &w); | ||
290 | } | ||
291 | |||
292 | void | ||
293 | pty_setowner(struct passwd *pw, const char *ttyname) | ||
294 | { | ||
295 | struct group *grp; | ||
296 | gid_t gid; | ||
297 | mode_t mode; | ||
298 | struct stat st; | ||
299 | |||
300 | /* Determine the group to make the owner of the tty. */ | ||
301 | grp = getgrnam("tty"); | ||
302 | if (grp) { | ||
303 | gid = grp->gr_gid; | ||
304 | mode = S_IRUSR | S_IWUSR | S_IWGRP; | ||
305 | } else { | ||
306 | gid = pw->pw_gid; | ||
307 | mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Change owner and mode of the tty as required. | ||
312 | * Warn but continue if filesystem is read-only and the uids match. | ||
313 | */ | ||
314 | if (stat(ttyname, &st)) | ||
315 | fatal("stat(%.100s) failed: %.100s", ttyname, | ||
316 | strerror(errno)); | ||
317 | |||
318 | if (st.st_uid != pw->pw_uid || st.st_gid != gid) { | ||
319 | if (chown(ttyname, pw->pw_uid, gid) < 0) { | ||
320 | if (errno == EROFS && st.st_uid == pw->pw_uid) | ||
321 | error("chown(%.100s, %d, %d) failed: %.100s", | ||
322 | ttyname, pw->pw_uid, gid, | ||
323 | strerror(errno)); | ||
324 | else | ||
325 | fatal("chown(%.100s, %d, %d) failed: %.100s", | ||
326 | ttyname, pw->pw_uid, gid, | ||
327 | strerror(errno)); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) { | ||
332 | if (chmod(ttyname, mode) < 0) { | ||
333 | if (errno == EROFS && | ||
334 | (st.st_mode & (S_IRGRP | S_IROTH)) == 0) | ||
335 | error("chmod(%.100s, 0%o) failed: %.100s", | ||
336 | ttyname, mode, strerror(errno)); | ||
337 | else | ||
338 | fatal("chmod(%.100s, 0%o) failed: %.100s", | ||
339 | ttyname, mode, strerror(errno)); | ||
340 | } | ||
341 | } | ||
342 | } | ||