11e8db6e2SBrian Feldman /* 21e8db6e2SBrian Feldman * Author: Tatu Ylonen <ylo@cs.hut.fi> 31e8db6e2SBrian Feldman * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 41e8db6e2SBrian Feldman * All rights reserved 51e8db6e2SBrian Feldman * Allocating a pseudo-terminal, and making it the controlling tty. 61e8db6e2SBrian Feldman * 71e8db6e2SBrian Feldman * As far as I am concerned, the code I have written for this software 81e8db6e2SBrian Feldman * can be used freely for any purpose. Any derived versions of this 91e8db6e2SBrian Feldman * software must be clearly marked as such, and if the derived work is 101e8db6e2SBrian Feldman * incompatible with the protocol description in the RFC file, it must be 111e8db6e2SBrian Feldman * called by a name other than "ssh" or "Secure Shell". 121e8db6e2SBrian Feldman */ 131e8db6e2SBrian Feldman 141e8db6e2SBrian Feldman #include "includes.h" 15cf2b5f3bSDag-Erling Smørgrav RCSID("$OpenBSD: sshpty.c,v 1.10 2003/06/12 07:57:38 markus Exp $"); 161e8db6e2SBrian Feldman 17989dd127SDag-Erling Smørgrav #ifdef HAVE_UTIL_H 18989dd127SDag-Erling Smørgrav # include <util.h> 19989dd127SDag-Erling Smørgrav #endif /* HAVE_UTIL_H */ 20989dd127SDag-Erling Smørgrav 211e8db6e2SBrian Feldman #include "sshpty.h" 221e8db6e2SBrian Feldman #include "log.h" 23989dd127SDag-Erling Smørgrav #include "misc.h" 241e8db6e2SBrian Feldman 251e8db6e2SBrian Feldman /* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */ 261e8db6e2SBrian Feldman #if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY) 271e8db6e2SBrian Feldman #undef HAVE_DEV_PTMX 281e8db6e2SBrian Feldman #endif 291e8db6e2SBrian Feldman 30989dd127SDag-Erling Smørgrav #ifdef HAVE_PTY_H 31989dd127SDag-Erling Smørgrav # include <pty.h> 32989dd127SDag-Erling Smørgrav #endif 33989dd127SDag-Erling Smørgrav #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) 34989dd127SDag-Erling Smørgrav # include <sys/stropts.h> 35989dd127SDag-Erling Smørgrav #endif 36989dd127SDag-Erling Smørgrav 371e8db6e2SBrian Feldman #ifndef O_NOCTTY 381e8db6e2SBrian Feldman #define O_NOCTTY 0 391e8db6e2SBrian Feldman #endif 401e8db6e2SBrian Feldman 411e8db6e2SBrian Feldman /* 421e8db6e2SBrian Feldman * Allocates and opens a pty. Returns 0 if no pty could be allocated, or 431e8db6e2SBrian Feldman * nonzero if a pty was successfully allocated. On success, open file 441e8db6e2SBrian Feldman * descriptors for the pty and tty sides and the name of the tty side are 451e8db6e2SBrian Feldman * returned (the buffer must be able to hold at least 64 characters). 461e8db6e2SBrian Feldman */ 471e8db6e2SBrian Feldman 481e8db6e2SBrian Feldman int 491e8db6e2SBrian Feldman pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) 501e8db6e2SBrian Feldman { 511e8db6e2SBrian Feldman #if defined(HAVE_OPENPTY) || defined(BSD4_4) 521e8db6e2SBrian Feldman /* openpty(3) exists in OSF/1 and some other os'es */ 53989dd127SDag-Erling Smørgrav char *name; 541e8db6e2SBrian Feldman int i; 551e8db6e2SBrian Feldman 56989dd127SDag-Erling Smørgrav i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); 571e8db6e2SBrian Feldman if (i < 0) { 581e8db6e2SBrian Feldman error("openpty: %.100s", strerror(errno)); 591e8db6e2SBrian Feldman return 0; 601e8db6e2SBrian Feldman } 61989dd127SDag-Erling Smørgrav name = ttyname(*ttyfd); 62989dd127SDag-Erling Smørgrav if (!name) 63989dd127SDag-Erling Smørgrav fatal("openpty returns device for which ttyname fails."); 64989dd127SDag-Erling Smørgrav 65989dd127SDag-Erling Smørgrav strlcpy(namebuf, name, namebuflen); /* possible truncation */ 661e8db6e2SBrian Feldman return 1; 671e8db6e2SBrian Feldman #else /* HAVE_OPENPTY */ 681e8db6e2SBrian Feldman #ifdef HAVE__GETPTY 691e8db6e2SBrian Feldman /* 701e8db6e2SBrian Feldman * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more 711e8db6e2SBrian Feldman * pty's automagically when needed 721e8db6e2SBrian Feldman */ 731e8db6e2SBrian Feldman char *slave; 741e8db6e2SBrian Feldman 751e8db6e2SBrian Feldman slave = _getpty(ptyfd, O_RDWR, 0622, 0); 761e8db6e2SBrian Feldman if (slave == NULL) { 771e8db6e2SBrian Feldman error("_getpty: %.100s", strerror(errno)); 781e8db6e2SBrian Feldman return 0; 791e8db6e2SBrian Feldman } 801e8db6e2SBrian Feldman strlcpy(namebuf, slave, namebuflen); 811e8db6e2SBrian Feldman /* Open the slave side. */ 821e8db6e2SBrian Feldman *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); 831e8db6e2SBrian Feldman if (*ttyfd < 0) { 841e8db6e2SBrian Feldman error("%.200s: %.100s", namebuf, strerror(errno)); 851e8db6e2SBrian Feldman close(*ptyfd); 861e8db6e2SBrian Feldman return 0; 871e8db6e2SBrian Feldman } 881e8db6e2SBrian Feldman return 1; 891e8db6e2SBrian Feldman #else /* HAVE__GETPTY */ 90989dd127SDag-Erling Smørgrav #if defined(HAVE_DEV_PTMX) 911e8db6e2SBrian Feldman /* 921e8db6e2SBrian Feldman * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 931e8db6e2SBrian Feldman * also has bsd-style ptys, but they simply do not work.) 941e8db6e2SBrian Feldman */ 951e8db6e2SBrian Feldman int ptm; 961e8db6e2SBrian Feldman char *pts; 97989dd127SDag-Erling Smørgrav mysig_t old_signal; 981e8db6e2SBrian Feldman 991e8db6e2SBrian Feldman ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); 1001e8db6e2SBrian Feldman if (ptm < 0) { 1011e8db6e2SBrian Feldman error("/dev/ptmx: %.100s", strerror(errno)); 1021e8db6e2SBrian Feldman return 0; 1031e8db6e2SBrian Feldman } 104cf2b5f3bSDag-Erling Smørgrav old_signal = signal(SIGCHLD, SIG_DFL); 1051e8db6e2SBrian Feldman if (grantpt(ptm) < 0) { 1061e8db6e2SBrian Feldman error("grantpt: %.100s", strerror(errno)); 1071e8db6e2SBrian Feldman return 0; 1081e8db6e2SBrian Feldman } 109cf2b5f3bSDag-Erling Smørgrav signal(SIGCHLD, old_signal); 1101e8db6e2SBrian Feldman if (unlockpt(ptm) < 0) { 1111e8db6e2SBrian Feldman error("unlockpt: %.100s", strerror(errno)); 1121e8db6e2SBrian Feldman return 0; 1131e8db6e2SBrian Feldman } 1141e8db6e2SBrian Feldman pts = ptsname(ptm); 1151e8db6e2SBrian Feldman if (pts == NULL) 1161e8db6e2SBrian Feldman error("Slave pty side name could not be obtained."); 1171e8db6e2SBrian Feldman strlcpy(namebuf, pts, namebuflen); 1181e8db6e2SBrian Feldman *ptyfd = ptm; 1191e8db6e2SBrian Feldman 1201e8db6e2SBrian Feldman /* Open the slave side. */ 1211e8db6e2SBrian Feldman *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); 1221e8db6e2SBrian Feldman if (*ttyfd < 0) { 1231e8db6e2SBrian Feldman error("%.100s: %.100s", namebuf, strerror(errno)); 1241e8db6e2SBrian Feldman close(*ptyfd); 1251e8db6e2SBrian Feldman return 0; 1261e8db6e2SBrian Feldman } 127989dd127SDag-Erling Smørgrav #ifndef HAVE_CYGWIN 128989dd127SDag-Erling Smørgrav /* 129989dd127SDag-Erling Smørgrav * Push the appropriate streams modules, as described in Solaris pts(7). 130989dd127SDag-Erling Smørgrav * HP-UX pts(7) doesn't have ttcompat module. 131989dd127SDag-Erling Smørgrav */ 1321e8db6e2SBrian Feldman if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) 1331e8db6e2SBrian Feldman error("ioctl I_PUSH ptem: %.100s", strerror(errno)); 1341e8db6e2SBrian Feldman if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) 1351e8db6e2SBrian Feldman error("ioctl I_PUSH ldterm: %.100s", strerror(errno)); 136989dd127SDag-Erling Smørgrav #ifndef __hpux 1371e8db6e2SBrian Feldman if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) 1381e8db6e2SBrian Feldman error("ioctl I_PUSH ttcompat: %.100s", strerror(errno)); 139989dd127SDag-Erling Smørgrav #endif 140989dd127SDag-Erling Smørgrav #endif 1411e8db6e2SBrian Feldman return 1; 1421e8db6e2SBrian Feldman #else /* HAVE_DEV_PTMX */ 1431e8db6e2SBrian Feldman #ifdef HAVE_DEV_PTS_AND_PTC 1441e8db6e2SBrian Feldman /* AIX-style pty code. */ 1451e8db6e2SBrian Feldman const char *name; 1461e8db6e2SBrian Feldman 1471e8db6e2SBrian Feldman *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY); 1481e8db6e2SBrian Feldman if (*ptyfd < 0) { 1491e8db6e2SBrian Feldman error("Could not open /dev/ptc: %.100s", strerror(errno)); 1501e8db6e2SBrian Feldman return 0; 1511e8db6e2SBrian Feldman } 1521e8db6e2SBrian Feldman name = ttyname(*ptyfd); 1531e8db6e2SBrian Feldman if (!name) 1541e8db6e2SBrian Feldman fatal("Open of /dev/ptc returns device for which ttyname fails."); 1551e8db6e2SBrian Feldman strlcpy(namebuf, name, namebuflen); 1561e8db6e2SBrian Feldman *ttyfd = open(name, O_RDWR | O_NOCTTY); 1571e8db6e2SBrian Feldman if (*ttyfd < 0) { 1581e8db6e2SBrian Feldman error("Could not open pty slave side %.100s: %.100s", 1591e8db6e2SBrian Feldman name, strerror(errno)); 1601e8db6e2SBrian Feldman close(*ptyfd); 1611e8db6e2SBrian Feldman return 0; 1621e8db6e2SBrian Feldman } 1631e8db6e2SBrian Feldman return 1; 1641e8db6e2SBrian Feldman #else /* HAVE_DEV_PTS_AND_PTC */ 165f388f5efSDag-Erling Smørgrav #ifdef _UNICOS 1661e8db6e2SBrian Feldman char buf[64]; 1671e8db6e2SBrian Feldman int i; 168989dd127SDag-Erling Smørgrav int highpty; 1691e8db6e2SBrian Feldman 170989dd127SDag-Erling Smørgrav #ifdef _SC_CRAY_NPTY 171989dd127SDag-Erling Smørgrav highpty = sysconf(_SC_CRAY_NPTY); 172989dd127SDag-Erling Smørgrav if (highpty == -1) 173989dd127SDag-Erling Smørgrav highpty = 128; 174989dd127SDag-Erling Smørgrav #else 175989dd127SDag-Erling Smørgrav highpty = 128; 176989dd127SDag-Erling Smørgrav #endif 177989dd127SDag-Erling Smørgrav 178989dd127SDag-Erling Smørgrav for (i = 0; i < highpty; i++) { 179989dd127SDag-Erling Smørgrav snprintf(buf, sizeof(buf), "/dev/pty/%03d", i); 1801e8db6e2SBrian Feldman *ptyfd = open(buf, O_RDWR|O_NOCTTY); 1811e8db6e2SBrian Feldman if (*ptyfd < 0) 1821e8db6e2SBrian Feldman continue; 183989dd127SDag-Erling Smørgrav snprintf(namebuf, namebuflen, "/dev/ttyp%03d", i); 1841e8db6e2SBrian Feldman /* Open the slave side. */ 1851e8db6e2SBrian Feldman *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); 1861e8db6e2SBrian Feldman if (*ttyfd < 0) { 1871e8db6e2SBrian Feldman error("%.100s: %.100s", namebuf, strerror(errno)); 1881e8db6e2SBrian Feldman close(*ptyfd); 1891e8db6e2SBrian Feldman return 0; 1901e8db6e2SBrian Feldman } 1911e8db6e2SBrian Feldman return 1; 1921e8db6e2SBrian Feldman } 1931e8db6e2SBrian Feldman return 0; 194989dd127SDag-Erling Smørgrav #else 195989dd127SDag-Erling Smørgrav /* BSD-style pty code. */ 196989dd127SDag-Erling Smørgrav char buf[64]; 197989dd127SDag-Erling Smørgrav int i; 198989dd127SDag-Erling Smørgrav const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; 199989dd127SDag-Erling Smørgrav const char *ptyminors = "0123456789abcdef"; 200989dd127SDag-Erling Smørgrav int num_minors = strlen(ptyminors); 201989dd127SDag-Erling Smørgrav int num_ptys = strlen(ptymajors) * num_minors; 202989dd127SDag-Erling Smørgrav struct termios tio; 203989dd127SDag-Erling Smørgrav 204989dd127SDag-Erling Smørgrav for (i = 0; i < num_ptys; i++) { 205989dd127SDag-Erling Smørgrav snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], 206989dd127SDag-Erling Smørgrav ptyminors[i % num_minors]); 207989dd127SDag-Erling Smørgrav snprintf(namebuf, namebuflen, "/dev/tty%c%c", 208989dd127SDag-Erling Smørgrav ptymajors[i / num_minors], ptyminors[i % num_minors]); 209989dd127SDag-Erling Smørgrav 210989dd127SDag-Erling Smørgrav *ptyfd = open(buf, O_RDWR | O_NOCTTY); 211989dd127SDag-Erling Smørgrav if (*ptyfd < 0) { 212989dd127SDag-Erling Smørgrav /* Try SCO style naming */ 213989dd127SDag-Erling Smørgrav snprintf(buf, sizeof buf, "/dev/ptyp%d", i); 214989dd127SDag-Erling Smørgrav snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); 215989dd127SDag-Erling Smørgrav *ptyfd = open(buf, O_RDWR | O_NOCTTY); 216989dd127SDag-Erling Smørgrav if (*ptyfd < 0) 217989dd127SDag-Erling Smørgrav continue; 218989dd127SDag-Erling Smørgrav } 219989dd127SDag-Erling Smørgrav 220989dd127SDag-Erling Smørgrav /* Open the slave side. */ 221989dd127SDag-Erling Smørgrav *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); 222989dd127SDag-Erling Smørgrav if (*ttyfd < 0) { 223989dd127SDag-Erling Smørgrav error("%.100s: %.100s", namebuf, strerror(errno)); 224989dd127SDag-Erling Smørgrav close(*ptyfd); 225989dd127SDag-Erling Smørgrav return 0; 226989dd127SDag-Erling Smørgrav } 227989dd127SDag-Erling Smørgrav /* set tty modes to a sane state for broken clients */ 228989dd127SDag-Erling Smørgrav if (tcgetattr(*ptyfd, &tio) < 0) 229cf2b5f3bSDag-Erling Smørgrav logit("Getting tty modes for pty failed: %.100s", strerror(errno)); 230989dd127SDag-Erling Smørgrav else { 231989dd127SDag-Erling Smørgrav tio.c_lflag |= (ECHO | ISIG | ICANON); 232989dd127SDag-Erling Smørgrav tio.c_oflag |= (OPOST | ONLCR); 233989dd127SDag-Erling Smørgrav tio.c_iflag |= ICRNL; 234989dd127SDag-Erling Smørgrav 235989dd127SDag-Erling Smørgrav /* Set the new modes for the terminal. */ 236989dd127SDag-Erling Smørgrav if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) 237cf2b5f3bSDag-Erling Smørgrav logit("Setting tty modes for pty failed: %.100s", strerror(errno)); 238989dd127SDag-Erling Smørgrav } 239989dd127SDag-Erling Smørgrav 240989dd127SDag-Erling Smørgrav return 1; 241989dd127SDag-Erling Smørgrav } 242989dd127SDag-Erling Smørgrav return 0; 243989dd127SDag-Erling Smørgrav #endif /* CRAY */ 2441e8db6e2SBrian Feldman #endif /* HAVE_DEV_PTS_AND_PTC */ 2451e8db6e2SBrian Feldman #endif /* HAVE_DEV_PTMX */ 2461e8db6e2SBrian Feldman #endif /* HAVE__GETPTY */ 2471e8db6e2SBrian Feldman #endif /* HAVE_OPENPTY */ 2481e8db6e2SBrian Feldman } 2491e8db6e2SBrian Feldman 2501e8db6e2SBrian Feldman /* Releases the tty. Its ownership is returned to root, and permissions to 0666. */ 2511e8db6e2SBrian Feldman 2521e8db6e2SBrian Feldman void 2531e8db6e2SBrian Feldman pty_release(const char *ttyname) 2541e8db6e2SBrian Feldman { 2551e8db6e2SBrian Feldman if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0) 2561e8db6e2SBrian Feldman error("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno)); 2571e8db6e2SBrian Feldman if (chmod(ttyname, (mode_t) 0666) < 0) 2581e8db6e2SBrian Feldman error("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno)); 2591e8db6e2SBrian Feldman } 2601e8db6e2SBrian Feldman 261cf2b5f3bSDag-Erling Smørgrav /* Makes the tty the process's controlling tty and sets it to sane modes. */ 2621e8db6e2SBrian Feldman 2631e8db6e2SBrian Feldman void 2641e8db6e2SBrian Feldman pty_make_controlling_tty(int *ttyfd, const char *ttyname) 2651e8db6e2SBrian Feldman { 2661e8db6e2SBrian Feldman int fd; 267989dd127SDag-Erling Smørgrav #ifdef USE_VHANGUP 268989dd127SDag-Erling Smørgrav void *old; 269989dd127SDag-Erling Smørgrav #endif /* USE_VHANGUP */ 270989dd127SDag-Erling Smørgrav 271f388f5efSDag-Erling Smørgrav #ifdef _UNICOS 272989dd127SDag-Erling Smørgrav if (setsid() < 0) 273989dd127SDag-Erling Smørgrav error("setsid: %.100s", strerror(errno)); 274989dd127SDag-Erling Smørgrav 275989dd127SDag-Erling Smørgrav fd = open(ttyname, O_RDWR|O_NOCTTY); 276989dd127SDag-Erling Smørgrav if (fd != -1) { 277cf2b5f3bSDag-Erling Smørgrav signal(SIGHUP, SIG_IGN); 278989dd127SDag-Erling Smørgrav ioctl(fd, TCVHUP, (char *)NULL); 279cf2b5f3bSDag-Erling Smørgrav signal(SIGHUP, SIG_DFL); 280989dd127SDag-Erling Smørgrav setpgid(0, 0); 281989dd127SDag-Erling Smørgrav close(fd); 282989dd127SDag-Erling Smørgrav } else { 283989dd127SDag-Erling Smørgrav error("Failed to disconnect from controlling tty."); 284989dd127SDag-Erling Smørgrav } 285989dd127SDag-Erling Smørgrav 286989dd127SDag-Erling Smørgrav debug("Setting controlling tty using TCSETCTTY."); 287989dd127SDag-Erling Smørgrav ioctl(*ttyfd, TCSETCTTY, NULL); 288989dd127SDag-Erling Smørgrav fd = open("/dev/tty", O_RDWR); 289989dd127SDag-Erling Smørgrav if (fd < 0) 290989dd127SDag-Erling Smørgrav error("%.100s: %.100s", ttyname, strerror(errno)); 291989dd127SDag-Erling Smørgrav close(*ttyfd); 292989dd127SDag-Erling Smørgrav *ttyfd = fd; 293f388f5efSDag-Erling Smørgrav #else /* _UNICOS */ 2941e8db6e2SBrian Feldman 2951e8db6e2SBrian Feldman /* First disconnect from the old controlling tty. */ 2961e8db6e2SBrian Feldman #ifdef TIOCNOTTY 2971e8db6e2SBrian Feldman fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); 2981e8db6e2SBrian Feldman if (fd >= 0) { 2991e8db6e2SBrian Feldman (void) ioctl(fd, TIOCNOTTY, NULL); 3001e8db6e2SBrian Feldman close(fd); 3011e8db6e2SBrian Feldman } 3021e8db6e2SBrian Feldman #endif /* TIOCNOTTY */ 3031e8db6e2SBrian Feldman if (setsid() < 0) 3041e8db6e2SBrian Feldman error("setsid: %.100s", strerror(errno)); 3051e8db6e2SBrian Feldman 3061e8db6e2SBrian Feldman /* 3071e8db6e2SBrian Feldman * Verify that we are successfully disconnected from the controlling 3081e8db6e2SBrian Feldman * tty. 3091e8db6e2SBrian Feldman */ 3101e8db6e2SBrian Feldman fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); 3111e8db6e2SBrian Feldman if (fd >= 0) { 3121e8db6e2SBrian Feldman error("Failed to disconnect from controlling tty."); 3131e8db6e2SBrian Feldman close(fd); 3141e8db6e2SBrian Feldman } 3151e8db6e2SBrian Feldman /* Make it our controlling tty. */ 3161e8db6e2SBrian Feldman #ifdef TIOCSCTTY 3171e8db6e2SBrian Feldman debug("Setting controlling tty using TIOCSCTTY."); 3181e8db6e2SBrian Feldman if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) 3191e8db6e2SBrian Feldman error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); 3201e8db6e2SBrian Feldman #endif /* TIOCSCTTY */ 321989dd127SDag-Erling Smørgrav #ifdef HAVE_NEWS4 322989dd127SDag-Erling Smørgrav if (setpgrp(0,0) < 0) 323989dd127SDag-Erling Smørgrav error("SETPGRP %s",strerror(errno)); 324989dd127SDag-Erling Smørgrav #endif /* HAVE_NEWS4 */ 325989dd127SDag-Erling Smørgrav #ifdef USE_VHANGUP 326cf2b5f3bSDag-Erling Smørgrav old = signal(SIGHUP, SIG_IGN); 327989dd127SDag-Erling Smørgrav vhangup(); 328cf2b5f3bSDag-Erling Smørgrav signal(SIGHUP, old); 329989dd127SDag-Erling Smørgrav #endif /* USE_VHANGUP */ 3301e8db6e2SBrian Feldman fd = open(ttyname, O_RDWR); 331989dd127SDag-Erling Smørgrav if (fd < 0) { 3321e8db6e2SBrian Feldman error("%.100s: %.100s", ttyname, strerror(errno)); 333989dd127SDag-Erling Smørgrav } else { 334989dd127SDag-Erling Smørgrav #ifdef USE_VHANGUP 335989dd127SDag-Erling Smørgrav close(*ttyfd); 336989dd127SDag-Erling Smørgrav *ttyfd = fd; 337989dd127SDag-Erling Smørgrav #else /* USE_VHANGUP */ 3381e8db6e2SBrian Feldman close(fd); 339989dd127SDag-Erling Smørgrav #endif /* USE_VHANGUP */ 340989dd127SDag-Erling Smørgrav } 3411e8db6e2SBrian Feldman /* Verify that we now have a controlling tty. */ 3421e8db6e2SBrian Feldman fd = open(_PATH_TTY, O_WRONLY); 3431e8db6e2SBrian Feldman if (fd < 0) 3441e8db6e2SBrian Feldman error("open /dev/tty failed - could not set controlling tty: %.100s", 3451e8db6e2SBrian Feldman strerror(errno)); 346a82e551fSDag-Erling Smørgrav else 3471e8db6e2SBrian Feldman close(fd); 348f388f5efSDag-Erling Smørgrav #endif /* _UNICOS */ 3491e8db6e2SBrian Feldman } 3501e8db6e2SBrian Feldman 3511e8db6e2SBrian Feldman /* Changes the window size associated with the pty. */ 3521e8db6e2SBrian Feldman 3531e8db6e2SBrian Feldman void 3541e8db6e2SBrian Feldman pty_change_window_size(int ptyfd, int row, int col, 3551e8db6e2SBrian Feldman int xpixel, int ypixel) 3561e8db6e2SBrian Feldman { 3571e8db6e2SBrian Feldman struct winsize w; 358a82e551fSDag-Erling Smørgrav 3591e8db6e2SBrian Feldman w.ws_row = row; 3601e8db6e2SBrian Feldman w.ws_col = col; 3611e8db6e2SBrian Feldman w.ws_xpixel = xpixel; 3621e8db6e2SBrian Feldman w.ws_ypixel = ypixel; 3631e8db6e2SBrian Feldman (void) ioctl(ptyfd, TIOCSWINSZ, &w); 3641e8db6e2SBrian Feldman } 3651e8db6e2SBrian Feldman 3661e8db6e2SBrian Feldman void 3671e8db6e2SBrian Feldman pty_setowner(struct passwd *pw, const char *ttyname) 3681e8db6e2SBrian Feldman { 3691e8db6e2SBrian Feldman struct group *grp; 3701e8db6e2SBrian Feldman gid_t gid; 3711e8db6e2SBrian Feldman mode_t mode; 3721e8db6e2SBrian Feldman struct stat st; 3731e8db6e2SBrian Feldman 3741e8db6e2SBrian Feldman /* Determine the group to make the owner of the tty. */ 3751e8db6e2SBrian Feldman grp = getgrnam("tty"); 3761e8db6e2SBrian Feldman if (grp) { 3771e8db6e2SBrian Feldman gid = grp->gr_gid; 3781e8db6e2SBrian Feldman mode = S_IRUSR | S_IWUSR | S_IWGRP; 3791e8db6e2SBrian Feldman } else { 3801e8db6e2SBrian Feldman gid = pw->pw_gid; 3811e8db6e2SBrian Feldman mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH; 3821e8db6e2SBrian Feldman } 3831e8db6e2SBrian Feldman 3841e8db6e2SBrian Feldman /* 3851e8db6e2SBrian Feldman * Change owner and mode of the tty as required. 386af12a3e7SDag-Erling Smørgrav * Warn but continue if filesystem is read-only and the uids match/ 387af12a3e7SDag-Erling Smørgrav * tty is owned by root. 3881e8db6e2SBrian Feldman */ 3891e8db6e2SBrian Feldman if (stat(ttyname, &st)) 3901e8db6e2SBrian Feldman fatal("stat(%.100s) failed: %.100s", ttyname, 3911e8db6e2SBrian Feldman strerror(errno)); 3921e8db6e2SBrian Feldman 3931e8db6e2SBrian Feldman if (st.st_uid != pw->pw_uid || st.st_gid != gid) { 3941e8db6e2SBrian Feldman if (chown(ttyname, pw->pw_uid, gid) < 0) { 395af12a3e7SDag-Erling Smørgrav if (errno == EROFS && 396af12a3e7SDag-Erling Smørgrav (st.st_uid == pw->pw_uid || st.st_uid == 0)) 397e73e9afaSDag-Erling Smørgrav debug("chown(%.100s, %u, %u) failed: %.100s", 398a82e551fSDag-Erling Smørgrav ttyname, (u_int)pw->pw_uid, (u_int)gid, 3991e8db6e2SBrian Feldman strerror(errno)); 4001e8db6e2SBrian Feldman else 401a82e551fSDag-Erling Smørgrav fatal("chown(%.100s, %u, %u) failed: %.100s", 402a82e551fSDag-Erling Smørgrav ttyname, (u_int)pw->pw_uid, (u_int)gid, 4031e8db6e2SBrian Feldman strerror(errno)); 4041e8db6e2SBrian Feldman } 4051e8db6e2SBrian Feldman } 4061e8db6e2SBrian Feldman 4071e8db6e2SBrian Feldman if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) { 4081e8db6e2SBrian Feldman if (chmod(ttyname, mode) < 0) { 4091e8db6e2SBrian Feldman if (errno == EROFS && 4101e8db6e2SBrian Feldman (st.st_mode & (S_IRGRP | S_IROTH)) == 0) 411e73e9afaSDag-Erling Smørgrav debug("chmod(%.100s, 0%o) failed: %.100s", 412cf2b5f3bSDag-Erling Smørgrav ttyname, (u_int)mode, strerror(errno)); 4131e8db6e2SBrian Feldman else 4141e8db6e2SBrian Feldman fatal("chmod(%.100s, 0%o) failed: %.100s", 415cf2b5f3bSDag-Erling Smørgrav ttyname, (u_int)mode, strerror(errno)); 4161e8db6e2SBrian Feldman } 4171e8db6e2SBrian Feldman } 4181e8db6e2SBrian Feldman } 419