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 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <fcntl.h> 27#include <signal.h> 28 29#include "config.h" 30#include "screen.h" 31 32#ifndef sun 33# include <sys/ioctl.h> 34#endif 35 36/* for solaris 2.1, Unixware (SVR4.2) and possibly others */ 37#ifndef __APPLE__ 38#ifdef HAVE_SVR4_PTYS 39# include <sys/stropts.h> 40#endif 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 74extern int eff_uid; 75 76/* used for opening a new pty-pair: */ 77static char PtyName[32], TtyName[32]; 78 79#if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS)) 80# ifdef hpux 81static char PtyProto[] = "/dev/ptym/ptyXY"; 82static char TtyProto[] = "/dev/pty/ttyXY"; 83# else 84# ifdef M_UNIX 85static char PtyProto[] = "/dev/ptypXY"; 86static char TtyProto[] = "/dev/ttypXY"; 87# else 88static char PtyProto[] = "/dev/ptyXY"; 89static char TtyProto[] = "/dev/ttyXY"; 90# endif 91# endif /* hpux */ 92#endif 93 94static void initmaster __P((int)); 95 96#if defined(sun) 97/* sun's utmp_update program opens the salve side, thus corrupting 98 */ 99int pty_preopen = 1; 100#else 101int 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 114static void 115initmaster(f) 116int 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 130void 131InitPTY(f) 132int 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 152int 153OpenPTY(ttyn) 154char **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 169int 170OpenPTY(ttyn) 171char **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 193int 194OpenPTY(ttyn) 195char **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 221int 222OpenPTY(ttyn) 223char **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 247int 248OpenPTY(ttyn) 249char **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 291int 292OpenPTY(ttyn) 293char **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 320int 321OpenPTY(ttyn) 322char **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 338int 339OpenPTY(ttyn) 340char **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 389 390