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