pty.c revision 157184
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