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