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 38efcad6b7SDag-Erling Smørgrav #ifdef HAVE_UTIL_H 39efcad6b7SDag-Erling Smørgrav # include <util.h> 40efcad6b7SDag-Erling Smørgrav #endif /* HAVE_UTIL_H */ 41efcad6b7SDag-Erling Smørgrav 42efcad6b7SDag-Erling Smørgrav #ifdef HAVE_PTY_H 43efcad6b7SDag-Erling Smørgrav # include <pty.h> 44efcad6b7SDag-Erling Smørgrav #endif 45efcad6b7SDag-Erling Smørgrav #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H) 46efcad6b7SDag-Erling Smørgrav # include <sys/stropts.h> 47efcad6b7SDag-Erling Smørgrav #endif 48efcad6b7SDag-Erling Smørgrav 49efcad6b7SDag-Erling Smørgrav #ifndef O_NOCTTY 50efcad6b7SDag-Erling Smørgrav #define O_NOCTTY 0 51efcad6b7SDag-Erling Smørgrav #endif 52efcad6b7SDag-Erling Smørgrav 53efcad6b7SDag-Erling Smørgrav int 54efcad6b7SDag-Erling Smørgrav openpty(int *amaster, int *aslave, char *name, struct termios *termp, 55efcad6b7SDag-Erling Smørgrav struct winsize *winp) 56efcad6b7SDag-Erling Smørgrav { 57efcad6b7SDag-Erling Smørgrav #if defined(HAVE__GETPTY) 58efcad6b7SDag-Erling Smørgrav /* 59efcad6b7SDag-Erling Smørgrav * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more 60efcad6b7SDag-Erling Smørgrav * pty's automagically when needed 61efcad6b7SDag-Erling Smørgrav */ 62efcad6b7SDag-Erling Smørgrav char *slave; 63efcad6b7SDag-Erling Smørgrav 64efcad6b7SDag-Erling Smørgrav if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) 65efcad6b7SDag-Erling Smørgrav return (-1); 66efcad6b7SDag-Erling Smørgrav 67efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 68efcad6b7SDag-Erling Smørgrav if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { 69efcad6b7SDag-Erling Smørgrav close(*amaster); 70efcad6b7SDag-Erling Smørgrav return (-1); 71efcad6b7SDag-Erling Smørgrav } 72efcad6b7SDag-Erling Smørgrav return (0); 73efcad6b7SDag-Erling Smørgrav 74efcad6b7SDag-Erling Smørgrav #elif defined(HAVE_DEV_PTMX) 75efcad6b7SDag-Erling Smørgrav /* 76efcad6b7SDag-Erling Smørgrav * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 77efcad6b7SDag-Erling Smørgrav * also has bsd-style ptys, but they simply do not work.) 78efcad6b7SDag-Erling Smørgrav */ 79efcad6b7SDag-Erling Smørgrav int ptm; 80efcad6b7SDag-Erling Smørgrav char *pts; 81efcad6b7SDag-Erling Smørgrav mysig_t old_signal; 82efcad6b7SDag-Erling Smørgrav 83efcad6b7SDag-Erling Smørgrav if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) 84efcad6b7SDag-Erling Smørgrav return (-1); 85efcad6b7SDag-Erling Smørgrav 86efcad6b7SDag-Erling Smørgrav /* XXX: need to close ptm on error? */ 87efcad6b7SDag-Erling Smørgrav old_signal = signal(SIGCHLD, SIG_DFL); 88efcad6b7SDag-Erling Smørgrav if (grantpt(ptm) < 0) 89efcad6b7SDag-Erling Smørgrav return (-1); 90efcad6b7SDag-Erling Smørgrav signal(SIGCHLD, old_signal); 91efcad6b7SDag-Erling Smørgrav 92efcad6b7SDag-Erling Smørgrav if (unlockpt(ptm) < 0) 93efcad6b7SDag-Erling Smørgrav return (-1); 94efcad6b7SDag-Erling Smørgrav 95efcad6b7SDag-Erling Smørgrav if ((pts = ptsname(ptm)) == NULL) 96efcad6b7SDag-Erling Smørgrav return (-1); 97efcad6b7SDag-Erling Smørgrav *amaster = ptm; 98efcad6b7SDag-Erling Smørgrav 99efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 100efcad6b7SDag-Erling Smørgrav if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { 101efcad6b7SDag-Erling Smørgrav close(*amaster); 102efcad6b7SDag-Erling Smørgrav return (-1); 103efcad6b7SDag-Erling Smørgrav } 104efcad6b7SDag-Erling Smørgrav 105efcad6b7SDag-Erling Smørgrav #ifndef HAVE_CYGWIN 106efcad6b7SDag-Erling Smørgrav /* 107efcad6b7SDag-Erling Smørgrav * Try to push the appropriate streams modules, as described 108efcad6b7SDag-Erling Smørgrav * in Solaris pts(7). 109efcad6b7SDag-Erling Smørgrav */ 110efcad6b7SDag-Erling Smørgrav ioctl(*aslave, I_PUSH, "ptem"); 111efcad6b7SDag-Erling Smørgrav ioctl(*aslave, I_PUSH, "ldterm"); 112efcad6b7SDag-Erling Smørgrav # ifndef __hpux 113efcad6b7SDag-Erling Smørgrav ioctl(*aslave, I_PUSH, "ttcompat"); 114efcad6b7SDag-Erling Smørgrav # endif /* __hpux */ 115efcad6b7SDag-Erling Smørgrav #endif /* HAVE_CYGWIN */ 116efcad6b7SDag-Erling Smørgrav 117efcad6b7SDag-Erling Smørgrav return (0); 118efcad6b7SDag-Erling Smørgrav 119efcad6b7SDag-Erling Smørgrav #elif defined(HAVE_DEV_PTS_AND_PTC) 120efcad6b7SDag-Erling Smørgrav /* AIX-style pty code. */ 121efcad6b7SDag-Erling Smørgrav const char *ttname; 122efcad6b7SDag-Erling Smørgrav 123efcad6b7SDag-Erling Smørgrav if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) 124efcad6b7SDag-Erling Smørgrav return (-1); 125efcad6b7SDag-Erling Smørgrav if ((ttname = ttyname(*amaster)) == NULL) 126efcad6b7SDag-Erling Smørgrav return (-1); 127efcad6b7SDag-Erling Smørgrav if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { 128efcad6b7SDag-Erling Smørgrav close(*amaster); 129efcad6b7SDag-Erling Smørgrav return (-1); 130efcad6b7SDag-Erling Smørgrav } 131efcad6b7SDag-Erling Smørgrav return (0); 132efcad6b7SDag-Erling Smørgrav 133efcad6b7SDag-Erling Smørgrav #elif defined(_UNICOS) 134efcad6b7SDag-Erling Smørgrav char ptbuf[64], ttbuf[64]; 135efcad6b7SDag-Erling Smørgrav int i; 136efcad6b7SDag-Erling Smørgrav int highpty; 137efcad6b7SDag-Erling Smørgrav 138efcad6b7SDag-Erling Smørgrav highpty = 128; 139efcad6b7SDag-Erling Smørgrav #ifdef _SC_CRAY_NPTY 140efcad6b7SDag-Erling Smørgrav if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1) 141efcad6b7SDag-Erling Smørgrav highpty = 128; 142efcad6b7SDag-Erling Smørgrav #endif /* _SC_CRAY_NPTY */ 143efcad6b7SDag-Erling Smørgrav 144efcad6b7SDag-Erling Smørgrav for (i = 0; i < highpty; i++) { 145efcad6b7SDag-Erling Smørgrav snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i); 146efcad6b7SDag-Erling Smørgrav snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i); 147efcad6b7SDag-Erling Smørgrav if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1) 148efcad6b7SDag-Erling Smørgrav continue; 149efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 150efcad6b7SDag-Erling Smørgrav if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) { 151efcad6b7SDag-Erling Smørgrav close(*amaster); 152efcad6b7SDag-Erling Smørgrav return (-1); 153efcad6b7SDag-Erling Smørgrav } 154efcad6b7SDag-Erling Smørgrav return (0); 155efcad6b7SDag-Erling Smørgrav } 156efcad6b7SDag-Erling Smørgrav return (-1); 157efcad6b7SDag-Erling Smørgrav 158efcad6b7SDag-Erling Smørgrav #else 159efcad6b7SDag-Erling Smørgrav /* BSD-style pty code. */ 160efcad6b7SDag-Erling Smørgrav char ptbuf[64], ttbuf[64]; 161efcad6b7SDag-Erling Smørgrav int i; 162efcad6b7SDag-Erling Smørgrav const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" 163efcad6b7SDag-Erling Smørgrav "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 164efcad6b7SDag-Erling Smørgrav const char *ptyminors = "0123456789abcdef"; 165efcad6b7SDag-Erling Smørgrav int num_minors = strlen(ptyminors); 166efcad6b7SDag-Erling Smørgrav int num_ptys = strlen(ptymajors) * num_minors; 167efcad6b7SDag-Erling Smørgrav struct termios tio; 168efcad6b7SDag-Erling Smørgrav 169efcad6b7SDag-Erling Smørgrav for (i = 0; i < num_ptys; i++) { 170efcad6b7SDag-Erling Smørgrav snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", 171efcad6b7SDag-Erling Smørgrav ptymajors[i / num_minors], ptyminors[i % num_minors]); 172efcad6b7SDag-Erling Smørgrav snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c", 173efcad6b7SDag-Erling Smørgrav ptymajors[i / num_minors], ptyminors[i % num_minors]); 174efcad6b7SDag-Erling Smørgrav 175efcad6b7SDag-Erling Smørgrav if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { 176efcad6b7SDag-Erling Smørgrav /* Try SCO style naming */ 177efcad6b7SDag-Erling Smørgrav snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); 178efcad6b7SDag-Erling Smørgrav snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i); 179efcad6b7SDag-Erling Smørgrav if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) 180efcad6b7SDag-Erling Smørgrav continue; 181efcad6b7SDag-Erling Smørgrav } 182efcad6b7SDag-Erling Smørgrav 183efcad6b7SDag-Erling Smørgrav /* Open the slave side. */ 184efcad6b7SDag-Erling Smørgrav if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) { 185efcad6b7SDag-Erling Smørgrav close(*amaster); 186efcad6b7SDag-Erling Smørgrav return (-1); 187efcad6b7SDag-Erling Smørgrav } 188efcad6b7SDag-Erling Smørgrav /* set tty modes to a sane state for broken clients */ 189efcad6b7SDag-Erling Smørgrav if (tcgetattr(*amaster, &tio) != -1) { 190efcad6b7SDag-Erling Smørgrav tio.c_lflag |= (ECHO | ISIG | ICANON); 191efcad6b7SDag-Erling Smørgrav tio.c_oflag |= (OPOST | ONLCR); 192efcad6b7SDag-Erling Smørgrav tio.c_iflag |= ICRNL; 193efcad6b7SDag-Erling Smørgrav tcsetattr(*amaster, TCSANOW, &tio); 194efcad6b7SDag-Erling Smørgrav } 195efcad6b7SDag-Erling Smørgrav 196efcad6b7SDag-Erling Smørgrav return (0); 197efcad6b7SDag-Erling Smørgrav } 198efcad6b7SDag-Erling Smørgrav return (-1); 199efcad6b7SDag-Erling Smørgrav #endif 200efcad6b7SDag-Erling Smørgrav } 201efcad6b7SDag-Erling Smørgrav 202efcad6b7SDag-Erling Smørgrav #endif /* !defined(HAVE_OPENPTY) */ 203efcad6b7SDag-Erling Smørgrav 204