1efcad6b7SDag-Erling Smørgrav /* 2efcad6b7SDag-Erling Smørgrav * Please note: this implementation of openpty() is far from complete. 3efcad6b7SDag-Erling Smørgrav * it is just enough for portable OpenSSH's needs. 4efcad6b7SDag-Erling Smørgrav */ 5efcad6b7SDag-Erling Smørgrav 6efcad6b7SDag-Erling Smørgrav /* 7efcad6b7SDag-Erling Smørgrav * Copyright (c) 2004 Damien Miller <djm@mindrot.org> 8efcad6b7SDag-Erling Smørgrav * 9efcad6b7SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 10efcad6b7SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 11efcad6b7SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 12efcad6b7SDag-Erling Smørgrav * 13efcad6b7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14efcad6b7SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15efcad6b7SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16efcad6b7SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17efcad6b7SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18efcad6b7SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19efcad6b7SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20efcad6b7SDag-Erling Smørgrav */ 21efcad6b7SDag-Erling Smørgrav 22efcad6b7SDag-Erling Smørgrav /* 23efcad6b7SDag-Erling Smørgrav * Author: Tatu Ylonen <ylo@cs.hut.fi> 24efcad6b7SDag-Erling Smørgrav * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 25efcad6b7SDag-Erling Smørgrav * All rights reserved 26efcad6b7SDag-Erling Smørgrav * Allocating a pseudo-terminal, and making it the controlling tty. 27efcad6b7SDag-Erling Smørgrav * 28efcad6b7SDag-Erling Smørgrav * As far as I am concerned, the code I have written for this software 29efcad6b7SDag-Erling Smørgrav * can be used freely for any purpose. Any derived versions of this 30efcad6b7SDag-Erling Smørgrav * software must be clearly marked as such, and if the derived work is 31efcad6b7SDag-Erling Smørgrav * incompatible with the protocol description in the RFC file, it must be 32efcad6b7SDag-Erling Smørgrav * called by a name other than "ssh" or "Secure Shell". 33efcad6b7SDag-Erling Smørgrav */ 34efcad6b7SDag-Erling Smørgrav 35efcad6b7SDag-Erling Smørgrav #include "includes.h" 36efcad6b7SDag-Erling Smørgrav #if !defined(HAVE_OPENPTY) 37efcad6b7SDag-Erling Smørgrav 38761efaa7SDag-Erling Smørgrav #include <sys/types.h> 39761efaa7SDag-Erling Smørgrav 40761efaa7SDag-Erling Smørgrav #include <stdlib.h> 41761efaa7SDag-Erling Smørgrav 42761efaa7SDag-Erling Smørgrav #ifdef HAVE_SYS_STAT_H 43761efaa7SDag-Erling Smørgrav # include <sys/stat.h> 44761efaa7SDag-Erling Smørgrav #endif 45761efaa7SDag-Erling Smørgrav #ifdef HAVE_SYS_IOCTL_H 46761efaa7SDag-Erling Smørgrav # include <sys/ioctl.h> 47761efaa7SDag-Erling Smørgrav #endif 48761efaa7SDag-Erling Smørgrav 49761efaa7SDag-Erling Smørgrav #ifdef HAVE_FCNTL_H 50761efaa7SDag-Erling Smørgrav # include <fcntl.h> 51761efaa7SDag-Erling Smørgrav #endif 52761efaa7SDag-Erling Smørgrav 53efcad6b7SDag-Erling Smørgrav #ifdef HAVE_UTIL_H 54efcad6b7SDag-Erling Smørgrav # include <util.h> 55efcad6b7SDag-Erling Smørgrav #endif /* HAVE_UTIL_H */ 56efcad6b7SDag-Erling Smørgrav 57efcad6b7SDag-Erling Smørgrav #ifdef HAVE_PTY_H 58efcad6b7SDag-Erling Smørgrav # include <pty.h> 59efcad6b7SDag-Erling Smørgrav #endif 60efcad6b7SDag-Erling Smørgrav #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) 61efcad6b7SDag-Erling Smørgrav # include <sys/stropts.h> 62efcad6b7SDag-Erling Smørgrav #endif 63efcad6b7SDag-Erling Smørgrav 64761efaa7SDag-Erling Smørgrav #include <signal.h> 65761efaa7SDag-Erling Smørgrav #include <string.h> 66761efaa7SDag-Erling Smørgrav #include <unistd.h> 67761efaa7SDag-Erling Smørgrav 68efcad6b7SDag-Erling Smørgrav #ifndef O_NOCTTY 69efcad6b7SDag-Erling Smørgrav #define O_NOCTTY 0 70efcad6b7SDag-Erling Smørgrav #endif 71efcad6b7SDag-Erling Smørgrav 72efcad6b7SDag-Erling Smørgrav int 73efcad6b7SDag-Erling Smørgrav openpty(int *amaster, int *aslave, char *name, struct termios *termp, 74efcad6b7SDag-Erling Smørgrav struct winsize *winp) 75efcad6b7SDag-Erling Smørgrav { 76efcad6b7SDag-Erling Smørgrav #if defined(HAVE__GETPTY) 77efcad6b7SDag-Erling Smørgrav /* 78efcad6b7SDag-Erling Smørgrav * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more 79efcad6b7SDag-Erling Smørgrav * pty's automagically when needed 80efcad6b7SDag-Erling Smørgrav */ 81efcad6b7SDag-Erling Smørgrav char *slave; 82efcad6b7SDag-Erling Smørgrav 83efcad6b7SDag-Erling Smørgrav if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) 84efcad6b7SDag-Erling Smørgrav return (-1); 85efcad6b7SDag-Erling Smørgrav 86efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 87efcad6b7SDag-Erling Smørgrav if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { 88efcad6b7SDag-Erling Smørgrav close(*amaster); 89efcad6b7SDag-Erling Smørgrav return (-1); 90efcad6b7SDag-Erling Smørgrav } 91efcad6b7SDag-Erling Smørgrav return (0); 92efcad6b7SDag-Erling Smørgrav 93efcad6b7SDag-Erling Smørgrav #elif defined(HAVE_DEV_PTMX) 94efcad6b7SDag-Erling Smørgrav /* 95efcad6b7SDag-Erling Smørgrav * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 96efcad6b7SDag-Erling Smørgrav * also has bsd-style ptys, but they simply do not work.) 97efcad6b7SDag-Erling Smørgrav */ 98efcad6b7SDag-Erling Smørgrav int ptm; 99efcad6b7SDag-Erling Smørgrav char *pts; 100efcad6b7SDag-Erling Smørgrav mysig_t old_signal; 101efcad6b7SDag-Erling Smørgrav 102efcad6b7SDag-Erling Smørgrav if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) 103efcad6b7SDag-Erling Smørgrav return (-1); 104efcad6b7SDag-Erling Smørgrav 105efcad6b7SDag-Erling Smørgrav /* XXX: need to close ptm on error? */ 106efcad6b7SDag-Erling Smørgrav old_signal = signal(SIGCHLD, SIG_DFL); 107efcad6b7SDag-Erling Smørgrav if (grantpt(ptm) < 0) 108efcad6b7SDag-Erling Smørgrav return (-1); 109efcad6b7SDag-Erling Smørgrav signal(SIGCHLD, old_signal); 110efcad6b7SDag-Erling Smørgrav 111efcad6b7SDag-Erling Smørgrav if (unlockpt(ptm) < 0) 112efcad6b7SDag-Erling Smørgrav return (-1); 113efcad6b7SDag-Erling Smørgrav 114efcad6b7SDag-Erling Smørgrav if ((pts = ptsname(ptm)) == NULL) 115efcad6b7SDag-Erling Smørgrav return (-1); 116efcad6b7SDag-Erling Smørgrav *amaster = ptm; 117efcad6b7SDag-Erling Smørgrav 118efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 119efcad6b7SDag-Erling Smørgrav if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { 120efcad6b7SDag-Erling Smørgrav close(*amaster); 121efcad6b7SDag-Erling Smørgrav return (-1); 122efcad6b7SDag-Erling Smørgrav } 123efcad6b7SDag-Erling Smørgrav 124efcad6b7SDag-Erling Smørgrav /* 125efcad6b7SDag-Erling Smørgrav * Try to push the appropriate streams modules, as described 126efcad6b7SDag-Erling Smørgrav * in Solaris pts(7). 127efcad6b7SDag-Erling Smørgrav */ 128efcad6b7SDag-Erling Smørgrav ioctl(*aslave, I_PUSH, "ptem"); 129efcad6b7SDag-Erling Smørgrav ioctl(*aslave, I_PUSH, "ldterm"); 130efcad6b7SDag-Erling Smørgrav # ifndef __hpux 131efcad6b7SDag-Erling Smørgrav ioctl(*aslave, I_PUSH, "ttcompat"); 132efcad6b7SDag-Erling Smørgrav # endif /* __hpux */ 133efcad6b7SDag-Erling Smørgrav 134efcad6b7SDag-Erling Smørgrav return (0); 135efcad6b7SDag-Erling Smørgrav 136efcad6b7SDag-Erling Smørgrav #elif defined(HAVE_DEV_PTS_AND_PTC) 137efcad6b7SDag-Erling Smørgrav /* AIX-style pty code. */ 138efcad6b7SDag-Erling Smørgrav const char *ttname; 139efcad6b7SDag-Erling Smørgrav 140efcad6b7SDag-Erling Smørgrav if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) 141efcad6b7SDag-Erling Smørgrav return (-1); 142efcad6b7SDag-Erling Smørgrav if ((ttname = ttyname(*amaster)) == NULL) 143efcad6b7SDag-Erling Smørgrav return (-1); 144efcad6b7SDag-Erling Smørgrav if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { 145efcad6b7SDag-Erling Smørgrav close(*amaster); 146efcad6b7SDag-Erling Smørgrav return (-1); 147efcad6b7SDag-Erling Smørgrav } 148efcad6b7SDag-Erling Smørgrav return (0); 149efcad6b7SDag-Erling Smørgrav 150efcad6b7SDag-Erling Smørgrav #elif defined(_UNICOS) 151efcad6b7SDag-Erling Smørgrav char ptbuf[64], ttbuf[64]; 152efcad6b7SDag-Erling Smørgrav int i; 153efcad6b7SDag-Erling Smørgrav int highpty; 154efcad6b7SDag-Erling Smørgrav 155efcad6b7SDag-Erling Smørgrav highpty = 128; 156efcad6b7SDag-Erling Smørgrav #ifdef _SC_CRAY_NPTY 157efcad6b7SDag-Erling Smørgrav if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1) 158efcad6b7SDag-Erling Smørgrav highpty = 128; 159efcad6b7SDag-Erling Smørgrav #endif /* _SC_CRAY_NPTY */ 160efcad6b7SDag-Erling Smørgrav 161efcad6b7SDag-Erling Smørgrav for (i = 0; i < highpty; i++) { 162efcad6b7SDag-Erling Smørgrav snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i); 163efcad6b7SDag-Erling Smørgrav snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i); 164efcad6b7SDag-Erling Smørgrav if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1) 165efcad6b7SDag-Erling Smørgrav continue; 166efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 167efcad6b7SDag-Erling Smørgrav if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) { 168efcad6b7SDag-Erling Smørgrav close(*amaster); 169efcad6b7SDag-Erling Smørgrav return (-1); 170efcad6b7SDag-Erling Smørgrav } 171efcad6b7SDag-Erling Smørgrav return (0); 172efcad6b7SDag-Erling Smørgrav } 173efcad6b7SDag-Erling Smørgrav return (-1); 174efcad6b7SDag-Erling Smørgrav 175efcad6b7SDag-Erling Smørgrav #else 176efcad6b7SDag-Erling Smørgrav /* BSD-style pty code. */ 177efcad6b7SDag-Erling Smørgrav char ptbuf[64], ttbuf[64]; 178efcad6b7SDag-Erling Smørgrav int i; 179efcad6b7SDag-Erling Smørgrav const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" 180efcad6b7SDag-Erling Smørgrav "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 181efcad6b7SDag-Erling Smørgrav const char *ptyminors = "0123456789abcdef"; 182efcad6b7SDag-Erling Smørgrav int num_minors = strlen(ptyminors); 183efcad6b7SDag-Erling Smørgrav int num_ptys = strlen(ptymajors) * num_minors; 184efcad6b7SDag-Erling Smørgrav struct termios tio; 185efcad6b7SDag-Erling Smørgrav 186efcad6b7SDag-Erling Smørgrav for (i = 0; i < num_ptys; i++) { 187efcad6b7SDag-Erling Smørgrav snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", 188efcad6b7SDag-Erling Smørgrav ptymajors[i / num_minors], ptyminors[i % num_minors]); 189efcad6b7SDag-Erling Smørgrav snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c", 190efcad6b7SDag-Erling Smørgrav ptymajors[i / num_minors], ptyminors[i % num_minors]); 191efcad6b7SDag-Erling Smørgrav 192efcad6b7SDag-Erling Smørgrav if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { 193efcad6b7SDag-Erling Smørgrav /* Try SCO style naming */ 194efcad6b7SDag-Erling Smørgrav snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); 195efcad6b7SDag-Erling Smørgrav snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i); 196efcad6b7SDag-Erling Smørgrav if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) 197efcad6b7SDag-Erling Smørgrav continue; 198efcad6b7SDag-Erling Smørgrav } 199efcad6b7SDag-Erling Smørgrav 200efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 201efcad6b7SDag-Erling Smørgrav if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) { 202efcad6b7SDag-Erling Smørgrav close(*amaster); 203efcad6b7SDag-Erling Smørgrav return (-1); 204efcad6b7SDag-Erling Smørgrav } 205efcad6b7SDag-Erling Smørgrav /* set tty modes to a sane state for broken clients */ 206efcad6b7SDag-Erling Smørgrav if (tcgetattr(*amaster, &tio) != -1) { 207efcad6b7SDag-Erling Smørgrav tio.c_lflag |= (ECHO | ISIG | ICANON); 208efcad6b7SDag-Erling Smørgrav tio.c_oflag |= (OPOST | ONLCR); 209efcad6b7SDag-Erling Smørgrav tio.c_iflag |= ICRNL; 210efcad6b7SDag-Erling Smørgrav tcsetattr(*amaster, TCSANOW, &tio); 211efcad6b7SDag-Erling Smørgrav } 212efcad6b7SDag-Erling Smørgrav 213efcad6b7SDag-Erling Smørgrav return (0); 214efcad6b7SDag-Erling Smørgrav } 215efcad6b7SDag-Erling Smørgrav return (-1); 216efcad6b7SDag-Erling Smørgrav #endif 217efcad6b7SDag-Erling Smørgrav } 218efcad6b7SDag-Erling Smørgrav 219efcad6b7SDag-Erling Smørgrav #endif /* !defined(HAVE_OPENPTY) */ 220efcad6b7SDag-Erling Smørgrav 221