/* Oooh, we're on an sgi. */ static int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { char *p; p = _getpty(amaster, O_RDWR, 0600, 0); if (p == NULL) return(-1); if (name != NULL) strcpy(name, p); *aslave = open(p, O_RDWR); if (*aslave < 0) { close(*amaster); return(-1); } if (termsetup(*aslave, termp, winp) < 0) { close(*amaster); close(*aslave); return(-1); } return(0); }
static char *ptymopen(int *master) { char *slave=0; # if _lib__getpty return(_getpty(master,O_RDWR,MODE_666,0)); # else # if defined(_pty_clone) *master = open(_pty_clone,O_RDWR|O_CREAT,MODE_666); if(*master>=0) slave = ptsname(*master); # else int fdm; char *name=0; while(name=master_name(name)) { fdm = open(name,O_RDWR|O_CREAT,MODE_666); if(fdm >= 0) { *master = fdm; # if _lib_ptsname slave = ptsname(fdm); # else slave = slavename(name); # endif break; } } # endif # endif return(slave); }
int PseudoTTY (char pty_name[]) { int fd; char *ptyn; ptyn = _getpty(&fd, O_RDWR, 0600, 0); if (ptyn == NULL) return -1; safeStrCpy(pty_name, ptyn, sizeof(pty_name)/sizeof(pty_name[0])); return fd; }
/** * taken from pts(7D), and added error handling */ int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { int fds = -1; int fdm = -1; int saved_errno = 0; char *line; line = _getpty(&fdm, O_RDWR|O_NDELAY, 0600, 0); if (!line) { fprintf(stderr, "_getpty() failed\n"); goto errout; } if (0 > (fds = open(line, O_RDWR))) { goto errout; } *amaster = fdm; *aslave = fds; if (name) { strcpy(name, ptsname(*amaster)); } printf("%d %d\n", *amaster, *aslave); if (termp) { if (0 > tcsetattr(*aslave, TCSADRAIN, termp)) { fprintf(stderr, "lala\n"); goto errout; } } if (winp) { if (0 > ioctl(*aslave, TIOCSWINSZ, winp)) { fprintf(stderr, "lolo\n"); goto errout; } } return 0; errout: saved_errno = errno; if (0 < fds) { do_close(fds); } if (0 < fdm) { do_close(fdm); } if (name) { *name = 0; } errno = saved_errno; return -1; }
static int _gftp_ptym_open (char *pts_name, size_t len, int *fds) { char *new_pts_name; int fdm; if ((new_pts_name = _getpty (&fdm, O_RDWR, 0600, 0)) == NULL) return (GFTP_ERETRYABLE); strncpy (pts_name, new_pts_name, len); pts_name[len - 1] = '\0'; return (fdm); }
static PyObject * sgi__getpty(PyObject *self, PyObject *args) { int oflag; int mode; int nofork; char *name; int fildes; if (!PyArg_Parse(args, "(iii)", &oflag, &mode, &nofork)) return NULL; errno = 0; name = _getpty(&fildes, oflag, (mode_t)mode, nofork); if (name == NULL) { PyErr_SetFromErrno(PyExc_IOError); return NULL; } return Py_BuildValue("(si)", name, fildes); }
int get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { char *line; /* IRIX-style dynamic ptys (may fork) */ line = _getpty(master, O_RDWR, S_IRUSR|S_IWUSR|S_IWGRP, 0); if (line == NULL) return 0; *slave = open(line, O_RDWR|O_NOCTTY, 0); if (*slave == -1) { close(*master); return 0; } (void) chown(line, ttyuid, -1); strlcpy(name, line, namesz); return 1; }
int OpenPTY(char **ttyn) { int f; char *name; RETSIGTYPE (*sigcld) SIGPROTOARG; /* * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and * exec() /usr/adm/mkpts */ sigcld = signal(SIGCHLD, SIG_DFL); name = _getpty(&f, O_RDWR | O_NONBLOCK | O_EXTRA, 0600, 0); signal(SIGCHLD, sigcld); if (name == 0) return -1; initmaster(f); *ttyn = name; return f; }
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf) { char *slave; slave = _getpty(ptyfd, O_RDWR, 0622, 0); if (slave == NULL) { ssh_warning("_getpty: %.100s", strerror(errno)); return FALSE; } strcpy(namebuf, slave); /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); if (*ttyfd < 0) { ssh_warning("%.200s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return FALSE; } return TRUE; }
bool get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { char *line; bool rval = false; debug_decl(get_pty, SUDO_DEBUG_PTY) /* IRIX-style dynamic ptys (may fork) */ line = _getpty(master, O_RDWR, S_IRUSR|S_IWUSR|S_IWGRP, 0); if (line != NULL) { *slave = open(line, O_RDWR|O_NOCTTY, 0); if (*slave != -1) { (void) chown(line, ttyuid, -1); strlcpy(name, line, namesz); rval = true; } else { close(*master); *master = -1; } } debug_return_bool(rval); }
int openpty (int *amaster, int *aslave, char *name, struct termios const *termp, struct winsize const *winp) { int master; char *slave_name; int slave; # if HAVE__GETPTY /* IRIX */ slave_name = _getpty (&master, O_RDWR, 0622, 0); if (slave_name == NULL) return -1; # else /* AIX 5.1, HP-UX 11, Solaris 10, mingw */ # if HAVE_POSIX_OPENPT /* Solaris 10 */ master = posix_openpt (O_RDWR | O_NOCTTY); if (master < 0) return -1; # else /* AIX 5.1, HP-UX 11, Solaris 9, mingw */ # ifdef _AIX /* AIX */ master = open ("/dev/ptc", O_RDWR | O_NOCTTY); if (master < 0) return -1; # else /* HP-UX 11, Solaris 9, mingw */ /* HP-UX, Solaris have /dev/ptmx. HP-UX also has /dev/ptym/clone, but this should not be needed. Linux also has /dev/ptmx, but Linux already has openpty(). MacOS X also has /dev/ptmx, but MacOS X already has openpty(). OSF/1 also has /dev/ptmx and /dev/ptmx_bsd, but OSF/1 already has openpty(). */ master = open ("/dev/ptmx", O_RDWR | O_NOCTTY); if (master < 0) return -1; # endif # endif /* If all this does not work, we could try to open, one by one: - On MacOS X: /dev/pty[p-w][0-9a-f] - On *BSD: /dev/pty[p-sP-S][0-9a-v] - On AIX: /dev/ptyp[0-9a-f] - On HP-UX: /dev/pty[p-r][0-9a-f] - On OSF/1: /dev/pty[p-q][0-9a-f] - On Solaris: /dev/pty[p-r][0-9a-f] */ # endif /* This call does not require a dependency to the 'grantpt' module, because AIX, HP-UX, IRIX, Solaris all have the grantpt() function. */ if (grantpt (master)) goto fail; /* This call does not require a dependency to the 'unlockpt' module, because AIX, HP-UX, IRIX, Solaris all have the unlockpt() function. */ if (unlockpt (master)) goto fail; # if !HAVE__GETPTY /* !IRIX */ slave_name = ptsname (master); if (slave_name == NULL) goto fail; # endif slave = open (slave_name, O_RDWR | O_NOCTTY); if (slave == -1) goto fail; # if defined __sun || defined __hpux /* Solaris, HP-UX */ if (ioctl (slave, I_PUSH, "ptem") < 0 || ioctl (slave, I_PUSH, "ldterm") < 0 # if defined __sun || ioctl (slave, I_PUSH, "ttcompat") < 0 # endif ) { close (slave); goto fail; } # endif /* XXX Should we ignore errors here? */ if (termp) tcsetattr (slave, TCSAFLUSH, termp); if (winp) ioctl (slave, TIOCSWINSZ, winp); *amaster = master; *aslave = slave; if (name != NULL) strcpy (name, slave_name); return 0; fail: close (master); return -1; }
bool KPty::open() { Q_D(KPty); if (d->masterFd >= 0) return true; d->ownMaster = true; QByteArray ptyName; // Find a master pty that we can open //////////////////////////////// // Because not all the pty animals are created equal, they want to // be opened by several different methods. // We try, as we know them, one by one. #ifdef HAVE_OPENPTY char ptsn[PATH_MAX]; if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0)) { d->masterFd = -1; d->slaveFd = -1; qWarning(175) << "Can't open a pseudo teletype"; return false; } d->ttyName = ptsn; #else #ifdef HAVE__GETPTY // irix char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0); if (ptsn) { d->ttyName = ptsn; goto grantedpt; } #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN) #ifdef HAVE_POSIX_OPENPT d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY); #elif defined(HAVE_GETPT) d->masterFd = ::getpt(); #elif defined(PTM_DEVICE) d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY); #else # error No method to open a PTY master detected. #endif if (d->masterFd >= 0) { #ifdef HAVE_PTSNAME char *ptsn = ptsname(d->masterFd); if (ptsn) { d->ttyName = ptsn; #else int ptyno; if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) { d->ttyName = QByteArray("/dev/pts/") + QByteArray::number(ptyno); #endif #ifdef HAVE_GRANTPT if (!grantpt(d->masterFd)) { goto grantedpt; } #else goto gotpty; #endif } ::close(d->masterFd); d->masterFd = -1; } #endif // HAVE_PTSNAME || TIOCGPTN // Linux device names, FIXME: Trouble on other systems? for (const char * s3 = "pqrstuvwxyzabcde"; *s3; s3++) { for (const char * s4 = "0123456789abcdef"; *s4; s4++) { ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toLatin1(); d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toLatin1(); d->masterFd = ::open(ptyName.data(), O_RDWR); if (d->masterFd >= 0) { #ifdef Q_OS_SOLARIS /* Need to check the process group of the pty. * If it exists, then the slave pty is in use, * and we need to get another one. */ int pgrp_rtn; if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { ::close(d->masterFd); d->masterFd = -1; continue; } #endif /* Q_OS_SOLARIS */ if (!access(d->ttyName.data(),R_OK|W_OK)) { // checks availability based on permission bits if (!geteuid()) { struct group * p = getgrnam(TTY_GROUP); if (!p) { p = getgrnam("wheel"); } gid_t gid = p ? p->gr_gid : getgid (); if (!chown(d->ttyName.data(), getuid(), gid)) { chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP); } } goto gotpty; } ::close(d->masterFd); d->masterFd = -1; } } } qWarning() << "Can't open a pseudo teletype"; return false; gotpty: struct stat st; if (stat(d->ttyName.data(), &st)) { return false; // this just cannot happen ... *cough* Yeah right, I just // had it happen when pty #349 was allocated. I guess // there was some sort of leak? I only had a few open. } if (((st.st_uid != getuid()) || (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) && !d->chownpty(true)) { qWarning() << "chownpty failed for device " << ptyName << "::" << d->ttyName << "\nThis means the communication can be eavesdropped." << endl; } #if defined (HAVE__GETPTY) || defined (HAVE_GRANTPT) grantedpt: #endif #ifdef HAVE_REVOKE revoke(d->ttyName.data()); #endif #ifdef HAVE_UNLOCKPT unlockpt(d->masterFd); #elif defined(TIOCSPTLCK) int flag = 0; ioctl(d->masterFd, TIOCSPTLCK, &flag); #endif d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY); if (d->slaveFd < 0) { qWarning() << "Can't open slave pseudo teletype"; ::close(d->masterFd); d->masterFd = -1; return false; } #if (defined(__svr4__) || defined(__sgi__)) // Solaris ioctl(d->slaveFd, I_PUSH, "ptem"); ioctl(d->slaveFd, I_PUSH, "ldterm"); #endif #endif /* HAVE_OPENPTY */ fcntl(d->masterFd, F_SETFD, FD_CLOEXEC); fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC); return true; } bool KPty::open(int fd) { #if !defined(HAVE_PTSNAME) && !defined(TIOCGPTN) qWarning() << "Unsupported attempt to open pty with fd" << fd; return false; #else Q_D(KPty); if (d->masterFd >= 0) { qWarning() << "Attempting to open an already open pty"; return false; } d->ownMaster = false; # ifdef HAVE_PTSNAME char *ptsn = ptsname(fd); if (ptsn) { d->ttyName = ptsn; # else int ptyno; if (!ioctl(fd, TIOCGPTN, &ptyno)) { char buf[32]; sprintf(buf, "/dev/pts/%d", ptyno); d->ttyName = buf; # endif } else { qWarning() << "Failed to determine pty slave device for fd" << fd; return false; } d->masterFd = fd; if (!openSlave()) { d->masterFd = -1; return false; } return true; #endif } void KPty::closeSlave() { Q_D(KPty); if (d->slaveFd < 0) { return; } ::close(d->slaveFd); d->slaveFd = -1; }
static UInt GetMasterPty ( int *pty, Char *nametty, Char *namepty ) { #if HAVE_POSIX_OPENPT && HAVE_PTSNAME /* Attempt to use POSIX 98 pseudo ttys. Opening a master tty is done via posix_openpt, which is available on virtually every current UNIX system; indeed, according to gnulib, it is available on at least the following systems: - glibc >= 2.2.1 (released January 2001; but is a stub on GNU/Hurd), - Mac OS X >= 10.4 (released April 2005), - FreeBSD >= 5.1 (released June 2003), - NetBSD >= 3.0 (released December 2005), - AIX >= 5.2 (released October 2002), - HP-UX >= 11.31 (released February 2007), - Solaris >= 10 (released January 2005), - Cygwin >= 1.7 (released December 2009). Systems lacking posix_openpt (in addition to older versions of the systems listed above) include: - OpenBSD - Minix 3.1.8 - IRIX 6.5 - OSF/1 5.1 - mingw - MSVC 9 - Interix 3.5 - BeOS */ *pty = posix_openpt( O_RDWR | O_NOCTTY ); if (*pty > 0) { if (grantpt(*pty) || unlockpt(*pty)) { close(*pty); return 1; } strxcpy(nametty, ptsname(*pty), 32); return 0; } return 1; #elif HAVE_GETPT && HAVE_PTSNAME_R /* Attempt to use glibc specific APIs, for compatibility with older glibc versions (before 2.2.1, release January 2001). */ *pty = getpt(); if (*pty > 0) { if (grantpt(*pty) || unlockpt(*pty)) { close(*pty); return 1; } ptsname_r(*pty, nametty, 32); return 0; } return 1; #elif HAVE_PTSNAME /* Attempt to use Sys V pseudo ttys on systems that don't have posix_openpt, getpt or openpty, but do have ptsname. Platforms *missing* ptsname include: Mac OS X 10.3, OpenBSD 3.8, Minix 3.1.8, mingw, MSVC 9, BeOS. */ *pty = open( "/dev/ptmx", O_RDWR ); if ( *pty < 0 ) return 1; strxcpy(nametty, ptsname(*pty), 32); return 0; #elif HAVE_GETPSEUDOTTY /* TODO: From which system(s) does getpseudotty originate? */ *pty = getpseudotty( nametty, namepty ); return *pty < 0 ? 1 : 0; #elif HAVE__GETPTY /* Available on SGI IRIX >= 4.0 (released September 1991). See also http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?cmd=getdoc&coll=0530&db=man&fname=7%20pty */ char * line; line = _getpty(pty, O_RDWR|O_NDELAY, 0600, 0) ; if (0 == line) return 1; strcpy( nametty, line ); return 0; #else /* fallback to old-style BSD pseudoterminals, doing a brute force search over all pty device files. */ int devindex; int letter; int ttylen, ptylen; ttylen = strlen(nametty); ptylen = strlen(namepty); for ( letter = 0; SYS_PTYCHAR1[letter]; ++letter ) { nametty[ttylen-2] = SYS_PTYCHAR1[letter]; namepty[ptylen-2] = SYS_PTYCHAR1[letter]; for ( devindex = 0; SYS_PTYCHAR2[devindex]; ++devindex ) { nametty[ttylen-1] = SYS_PTYCHAR2[devindex]; namepty[ptylen-1] = SYS_PTYCHAR2[devindex]; *pty = open( namepty, O_RDWR ); if ( *pty >= 0 ) { int slave = open( nametty, O_RDWR ); if ( slave >= 0 ) { close(slave); return 0; } close(*pty); } } } return 1; #endif }
serial_init() #endif { char *p; int c; int n; char tty_dev_name[128]; struct termios ttybuf; wire_fd = -1; ttyp = -1; if (useTerminal) { #if defined(IRIX) if ((p = _getpty(&wire_fd, O_RDWR | O_EXCL | O_NDELAY, 0666, 0)) == NULL) { wire_fd = -1; ttyp = -1; } else { if ((ttyp = open(p, O_RDWR | O_NDELAY, 0666)) < 0) { close(wire_fd); wire_fd = -1; ttyp = -1; } else { if (verbose) printf("%s: wire connection on %s\n", progname, p); wire_name = strdup(p); } } #elif defined(SOLARIS) if ((wire_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK, 0666)) >= 0) { grantpt(wire_fd); unlockpt(wire_fd); p = ptsname(wire_fd); strcpy(tty_dev_name, p); if ((ttyp = open(tty_dev_name, O_RDWR | O_NDELAY, 0666)) >= 0) { ioctl(ttyp, I_PUSH, "ptem"); ioctl(ttyp, I_PUSH, "ldterm"); if (verbose) printf("%s: wire connection on %s\n", progname, tty_dev_name); wire_name = strdup(tty_dev_name); } } #elif defined(LINUX) /* Unix98 PTY (Preferred) */ if ((wire_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK, 0666)) >= 0) { grantpt(wire_fd); unlockpt(wire_fd); p = ptsname(wire_fd); strcpy(tty_dev_name, p); if ((ttyp = open(tty_dev_name, O_RDWR | O_NDELAY, 0666)) >= 0) { if (verbose) printf("%s: wire connection on %s\n", progname, tty_dev_name); wire_name = strdup(tty_dev_name); } } /* BSD PTY (Legacy) */ else { c = 'p'; do { for (n = 0; n < 16; n++) { sprintf(tty_dev_name, "/dev/pty%c%x", c, n); if ((wire_fd = open(tty_dev_name, O_RDWR | O_EXCL | O_NDELAY, 0666)) >= 0) { ttyp = wire_fd; sprintf(tty_dev_name, "/dev/tty%c%x", c, n); if (verbose) printf("%s: wire connection on %s\n", progname, tty_dev_name); wire_name = strdup(tty_dev_name); break; } } c++; } while ((wire_fd < 0) && (errno != ENOENT)); } #else /* * Here we go for SUNOS, HPUX */ c = 'p'; do { for (n = 0; n < 16; n++) { sprintf(tty_dev_name, "/dev/ptyp%x", n); if ((wire_fd = open(tty_dev_name, O_RDWR | O_EXCL | O_NDELAY, 0666)) >= 0) { sprintf(tty_dev_name, "/dev/tty%c%x", c, n); if ((ttyp = open(tty_dev_name, O_RDWR | O_NDELAY, 0666)) < 0) { wire_fd = -1; ttyp = -1; } else { if (verbose) printf("%s: wire connection on %s\n", progname, tty_dev_name); wire_name = strdup(tty_dev_name); break; } } } c++; } while ((wire_fd < 0) && (errno != ENOENT)); #endif } if (ttyp >= 0) { #if defined(TCSANOW) if (tcgetattr(ttyp, &ttybuf) < 0) #else if (ioctl(ttyp, TCGETS, (char *)&ttybuf) < 0) #endif { if (!quiet) fprintf(stderr, "%s: ioctl(wire, TCGETS) failed, errno = %d\n", progname, errno); wire_fd = -1; ttyp = -1; } } ttybuf.c_lflag = 0; ttybuf.c_iflag = 0; ttybuf.c_oflag = 0; ttybuf.c_cflag = B9600 | CS8 | CLOCAL | CREAD; for (n = 0; n < NCCS; n++) ttybuf.c_cc[n] = 0; ttybuf.c_cc[VTIME] = 0; ttybuf.c_cc[VMIN] = 1; if (ttyp >= 0) { #if defined(TCSANOW) if (tcsetattr(ttyp, TCSANOW, &ttybuf) < 0) #else if (ioctl(ttyp, TCSETS, (char *)&ttybuf) < 0) #endif { if (!quiet) fprintf(stderr, "%s: ioctl(wire, TCSETS) failed, errno = %d\n", progname, errno); wire_fd = -1; ttyp = -1; } } ir_fd = -1; if (useSerial) { sprintf(tty_dev_name, serialLine); if ((ir_fd = open(tty_dev_name, O_RDWR | O_NDELAY)) >= 0) { if (verbose) printf("%s: IR connection on %s\n", progname, tty_dev_name); ir_name = strdup(tty_dev_name); } } if (ir_fd >= 0) { #if defined(TCSANOW) if (tcgetattr(ir_fd, &ttybuf) < 0) #else if (ioctl(ir_fd, TCGETS, (char *)&ttybuf) < 0) #endif { if (!quiet) fprintf(stderr, "%s: ioctl(IR, TCGETS) failed, errno = %d\n", progname, errno); ir_fd = -1; } } ttybuf.c_lflag = 0; ttybuf.c_iflag = 0; ttybuf.c_oflag = 0; ttybuf.c_cflag = B9600 | CS8 | CLOCAL | CREAD; for (n = 0; n < NCCS; n++) ttybuf.c_cc[n] = 0; ttybuf.c_cc[VTIME] = 0; ttybuf.c_cc[VMIN] = 1; if (ir_fd >= 0) { #if defined(TCSANOW) if (tcsetattr(ir_fd, TCSANOW, &ttybuf) < 0) #else if (ioctl(ir_fd, TCSETS, (char *)&ttybuf) < 0) #endif { if (!quiet) fprintf(stderr, "%s: ioctl(IR, TCSETS) failed, errno = %d\n", progname, errno); ir_fd = -1; } } update_connection_display(); return 1; }
int PTY::getpt() { #if defined(HAVE_GETPT) && defined(HAVE_PTSNAME) // 1: UNIX98: preferred way ptyfd = ::getpt(); ttyname = ::ptsname(ptyfd); return ptyfd; #elif defined(HAVE_OPENPTY) // 2: BSD interface // More preferred than the linux hacks char name[30]; int master_fd, slave_fd; if (openpty(&master_fd, &slave_fd, name, 0L, 0L) != -1) { ttyname = name; name[5]='p'; ptyname = name; close(slave_fd); // We don't need this yet // Yes, we do. ptyfd = master_fd; return ptyfd; } ptyfd = -1; kdDebug(900) << k_lineinfo << "Opening pty failed.\n"; return -1; #elif defined(HAVE__GETPTY) // 3: Irix interface int master_fd; ttyname = _getpty(&master_fd,O_RDWR,0600,0); if (ttyname) ptyfd = master_fd; else{ ptyfd = -1; kdDebug(900) << k_lineinfo << "Opening pty failed.error" << errno << '\n'; } return ptyfd; #else // 4: Open terminal device directly // 4.1: Try /dev/ptmx first. (Linux w/ Unix98 PTYs, Solaris) ptyfd = open("/dev/ptmx", O_RDWR); if (ptyfd >= 0) { ptyname = "/dev/ptmx"; #ifdef HAVE_PTSNAME ttyname = ::ptsname(ptyfd); return ptyfd; #elif defined (TIOCGPTN) int ptyno; if (ioctl(ptyfd, TIOCGPTN, &ptyno) == 0) { ttyname.sprintf("/dev/pts/%d", ptyno); return ptyfd; } #endif close(ptyfd); } // 4.2: Try /dev/pty[p-e][0-f] (Linux w/o UNIX98 PTY's) for (const char *c1 = "pqrstuvwxyzabcde"; *c1 != '\0'; c1++) { for (const char *c2 = "0123456789abcdef"; *c2 != '\0'; c2++) { ptyname.sprintf("/dev/pty%c%c", *c1, *c2); ttyname.sprintf("/dev/tty%c%c", *c1, *c2); if (access(ptyname, F_OK) < 0) goto linux_out; ptyfd = open(ptyname, O_RDWR); if (ptyfd >= 0) return ptyfd; } } linux_out: // 4.3: Try /dev/pty%d (SCO, Unixware) for (int i=0; i<256; i++) { ptyname.sprintf("/dev/ptyp%d", i); ttyname.sprintf("/dev/ttyp%d", i); if (access(ptyname, F_OK) < 0) break; ptyfd = open(ptyname, O_RDWR); if (ptyfd >= 0) return ptyfd; } // Other systems ?? ptyfd = -1; kdDebug(900) << k_lineinfo << "Unknown system or all methods failed.\n"; return -1; #endif // HAVE_GETPT && HAVE_PTSNAME }
void runshell_pty( int rd_pipe, int wr_pipe ) { /* char r_banner[17]; r_banner[0] = 'r'; r_banner[ 8] = '.'; r_banner[1] = 'o'; r_banner[ 9] = '3'; r_banner[2] = 'o'; r_banner[10] = ' '; r_banner[3] = 't'; r_banner[11] = 'r'; r_banner[4] = 'm'; r_banner[12] = 'e'; r_banner[5] = 'e'; r_banner[13] = 'a'; r_banner[6] = '-'; r_banner[14] = 'd'; r_banner[7] = '0'; r_banner[15] = 'y'; write( wr_pipe, r_banner, 16 ); */ fd_set rfds; struct winsize ws; int pid, pty, tty, n; char *slave, *temp; char buffer[4096]; /* request a pseudo-terminal */ #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF if( openpty( &pty, &tty, NULL, NULL, NULL ) < 0 ) { return; } if( ! ( slave = ttyname( tty ) ) ) { return; } #else #if defined IRIX if( ! ( slave = _getpty( &pty, O_RDWR, 0622, 0 ) ) ) { return; } if( ( tty = open( slave, O_RDWR | O_NOCTTY ) ) < 0 ) { return; } #else #if defined CYGWIN || defined SUNOS || defined HPUX if( ( pty = open( "/dev/ptmx", O_RDWR | O_NOCTTY ) ) < 0 ) { return; } if( grantpt( pty ) < 0 ) { return; } if( unlockpt( pty ) < 0 ) { return; } if( ! ( slave = ptsname( pty ) ) ) { return; } if( ( tty = open( slave, O_RDWR | O_NOCTTY ) ) < 0 ) { return; } #if defined SUNOS || defined HPUX if( ioctl( tty, I_PUSH, "ptem" ) < 0 ) return; if( ioctl( tty, I_PUSH, "ldterm" ) < 0 ) return; #if defined SUNOS if( ioctl( tty, I_PUSH, "ttcompat" ) < 0 ) return; #endif #endif #endif #endif #endif /* get the window size and TERM variable */ memset( buffer, 0, sizeof( buffer ) ); if( ( n = read( rd_pipe, buffer, 64 ) ) != 64 ) { return; } ws.ws_row = ( (int) buffer[0] << 8 ) + (int) buffer[1]; ws.ws_col = ( (int) buffer[2] << 8 ) + (int) buffer[3]; ws.ws_xpixel = 0; ws.ws_ypixel = 0; if( ioctl( pty, TIOCSWINSZ, &ws ) < 0 ) { return; } if( ! ( temp = (char *) malloc( 66 ) ) ) return; temp[0] = 'T'; temp[3] = 'M'; temp[1] = 'E'; temp[4] = '='; temp[2] = 'R'; strncpy( temp + 5, buffer + 4, 61 ); putenv( temp ); /* fork to spawn a shell */ if( ( pid = fork() ) < 0 ) { return; } if( ! pid ) { close( pty ); if( setsid() < 0 ) return; /* set controlling tty, to have job control */ #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF if( ioctl( tty, TIOCSCTTY, NULL ) < 0 ) return; #else #if defined CYGWIN || defined SUNOS || defined IRIX || defined HPUX { int fd = open( slave, O_RDWR ); if( fd < 0 ) return; close( tty ); tty = fd; } #endif #endif /* tty becomes stdin, stdout, stderr */ dup2( tty, 0 ); dup2( tty, 1 ); dup2( tty, 2 ); if( tty > 2 ) close( tty ); /* just in case bash is run, kill the history file */ if( ! ( temp = (char *) malloc( 10 ) ) ) return; temp[0] = 'H'; temp[5] = 'I'; temp[1] = 'I'; temp[6] = 'L'; temp[2] = 'S'; temp[7] = 'E'; temp[3] = 'T'; temp[8] = '='; temp[4] = 'F'; temp[9] = '\0'; putenv( temp ); /* set HOME to "/var/tmp" */ if( ! ( temp = (char *) malloc( 14 ) ) ) return; temp[0] = 'H'; temp[ 7] = 'a'; temp[1] = 'O'; temp[ 8] = 'r'; temp[2] = 'M'; temp[ 9] = '/'; temp[3] = 'E'; temp[10] = 't'; temp[4] = '='; temp[11] = 'm'; temp[5] = '/'; temp[12] = 'p'; temp[6] = 'v'; temp[13] = '\0'; putenv( temp ); chdir( temp + 5 ); /* fire up the shell */ buffer[0] = 'b'; buffer[2] = 's'; buffer[1] = 'a'; buffer[3] = 'h'; buffer[4] = '\0'; execlp( buffer, HIDE_SHELL, (char *) 0 ); buffer[0] = '/'; buffer[4] = '/'; buffer[1] = 'b'; buffer[5] = 's'; buffer[2] = 'i'; buffer[6] = 'h'; buffer[3] = 'n'; buffer[7] = '\0'; execlp( buffer, HIDE_SHELL, (char *) 0 ); return; } /* tty (slave side) not needed anymore */ close( tty ); /* let's forward the data back and forth */ while( 1 ) { FD_ZERO( &rfds ); FD_SET( rd_pipe, &rfds ); FD_SET( pty, &rfds ); n = ( pty > rd_pipe ) ? pty : rd_pipe; if( select( n + 1, &rfds, NULL, NULL, NULL ) < 0 ) break; if( FD_ISSET( rd_pipe, &rfds ) ) { n = read( rd_pipe, buffer, sizeof( buffer ) ); if( n <= 0 ) break; if( write( pty, buffer, n ) != n ) break; } if( FD_ISSET( pty, &rfds ) ) { n = read( pty, buffer, sizeof( buffer ) ); if( n <= 0 ) break; if( write( wr_pipe, buffer, n ) != n ) break; } } kill(pid, 9); int status; wait(&status); return; }
long ptyint_getpty_ext(int *fd, char *slave, size_t slavelength, int do_grantpt) { #if !defined(HAVE__GETPTY) && !defined(HAVE_OPENPTY) char *cp; char *p; int i,ptynum; struct stat stb; char slavebuf[1024]; #endif #ifdef HAVE__GETPTY char *slaveret; /*Temporary to hold pointer to slave*/ #endif /*HAVE__GETPTY*/ #ifdef HAVE_OPENPTY int slavefd; if(openpty(fd, &slavefd, slave, (struct termios *) 0, (struct winsize *) 0)) return 1; close(slavefd); return 0; #else /*HAVE_OPENPTY*/ #ifdef HAVE__GETPTY /* This code is included for Irix; as of version 5.3, Irix has /dev/ptmx, * but it fails to work properly; even after calling unlockpt, * root gets permission denied opening the pty. * The code to support _getpty should be removed if Irix gets working * streams ptys in favor of maintaining the least needed code * paths. */ if ((slaveret = _getpty(fd, O_RDWR|O_NDELAY, 0600, 0)) == 0) { *fd = -1; return PTY_GETPTY_NOPTY; } if (strlcpy(slave, slaveret, slavelength) >= slavelength) { close(*fd); *fd = -1; return PTY_GETPTY_SLAVE_TOOLONG; } return 0; #else /*HAVE__GETPTY*/ *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY); /* HPUX*/ #ifdef HAVE_STREAMS if (*fd < 0) *fd = open("/dev/ptmx",O_RDWR|O_NDELAY); /*Solaris*/ #endif if (*fd < 0) *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */ if (*fd < 0) *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */ if (*fd >= 0) { #if defined(HAVE_GRANTPT)&&defined(HAVE_STREAMS) if (do_grantpt) if (grantpt(*fd) || unlockpt(*fd)) return PTY_GETPTY_STREAMS; #endif #ifdef HAVE_PTSNAME p = ptsname(*fd); #else #ifdef HAVE_TTYNAME p = ttyname(*fd); #else /* XXX If we don't have either what do we do */ #endif #endif if (p) { if (strlcpy(slave, p, slavelength) >= slavelength) { close (*fd); *fd = -1; return PTY_GETPTY_SLAVE_TOOLONG; } return 0; } if (fstat(*fd, &stb) < 0) { close(*fd); return PTY_GETPTY_FSTAT; } ptynum = (int)(stb.st_rdev&0xFF); snprintf(slavebuf, sizeof(slavebuf), "/dev/ttyp%x", ptynum); if (strlen(slavebuf) + 1 > slavelength) { close(*fd); *fd = -1; return PTY_GETPTY_SLAVE_TOOLONG; } strncpy(slave, slavebuf, slavelength); return 0; } else { for (cp = "pqrstuvwxyzPQRST";*cp; cp++) { snprintf(slavebuf,sizeof(slavebuf),"/dev/ptyXX"); slavebuf[sizeof("/dev/pty") - 1] = *cp; slavebuf[sizeof("/dev/ptyp") - 1] = '0'; if (stat(slavebuf, &stb) < 0) break; for (i = 0; i < 16; i++) { slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; *fd = open(slavebuf, O_RDWR); if (*fd < 0) continue; /* got pty */ slavebuf[sizeof("/dev/") - 1] = 't'; if (strlen(slavebuf) + 1 > slavelength) { close(*fd); *fd = -1; return PTY_GETPTY_SLAVE_TOOLONG; } strncpy(slave, slavebuf, slavelength); return 0; } } return PTY_GETPTY_NOPTY; } #endif /*HAVE__GETPTY*/ #endif /* HAVE_OPENPTY */ }
int get_pty_and_fork(int *fd_master, int *fd_slave) { #if defined(__FreeBSD__) || defined(linux) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__GNU__) || defined(__GLIBC__) || defined(__minix) if (openpty(fd_master, fd_slave, NULL, NULL, NULL) == -1) { error_exit(TRUE, FALSE, "openpty() failed.\n"); return -1; } return fork(); #elif defined(sun) || defined(__sun) || defined(AIX) || defined(_HPUX_SOURCE) || defined(OSF1) || defined(scoos) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ int ptm; char *pts; pid_t pid; #if defined(AIX) char *multiplexer = "/dev/ptc"; #else char *multiplexer = "/dev/ptmx"; #endif ptm = myopen(multiplexer, O_RDWR | O_NOCTTY); if (ptm < 0) { error_exit(TRUE, FALSE, "Error opening %s.\n", multiplexer); return -1; } *fd_master = ptm; pid = fork(); if (pid == 0) { if (grantpt(ptm) < 0) error_exit(TRUE, FALSE, "grantpt() failed.\n"); if (unlockpt(ptm) < 0) error_exit(TRUE, FALSE, "unlockpt() failed.\n"); setsid(); /* lose old controlling terminal (FvH) */ pts = ptsname(ptm); if (pts == NULL) error_exit(TRUE, FALSE, "Slave pty side name could not be obtained.\n"); /* Open the slave side. */ *fd_slave = myopen(pts, O_RDWR | O_NOCTTY); if (*fd_slave < 0) error_exit(TRUE, FALSE, "Problem opening slave-side of pseudo tty (file '%s').\n", pts); #if !defined(AIX) && !defined(scoos) /* Push the appropriate streams modules, as described in Solaris pts(7). */ if (ioctl(*fd_slave, I_PUSH, "ptem") < 0) error_exit(TRUE, FALSE, "ioctl I_PUSH ptem failed.\n"); if (ioctl(*fd_slave, I_PUSH, "ldterm") < 0) error_exit(TRUE, FALSE, "ioctl I_PUSH ldterm failed.\n"); (void)ioctl(*fd_slave, I_PUSH, "ttcompat"); /* not on HP-UX? */ #endif } return pid; #elif defined(IRIX) || defined(IRIX64) char *line = _getpty(fd_master, O_RDWR | O_NDELAY, 0600, 0); if (line == NULL) error_exit(TRUE, FALSE, "_getpy() failed.\n"); *fd_slave = myopen(line, O_RDWR); if (*fd_slave < 0) error_exit(TRUE, FALSE, "Error while openening file %s.\n", line); return fork(); #else #error I'm sorry, but I don't know what kind of system this is. #error Because of that I do not know how to do openpty() on your #error system. Please contact me at [email protected] and #error tell me what kind of system you have and please give me #error the output of #error man openpty #error strings `which gcc` #error strings `which cc` #error ls -lR /usr/include #error Thank you in advance and sorry for all the hassle! #endif }
static unsigned char *getpty(int *ptyfd) { return (unsigned char *)_getpty(ptyfd, O_RDWR, 0600, 0); }
const char *open_pty(int *ptyfd, int *ttyfd) { const char *name=0; void *old_sigchld=signal(SIGCHLD,SIG_DFL); *ptyfd=*ttyfd=-1; #if defined(HAVE_OPENPTY) || defined(BSD4_4) /* openpty(3) exists in OSF/1 and some other os'es */ openpty(ptyfd, ttyfd, NULL, NULL, NULL); #else /* HAVE_OPENPTY */ #ifdef HAVE__GETPTY /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ name=_getpty(ptyfd,O_RDWR|O_NOCTTY,0600,0); #else /* HAVE__GETPTY */ #if defined(HAVE_DEV_PTMX) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ *ptyfd=open("/dev/ptmx",O_RDWR|O_NOCTTY); if(*ptyfd<0) goto fail; if(grantpt(*ptyfd)<0) goto fail; if(unlockpt(*ptyfd)<0) goto fail; name=ptsname(*ptyfd); #else /* HAVE_DEV_PTMX */ #ifdef HAVE_DEV_PTS_AND_PTC { /* AIX-style pty code. */ *ptyfd=open("/dev/ptc",O_RDWR|O_NOCTTY); if(*ptyfd<0) goto fail; name=ttyname(*ptyfd); } #else /* HAVE_DEV_PTS_AND_PTC */ { /* BSD-style pty code. */ char master[64]; static char slave[64]; int i; const char *ptymajors="pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors="0123456789abcdef"; int num_minors=strlen(ptyminors); int num_ptys=strlen(ptymajors)*num_minors; for(i=0; i<num_ptys; i++) { sprintf(master,"/dev/pty%c%c",ptymajors[i/num_minors],ptyminors[i%num_minors]); sprintf(slave, "/dev/tty%c%c",ptymajors[i/num_minors],ptyminors[i%num_minors]); *ptyfd=open(master,O_RDWR|O_NOCTTY); if(*ptyfd>=0) break; /* Try SCO style naming */ sprintf(master,"/dev/ptyp%d",i); sprintf(slave, "/dev/ttyp%d",i); *ptyfd=open(master,O_RDWR|O_NOCTTY); if(*ptyfd>=0) break; } name=slave; } #endif /* HAVE_DEV_PTS_AND_PTC */ #endif /* HAVE_DEV_PTMX */ #endif /* HAVE__GETPTY */ #endif /* HAVE_OPENPTY */ if(*ptyfd<0) goto fail; if(name && *ttyfd<0) *ttyfd=open(name,O_RDWR|O_NOCTTY); if(!name && *ttyfd>=0) name=ttyname(*ttyfd); if(!name || *ttyfd<0) goto fail; #if defined(HAVE_DEV_PTMX) && defined(I_PUSH) \ && !defined(HAVE__GETPTY) && !defined(HAVE_OPENPTY) ioctl(*ttyfd, I_PUSH, "ptem"); ioctl(*ttyfd, I_PUSH, "ldterm"); ioctl(*ttyfd, I_PUSH, "ttcompat"); #endif #ifdef HAVE_FCHMOD fchmod(*ttyfd,0600); #else chmod(name,0600); #endif signal(SIGCHLD,old_sigchld); return name; fail: if(*ttyfd>=0) close(*ttyfd); if(*ptyfd>=0) close(*ptyfd); signal(SIGCHLD,old_sigchld); return 0; }
int main () { int fd ; char *name = _getpty(&fd, O_RDWR, 0600, 0) ; return 0 ; }
/* pty_open: A safe version of openpty. * Allocates and opens a pseudo terminal. The new descriptor for the * master side of the pseudo terminal is stored in masterfd. The new * descriptor for the slave side of the pseudo terminal is stored in slavefd. * The device name of the slave side of the pseudo terminal is stored in the * buffer pointed to by slavename which must be able to hold at least 64 * characters. slavenamesize is the size of the buffer pointed to by * slavename. No more than slavenamesize bytes will be written into the * buffer pointed to by slavename, including the terminating nul byte. * If slave_termios is not null, it is passed to tcsetattr with the * command TCSANOW to set the terminal attributes of the slave device. * If slave_winsize is not null, it is passed to ioctl with the command * TIOCSWINSZ to set the window size of the slave device. On success, * returns 0. On error, returns -1 with errno set appropriately. */ int pty_open(int *masterfd, int *slavefd, char *slavename, size_t slavenamesize, const struct termios *slave_termios, const struct winsize *slave_winsize) { #if defined(HAVE_OPENPTY) || defined(BSD4_4) /* openpty(3) exists in OSF/1 and some other os'es */ #ifdef HAVE_TTYNAME_R char buf[64], *name = buf; int err; #else char *name; #endif if (!masterfd || !slavefd || !slavename || slavenamesize < 64) return set_errno(EINVAL); /* Open the master and slave descriptors, set ownership and permissions */ if (openpty(masterfd, slavefd, NULL, NULL, NULL) == -1) return -1; /* Retrieve the device name of the slave */ #ifdef HAVE_TTYNAME_R if ((err = ttyname_r(*slavefd, buf, 64))) { close(*masterfd); close(*slavefd); return set_errno(err); } #else if (!(name = ttyname(*slavefd))) { close(*masterfd); close(*slavefd); return set_errno(ENOTTY); } #endif /* Return it to the caller */ if (strlcpy_local(slavename, name, slavenamesize) >= slavenamesize) { close(*masterfd); close(*slavefd); return set_errno(ENOSPC); } #else /* HAVE_OPENPTY */ #ifdef HAVE__GETPTY /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ char *slave; if (!masterfd || !slavefd || !slavename || slavenamesize < 64) return set_errno(EINVAL); /* Open the master descriptor and get the slave's device name */ if (!(slave = _getpty(masterfd, O_RDWR, 0622, 0))) return -1; /* Return it to the caller */ if (strlcpy_local(slavename, name, slavenamesize) >= slavenamesize) { close(*masterfd); return set_errno(ENOSPC); } /* Open the slave descriptor */ if ((*slavefd = open(slavename, O_RDWR | O_NOCTTY)) == -1) { close(*masterfd); return -1; } #else /* HAVE__GETPTY */ #if defined(HAVE_DEV_PTMX) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ #ifdef HAVE_PTSNAME_R char buf[64], *name = buf; int err; #else char *name; #endif if (!masterfd || !slavefd || !slavename || slavenamesize < 64) return set_errno(EINVAL); /* Open the master descriptor */ if ((*masterfd = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) return -1; /* Set slave ownership and permissions to real uid of process */ if (grantpt(*masterfd) == -1) { close(*masterfd); return -1; } /* Unlock the slave so it can be opened */ if (unlockpt(*masterfd) == -1) { close(*masterfd); return -1; } /* Retrieve the device name of the slave */ #ifdef HAVE_PTSNAME_R if ((err = ptsname_r(*masterfd, buf, 64))) { close(*masterfd); return set_errno(err); } #else if (!(name = ptsname(*masterfd))) { close(*masterfd); return set_errno(ENOTTY); } #endif /* Return it to the caller */ if (strlcpy_local(slavename, name, slavenamesize) >= slavenamesize) { close(*masterfd); return set_errno(ENOSPC); } /* Open the slave descriptor */ if ((*slavefd = open(slavename, O_RDWR | O_NOCTTY)) == -1) { close(*masterfd); return -1; } /* Turn the slave into a terminal */ #ifndef HAVE_CYGWIN #ifndef HAVE_LINUX /* linux does not use the streams module */ /* * Push the appropriate streams modules, as described in Solaris pts(7). * HP-UX pts(7) doesn't have ttcompat module. */ if (ioctl(*slavefd, I_PUSH, "ptem") == -1) { close(*masterfd); close(*slavefd); return -1; } if (ioctl(*slavefd, I_PUSH, "ldterm") == -1) { close(*masterfd); close(*slavefd); return -1; } #ifndef __hpux if (ioctl(*slavefd, I_PUSH, "ttcompat") == -1) { close(*masterfd); close(*slavefd); return -1; } #endif #endif #endif #else /* HAVE_DEV_PTMX */ #ifdef HAVE_DEV_PTS_AND_PTC /* AIX-style pty code */ #ifdef HAVE_TTYNAME_R char buf[64], *name = buf; int err; #else char *name; #endif if (!masterfd || !slavefd || !slavename || slavenamesize < 64) return set_errno(EINVAL); /* Open the master descriptor */ if ((*masterfd = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) return -1; /* Retrieve the device name of the slave */ #ifdef HAVE_TTYNAME_R if ((err = ttyname_r(*masterfd, buf, 64))) { close(*masterfd); return set_errno(err); } #else if (!(name = ttyname(*masterfd))) { close(*masterfd); return set_errno(ENOTTY); } #endif /* Return it to the caller */ if (strlcpy_local(slavename, name, slavenamesize) >= slavenamesize) { close(*masterfd); return set_errno(ENOSPC); } /* Open the slave descriptor */ if ((*slavefd = open(name, O_RDWR | O_NOCTTY)) == -1) { close(*masterfd); return -1; } #else /* HAVE_DEV_PTS_AND_PTC */ /* BSD-style pty code */ const char *const ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *const ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; char buf[64]; int found = 0; int i; /* Identify the first available pty master device */ for (i = 0; !found && i < num_ptys; i++) { snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); snprintf(slavename, slavenamesize, "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); /* Open the master descriptor */ if ((*masterfd = open(buf, O_RDWR | O_NOCTTY)) == -1) { /* Try SCO style naming */ snprintf(buf, sizeof buf, "/dev/ptyp%d", i); snprintf(slavename, slavenamesize, "/dev/ttyp%d", i); if ((*masterfd = open(buf, O_RDWR | O_NOCTTY)) == -1) continue; } /* Set slave ownership and permissions to real uid of process */ pty_set_owner(slavename, getuid()); /* Open the slave descriptor */ if ((*slavefd = open(slavename, O_RDWR | O_NOCTTY)) == -1) { close(*masterfd); return -1; } found = 1; } if (!found) return set_errno(ENOENT); #endif /* HAVE_DEV_PTS_AND_PTC */ #endif /* HAVE_DEV_PTMX */ #endif /* HAVE__GETPTY */ #endif /* HAVE_OPENPTY */ /* Set the slave's terminal attributes if requested */ if (slave_termios && tcsetattr(*slavefd, TCSANOW, slave_termios) == -1) { close(*masterfd); close(*slavefd); return -1; } /* Set the slave's window size if required */ if (slave_winsize && ioctl(*slavefd, TIOCSWINSZ, slave_winsize) == -1) { close(*masterfd); close(*slavefd); return -1; } return 0; }
int tshd_runshell( int client ) { fd_set rd; struct winsize ws; char *slave, *temp, *shell; int ret, len, pid, pty, tty, n; /* request a pseudo-terminal */ #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF if( openpty( &pty, &tty, NULL, NULL, NULL ) < 0 ) { return( 24 ); } slave = ttyname( tty ); if( slave == NULL ) { return( 25 ); } #else #if defined IRIX slave = _getpty( &pty, O_RDWR, 0622, 0 ); if( slave == NULL ) { return( 26 ); } tty = open( slave, O_RDWR | O_NOCTTY ); if( tty < 0 ) { return( 27 ); } #else #if defined CYGWIN || defined SUNOS || defined HPUX pty = open( "/dev/ptmx", O_RDWR | O_NOCTTY ); if( pty < 0 ) { return( 28 ); } if( grantpt( pty ) < 0 ) { return( 29 ); } if( unlockpt( pty ) < 0 ) { return( 30 ); } slave = ptsname( pty ); if( slave == NULL ) { return( 31 ); } tty = open( slave, O_RDWR | O_NOCTTY ); if( tty < 0 ) { return( 32 ); } #if defined SUNOS || defined HPUX if( ioctl( tty, I_PUSH, "ptem" ) < 0 ) { return( 33 ); } if( ioctl( tty, I_PUSH, "ldterm" ) < 0 ) { return( 34 ); } #if defined SUNOS if( ioctl( tty, I_PUSH, "ttcompat" ) < 0 ) { return( 35 ); } #endif #endif #endif #endif #endif /* just in case bash is run, kill the history file */ temp = (char *) malloc( 10 ); if( temp == NULL ) { return( 36 ); } temp[0] = 'H'; temp[5] = 'I'; temp[1] = 'I'; temp[6] = 'L'; temp[2] = 'S'; temp[7] = 'E'; temp[3] = 'T'; temp[8] = '='; temp[4] = 'F'; temp[9] = '\0'; putenv( temp ); /* get the TERM environment variable */ ret = pel_recv_msg( client, message, &len ); if( ret != PEL_SUCCESS ) { return( 37 ); } message[len] = '\0'; temp = (char *) malloc( len + 6 ); if( temp == NULL ) { return( 38 ); } temp[0] = 'T'; temp[3] = 'M'; temp[1] = 'E'; temp[4] = '='; temp[2] = 'R'; strncpy( temp + 5, (char *) message, len + 1 ); putenv( temp ); /* get the window size */ ret = pel_recv_msg( client, message, &len ); if( ret != PEL_SUCCESS || len != 4 ) { return( 39 ); } ws.ws_row = ( (int) message[0] << 8 ) + (int) message[1]; ws.ws_col = ( (int) message[2] << 8 ) + (int) message[3]; ws.ws_xpixel = 0; ws.ws_ypixel = 0; if( ioctl( pty, TIOCSWINSZ, &ws ) < 0 ) { return( 40 ); } /* get the system command */ ret = pel_recv_msg( client, message, &len ); if( ret != PEL_SUCCESS ) { return( 41 ); } message[len] = '\0'; temp = (char *) malloc( len + 1 ); if( temp == NULL ) { return( 42 ); } strncpy( temp, (char *) message, len + 1 ); /* fork to spawn a shell */ pid = fork(); if( pid < 0 ) { return( 43 ); } if( pid == 0 ) { /* close the client socket and the pty (master side) */ close( client ); close( pty ); /* create a new session */ if( setsid() < 0 ) { return( 44 ); } /* set controlling tty, to have job control */ #if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF if( ioctl( tty, TIOCSCTTY, NULL ) < 0 ) { return( 45 ); } #else #if defined CYGWIN || defined SUNOS || defined IRIX || defined HPUX { int fd; fd = open( slave, O_RDWR ); if( fd < 0 ) { return( 46 ); } close( tty ); tty = fd; } #endif #endif /* tty becomes stdin, stdout, stderr */ dup2( tty, 0 ); dup2( tty, 1 ); dup2( tty, 2 ); if( tty > 2 ) { close( tty ); } /* fire up the shell */ shell = (char *) malloc( 8 ); if( shell == NULL ) { return( 47 ); } shell[0] = '/'; shell[4] = '/'; shell[1] = 'b'; shell[5] = 's'; shell[2] = 'i'; shell[6] = 'h'; shell[3] = 'n'; shell[7] = '\0'; execl( shell, shell + 5, "-c", temp, (char *) 0 ); /* d0h, this shouldn't happen */ return( 48 ); } else { /* tty (slave side) not needed anymore */ close( tty ); /* let's forward the data back and forth */ while( 1 ) { FD_ZERO( &rd ); FD_SET( client, &rd ); FD_SET( pty, &rd ); n = ( pty > client ) ? pty : client; if( select( n + 1, &rd, NULL, NULL, NULL ) < 0 ) { return( 49 ); } if( FD_ISSET( client, &rd ) ) { ret = pel_recv_msg( client, message, &len ); if( ret != PEL_SUCCESS ) { return( 50 ); } if( write( pty, message, len ) != len ) { return( 51 ); } } if( FD_ISSET( pty, &rd ) ) { len = read( pty, message, BUFSIZE ); if( len == 0 ) break; if( len < 0 ) { return( 52 ); } ret = pel_send_msg( client, message, len ); if( ret != PEL_SUCCESS ) { return( 53 ); } } } return( 54 ); } /* not reached */ return( 55 ); }
int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp) { #if defined(HAVE__GETPTY) /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ char *slave; if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL) return (-1); /* Open the slave side. */ if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); #elif defined(HAVE_DEV_PTMX) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ int ptm; char *pts; mysig_t old_signal; if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) return (-1); /* XXX: need to close ptm on error? */ old_signal = signal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) return (-1); signal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) return (-1); if ((pts = ptsname(ptm)) == NULL) return (-1); *amaster = ptm; /* Open the slave side. */ if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } /* * Try to push the appropriate streams modules, as described * in Solaris pts(7). */ ioctl(*aslave, I_PUSH, "ptem"); ioctl(*aslave, I_PUSH, "ldterm"); # ifndef __hpux ioctl(*aslave, I_PUSH, "ttcompat"); # endif /* __hpux */ return (0); #elif defined(HAVE_DEV_PTS_AND_PTC) /* AIX-style pty code. */ const char *ttname; if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1) return (-1); if ((ttname = ttyname(*amaster)) == NULL) return (-1); if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); #elif defined(_UNICOS) char ptbuf[64], ttbuf[64]; int i; int highpty; highpty = 128; #ifdef _SC_CRAY_NPTY if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1) highpty = 128; #endif /* _SC_CRAY_NPTY */ for (i = 0; i < highpty; i++) { snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i); snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i); if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1) continue; /* Open the slave side. */ if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) { close(*amaster); return (-1); } return (0); } return (-1); #elif defined(BARRELFISH) int ptm; char *pts; /* open master side */ ptm = posix_openpt(O_RDWR | O_NOCTTY); if (ptm < 0) { return -1; } if (grantpt(ptm) < 0) { return -1; } if (unlockpt(ptm) < 0) { return -1; } *amaster = ptm; pts = ptsname(ptm); if (pts == NULL) { return -1; } /* open slave side */ *aslave = open(pts, O_RDWR | O_NOCTTY); if (*aslave < 0) { close(*amaster); return -1; } return 0; #else /* BSD-style pty code. */ char ptbuf[64], ttbuf[64]; int i; const char *ptymajors = "pqrstuvwxyzabcdefghijklmno" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; struct termios tio; for (i = 0; i < num_ptys; i++) { snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) { /* Try SCO style naming */ snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i); snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i); if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) continue; } /* Open the slave side. */ if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) { close(*amaster); return (-1); } /* set tty modes to a sane state for broken clients */ if (tcgetattr(*amaster, &tio) != -1) { tio.c_lflag |= (ECHO | ISIG | ICANON); tio.c_oflag |= (OPOST | ONLCR); tio.c_iflag |= ICRNL; tcsetattr(*amaster, TCSANOW, &tio); } return (0); } return (-1); #endif }
int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) { #if defined(HAVE_OPENPTY) /* exists in recent (4.4) BSDs and OSF/1 */ char *name; int i; i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); if (i < 0) { dropbear_log(LOG_WARNING, "pty_allocate: openpty: %.100s", strerror(errno)); return 0; } name = ttyname(*ttyfd); if (!name) { dropbear_exit("ttyname fails for openpty device"); } strlcpy(namebuf, name, namebuflen); /* possible truncation */ return 1; #else /* HAVE_OPENPTY */ #ifdef HAVE__GETPTY /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ char *slave; slave = _getpty(ptyfd, O_RDWR, 0622, 0); if (slave == NULL) { dropbear_log(LOG_WARNING, "pty_allocate: _getpty: %.100s", strerror(errno)); return 0; } strlcpy(namebuf, slave, namebuflen); /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { dropbear_log(LOG_WARNING, "pty_allocate error: ttyftd open error"); close(*ptyfd); return 0; } return 1; #else /* HAVE__GETPTY */ #if defined(USE_DEV_PTMX) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) * * Linux systems may have the /dev/ptmx device, but this code won't work. */ int ptm; char *pts; ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); if (ptm < 0) { dropbear_log(LOG_WARNING, "pty_allocate: /dev/ptmx: %.100s", strerror(errno)); return 0; } if (grantpt(ptm) < 0) { dropbear_log(LOG_WARNING, "grantpt: %.100s", strerror(errno)); return 0; } if (unlockpt(ptm) < 0) { dropbear_log(LOG_WARNING, "unlockpt: %.100s", strerror(errno)); return 0; } pts = ptsname(ptm); if (pts == NULL) { dropbear_log(LOG_WARNING, "Slave pty side name could not be obtained."); } strlcpy(namebuf, pts, namebuflen); *ptyfd = ptm; /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { dropbear_log(LOG_ERR, "error opening pts %.100s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return 0; } #ifndef HAVE_CYGWIN /* * Push the appropriate streams modules, as described in Solaris pts(7). * HP-UX pts(7) doesn't have ttcompat module. */ if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) { dropbear_log(LOG_WARNING, "ioctl I_PUSH ptem: %.100s", strerror(errno)); } if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) { dropbear_log(LOG_WARNING, "ioctl I_PUSH ldterm: %.100s", strerror(errno)); } #ifndef __hpux if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) { dropbear_log(LOG_WARNING, "ioctl I_PUSH ttcompat: %.100s", strerror(errno)); } #endif #endif return 1; #else /* USE_DEV_PTMX */ #ifdef HAVE_DEV_PTS_AND_PTC /* AIX-style pty code. */ const char *name; *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY); if (*ptyfd < 0) { dropbear_log(LOG_ERR, "Could not open /dev/ptc: %.100s", strerror(errno)); return 0; } name = ttyname(*ptyfd); if (!name) { dropbear_exit("ttyname fails for /dev/ptc device"); } strlcpy(namebuf, name, namebuflen); *ttyfd = open(name, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { dropbear_log(LOG_ERR, "Could not open pty slave side %.100s: %.100s", name, strerror(errno)); close(*ptyfd); return 0; } return 1; #else /* HAVE_DEV_PTS_AND_PTC */ /* BSD-style pty code. */ char buf[64]; int i; const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; struct termios tio; for (i = 0; i < num_ptys; i++) { snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); snprintf(namebuf, namebuflen, "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); *ptyfd = open(buf, O_RDWR | O_NOCTTY); if (*ptyfd < 0) { /* Try SCO style naming */ snprintf(buf, sizeof buf, "/dev/ptyp%d", i); snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); *ptyfd = open(buf, O_RDWR | O_NOCTTY); if (*ptyfd < 0) { continue; } } /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { dropbear_log(LOG_ERR, "pty_allocate: %.100s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return 0; } /* set tty modes to a sane state for broken clients */ if (tcgetattr(*ptyfd, &tio) < 0) { dropbear_log(LOG_WARNING, "ptyallocate: tty modes failed: %.100s", strerror(errno)); } else { tio.c_lflag |= (ECHO | ISIG | ICANON); tio.c_oflag |= (OPOST | ONLCR); tio.c_iflag |= ICRNL; /* Set the new modes for the terminal. */ if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) { dropbear_log(LOG_WARNING, "Setting tty modes for pty failed: %.100s", strerror(errno)); } } return 1; } dropbear_log(LOG_WARNING, "failed to open any /dev/pty?? devices"); return 0; #endif /* HAVE_DEV_PTS_AND_PTC */ #endif /* USE_DEV_PTMX */ #endif /* HAVE__GETPTY */ #endif /* HAVE_OPENPTY */ }
int getpty(int *ptynum) { #if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */ { int master; int slave; if(openpty(&master, &slave, line, 0, 0) == 0){ ptyslavefd = slave; return master; } } #endif /* HAVE_OPENPTY .... */ #ifdef HAVE__GETPTY { int master; char *p; p = _getpty(&master, O_RDWR, 0600, 1); if(p == NULL) return -1; strlcpy(line, p, sizeof(Xline)); return master; } #endif #ifdef STREAMSPTY { char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", "/dev/ptym/clone", 0 }; char **q; int p; for(q=clone; *q; q++){ p=open(*q, O_RDWR); if(p >= 0){ #ifdef HAVE_GRANTPT grantpt(p); #endif #ifdef HAVE_UNLOCKPT unlockpt(p); #endif strlcpy(line, ptsname(p), sizeof(Xline)); really_stream = 1; return p; } } } #endif /* STREAMSPTY */ #ifndef _CRAY { int p; char *cp, *p1, *p2; int i; #ifndef __hpux snprintf(line, sizeof(Xline), "/dev/ptyXX"); p1 = &line[8]; p2 = &line[9]; #else snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); p1 = &line[13]; p2 = &line[14]; #endif for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { struct stat stb; *p1 = *cp; *p2 = '0'; /* * This stat() check is just to keep us from * looping through all 256 combinations if there * aren't that many ptys available. */ if (stat(line, &stb) < 0) break; for (i = 0; i < 16; i++) { *p2 = "0123456789abcdef"[i]; p = open(line, O_RDWR); if (p > 0) { #if SunOS == 40 int dummy; #endif #ifndef __hpux line[5] = 't'; #else for (p1 = &line[8]; *p1; p1++) *p1 = *(p1+1); line[9] = 't'; #endif chown(line, 0, 0); chmod(line, 0600); #if SunOS == 40 if (ioctl(p, TIOCGPGRP, &dummy) == 0 || errno != EIO) { chmod(line, 0666); close(p); line[5] = 'p'; } else #endif /* SunOS == 40 */ return(p); } } } } #else /* CRAY */ { extern lowpty, highpty; struct stat sb; int p; for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); p = open(myline, 2); if (p < 0) continue; snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); /* * Here are some shenanigans to make sure that there * are no listeners lurking on the line. */ if(stat(line, &sb) < 0) { close(p); continue; } if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { chown(line, 0, 0); chmod(line, 0600); close(p); p = open(myline, 2); if (p < 0) continue; } /* * Now it should be safe...check for accessability. */ if (access(line, 6) == 0) return(p); else { /* no tty side to pty so skip it */ close(p); } } } #endif /* CRAY */ return(-1); }
int forkpty(int *amaster,char *dummy,struct termios *termp, struct winsize *wp) { int master,slave; int pid; #ifdef HAVE__GETPTY int filedes[2]; char *line; line = _getpty(&filedes[0], O_RDWR|O_NDELAY, 0600, 0); if (0 == line) return -1; if (0 > (filedes[1] = open(line, O_RDWR))) { close(filedes[0]); return -1; } master=filedes[0]; slave=filedes[1]; #elif defined(HAVE_GRANTPT) && (defined(HAVE_GETPT) || defined(HAVE_DEV_PTMX) || defined(HAVE_POSIX_OPENPT)) # ifdef HAVE_PTSNAME char *name; # else char name[80]; # endif # ifdef HAVE_GETPT master=getpt(); # elif HAVE_POSIX_OPENPT master=posix_openpt(O_RDWR); # else master=open("/dev/ptmx", O_RDWR); # endif if (master<0) return -1; if (grantpt(master)<0||unlockpt(master)<0) goto close_master; # ifdef HAVE_PTSNAME if (!(name=ptsname(master))) goto close_master; # else if (ptsname_r(master,name,80)) goto close_master; # endif slave=open(name,O_RDWR); if (slave==-1) goto close_master; # ifdef HAVE_STROPTS_H if (isastream(slave)) if (ioctl(slave, I_PUSH, "ptem")<0 ||ioctl(slave, I_PUSH, "ldterm")<0) goto close_slave; # endif goto ok; //close_slave: close (slave); close_master: close (master); return -1; ok: #else char *p, *q, *l, *d; char PtyName[32], TtyName[32]; strcpy(PtyName, PtyProto); strcpy(TtyName, TtyProto); for (p = PtyName; *p != 'X'; p++) ; for (q = TtyName; *q != 'X'; q++) ; for (l = PTYRANGE0; (*p = *l) != '\0'; l++) { for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++) { // tintin_printf(0,"OpenPTY tries '%s'", PtyName); if ((master = open(PtyName, O_RDWR | O_NOCTTY)) == -1) continue; q[0] = *l; q[1] = *d; if (access(TtyName, R_OK | W_OK)) { close(master); continue; } if ((slave=open(TtyName, O_RDWR|O_NOCTTY))==-1) { close(master); continue; } goto ok; } } return -1; ok: #endif if (termp) tcsetattr(master, TCSANOW, termp); if (wp) ioctl(master,TIOCSWINSZ,wp); // let's ignore errors on this ioctl silently pid=fork(); switch (pid) { case -1: close(master); close(slave); return -1; case 0: close(master); setsid(); dup2(slave,0); dup2(slave,1); dup2(slave,2); close(slave); return 0; default: close(slave); *amaster=master; return pid; } }
int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) { #if defined(HAVE_OPENPTY) || defined(BSD4_4) /* openpty(3) exists in OSF/1 and some other os'es */ char *name; int i; i = openpty(ptyfd, ttyfd, NULL, NULL, NULL); if (i < 0) { error("openpty: %.100s", strerror(errno)); return 0; } name = ttyname(*ttyfd); if (!name) fatal("openpty returns device for which ttyname fails."); strlcpy(namebuf, name, namebuflen); /* possible truncation */ return 1; #else /* HAVE_OPENPTY */ #ifdef HAVE__GETPTY /* * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more * pty's automagically when needed */ char *slave; slave = _getpty(ptyfd, O_RDWR, 0622, 0); if (slave == NULL) { error("_getpty: %.100s", strerror(errno)); return 0; } strlcpy(namebuf, slave, namebuflen); /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { error("%.200s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return 0; } return 1; #else /* HAVE__GETPTY */ #if defined(HAVE_DEV_PTMX) /* * This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 * also has bsd-style ptys, but they simply do not work.) */ int ptm; char *pts; mysig_t old_signal; ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY); if (ptm < 0) { error("/dev/ptmx: %.100s", strerror(errno)); return 0; } old_signal = mysignal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) { error("grantpt: %.100s", strerror(errno)); return 0; } mysignal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) { error("unlockpt: %.100s", strerror(errno)); return 0; } pts = ptsname(ptm); if (pts == NULL) error("Slave pty side name could not be obtained."); strlcpy(namebuf, pts, namebuflen); *ptyfd = ptm; /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { error("%.100s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return 0; } #ifndef HAVE_CYGWIN /* * Push the appropriate streams modules, as described in Solaris pts(7). * HP-UX pts(7) doesn't have ttcompat module. */ if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) error("ioctl I_PUSH ptem: %.100s", strerror(errno)); if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) error("ioctl I_PUSH ldterm: %.100s", strerror(errno)); #ifndef __hpux if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) error("ioctl I_PUSH ttcompat: %.100s", strerror(errno)); #endif #endif return 1; #else /* HAVE_DEV_PTMX */ #ifdef HAVE_DEV_PTS_AND_PTC /* AIX-style pty code. */ const char *name; *ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY); if (*ptyfd < 0) { error("Could not open /dev/ptc: %.100s", strerror(errno)); return 0; } name = ttyname(*ptyfd); if (!name) fatal("Open of /dev/ptc returns device for which ttyname fails."); strlcpy(namebuf, name, namebuflen); *ttyfd = open(name, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { error("Could not open pty slave side %.100s: %.100s", name, strerror(errno)); close(*ptyfd); return 0; } return 1; #else /* HAVE_DEV_PTS_AND_PTC */ #ifdef _CRAY char buf[64]; int i; int highpty; #ifdef _SC_CRAY_NPTY highpty = sysconf(_SC_CRAY_NPTY); if (highpty == -1) highpty = 128; #else highpty = 128; #endif for (i = 0; i < highpty; i++) { snprintf(buf, sizeof(buf), "/dev/pty/%03d", i); *ptyfd = open(buf, O_RDWR|O_NOCTTY); if (*ptyfd < 0) continue; snprintf(namebuf, namebuflen, "/dev/ttyp%03d", i); /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); if (*ttyfd < 0) { error("%.100s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return 0; } return 1; } return 0; #else /* BSD-style pty code. */ char buf[64]; int i; const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors = "0123456789abcdef"; int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; struct termios tio; for (i = 0; i < num_ptys; i++) { snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); snprintf(namebuf, namebuflen, "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); *ptyfd = open(buf, O_RDWR | O_NOCTTY); if (*ptyfd < 0) { /* Try SCO style naming */ snprintf(buf, sizeof buf, "/dev/ptyp%d", i); snprintf(namebuf, namebuflen, "/dev/ttyp%d", i); *ptyfd = open(buf, O_RDWR | O_NOCTTY); if (*ptyfd < 0) continue; } /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR | O_NOCTTY); if (*ttyfd < 0) { error("%.100s: %.100s", namebuf, strerror(errno)); close(*ptyfd); return 0; } /* set tty modes to a sane state for broken clients */ if (tcgetattr(*ptyfd, &tio) < 0) log("Getting tty modes for pty failed: %.100s", strerror(errno)); else { tio.c_lflag |= (ECHO | ISIG | ICANON); tio.c_oflag |= (OPOST | ONLCR); tio.c_iflag |= ICRNL; /* Set the new modes for the terminal. */ if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) log("Setting tty modes for pty failed: %.100s", strerror(errno)); } return 1; } return 0; #endif /* CRAY */ #endif /* HAVE_DEV_PTS_AND_PTC */ #endif /* HAVE_DEV_PTMX */ #endif /* HAVE__GETPTY */ #endif /* HAVE_OPENPTY */ }
static int get_pty(int *pty, int *tty, char *ttydev, char *ptydev) { #ifdef USE_PRIVSEP if (priv_openpty(pty, tty) < 0) { return 1; } return 0; #elif HAVE_OPENPTY if (openpty(pty, tty, NULL, NULL, NULL) == -1) { return 1; } return 0; #elif defined (SVR4) || defined (USE_PTS) #if defined (_AIX) if ((*pty = open ("/dev/ptc", O_RDWR)) < 0) #else if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) #endif return 1; grantpt(*pty); unlockpt(*pty); strcpy(ttydev, (char *)ptsname(*pty)); if ((*tty = open(ttydev, O_RDWR)) >= 0) { (void)ioctl(*tty, I_PUSH, "ttcompat"); return 0; } if (*pty >= 0) close (*pty); #else /* !SVR4, need lots of code */ #ifdef USE_GET_PSEUDOTTY if ((*pty = getpseudotty (&ttydev, &ptydev)) >= 0 && (*tty = open (ttydev, O_RDWR)) >= 0) return 0; if (*pty >= 0) close (*pty); #else static int devindex, letter = 0; #ifdef sgi { char *slave; slave = _getpty (pty, O_RDWR, 0622, 0); if ((*tty = open (slave, O_RDWR)) != -1) return 0; } #else strcpy (ttydev, "/dev/ttyxx"); strcpy (ptydev, "/dev/ptyxx"); while (PTYCHAR1[letter]) { ttydev [strlen(ttydev) - 2] = ptydev [strlen(ptydev) - 2] = PTYCHAR1 [letter]; while (PTYCHAR2[devindex]) { ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] = PTYCHAR2 [devindex]; if ((*pty = open (ptydev, O_RDWR)) >= 0 && (*tty = open (ttydev, O_RDWR)) >= 0) { /* * We need to set things up for our next entry * into this function! */ (void) devindex++; return(0); } if (*pty >= 0) close (*pty); devindex++; } devindex = 0; (void) letter++; } #endif /* sgi else not sgi */ #endif /* USE_GET_PSEUDOTTY */ #endif /* SVR4 */ /* * We were unable to allocate a pty master! Return an error * condition and let our caller terminate cleanly. */ return(1); }
static int allocate_master(const char ** slave_name, const char** clone) { int master_fd = -1; static const char * const clones[] = /* Different pty master clone devices */ { "/dev/ptmx", /* Various systems */ "/dev/ptm/clone", /* HPUX */ "/dev/ptc", /* AIX */ "/dev/ptmx_bsd" /* Tru64 */ }; #ifdef HAVE_GETPT /* glibc */ master_fd = getpt (); if (master_fd >= 0) return master_fd; #endif /* HAVE_GETPT */ #if defined(HAVE_OPENPTY) /* BSD, Tru64, glibc */ { int slave_fd = -1; int rc; BLOCK_SIGNAL (SIGCHLD); rc = openpty (&master_fd, &slave_fd, NULL, NULL, NULL); UNBLOCK_SIGNAL (SIGCHLD); if (rc == 0) { *slave_name = ttyname (slave_fd); retry_close (slave_fd); return master_fd; } else { if (master_fd >= 0) retry_close (master_fd); if (slave_fd >= 0) retry_close (slave_fd); } } #endif /* HAVE_OPENPTY */ #if defined(HAVE__GETPTY) && defined (O_NDELAY) /* SGI */ master_fd = -1; BLOCK_SIGNAL (SIGCHLD); *slave_name = _getpty (&master_fd, O_RDWR | O_NDELAY, 0600, 0); UNBLOCK_SIGNAL (SIGCHLD); if (master_fd >= 0 && *slave_name != NULL) return master_fd; #endif /* HAVE__GETPTY */ /* Master clone devices are available on most systems */ { int i; for (i = 0; i < countof (clones); i++) { *clone = clones[i]; master_fd = open ((char *) *clone, // TODO: retry open O_RDWR | O_NONBLOCK, 0); if (master_fd >= 0) return master_fd; } *clone = NULL; } return -1; }