Commit | Line | Data |
---|---|---|
b585a9fa EZ |
1 | /* Copyright (c) 1993-2002 |
2 | * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) | |
3 | * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) | |
4 | * Copyright (c) 1987 Oliver Laumann | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2, or (at your option) | |
9 | * any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program (see the file COPYING); if not, write to the | |
18 | * Free Software Foundation, Inc., | |
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
20 | * | |
21 | **************************************************************** | |
22 | */ | |
cc88a640 | 23 | #include "config.h" |
b585a9fa EZ |
24 | |
25 | #include <sys/types.h> | |
26 | #include <sys/stat.h> | |
27 | #include <fcntl.h> | |
28 | #include <signal.h> | |
29 | ||
cc88a640 JK |
30 | #include <unistd.h> |
31 | ||
b585a9fa EZ |
32 | #include "screen.h" |
33 | ||
34 | #ifndef sun | |
35 | # include <sys/ioctl.h> | |
36 | #endif | |
37 | ||
38 | /* for solaris 2.1, Unixware (SVR4.2) and possibly others */ | |
cc88a640 | 39 | #if defined (HAVE_SVR4_PTYS) && defined (HAVE_SYS_STROPTS_H) |
b585a9fa EZ |
40 | # include <sys/stropts.h> |
41 | #endif | |
42 | ||
43 | #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL) | |
44 | # include <sys/ttold.h> | |
45 | #endif | |
46 | ||
47 | #ifdef ISC | |
48 | # include <sys/tty.h> | |
49 | # include <sys/sioctl.h> | |
50 | # include <sys/pty.h> | |
51 | #endif | |
52 | ||
53 | #ifdef sgi | |
54 | # include <sys/sysmacros.h> | |
55 | #endif /* sgi */ | |
56 | ||
57 | #include "extern.h" | |
58 | ||
59 | /* | |
60 | * if no PTYRANGE[01] is in the config file, we pick a default | |
61 | */ | |
62 | #ifndef PTYRANGE0 | |
63 | # define PTYRANGE0 "qpr" | |
64 | #endif | |
65 | #ifndef PTYRANGE1 | |
66 | # define PTYRANGE1 "0123456789abcdef" | |
67 | #endif | |
68 | ||
69 | /* SVR4 pseudo ttys don't seem to work with SCO-5 */ | |
70 | #ifdef M_UNIX | |
71 | # undef HAVE_SVR4_PTYS | |
72 | #endif | |
73 | ||
74 | extern int eff_uid; | |
75 | ||
76 | /* used for opening a new pty-pair: */ | |
77 | static char PtyName[32], TtyName[32]; | |
78 | ||
79 | #if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS)) | |
80 | # ifdef hpux | |
81 | static char PtyProto[] = "/dev/ptym/ptyXY"; | |
82 | static char TtyProto[] = "/dev/pty/ttyXY"; | |
83 | # else | |
84 | # ifdef M_UNIX | |
85 | static char PtyProto[] = "/dev/ptypXY"; | |
86 | static char TtyProto[] = "/dev/ttypXY"; | |
87 | # else | |
88 | static char PtyProto[] = "/dev/ptyXY"; | |
89 | static char TtyProto[] = "/dev/ttyXY"; | |
90 | # endif | |
91 | # endif /* hpux */ | |
92 | #endif | |
93 | ||
94 | static void initmaster __P((int)); | |
95 | ||
96 | #if defined(sun) | |
97 | /* sun's utmp_update program opens the salve side, thus corrupting | |
98 | */ | |
99 | int pty_preopen = 1; | |
100 | #else | |
101 | int pty_preopen = 0; | |
102 | #endif | |
103 | ||
104 | /* | |
105 | * Open all ptys with O_NOCTTY, just to be on the safe side | |
106 | * (RISCos mips breaks otherwise) | |
107 | */ | |
108 | #ifndef O_NOCTTY | |
109 | # define O_NOCTTY 0 | |
110 | #endif | |
111 | ||
112 | /***************************************************************/ | |
113 | ||
114 | static void | |
115 | initmaster(f) | |
116 | int f; | |
117 | { | |
118 | #ifdef POSIX | |
119 | tcflush(f, TCIOFLUSH); | |
120 | #else | |
121 | # ifdef TIOCFLUSH | |
122 | (void) ioctl(f, TIOCFLUSH, (char *) 0); | |
123 | # endif | |
124 | #endif | |
125 | #ifdef LOCKPTY | |
126 | (void) ioctl(f, TIOCEXCL, (char *) 0); | |
127 | #endif | |
128 | } | |
129 | ||
130 | void | |
131 | InitPTY(f) | |
132 | int f; | |
133 | { | |
134 | if (f < 0) | |
135 | return; | |
136 | #if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX) | |
137 | if (ioctl(f, I_PUSH, "ptem")) | |
138 | Panic(errno, "InitPTY: cannot I_PUSH ptem"); | |
139 | if (ioctl(f, I_PUSH, "ldterm")) | |
140 | Panic(errno, "InitPTY: cannot I_PUSH ldterm"); | |
141 | # ifdef sun | |
142 | if (ioctl(f, I_PUSH, "ttcompat")) | |
143 | Panic(errno, "InitPTY: cannot I_PUSH ttcompat"); | |
144 | # endif | |
145 | #endif | |
146 | } | |
147 | ||
148 | /***************************************************************/ | |
149 | ||
150 | #if defined(OSX) && !defined(PTY_DONE) | |
151 | #define PTY_DONE | |
152 | int | |
153 | OpenPTY(ttyn) | |
154 | char **ttyn; | |
155 | { | |
156 | register int f; | |
157 | if ((f = open_controlling_pty(TtyName)) < 0) | |
158 | return -1; | |
159 | initmaster(f); | |
160 | *ttyn = TtyName; | |
161 | return f; | |
162 | } | |
163 | #endif | |
164 | ||
165 | /***************************************************************/ | |
166 | ||
167 | #if (defined(sequent) || defined(_SEQUENT_)) && !defined(PTY_DONE) | |
168 | #define PTY_DONE | |
169 | int | |
170 | OpenPTY(ttyn) | |
171 | char **ttyn; | |
172 | { | |
173 | char *m, *s; | |
174 | register int f; | |
175 | ||
176 | if ((f = getpseudotty(&s, &m)) < 0) | |
177 | return -1; | |
178 | #ifdef _SEQUENT_ | |
179 | fvhangup(s); | |
180 | #endif | |
181 | strncpy(PtyName, m, sizeof(PtyName)); | |
182 | strncpy(TtyName, s, sizeof(TtyName)); | |
183 | initmaster(f); | |
184 | *ttyn = TtyName; | |
185 | return f; | |
186 | } | |
187 | #endif | |
188 | ||
189 | /***************************************************************/ | |
190 | ||
191 | #if defined(__sgi) && !defined(PTY_DONE) | |
192 | #define PTY_DONE | |
193 | int | |
194 | OpenPTY(ttyn) | |
195 | char **ttyn; | |
196 | { | |
197 | int f; | |
198 | char *name, *_getpty(); | |
199 | sigret_t (*sigcld)__P(SIGPROTOARG); | |
200 | ||
201 | /* | |
202 | * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and | |
203 | * exec() /usr/adm/mkpts | |
204 | */ | |
205 | sigcld = signal(SIGCHLD, SIG_DFL); | |
206 | name = _getpty(&f, O_RDWR | O_NONBLOCK, 0600, 0); | |
207 | signal(SIGCHLD, sigcld); | |
208 | ||
209 | if (name == 0) | |
210 | return -1; | |
211 | initmaster(f); | |
212 | *ttyn = name; | |
213 | return f; | |
214 | } | |
215 | #endif | |
216 | ||
217 | /***************************************************************/ | |
218 | ||
219 | #if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE) | |
220 | #define PTY_DONE | |
221 | int | |
222 | OpenPTY(ttyn) | |
223 | char **ttyn; | |
224 | { | |
225 | register int f; | |
226 | struct stat buf; | |
227 | ||
228 | strcpy(PtyName, "/dev/ptc"); | |
229 | if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) | |
230 | return -1; | |
231 | if (fstat(f, &buf) < 0) | |
232 | { | |
233 | close(f); | |
234 | return -1; | |
235 | } | |
236 | sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev)); | |
237 | initmaster(f); | |
238 | *ttyn = TtyName; | |
239 | return f; | |
240 | } | |
241 | #endif | |
242 | ||
243 | /***************************************************************/ | |
244 | ||
245 | #if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE) | |
246 | #define PTY_DONE | |
247 | int | |
248 | OpenPTY(ttyn) | |
249 | char **ttyn; | |
250 | { | |
251 | register int f; | |
252 | char *m, *ptsname(); | |
253 | int unlockpt __P((int)), grantpt __P((int)); | |
254 | #if defined(HAVE_GETPT) && defined(linux) | |
255 | int getpt __P((void)); | |
256 | #endif | |
257 | sigret_t (*sigcld)__P(SIGPROTOARG); | |
258 | ||
259 | strcpy(PtyName, "/dev/ptmx"); | |
260 | #if defined(HAVE_GETPT) && defined(linux) | |
261 | if ((f = getpt()) == -1) | |
262 | #else | |
263 | if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1) | |
264 | #endif | |
265 | return -1; | |
266 | ||
267 | /* | |
268 | * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and | |
269 | * exec()s pt_chmod | |
270 | */ | |
271 | sigcld = signal(SIGCHLD, SIG_DFL); | |
272 | if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f)) | |
273 | { | |
274 | signal(SIGCHLD, sigcld); | |
275 | close(f); | |
276 | return -1; | |
277 | } | |
278 | signal(SIGCHLD, sigcld); | |
279 | strncpy(TtyName, m, sizeof(TtyName)); | |
280 | initmaster(f); | |
281 | *ttyn = TtyName; | |
282 | return f; | |
283 | } | |
284 | #endif | |
285 | ||
286 | /***************************************************************/ | |
287 | ||
288 | #if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE) | |
289 | #define PTY_DONE | |
290 | ||
291 | int | |
292 | OpenPTY(ttyn) | |
293 | char **ttyn; | |
294 | { | |
295 | register int f; | |
296 | ||
297 | /* a dumb looking loop replaced by mycrofts code: */ | |
298 | strcpy (PtyName, "/dev/ptc"); | |
299 | if ((f = open (PtyName, O_RDWR | O_NOCTTY)) < 0) | |
300 | return -1; | |
301 | strncpy(TtyName, ttyname(f), sizeof(TtyName)); | |
302 | if (eff_uid && access(TtyName, R_OK | W_OK)) | |
303 | { | |
304 | close(f); | |
305 | return -1; | |
306 | } | |
307 | initmaster(f); | |
308 | # ifdef _IBMR2 | |
309 | pty_preopen = 1; | |
310 | # endif | |
311 | *ttyn = TtyName; | |
312 | return f; | |
313 | } | |
314 | #endif | |
315 | ||
316 | /***************************************************************/ | |
317 | ||
318 | #if defined(HAVE_OPENPTY) && !defined(PTY_DONE) | |
319 | #define PTY_DONE | |
320 | int | |
321 | OpenPTY(ttyn) | |
322 | char **ttyn; | |
323 | { | |
324 | int f, s; | |
325 | if (openpty(&f, &s, TtyName, NULL, NULL) != 0) | |
326 | return -1; | |
327 | close(s); | |
328 | initmaster(f); | |
329 | pty_preopen = 1; | |
330 | *ttyn = TtyName; | |
331 | return f; | |
332 | } | |
333 | #endif | |
334 | ||
335 | /***************************************************************/ | |
336 | ||
337 | #ifndef PTY_DONE | |
338 | int | |
339 | OpenPTY(ttyn) | |
340 | char **ttyn; | |
341 | { | |
342 | register char *p, *q, *l, *d; | |
343 | register int f; | |
344 | ||
345 | debug("OpenPTY: Using BSD style ptys.\n"); | |
346 | strcpy(PtyName, PtyProto); | |
347 | strcpy(TtyName, TtyProto); | |
348 | for (p = PtyName; *p != 'X'; p++) | |
349 | ; | |
350 | for (q = TtyName; *q != 'X'; q++) | |
351 | ; | |
352 | for (l = PTYRANGE0; (*p = *l) != '\0'; l++) | |
353 | { | |
354 | for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++) | |
355 | { | |
356 | debug1("OpenPTY tries '%s'\n", PtyName); | |
357 | if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1) | |
358 | continue; | |
359 | q[0] = *l; | |
360 | q[1] = *d; | |
361 | if (eff_uid && access(TtyName, R_OK | W_OK)) | |
362 | { | |
363 | close(f); | |
364 | continue; | |
365 | } | |
366 | #if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3) | |
367 | /* Hack to ensure that the slave side of the pty is | |
368 | * unused. May not work in anything other than SunOS4.1 | |
369 | */ | |
370 | { | |
371 | int pgrp; | |
372 | ||
373 | /* tcgetpgrp does not work (uses TIOCGETPGRP)! */ | |
374 | if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO) | |
375 | { | |
376 | close(f); | |
377 | continue; | |
378 | } | |
379 | } | |
380 | #endif | |
381 | initmaster(f); | |
382 | *ttyn = TtyName; | |
383 | return f; | |
384 | } | |
385 | } | |
386 | return -1; | |
387 | } | |
388 | #endif |