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: */
23: #include "config.h"
24:
25: #include <sys/types.h>
26: #include <sys/stat.h>
27: #include <fcntl.h>
28: #include <signal.h>
29:
30: #include <unistd.h>
31:
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 */
39: #if defined (HAVE_SVR4_PTYS) && defined (HAVE_SYS_STROPTS_H)
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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>