1157184Sache/* Copyright (c) 1993-2002
2157184Sache *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3157184Sache *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4157184Sache * Copyright (c) 1987 Oliver Laumann
5157184Sache *
6157184Sache * This program is free software; you can redistribute it and/or modify
7157184Sache * it under the terms of the GNU General Public License as published by
8157184Sache * the Free Software Foundation; either version 2, or (at your option)
9157184Sache * any later version.
10157184Sache *
11157184Sache * This program is distributed in the hope that it will be useful,
12157184Sache * but WITHOUT ANY WARRANTY; without even the implied warranty of
13157184Sache * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14157184Sache * GNU General Public License for more details.
15157184Sache *
16157184Sache * You should have received a copy of the GNU General Public License
17157184Sache * along with this program (see the file COPYING); if not, write to the
18157184Sache * Free Software Foundation, Inc.,
19157184Sache * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
20157184Sache *
21157184Sache ****************************************************************
22157184Sache */
23157184Sache
24157184Sache#include <sys/types.h>
25157184Sache#include <sys/stat.h>
26157184Sache#include <fcntl.h>
27157184Sache#include <signal.h>
28157184Sache
29157184Sache#include "config.h"
30157184Sache#include "screen.h"
31157184Sache
32157184Sache#ifndef sun
33157184Sache# include <sys/ioctl.h>
34157184Sache#endif
35157184Sache
36157184Sache/* for solaris 2.1, Unixware (SVR4.2) and possibly others */
37157184Sache#ifdef HAVE_SVR4_PTYS
38157184Sache# include <sys/stropts.h>
39157184Sache#endif
40157184Sache
41157184Sache#if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL)
42157184Sache# include <sys/ttold.h>
43157184Sache#endif
44157184Sache
45157184Sache#ifdef ISC
46157184Sache# include <sys/tty.h>
47157184Sache# include <sys/sioctl.h>
48157184Sache# include <sys/pty.h>
49157184Sache#endif
50157184Sache
51157184Sache#ifdef sgi
52157184Sache# include <sys/sysmacros.h>
53157184Sache#endif /* sgi */
54157184Sache
55157184Sache#include "extern.h"
56157184Sache
57157184Sache/*
58157184Sache * if no PTYRANGE[01] is in the config file, we pick a default
59157184Sache */
60157184Sache#ifndef PTYRANGE0
61157184Sache# define PTYRANGE0 "qpr"
62157184Sache#endif
63157184Sache#ifndef PTYRANGE1
64157184Sache# define PTYRANGE1 "0123456789abcdef"
65157184Sache#endif
66157184Sache
67157184Sache/* SVR4 pseudo ttys don't seem to work with SCO-5 */
68157184Sache#ifdef M_UNIX
69157184Sache# undef HAVE_SVR4_PTYS
70157184Sache#endif
71157184Sache
72157184Sacheextern int eff_uid;
73157184Sache
74157184Sache/* used for opening a new pty-pair: */
75157184Sachestatic char PtyName[32], TtyName[32];
76157184Sache
77157184Sache#if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS))
78157184Sache# ifdef hpux
79157184Sachestatic char PtyProto[] = "/dev/ptym/ptyXY";
80157184Sachestatic char TtyProto[] = "/dev/pty/ttyXY";
81157184Sache# else
82157184Sache#  ifdef M_UNIX
83157184Sachestatic char PtyProto[] = "/dev/ptypXY";
84157184Sachestatic char TtyProto[] = "/dev/ttypXY";
85157184Sache#  else
86157184Sachestatic char PtyProto[] = "/dev/ptyXY";
87157184Sachestatic char TtyProto[] = "/dev/ttyXY";
88157184Sache#  endif
89157184Sache# endif /* hpux */
90157184Sache#endif
91157184Sache
92157184Sachestatic void initmaster __P((int));
93157184Sache
94157184Sache#if defined(sun)
95157184Sache/* sun's utmp_update program opens the salve side, thus corrupting
96157184Sache */
97157184Sacheint pty_preopen = 1;
98157184Sache#else
99157184Sacheint pty_preopen = 0;
100157184Sache#endif
101157184Sache
102157184Sache/*
103157184Sache *  Open all ptys with O_NOCTTY, just to be on the safe side
104157184Sache *  (RISCos mips breaks otherwise)
105157184Sache */
106157184Sache#ifndef O_NOCTTY
107157184Sache# define O_NOCTTY 0
108157184Sache#endif
109157184Sache
110157184Sache/***************************************************************/
111157184Sache
112157184Sachestatic void
113157184Sacheinitmaster(f)
114157184Sacheint f;
115157184Sache{
116157184Sache#ifdef POSIX
117157184Sache  tcflush(f, TCIOFLUSH);
118157184Sache#else
119157184Sache# ifdef TIOCFLUSH
120157184Sache  (void) ioctl(f, TIOCFLUSH, (char *) 0);
121157184Sache# endif
122157184Sache#endif
123157184Sache#ifdef LOCKPTY
124157184Sache  (void) ioctl(f, TIOCEXCL, (char *) 0);
125157184Sache#endif
126157184Sache}
127157184Sache
128157184Sachevoid
129157184SacheInitPTY(f)
130157184Sacheint f;
131157184Sache{
132157184Sache  if (f < 0)
133157184Sache    return;
134157184Sache#if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX)
135157184Sache  if (ioctl(f, I_PUSH, "ptem"))
136157184Sache    Panic(errno, "InitPTY: cannot I_PUSH ptem");
137157184Sache  if (ioctl(f, I_PUSH, "ldterm"))
138157184Sache    Panic(errno, "InitPTY: cannot I_PUSH ldterm");
139157184Sache# ifdef sun
140157184Sache  if (ioctl(f, I_PUSH, "ttcompat"))
141157184Sache    Panic(errno, "InitPTY: cannot I_PUSH ttcompat");
142157184Sache# endif
143157184Sache#endif
144157184Sache}
145157184Sache
146157184Sache/***************************************************************/
147157184Sache
148157184Sache#if defined(OSX) && !defined(PTY_DONE)
149157184Sache#define PTY_DONE
150157184Sacheint
151157184SacheOpenPTY(ttyn)
152157184Sachechar **ttyn;
153157184Sache{
154157184Sache  register int f;
155157184Sache  if ((f = open_controlling_pty(TtyName)) < 0)
156157184Sache    return -1;
157157184Sache  initmaster(f);
158157184Sache  *ttyn = TtyName;
159157184Sache  return f;
160157184Sache}
161157184Sache#endif
162157184Sache
163157184Sache/***************************************************************/
164157184Sache
165157184Sache#if (defined(sequent) || defined(_SEQUENT_)) && !defined(PTY_DONE)
166157184Sache#define PTY_DONE
167157184Sacheint
168157184SacheOpenPTY(ttyn)
169157184Sachechar **ttyn;
170157184Sache{
171157184Sache  char *m, *s;
172157184Sache  register int f;
173157184Sache
174157184Sache  if ((f = getpseudotty(&s, &m)) < 0)
175157184Sache    return -1;
176157184Sache#ifdef _SEQUENT_
177157184Sache  fvhangup(s);
178157184Sache#endif
179157184Sache  strncpy(PtyName, m, sizeof(PtyName));
180157184Sache  strncpy(TtyName, s, sizeof(TtyName));
181157184Sache  initmaster(f);
182157184Sache  *ttyn = TtyName;
183157184Sache  return f;
184157184Sache}
185157184Sache#endif
186157184Sache
187157184Sache/***************************************************************/
188157184Sache
189157184Sache#if defined(__sgi) && !defined(PTY_DONE)
190157184Sache#define PTY_DONE
191157184Sacheint
192157184SacheOpenPTY(ttyn)
193157184Sachechar **ttyn;
194157184Sache{
195157184Sache  int f;
196157184Sache  char *name, *_getpty();
197157184Sache  sigret_t (*sigcld)__P(SIGPROTOARG);
198157184Sache
199157184Sache  /*
200157184Sache   * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and
201157184Sache   * exec() /usr/adm/mkpts
202157184Sache   */
203157184Sache  sigcld = signal(SIGCHLD, SIG_DFL);
204157184Sache  name = _getpty(&f, O_RDWR | O_NONBLOCK, 0600, 0);
205157184Sache  signal(SIGCHLD, sigcld);
206157184Sache
207157184Sache  if (name == 0)
208157184Sache    return -1;
209157184Sache  initmaster(f);
210157184Sache  *ttyn = name;
211157184Sache  return f;
212157184Sache}
213157184Sache#endif
214157184Sache
215157184Sache/***************************************************************/
216157184Sache
217157184Sache#if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
218157184Sache#define PTY_DONE
219157184Sacheint
220157184SacheOpenPTY(ttyn)
221157184Sachechar **ttyn;
222157184Sache{
223157184Sache  register int f;
224157184Sache  struct stat buf;
225157184Sache
226157184Sache  strcpy(PtyName, "/dev/ptc");
227157184Sache  if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
228157184Sache    return -1;
229157184Sache  if (fstat(f, &buf) < 0)
230157184Sache    {
231157184Sache      close(f);
232157184Sache      return -1;
233157184Sache    }
234157184Sache  sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev));
235157184Sache  initmaster(f);
236157184Sache  *ttyn = TtyName;
237157184Sache  return f;
238157184Sache}
239157184Sache#endif
240157184Sache
241157184Sache/***************************************************************/
242157184Sache
243157184Sache#if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE)
244157184Sache#define PTY_DONE
245157184Sacheint
246157184SacheOpenPTY(ttyn)
247157184Sachechar **ttyn;
248157184Sache{
249157184Sache  register int f;
250157184Sache  char *m, *ptsname();
251157184Sache  int unlockpt __P((int)), grantpt __P((int));
252157184Sache#if defined(HAVE_GETPT) && defined(linux)
253157184Sache  int getpt __P((void));
254157184Sache#endif
255157184Sache  sigret_t (*sigcld)__P(SIGPROTOARG);
256157184Sache
257157184Sache  strcpy(PtyName, "/dev/ptmx");
258157184Sache#if defined(HAVE_GETPT) && defined(linux)
259157184Sache  if ((f = getpt()) == -1)
260157184Sache#else
261157184Sache  if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1)
262157184Sache#endif
263157184Sache    return -1;
264157184Sache
265157184Sache  /*
266157184Sache   * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and
267157184Sache   * exec()s pt_chmod
268157184Sache   */
269157184Sache  sigcld = signal(SIGCHLD, SIG_DFL);
270157184Sache  if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f))
271157184Sache    {
272157184Sache      signal(SIGCHLD, sigcld);
273157184Sache      close(f);
274157184Sache      return -1;
275157184Sache    }
276157184Sache  signal(SIGCHLD, sigcld);
277157184Sache  strncpy(TtyName, m, sizeof(TtyName));
278157184Sache  initmaster(f);
279157184Sache  *ttyn = TtyName;
280157184Sache  return f;
281157184Sache}
282157184Sache#endif
283157184Sache
284157184Sache/***************************************************************/
285157184Sache
286157184Sache#if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
287157184Sache#define PTY_DONE
288157184Sache
289157184Sacheint
290157184SacheOpenPTY(ttyn)
291157184Sachechar **ttyn;
292157184Sache{
293157184Sache  register int f;
294157184Sache
295157184Sache  /* a dumb looking loop replaced by mycrofts code: */
296157184Sache  strcpy (PtyName, "/dev/ptc");
297157184Sache  if ((f = open (PtyName, O_RDWR | O_NOCTTY)) < 0)
298157184Sache    return -1;
299157184Sache  strncpy(TtyName, ttyname(f), sizeof(TtyName));
300157184Sache  if (eff_uid && access(TtyName, R_OK | W_OK))
301157184Sache    {
302157184Sache      close(f);
303157184Sache      return -1;
304157184Sache    }
305157184Sache  initmaster(f);
306157184Sache# ifdef _IBMR2
307157184Sache  pty_preopen = 1;
308157184Sache# endif
309157184Sache  *ttyn = TtyName;
310157184Sache  return f;
311157184Sache}
312157184Sache#endif
313157184Sache
314157184Sache/***************************************************************/
315157184Sache
316157184Sache#if defined(HAVE_OPENPTY) && !defined(PTY_DONE)
317157184Sache#define PTY_DONE
318157184Sacheint
319157184SacheOpenPTY(ttyn)
320157184Sachechar **ttyn;
321157184Sache{
322157184Sache  int f, s;
323157184Sache  if (openpty(&f, &s, TtyName, NULL, NULL) != 0)
324157184Sache    return -1;
325157184Sache  close(s);
326157184Sache  initmaster(f);
327157184Sache  pty_preopen = 1;
328157184Sache  *ttyn = TtyName;
329157184Sache  return f;
330157184Sache}
331157184Sache#endif
332157184Sache
333157184Sache/***************************************************************/
334157184Sache
335157184Sache#ifndef PTY_DONE
336157184Sacheint
337157184SacheOpenPTY(ttyn)
338157184Sachechar **ttyn;
339157184Sache{
340157184Sache  register char *p, *q, *l, *d;
341157184Sache  register int f;
342157184Sache
343157184Sache  debug("OpenPTY: Using BSD style ptys.\n");
344157184Sache  strcpy(PtyName, PtyProto);
345157184Sache  strcpy(TtyName, TtyProto);
346157184Sache  for (p = PtyName; *p != 'X'; p++)
347157184Sache    ;
348157184Sache  for (q = TtyName; *q != 'X'; q++)
349157184Sache    ;
350157184Sache  for (l = PTYRANGE0; (*p = *l) != '\0'; l++)
351157184Sache    {
352157184Sache      for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++)
353157184Sache	{
354157184Sache	  debug1("OpenPTY tries '%s'\n", PtyName);
355157184Sache	  if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1)
356157184Sache	    continue;
357157184Sache	  q[0] = *l;
358157184Sache	  q[1] = *d;
359157184Sache	  if (eff_uid && access(TtyName, R_OK | W_OK))
360157184Sache	    {
361157184Sache	      close(f);
362157184Sache	      continue;
363157184Sache	    }
364157184Sache#if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3)
365157184Sache	  /* Hack to ensure that the slave side of the pty is
366157184Sache	   * unused. May not work in anything other than SunOS4.1
367157184Sache	   */
368157184Sache	    {
369157184Sache	      int pgrp;
370157184Sache
371157184Sache	      /* tcgetpgrp does not work (uses TIOCGETPGRP)! */
372157184Sache	      if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO)
373157184Sache		{
374157184Sache		  close(f);
375157184Sache		  continue;
376157184Sache		}
377157184Sache	    }
378157184Sache#endif
379157184Sache	  initmaster(f);
380157184Sache	  *ttyn = TtyName;
381157184Sache	  return f;
382157184Sache	}
383157184Sache    }
384157184Sache  return -1;
385157184Sache}
386157184Sache#endif
387157184Sache
388