diff options
Diffstat (limited to 'openbsd-compat/bsd-openpty.c')
-rw-r--r-- | openbsd-compat/bsd-openpty.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/openbsd-compat/bsd-openpty.c b/openbsd-compat/bsd-openpty.c new file mode 100644 index 000000000..daf5f8b81 --- /dev/null +++ b/openbsd-compat/bsd-openpty.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * Please note: this implementation of openpty() is far from complete. | ||
3 | * it is just enough for portable OpenSSH's needs. | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * Copyright (c) 2004 Damien Miller <djm@mindrot.org> | ||
8 | * | ||
9 | * Permission to use, copy, modify, and distribute this software for any | ||
10 | * purpose with or without fee is hereby granted, provided that the above | ||
11 | * copyright notice and this permission notice appear in all copies. | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | ||
24 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | ||
25 | * All rights reserved | ||
26 | * Allocating a pseudo-terminal, and making it the controlling tty. | ||
27 | * | ||
28 | * As far as I am concerned, the code I have written for this software | ||
29 | * can be used freely for any purpose. Any derived versions of this | ||
30 | * software must be clearly marked as such, and if the derived work is | ||
31 | * incompatible with the protocol description in the RFC file, it must be | ||
32 | * called by a name other than "ssh" or "Secure Shell". | ||
33 | */ | ||
34 | |||
35 | #include "includes.h" | ||
36 | #if !defined(HAVE_OPENPTY) | ||
37 | |||
38 | #ifdef HAVE_UTIL_H | ||
39 | # include <util.h> | ||
40 | #endif /* HAVE_UTIL_H */ | ||
41 | |||
42 | #ifdef HAVE_PTY_H | ||
43 | # include <pty.h> | ||
44 | #endif | ||
45 | #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) | ||
46 | # include <sys/stropts.h> | ||
47 | #endif | ||
48 | |||
49 | #ifndef O_NOCTTY | ||
50 | #define O_NOCTTY 0 | ||
51 | #endif | ||
52 | |||
53 | int | ||
54 | openpty(int *amaster, int *aslave, char *name, struct termios *termp, | ||
55 | struct winsize *winp) | ||
56 | { | ||
57 | #if defined(HAVE__GETPTY) | ||
58 | /* | ||
59 | * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more | ||
60 | * pty's automagically when needed | ||
61 | */ | ||
62 | char *slave; | ||
63 | |||
64 | if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) | ||
65 | return (-1); | ||
66 | |||
67 | /* Open the slave side. */ | ||
68 | if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { | ||
69 | close(*amaster); | ||
70 | return (-1); | ||
71 | } | ||
72 | return (0); | ||
73 | |||
74 | #elif defined(HAVE_DEV_PTMX) | ||
75 | /* | ||
76 | * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 | ||
77 | * also has bsd-style ptys, but they simply do not work.) | ||
78 | */ | ||
79 | int ptm; | ||
80 | char *pts; | ||
81 | mysig_t old_signal; | ||
82 | |||
83 | if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) | ||
84 | return (-1); | ||
85 | |||
86 | /* XXX: need to close ptm on error? */ | ||
87 | old_signal = signal(SIGCHLD, SIG_DFL); | ||
88 | if (grantpt(ptm) < 0) | ||
89 | return (-1); | ||
90 | signal(SIGCHLD, old_signal); | ||
91 | |||
92 | if (unlockpt(ptm) < 0) | ||
93 | return (-1); | ||
94 | |||
95 | if ((pts = ptsname(ptm)) == NULL) | ||
96 | return (-1); | ||
97 | *amaster = ptm; | ||
98 | |||
99 | /* Open the slave side. */ | ||
100 | if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { | ||
101 | close(*amaster); | ||
102 | return (-1); | ||
103 | } | ||
104 | |||
105 | #ifndef HAVE_CYGWIN | ||
106 | /* | ||
107 | * Try to push the appropriate streams modules, as described | ||
108 | * in Solaris pts(7). | ||
109 | */ | ||
110 | ioctl(*aslave, I_PUSH, "ptem"); | ||
111 | ioctl(*aslave, I_PUSH, "ldterm"); | ||
112 | # ifndef __hpux | ||
113 | ioctl(*aslave, I_PUSH, "ttcompat"); | ||
114 | # endif /* __hpux */ | ||
115 | #endif /* HAVE_CYGWIN */ | ||
116 | |||
117 | return (0); | ||
118 | |||
119 | #elif defined(HAVE_DEV_PTS_AND_PTC) | ||
120 | /* AIX-style pty code. */ | ||
121 | const char *ttname; | ||
122 | |||
123 | if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) | ||
124 | return (-1); | ||
125 | if ((ttname = ttyname(*amaster)) == NULL) | ||
126 | return (-1); | ||
127 | if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { | ||
128 | close(*amaster); | ||
129 | return (-1); | ||
130 | } | ||
131 | return (0); | ||
132 | |||
133 | #elif defined(_UNICOS) | ||
134 | char ptbuf[64], ttbuf[64]; | ||
135 | int i; | ||
136 | int highpty; | ||
137 | |||
138 | highpty = 128; | ||
139 | #ifdef _SC_CRAY_NPTY | ||
140 | if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1) | ||
141 | highpty = 128; | ||
142 | #endif /* _SC_CRAY_NPTY */ | ||
143 | |||
144 | for (i = 0; i < highpty; i++) { | ||
145 | snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i); | ||
146 | snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i); | ||
147 | if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1) | ||
148 | continue; | ||
149 | /* Open the slave side. */ | ||
150 | if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) { | ||
151 | close(*amaster); | ||
152 | return (-1); | ||
153 | } | ||
154 | return (0); | ||
155 | } | ||
156 | return (-1); | ||
157 | |||
158 | #else | ||
159 | /* BSD-style pty code. */ | ||
160 | char ptbuf[64], ttbuf[64]; | ||
161 | int i; | ||
162 | const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" | ||
163 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
164 | const char *ptyminors = "0123456789abcdef"; | ||
165 | int num_minors = strlen(ptyminors); | ||
166 | int num_ptys = strlen(ptymajors) * num_minors; | ||
167 | struct termios tio; | ||
168 | |||
169 | for (i = 0; i < num_ptys; i++) { | ||
170 | snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", | ||
171 | ptymajors[i / num_minors], ptyminors[i % num_minors]); | ||
172 | snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c", | ||
173 | ptymajors[i / num_minors], ptyminors[i % num_minors]); | ||
174 | |||
175 | if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { | ||
176 | /* Try SCO style naming */ | ||
177 | snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); | ||
178 | snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i); | ||
179 | if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) | ||
180 | continue; | ||
181 | } | ||
182 | |||
183 | /* Open the slave side. */ | ||
184 | if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) { | ||
185 | close(*amaster); | ||
186 | return (-1); | ||
187 | } | ||
188 | /* set tty modes to a sane state for broken clients */ | ||
189 | if (tcgetattr(*amaster, &tio) != -1) { | ||
190 | tio.c_lflag |= (ECHO | ISIG | ICANON); | ||
191 | tio.c_oflag |= (OPOST | ONLCR); | ||
192 | tio.c_iflag |= ICRNL; | ||
193 | tcsetattr(*amaster, TCSANOW, &tio); | ||
194 | } | ||
195 | |||
196 | return (0); | ||
197 | } | ||
198 | return (-1); | ||
199 | #endif | ||
200 | } | ||
201 | |||
202 | #endif /* !defined(HAVE_OPENPTY) */ | ||
203 | |||