ckupty.c
资源名称:cku197.tar.Z [点击查看]
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:42k
源码类别:
通讯/手机编程
开发平台:
Windows_Unix
- /* C K U P T Y -- C-Kermit pseudoterminal control functions for UNIX */
- /*
- Copyright 1995 by the Massachusetts Institute of Technology.
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted, provided
- that the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation, and that the name of M.I.T. not be used in advertising or
- publicity pertaining to distribution of the software without specific,
- written prior permission. Furthermore if you modify this software you must
- label your software as modified software and not distribute it in such a
- fashion that it might be confused with the original M.I.T. software.
- M.I.T. makes no representations about the suitability of this software for
- any purpose. It is provided "as is" without express or implied warranty.
- Modified for use in C-Kermit, and new material added, by:
- Jeffrey Altman <jaltman@columbia.edu>
- The Kermit Project, Columbia University, New York City
- November 1999
- */
- /*
- Built and tested successully on:
- . 4.4BSD, including BSDI/OS, NetBSD, FreeBSD, OpenBSD, Mac OS X
- . AIX 4.1 and later
- . DG/UX 5.4R4.11
- . Digital UNIX 3.2 and 4.0
- . HP-UX 9.00 and later
- . IRIX 6.0 and later
- . Linux
- . NeXTSTEP 3.x
- . QNX 4.25 (except PTY process termination not detected)
- . SCO OSR5.0.5
- . SCO Unixware 7
- . SINIX 5.42
- . Solaris 2.x and 7
- . SunOS 4.1.3
- Included but not tested yet in:
- . Macintosh OSX, OpenBSD, and any other BSD44-based system not listed above
- Failures include:
- . SCO UNIX 3.2v4.2 (compile fails with syntax error in <memory.h>)
- . HP-UX 8.00 and earlier (no vhangup or ptsname routines)
- */
- #include "ckcdeb.h" /* To pick up NETPTY definition */
- #ifndef NETPTY /* Selector for PTY support */
- char * ptyver = "No PTY support";
- #else /* (rest of this module...) */
- char * ptyver = "PTY support 7.0.011, 28 Nov 1999";
- /* These will no doubt need adjustment... */
- #ifndef NEXT
- #define HAVE_SETSID
- #endif /* NEXT */
- #define HAVE_KILLPG
- #define HAVE_TTYNAME
- #define HAVE_WAITPID
- #ifndef USE_TERMIO
- #ifdef LINUX
- #define USE_TERMIO
- #else
- #ifdef ATTSV
- #define USE_TERMIO
- #else
- #ifdef HPUX
- #define USE_TERMIO
- #else
- #ifdef AIX
- #define USE_TERMIO
- #else
- #ifdef BSD44ORPOSIX
- #define USE_TERMIO
- #else
- #ifdef IRIX60
- #define USE_TERMIO
- #else
- #ifdef QNX
- #define USE_TERMIO
- #endif /* QNX */
- #endif /* IRIX60 */
- #endif /* BSD44ORPOSIX */
- #endif /* AIX */
- #endif /* HPUX */
- #endif /* ATTSV */
- #endif /* LINUX */
- #endif /* USE_TERMIO */
- #ifdef QNX
- #include <fcntl.h>
- #endif /* QNX */
- #ifdef USE_TERMIO
- #define POSIX_TERMIOS /* Seems to be a misnomer */
- #endif /* USE_TERMIO */
- #ifdef NEXT
- #ifndef GETPGRP_ONEARG
- #define GETPGRP_ONEARG
- #endif /* GETPGRP_ONEARG */
- #endif /* NEXT */
- #ifdef WANT_UTMP /* See ckupty.h */
- /*
- WANT_UTMP is not defined because (a) the utmp/wtmp junk is the most
- nonportable part of this module, and (b) we're not logging anybody
- in, we're just running a process, and don't need to write utmp/wtmp records.
- */
- #ifndef HAVE_SETUTXENT /* Who has <utmpx.h> */
- #ifdef SOLARIS
- #define HAVE_SETUTXENT
- #else
- #ifdef IRIX60
- #define HAVE_SETUTXENT
- #else
- #ifdef CK_SCOV5
- #define HAVE_SETUTXENT
- #else
- #ifdef HPUX10
- #define HAVE_SETUTXENT
- #else
- #ifdef UNIXWARE
- #define HAVE_SETUTXENT
- #else
- #ifdef IRIX60
- #define HAVE_SETUTXENT
- #endif /* IRIX60 */
- #endif /* UNIXWARE */
- #endif /* HPUX10 */
- #endif /* CK_SCOV5 */
- #endif /* IRIX60 */
- #endif /* SOLARIS */
- #endif /* HAVE_SETUTXENT */
- #ifndef HAVE_UTHOST /* Does utmp include ut_host[]? */
- #ifdef HAVE_SETUTXENT /* utmpx always does */
- #define HAVE_UTHOST
- #else
- #ifdef LINUX /* Linux does */
- #define HAVE_UTHOST
- #else
- #ifdef SUNOS4 /* SunOS does */
- #define HAVE_UTHOST
- #else
- #ifdef AIX41 /* AIX 4.1 and later do */
- #define HAVE_UTHOST
- #endif /* AIX41 */
- #endif /* SUNOS4 */
- #endif /* LINUX */
- #endif /* HAVE_SETUTXENT */
- #endif /* HAVE_UTHOST */
- #ifndef HAVE_UT_HOST
- #ifndef NO_UT_HOST
- #define NO_UT_HOST
- #endif /* NO_UT_HOST */
- #endif /* HAVE_UT_HOST */
- #endif /* WANT_UTMP */
- #ifdef LINUX
- #define CK_VHANGUP
- #define HAVE_SYS_SELECT_H
- #define HAVE_GETUTENT
- #define HAVE_SETUTENT
- #define HAVE_UPDWTMP
- #endif /* LINUX */
- #ifdef HPUX10
- #define CK_VHANGUP
- #define VHANG_FIRST
- #define HAVE_PTSNAME
- #ifndef HAVE_PTYTRAP
- #define HAVE_PTYTRAP
- #endif /* HAVE_PTYTRAP */
- #else
- #ifdef HPUX9
- #define CK_VHANGUP
- #define VHANG_FIRST
- #define HAVE_PTSNAME
- #ifndef HAVE_PTYTRAP
- #define HAVE_PTYTRAP
- #endif /* HAVE_PTYTRAP */
- #endif /* HPUX9 */
- #endif /* HPUX10 */
- #ifdef SUNOS4
- #define CK_VHANGUP
- #define NO_UT_PID
- #define VHANG_FIRST
- #endif /* SUNOS4 */
- #ifdef IRIX60
- #define CK_VHANGUP
- #define HAVE__GETPTY
- #endif /* IRIX60 */
- #ifdef SINIX
- #define HAVE_STREAMS
- #define HAVE_GRANTPT
- #define HAVE_PTSNAME
- #define PUSH_PTEM
- #define PUSH_LDTERM
- #define PUSH_TTCOMPAT
- #endif /* SINIX */
- #ifdef ultrix
- #define MUST_SETPGRP
- #endif /* ultrix */
- #ifdef QNX
- #define MUST_SETPGRP
- #define NO_DEVTTY
- #define INIT_SPTY
- #endif /* QNX */
- #include "ckupty.h"
- #ifndef O_NDELAY
- #ifdef O_NONBLOCK
- #define O_NDELAY O_NONBLOCK
- #endif /* O_NONBLOCK */
- #endif /* O_NDELAY */
- #ifndef ONLCR
- #define ONLCR 0
- #endif /* ONLCR */
- #ifdef CK_WAIT_H
- #include <sys/wait.h>
- #endif /* CK_WAIT_H */
- #ifdef STREAMSPTY
- #ifndef INIT_SPTY
- #define INIT_SPTY
- #endif /* INIT_SPTY */
- #include <sys/stream.h>
- #include <stropts.h>
- #include <termio.h>
- /* Make sure we don't get the BSD version */
- #ifdef HAVE_SYS_TTY_H
- #include "/usr/include/sys/tty.h"
- #endif /* HAVE_SYS_TTY_H */
- #ifdef HAS_PTYVAR /* Where is this set? */
- #include <sys/ptyvar.h>
- #else /* HAS_PTYVAR */
- #ifndef TIOCPKT_FLUSHWRITE
- #define TIOCPKT_FLUSHWRITE 0x02
- #define TIOCPKT_NOSTOP 0x10
- #define TIOCPKT_DOSTOP 0x20
- #define TIOCPKT_IOCTL 0x40
- #endif /* TIOCPKT_FLUSHWRITE */
- #endif /* HAS_PTYVAR */
- #ifdef HAVE_TTY_H
- #include <tty.h>
- #endif /* HAVE_TTY_H */
- /*
- Because of the way ptyibuf is used with streams messages, we need
- ptyibuf+1 to be on a full-word boundary. The following weirdness
- is simply to make that happen.
- */
- long ptyibufbuf[BUFSIZ/sizeof(long)+1];
- char *ptyibuf = ((char *)&ptyibufbuf[1])-1;
- char *ptyip = ((char *)&ptyibufbuf[1])-1;
- char ptyibuf2[BUFSIZ];
- unsigned char ctlbuf[BUFSIZ];
- struct strbuf strbufc, strbufd;
- int readstream();
- #else /* ! STREAMSPTY */
- /* I/O data buffers, pointers, and counters. */
- char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
- char ptyibuf2[BUFSIZ];
- #endif /* ! STREAMSPTY */
- #ifndef USE_TERMIO
- struct termbuf {
- struct sgttyb sg;
- struct tchars tc;
- struct ltchars ltc;
- int state;
- int lflags;
- } termbuf, termbuf2;
- #define cfsetospeed(tp,val) (tp)->sg.sg_ospeed = (val)
- #define cfsetispeed(tp,val) (tp)->sg.sg_ispeed = (val)
- #define cfgetospeed(tp) (tp)->sg.sg_ospeed
- #define cfgetispeed(tp) (tp)->sg.sg_ispeed
- #else /* USE_TERMIO */
- #ifdef SYSV_TERMIO
- #define termios termio
- #endif /* SYSV_TERMIO */
- #ifndef TCSANOW
- #ifdef TCSETS
- #define TCSANOW TCSETS
- #define TCSADRAIN TCSETSW
- #define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
- #else /* TCSETS */
- #ifdef TCSETA
- #define TCSANOW TCSETA
- #define TCSADRAIN TCSETAW
- #define tcgetattr(f,t) ioctl(f,TCGETA,(char *)t)
- #else /* TCSETA */
- #define TCSANOW TIOCSETA
- #define TCSADRAIN TIOCSETAW
- #define tcgetattr(f,t) ioctl(f,TIOCGETA,(char *)t)
- #endif /* TCSETA */
- #endif /* TCSETS */
- #define tcsetattr(f,a,t) ioctl(f,a,t)
- #define cfsetospeed(tp,val) (tp)->c_cflag &= ~CBAUD;(tp)->c_cflag|=(val)
- #define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
- #ifdef CIBAUD
- #define cfsetispeed(tp,val)
- (tp)->c_cflag &= ~CIBAUD; (tp)->c_cflag |= ((val)<<IBSHIFT)
- #define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
- #else /* CIBAUD */
- #define cfsetispeed(tp,val) (tp)->c_cflag &= ~CBAUD; (tp)->c_cflag|=(val)
- #define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
- #endif /* CIBAUD */
- #endif /* TCSANOW */
- struct termios termbuf, termbuf2; /* pty control structure */
- #ifdef INIT_SPTY
- static int spty = -1;
- #endif /* INIT_SPTY */
- #endif /* USE_TERMIO */
- extern int ttyfd; /* Standard Kermit usage */
- static int msg = 0;
- /* termbuf routines (begin) */
- /*
- init_termbuf()
- copy_termbuf(cp)
- set_termbuf()
- These three routines are used to get and set the "termbuf" structure
- to and from the kernel. init_termbuf() gets the current settings.
- copy_termbuf() hands in a new "termbuf" to write to the kernel, and
- set_termbuf() writes the structure into the kernel.
- */
- VOID
- init_termbuf() {
- int rc = 0;
- memset(&termbuf,0,sizeof(termbuf));
- memset(&termbuf2,0,sizeof(termbuf2));
- #ifndef USE_TERMIO
- rc = ioctl(ttyfd, TIOCGETP, (char *)&termbuf.sg);
- rc |= ioctl(ttyfd, TIOCGETC, (char *)&termbuf.tc);
- rc |= ioctl(ttyfd, TIOCGLTC, (char *)&termbuf.ltc);
- #ifdef TIOCGSTATE
- rc |= ioctl(ttyfd, TIOCGSTATE, (char *)&termbuf.state);
- #endif /* TIOCGSTATE */
- #else /* USE_TERMIO */
- errno = 0;
- #ifdef INIT_SPTY
- rc = tcgetattr(spty, &termbuf);
- debug(F111,"init_termbuf() tcgetattr(spty)",ckitoa(rc),errno);
- #else
- rc = tcgetattr(ttyfd, &termbuf);
- debug(F111,"init_termbuf() tcgetattr(ttyfd)",ckitoa(rc),errno);
- #endif /* INIT_SPTY */
- #endif /* USE_TERMIO */
- if (!rc)
- termbuf2 = termbuf;
- }
- #ifdef TIOCPKT_IOCTL
- VOID
- copy_termbuf(cp, len) char *cp; int len; {
- if (len > sizeof(termbuf))
- len = sizeof(termbuf);
- memcpy((char *)&termbuf, cp, len);
- termbuf2 = termbuf;
- }
- #endif /* TIOCPKT_IOCTL */
- VOID
- set_termbuf() { /* Only make the necessary changes. */
- #ifndef USE_TERMIO
- if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
- ioctl(ttyfd, TIOCSETN, (char *)&termbuf.sg);
- if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
- ioctl(ttyfd, TIOCSETC, (char *)&termbuf.tc);
- if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
- sizeof(termbuf.ltc)))
- ioctl(ttyfd, TIOCSLTC, (char *)&termbuf.ltc);
- if (termbuf.lflags != termbuf2.lflags)
- ioctl(ttyfd, TIOCLSET, (char *)&termbuf.lflags);
- #else /* USE_TERMIO */
- if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) {
- int x;
- errno = 0;
- #ifdef INIT_SPTY
- x = tcsetattr(spty, TCSANOW, &termbuf);
- debug(F111,"set_termbuf tcsetattr(spty)",ckitoa(x),errno);
- #else
- x = tcsetattr(ttyfd, TCSANOW, &termbuf);
- debug(F111,"set_termbuf tcsetattr(ttyfd)",ckitoa(x),errno);
- #endif /* INIT_SPTY */
- }
- #endif /* USE_TERMIO */
- }
- /* termbuf routines (end) */
- VOID
- ptyint_vhangup() {
- #ifdef CK_VHANGUP
- #ifdef CK_POSIX_SIG
- struct sigaction sa;
- /* Initialize "sa" structure. */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_IGN;
- sigaction(SIGHUP, &sa, (struct sigaction *)0);
- vhangup();
- sa.sa_handler = SIG_DFL;
- sigaction(SIGHUP, &sa, (struct sigaction *)0);
- #else /* CK_POSIX_SIG */
- signal(SIGHUP,SIG_IGN);
- vhangup();
- signal(SIGHUP,SIG_DFL);
- #endif /* CK_POSIX_SIG */
- #endif /* CK_VHANGUP */
- }
- /*
- This routine is called twice. It's not particularly important that the
- setsid() or TIOCSTTY ioctls succeed (they may not the second time), but
- rather that we have a controlling terminal at the end. It is assumed that
- vhangup doesn't exist and confuse the process's notion of controlling
- terminal on any system without TIOCNOTTY. That is, either vhangup() leaves
- the controlling terminal in tact, breaks the association completely, or the
- system provides TIOCNOTTY to get things back into a reasonable state. In
- practice, vhangup() either breaks the association completely or doesn't
- effect controlling terminals, so this condition is met.
- */
- long
- ptyint_void_association() {
- int con_fd;
- #ifdef HAVE_SETSID
- debug(F110,
- "ptyint_void_association()",
- "setsid()",
- 0
- );
- setsid();
- #endif /* HAVE_SETSID */
- #ifndef NO_DEVTTY
- /* Void tty association first */
- #ifdef TIOCNOTTY
- con_fd = open("/dev/tty", O_RDWR);
- debug(F111,
- "ptyint_void_association() open(/dev/tty,O_RDWR)",
- "/dev/tty",
- con_fd);
- if (con_fd >= 0) {
- ioctl(con_fd, TIOCNOTTY, 0);
- close(con_fd);
- }
- #endif /* TIOCNOTTY */
- #endif /* NO_DEVTTY */
- return(0);
- }
- /* PID may be zero for unknown.*/
- long
- pty_cleanup(slave, pid, update_utmp) char *slave; int pid; int update_utmp; {
- int retval, fd;
- debug(F111,"pty_cleanup()",slave,pid);
- #ifdef WANT_UTMP
- if (update_utmp)
- pty_update_utmp(PTY_DEAD_PROCESS,
- 0,
- "",
- slave,
- (char *)0,
- PTY_UTMP_USERNAME_VALID
- );
- #endif /* WANT_UTMP */
- #ifdef SETUID
- chmod(slave, 0666);
- chown(slave, 0, 0);
- #endif /* SETUID */
- #ifdef HAVE_REVOKE
- revoke(slave);
- /*
- Revoke isn't guaranteed to send a SIGHUP to the processes it
- dissociates from the terminal. The best solution without a Posix
- mechanism for forcing a hangup is to killpg() the process group of the
- pty. This will at least kill the shell and hopefully, the child
- processes. This is not always the case, however. If the shell puts
- each job in a process group and doesn't pass along SIGHUP, all
- processes may not die.
- */
- if (pid > 0) {
- #ifdef HAVE_KILLPG
- killpg(pid, SIGHUP);
- #else
- kill(-(pid), SIGHUP);
- #endif /*HAVE_KILLPG*/
- }
- #else /* HAVE_REVOKE*/
- #ifdef VHANG_LAST
- {
- int status;
- #ifdef CK_POSIX_SIG
- sigset_t old, new;
- sigemptyset(&new);
- sigaddset(&new, SIGCHLD);
- sigprocmask(SIG_BLOCK, &new, &old);
- #else /*CK_POSIX_SIG*/
- int mask = sigblock(sigmask(SIGCHLD));
- #endif /*CK_POSIX_SIG*/
- switch (retval = fork()) {
- case -1:
- #ifdef CK_POSIX_SIG
- sigprocmask(SIG_SETMASK, &old, 0);
- #else /*CK_POSIX_SIG*/
- sigsetmask(mask);
- #endif /*CK_POSIX_SIG*/
- return errno;
- case 0:
- ptyint_void_association();
- if (retval = (pty_open_ctty(slave, &fd)))
- exit(retval);
- ptyint_vhangup();
- exit(0);
- break;
- default:
- #ifdef HAVE_WAITPID
- waitpid(retval, &status, 0);
- #else /*HAVE_WAITPID*/
- wait(&status);
- #endif /* HAVE_WAITPID */
- #ifdef CK_POSIX_SIG
- sigprocmask(SIG_SETMASK, &old, 0);
- #else /*CK_POSIX_SIG*/
- sigsetmask(mask);
- #endif /*CK_POSIX_SIG*/
- break;
- }
- }
- #endif /*VHANG_LAST*/
- #endif /* HAVE_REVOKE*/
- #ifndef HAVE_STREAMS
- slave[strlen("/dev/")] = 'p';
- #ifdef SETUID
- chmod(slave, 0666);
- chown(slave, 0, 0);
- #endif /* SETUID */
- #endif /* HAVE_STREAMS */
- return(0);
- }
- long
- pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
- char *cp;
- char *p;
- int i, ptynum;
- struct stat stb;
- #ifndef HAVE_OPENPTY
- #ifndef HAVE__GETPTY
- char slavebuf[1024];
- #endif /* HAVE__GETPTY */
- #endif /* HAVE_OPENPTY */
- #ifdef HAVE__GETPTY
- char *slaveret; /* Temp 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 (strlen(slaveret) > slavelength - 1) {
- close(*fd);
- *fd = -1;
- return(PTY_GETPTY_SLAVE_TOOLONG);
- } else {
- strcpy(slave, slaveret);
- }
- return(0);
- #else /* HAVE__GETPTY */
- *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY); /* HPUX */
- if (*fd >= 0) {
- debug(F110,"pty_getpty()","open(/dev/ptym/clone) success",0);
- goto have_fd;
- }
- #ifdef HAVE_STREAMS
- *fd = open("/dev/ptmx",O_RDWR|O_NDELAY); /*Solaris*/
- if (*fd >= 0) {
- debug(F110,"pty_getpty()","open(/dev/ptmx) success",0);
- goto have_fd;
- }
- #endif /* HAVE_STREAMS */
- *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
- if (*fd >= 0) {
- debug(F110,"pty_getpty()","open(/dev/ptc) success",0);
- goto have_fd;
- }
- *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */
- if (*fd >= 0)
- debug(F110,"pty_getpty()","open(/dev/pty) success",0);
- have_fd:
- if (*fd >= 0) {
- #ifdef HAVE_GRANTPT
- #ifdef HAVE_STREAMS
- if (grantpt(*fd) || unlockpt(*fd))
- return(PTY_GETPTY_STREAMS);
- #endif /* HAVE_STREAMS */
- #endif /* HAVE_GRANTPT */
- #ifdef HAVE_PTSNAME
- p = (char *)ptsname(*fd);
- debug(F110,"pty_getpty() ptsname()",p,0);
- #else
- #ifdef HAVE_TTYNAME
- p = ttyname(*fd);
- debug(F110,"pty_getpty() ttyname()",p,0);
- #else
- /* XXX If we don't have either what do we do? */
- return(PTY_GETPTY_NOPTY); /* punt */
- #endif /* HAVE_TTYNAME */
- #endif /* HAVE_PTSNAME */
- if (p) {
- if (strlen(p) > slavelength - 1) {
- close (*fd);
- *fd = -1;
- return(PTY_GETPTY_SLAVE_TOOLONG);
- }
- strcpy(slave, p);
- return(0);
- }
- if (fstat(*fd, &stb) < 0) {
- close(*fd);
- return(PTY_GETPTY_FSTAT);
- }
- ptynum = (int)(stb.st_rdev&0xFF);
- sprintf(slavebuf, "/dev/ttyp%x", ptynum);
- if (strlen(slavebuf) > slavelength - 1) {
- close(*fd);
- *fd = -1;
- return(PTY_GETPTY_SLAVE_TOOLONG);
- }
- debug(F110,"pty_getpty() slavebuf",slavebuf,0);
- ckstrncpy(slave, slavebuf, slavelength);
- return(0);
- } else {
- for (cp = "pqrstuvwxyzPQRST";*cp; cp++) {
- sprintf(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|O_NDELAY);
- if (*fd < 0)
- continue;
- debug(F110,"pty_getpty() found pty master",slavebuf,0);
- slavebuf[sizeof("/dev/") - 1] = 't'; /* got pty */
- if (strlen(slavebuf) > slavelength -1) {
- close(*fd);
- *fd = -1;
- return(PTY_GETPTY_SLAVE_TOOLONG);
- }
- debug(F110,"pty_getpty() slavebuf [2]",slavebuf,0);
- ckstrncpy(slave, slavebuf, slavelength);
- return(0);
- }
- }
- return(PTY_GETPTY_NOPTY);
- }
- #endif /*HAVE__GETPTY*/
- #endif /* HAVE_OPENPTY */
- }
- long
- pty_init() {
- #ifdef HAVE_PTYM
- static char dummy;
- tty_bank = &master_name[strlen("/dev/ptym/pty")];
- tty_num = &master_name[strlen("/dev/ptym/ptyX")];
- slave_bank = &slave_name[strlen("/dev/pty/tty")];
- slave_num = &slave_name[strlen("/dev/pty/ttyX")];
- #endif
- return(0L);
- }
- /*
- The following is an array of modules that should be pushed on the stream.
- See configure.in for caviats and notes about when this array is used and not
- used.
- */
- #ifdef HAVE_STREAMS
- #ifndef HAVE_LINE_PUSH
- static char *push_list[] = {
- #ifdef PUSH_PTEM
- "ptem",
- #endif
- #ifdef PUSH_LDTERM
- "ldterm",
- #endif
- #ifdef PUSH_TTCOMPAT
- "ttcompat",
- #endif
- 0
- };
- #endif /* HAVE_LINE_PUSH */
- #endif /* HAVE_STREAMS */
- long
- pty_initialize_slave (fd) int fd; {
- #ifdef POSIX_TERMIOS
- #ifndef ultrix
- struct termios new_termio;
- #else
- struct sgttyb b;
- #endif /* ultrix */
- #else
- struct sgttyb b;
- #endif /* POSIX_TERMIOS */
- int pid;
- int rc;
- debug(F111,"pty_initialize_slave()","fd",fd);
- #ifdef HAVE_STREAMS
- #ifdef HAVE_LINE_PUSH
- while (ioctl(fd,I_POP,0) == 0) ; /* Clear out any old lined's */
- if (line_push(fd) < 0) {
- debug(F110,"pty_initialize_slave()","line_push() failed",0);
- close(fd);
- fd = -1;
- return(PTY_OPEN_SLAVE_LINE_PUSHFAIL);
- }
- #else /*No line_push */
- {
- char **module = &push_list[0];
- while (*module) {
- if (ioctl(fd, I_PUSH, *(module++)) < 0) {
- debug(F110,"pty_initialize_slave()","ioctl(I_PUSH) failed",0);
- return(PTY_OPEN_SLAVE_PUSH_FAIL);
- }
- }
- }
- #endif /*LINE_PUSH*/
- #endif /*HAVE_STREAMS*/
- /*
- Under Ultrix 3.0, the pgrp of the slave pty terminal needs to be set
- explicitly. Why rlogind works at all without this on 4.3BSD is a mystery.
- */
- #ifdef GETPGRP_ONEARG
- pid = getpgrp(getpid());
- #else
- pid = getpgrp();
- #endif /* GETPGRP_ONEARG */
- debug(F111,"pty_initialize_slave()","pid",pid);
- #ifdef TIOCSPGRP
- ioctl(fd, TIOCSPGRP, &pid);
- #endif /* TIOCSPGRP */
- #ifdef POSIX_TERMIOS
- #ifndef ultrix
- tcsetpgrp(fd, pid);
- errno = 0;
- rc = tcgetattr(fd,&new_termio);
- debug(F111,"pty_initialize_slave tcgetattr(fd)",ckitoa(rc),errno);
- if (rc == 0) {
- new_termio.c_cc[VMIN] = 1;
- new_termio.c_cc[VTIME] = 0;
- rc = tcsetattr(fd,TCSANOW,&new_termio);
- debug(F111,"pty_initialize_slave tcsetattr(fd)",ckitoa(rc),errno);
- }
- #endif /* ultrix */
- #endif /* POSIX_TERMIOS */
- return(0L);
- }
- #ifdef WANT_UTMP
- long
- pty_logwtmp (tty, user, host) char *user, *tty, *host; {
- #ifdef HAVE_LOGWTMP
- logwtmp(tty,user,host);
- return(0);
- #else
- struct utmp ut;
- char *tmpx;
- char utmp_id[5];
- int loggingin = user[0]; /* Will be empty for logout */
- #ifndef NO_UT_HOST
- strncpy(ut.ut_host, host, sizeof(ut.ut_host));
- #endif /* NO_UT_HOST */
- strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
- ut.ut_time = time(0);
- #ifndef NO_UT_PID
- ut.ut_pid = getpid();
- strncpy(ut.ut_user, user, sizeof(ut.ut_user));
- tmpx = tty + strlen(tty) - 2;
- sprintf(utmp_id, "kr%s", tmpx);
- strncpy(ut.ut_id, utmp_id, sizeof(ut.ut_id));
- ut.ut_pid = (loggingin ? getpid() : 0);
- ut.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);
- #else
- strncpy(ut.ut_name, user, sizeof(ut.ut_name));
- #endif /* NO_UT_PID */
- return(ptyint_update_wtmp(&ut, host, user));
- #endif /* HAVE_LOGWTMP */
- }
- #endif /* WANT_UTMP */
- /*
- This routine is called twice. It's not particularly important that the
- setsid() or TIOCSTTY ioctls succeed (they may not the second time), but
- rather that we have a controlling terminal at the end. It is assumed that
- vhangup doesn't exist and confuse the process's notion of controlling
- terminal on any system without TIOCNOTTY. That is, either vhangup() leaves
- the controlling terminal in tact, breaks the association completely, or the
- system provides TIOCNOTTY to get things back into a reasonable state. In
- practice, vhangup() either breaks the association completely or doesn't
- effect controlling terminals, so this condition is met.
- */
- long
- pty_open_ctty(slave, fd) char * slave; int *fd; {
- int retval;
- debug(F110,"pty_open_ctty() slave",slave,0);
- /* First, dissociate from previous terminal */
- if ((retval = ptyint_void_association()) != 0) {
- debug(F111,
- "pty_open_ctty()",
- "ptyint_void_association() failed",
- retval
- );
- return(retval);
- }
- #ifdef MUST_SETPGRP
- /*
- The Ultrix (and other BSD tty drivers) require the process group
- to be zero in order to acquire the new tty as a controlling tty.
- */
- setpgrp(0,0);
- #endif /* MUST_SETPGRP */
- errno = 0;
- *fd = open(slave, O_RDWR);
- if (*fd < 0) {
- debug(F111,"pty_open_ctty() open failure", slave, errno);
- return(PTY_OPEN_SLAVE_OPENFAIL);
- }
- #ifdef DEBUG
- else if (deblog) {
- debug(F110, "pty_open_ctty() open ok", slave, 0);
- }
- #endif /* DEBUG */
- #ifdef MUST_SETPGRP
- setpgrp(0, getpid());
- #endif /* MUST_SETPGRP */
- #ifdef TIOCSCTTY
- errno = 0;
- retval = ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/
- debug(F111,"pty_open_ctty() ioctl TIOCSCTTY",ckitoa(retval),errno);
- #endif /* TIOCSTTY */
- return(0L);
- }
- long
- pty_open_slave(slave, fd) char *slave; int *fd; {
- int vfd, testfd;
- long retval;
- #ifdef CK_POSIX_SIG
- struct sigaction sa;
- sigemptyset(&sa.sa_mask); /* Initialize "sa" structure. */
- sa.sa_flags = 0;
- #endif /* CK_POSIX_SIG */
- /*
- First, chmod and chown the slave. If we have vhangup then we really need
- pty_open_ctty to make sure our controlling terminal is the pty we're
- opening. However, if we are using revoke or nothing then we just need a
- file descriiptor for the pty. Considering some OSes in this category break
- on the second call to open_ctty (currently OSF but others may), we simply
- use a descriptor if we can.
- */
- #ifdef VHANG_FIRST
- if ((retval = pty_open_ctty(slave, &vfd)) != 0) {
- debug(F111,
- "pty_open_slave() VHANG_FIRST",
- "pty_open_ctty() failed",
- retval
- );
- return(retval);
- }
- if (vfd < 0) {
- debug(F111,
- "pty_open_slave() VHANG_FIRST",
- "PTY_OPEN_SLAVE_OPENFAIL",
- vfd
- );
- return(PTY_OPEN_SLAVE_OPENFAIL);
- }
- #endif /* VHANG_FIRST */
- if (slave == NULL || *slave == ' ') {
- debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_TOOSHORT",0);
- return(PTY_OPEN_SLAVE_TOOSHORT);
- }
- #ifdef SETUID
- if (chmod(slave, 0)) {
- debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHMODFAIL",0);
- return(PTY_OPEN_SLAVE_CHMODFAIL);
- }
- if (chown(slave, 0, 0 ) == -1 ) {
- debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHOWNFAIL",0);
- return(PTY_OPEN_SLAVE_CHOWNFAIL);
- }
- #endif /* SETUID */
- #ifdef VHANG_FIRST
- ptyint_vhangup();
- close(vfd);
- #endif /* VHANG_FIRST */
- if ((retval = ptyint_void_association()) != 0) {
- debug(F111,
- "pty_open_slave()",
- "ptyint_void_association() failed",
- retval
- );
- return(retval);
- }
- #ifdef HAVE_REVOKE
- if (revoke (slave) < 0 ) {
- debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_REVOKEFAIL",0);
- return(PTY_OPEN_SLAVE_REVOKEFAIL);
- }
- #endif /* HAVE_REVOKE */
- /* Open the pty for real. */
- retval = pty_open_ctty(slave, fd);
- if (retval != 0) {
- debug(F111,"pty_open_slave()","pty_open_ctty() failed",retval);
- return(PTY_OPEN_SLAVE_OPENFAIL);
- }
- retval = pty_initialize_slave(*fd);
- if (retval) {
- debug(F111,"pty_open_slave()","pty_initialize_slave() failed",retval);
- return(retval);
- }
- #ifndef NO_DEVTTY
- testfd = open("/dev/tty", O_RDWR|O_NDELAY);
- if (testfd < 0) {
- debug(F110,"pty_open_slave() open failed","/dev/tty",0);
- close(*fd);
- *fd = -1;
- return(PTY_OPEN_SLAVE_NOCTTY);
- }
- close(testfd);
- #endif /* NO_DEVTTY */
- debug(F110,"pty_open_slave()","success",0);
- return(0L);
- }
- #ifdef WANT_UTMP
- #ifndef UTMP_FILE
- #ifdef _PATH_UTMP
- #define UTMP_FILE _PATH_UTMP
- #endif /* _PATH_UTMP */
- #endif /* UTMP_FILE */
- /* If it is *still* missing, assume /etc/utmp */
- #ifndef UTMP_FILE
- #define UTMP_FILE "/etc/utmp"
- #endif /* UTMP_FILE */
- #ifndef NO_UT_PID
- #define WTMP_REQUIRES_USERNAME
- #endif /* NO_UT_PID */
- long
- pty_update_utmp(process_type, pid, username, line, host, flags)
- int process_type;
- int pid;
- char *username, *line, *host;
- int flags;
- /* pty_update_utmp */ {
- struct utmp ent, ut;
- #ifndef HAVE_SETUTENT
- struct stat statb;
- int tty;
- #endif /* HAVE_SETUTENT */
- #ifdef HAVE_SETUTXENT
- struct utmpx utx;
- #endif /* HAVE_SETUTXENT */
- #ifndef NO_UT_PID
- char *tmpx;
- char utmp_id[5];
- #endif /* NO_UT_PID */
- char userbuf[32];
- int fd;
- debug(F100,"pty_update_utmp()","",0);
- strncpy(ent.ut_line, line+sizeof("/dev/")-1, sizeof(ent.ut_line));
- ent.ut_time = time(0);
- #ifdef NO_UT_PID
- if (process_type == PTY_LOGIN_PROCESS)
- return(0L);
- #else /* NO_UT_PID */
- ent.ut_pid = pid;
- switch (process_type) {
- case PTY_LOGIN_PROCESS:
- ent.ut_type = LOGIN_PROCESS;
- break;
- case PTY_USER_PROCESS:
- ent.ut_type = USER_PROCESS;
- break;
- case PTY_DEAD_PROCESS:
- ent.ut_type = DEAD_PROCESS;
- break;
- default:
- return(PTY_UPDATE_UTMP_PROCTYPE_INVALID);
- }
- #endif /*NO_UT_PID*/
- #ifndef NO_UT_HOST
- if (host)
- strncpy(ent.ut_host, host, sizeof(ent.ut_host));
- else
- ent.ut_host[0] = ' ';
- #endif /* NO_UT_HOST */
- #ifndef NO_UT_PID
- if (!strcmp (line, "/dev/console")) {
- char * s = NULL;
- #ifdef sun
- #ifdef __SVR4
- s = "co";
- #else
- s = "cons";
- #endif /* __SVR4 */
- #else
- s = "cons";
- #endif /* sun */
- strncpy(ent.ut_id, s, 4);
- } else {
- tmpx = line + strlen(line)-1;
- if (*(tmpx-1) != '/') tmpx--; /* last 2 chars unless it's a '/' */
- #ifdef __hpux
- strcpy(utmp_id, tmpx);
- #else
- sprintf(utmp_id, "kl%s", tmpx);
- #endif /* __hpux */
- strncpy(ent.ut_id, utmp_id, sizeof(ent.ut_id));
- }
- strncpy(ent.ut_user, username, sizeof(ent.ut_user));
- #else
- strncpy(ent.ut_name, username, sizeof(ent.ut_name));
- #endif /* NO_UT_PID */
- if (username[0])
- strncpy(userbuf, username, sizeof(userbuf));
- else
- userbuf[0] = ' ';
- #ifdef HAVE_SETUTENT
- utmpname(UTMP_FILE);
- setutent();
- /*
- If we need to preserve the user name in the wtmp structure and Our flags
- tell us we can obtain it from the utmp and we succeed in obtaining it, we
- then save the utmp structure we obtain, write out the utmp structure and
- change the username pointer so it is used by update_wtmp.
- */
- #ifdef WTMP_REQUIRES_USERNAME
- if ((!username[0]) && (flags&PTY_UTMP_USERNAME_VALID) &&line) {
- struct utmp *utptr;
- strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- utptr = getutline(&ut);
- if (utptr)
- strncpy(userbuf,utptr->ut_user,sizeof(ut.ut_user));
- }
- #endif /* WTMP_REQUIRES_USERNAME */
- pututline(&ent);
- endutent();
- #ifdef HAVE_SETUTXENT
- setutxent();
- #ifdef HAVE_GETUTMPX
- getutmpx(&ent, &utx);
- #else /* HAVE_GETUTMPX */
- /* For platforms like HPUX and Dec Unix which don't have getutmpx */
- strncpy(utx.ut_user, ent.ut_user, sizeof(ent.ut_user));
- strncpy(utx.ut_id, ent.ut_id, sizeof(ent.ut_id));
- strncpy(utx.ut_line, ent.ut_line, sizeof(ent.ut_line));
- utx.ut_pid = pid; /* kludge for Irix, etc. to avoid trunc. */
- utx.ut_type = ent.ut_type;
- #ifdef UT_EXIT_STRUCTURE_DIFFER
- utx.ut_exit.ut_exit = ent.ut_exit.e_exit;
- #else /* UT_EXIT_STRUCTURE_DIFFER */
- /* KLUDGE for now; eventually this will be a feature test... See PR#[40] */
- #ifdef __hpux
- utx.ut_exit.__e_termination = ent.ut_exit.e_termination;
- utx.ut_exit.__e_exit = ent.ut_exit.e_exit;
- #else /* __hpux */
- /* XXX do nothing for now; we don't even know the struct member exists */
- #endif /* __hpux */
- #endif /* UT_EXIT_STRUCTURE_DIFFER */
- utx.ut_tv.tv_sec = ent.ut_time;
- utx.ut_tv.tv_usec = 0;
- #endif /* HAVE_GETUTMPX */
- if (host)
- strncpy(utx.ut_host, host, sizeof(utx.ut_host));
- else
- utx.ut_host[0] = 0;
- pututxline(&utx);
- endutxent();
- #endif /* HAVE_SETUTXENT */
- #else /* HAVE_SETUTENT */
- if (flags&PTY_TTYSLOT_USABLE) {
- tty = ttyslot();
- } else {
- int lc;
- tty = -1;
- if ((fd = open(UTMP_FILE, O_RDWR)) < 0)
- return(errno);
- for (lc = 0;
- lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET) != -1;
- lc++
- ) {
- if (read(fd,
- (char *)&ut,
- sizeof(struct utmp)
- ) != sizeof(struct utmp)
- )
- break;
- if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
- tty = lc;
- #ifdef WTMP_REQUIRES_USERNAME
- if (!username&&(flags&PTY_UTMP_USERNAME_VALID))
- strncpy(userbuf, ut.ut_user, sizeof(ut.ut_user));
- #endif /* WTMP_REQUIRES_USERNAME */
- break;
- }
- }
- close(fd);
- }
- if (tty > 0 && (fd = open(UTMP_FILE, O_WRONLY, 0)) >= 0) {
- lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
- write(fd, (char *)&ent, sizeof(struct utmp));
- close(fd);
- }
- #endif /* HAVE_SETUTENT */
- /* Don't record LOGIN_PROCESS entries. */
- if (process_type == PTY_LOGIN_PROCESS)
- return(0);
- else
- return(ptyint_update_wtmp(&ent, host, userbuf));
- }
- #ifndef WTMP_FILE
- #ifdef _PATH_WTMP
- #define WTMP_FILE _PATH_WTMP
- #endif /* _PATH_WTMP */
- #endif /* WTMP_FILE */
- #ifndef WTMPX_FILE
- #ifdef _PATH_WTMPX
- #ifdef HAVE_UPDWTMPX
- #define WTMPX_FILE _PATH_WTMPX
- #endif /* HAVE_UPDWTMPX */
- #endif /* _PATH_WTMPX */
- #endif /* WTMPX_FILE */
- /* If it is *still* missing, assume /usr/adm/wtmp */
- #ifndef WTMP_FILE
- #define WTMP_FILE "/usr/adm/wtmp"
- #endif /* WTMP_FILE */
- #ifdef COMMENT
- /* The following test can not be made portably */
- /* #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) */
- /*
- This is ugly, but the lack of standardization in the utmp/utmpx space, and
- what glibc implements and doesn't make available, is even worse.
- */
- /* #undef HAVE_UPDWTMPX */ /* Don't use updwtmpx for glibc 2.1 */
- /* #endif */ /* __GLIBC__ etc */
- #else /* COMMENT */
- #ifdef __GLIBC__
- #undef HAVE_UPDWTMPX /* Don't use updwtmpx for glibc period */
- #endif /* __GLIBC__ */
- #endif /* COMMENT */
- long
- ptyint_update_wtmp(ent,host,user) struct utmp *ent; char *host; char *user; {
- struct utmp ut;
- struct stat statb;
- int fd;
- time_t uttime;
- #ifdef HAVE_UPDWTMPX
- struct utmpx utx;
- getutmpx(ent, &utx);
- if (host)
- strncpy(utx.ut_host, host, sizeof(utx.ut_host) );
- else
- utx.ut_host[0] = 0;
- if (user)
- strncpy(utx.ut_user, user, sizeof(utx.ut_user));
- updwtmpx(WTMPX_FILE, &utx);
- #endif /* HAVE_UPDWTMPX */
- #ifdef HAVE_UPDWTMP
- #ifndef HAVE_UPDWTMPX
- /* This is already performed byupdwtmpx if present.*/
- updwtmp(WTMP_FILE, ent);
- #endif /* HAVE_UPDWTMPX*/
- #else /* HAVE_UPDWTMP */
- if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) >= 0) {
- if (!fstat(fd, &statb)) {
- memset((char *)&ut, 0, sizeof(ut));
- #ifdef __hpux
- strncpy(ut.ut_id, ent->ut_id, sizeof (ut.ut_id));
- #endif /* __hpux */
- strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line));
- strncpy(ut.ut_name, ent->ut_name, sizeof(ut.ut_name));
- #ifndef NO_UT_HOST
- strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));
- #endif /* NO_UT_HOST */
- time(&uttime);
- ut.ut_time = uttime;
- #ifdef HAVE_GETUTENT
- #ifdef USER_PROCESS
- if (ent->ut_name) {
- if (!ut.ut_pid)
- ut.ut_pid = getpid();
- #ifndef __hpux
- ut.ut_type = USER_PROCESS;
- #else /* __hpux */
- ut.ut_type = ent->ut_type;
- #endif /* __hpux */
- } else {
- #ifdef EMPTY
- ut.ut_type = EMPTY;
- #else
- ut.ut_type = DEAD_PROCESS; /* For Linux brokenness*/
- #endif /* EMPTY */
- }
- #endif /* USER_PROCESS */
- #endif /* HAVE_GETUTENT */
- if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
- sizeof(struct utmp))
- #ifndef COHERENT
- ftruncate(fd, statb.st_size);
- #else
- chsize(fd, statb.st_size);
- #endif /* COHERENT */
- }
- close(fd);
- }
- #endif /* HAVE_UPDWTMP */
- return(0); /* no current failure cases; file not found is not failure!*/
- }
- #endif /* WANT_UTMP */
- static char Xline[17] = { 0, 0 };
- static int slavepid = -1;
- /*
- getptyslave()
- Open the slave side of the pty, and do any initialization that is necessary.
- The return value is a file descriptor for the slave side.
- */
- int
- getptyslave() {
- int t = -1;
- long retval;
- #ifdef TIOCGWINSZ
- struct winsize ws;
- extern int cmd_rows, cmd_cols;
- #endif /* TIOCGWINSZ */
- extern int def_tspeed, def_rspeed;
- debug(F100,"getptyslave()","",0);
- /*
- * Opening the slave side may cause initilization of the
- * kernel tty structure. We need remember the state of:
- * if linemode was turned on
- * terminal window size
- * terminal speed
- * so that we can reset them if we need to.
- */
- if ((retval = pty_open_slave(Xline, &t)) != 0) {
- perror(Xline);
- msg++;
- debug(F111,"getptyslave()","Unable to open slave",retval);
- return(-1);
- }
- debug(F111,"getptyslave","ttyfd",ttyfd);
- debug(F111,"getptyslave","t",t);
- #ifdef INIT_SPTY
- spty = t;
- #endif /* INIT_SPTY */
- #ifdef STREAMSPTY
- if (ioctl(t,I_PUSH,"pckt") < 0) {
- debug(F111,"getptyslave()","ioctl(I_PUSH) failed",errno);
- #ifndef _AIX
- fatal("I_PUSH pckt");
- #endif /* _AIX */
- }
- #endif /* STREAMSPTY */
- /* Set up the tty modes as we like them to be. */
- init_termbuf();
- #ifdef TIOCGWINSZ
- if (cmd_rows || cmd_cols) {
- memset((char *)&ws, 0, sizeof(ws));
- ws.ws_col = cmd_cols;
- ws.ws_row = cmd_rows;
- ioctl(t, TIOCSWINSZ, (char *)&ws);
- }
- #endif /* TIOCGWINSZ */
- /* Settings for sgtty based systems */
- #ifndef USE_TERMIO
- termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
- #endif /* USE_TERMIO */
- #ifndef OXTABS
- #define OXTABS 0
- #endif /* OXTABS */
- /* Settings for UNICOS and HPUX */
- #ifdef CRAY
- termbuf.c_oflag = OPOST|ONLCR|TAB3;
- termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
- termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
- termbuf.c_cflag = EXTB|HUPCL|CS8;
- #else /* CRAY */
- #ifdef HPUX
- termbuf.c_oflag = OPOST|ONLCR|TAB3;
- termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
- termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
- termbuf.c_cflag = EXTB|HUPCL|CS8;
- #else /* HPUX */
- #ifdef USE_TERMIO
- /*
- Settings for all other termios/termio based systems, other than 4.4BSD.
- In 4.4BSD the kernel does the initial terminal setup.
- */
- #ifdef BSD42
- #ifndef BSD44
- termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
- termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
- termbuf.c_iflag |= ICRNL|IGNPAR;
- termbuf.c_cflag |= HUPCL;
- termbuf.c_iflag &= ~IXOFF;
- #endif /* BSD44 */
- #else /* BSD42 */
- termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
- termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
- termbuf.c_iflag |= ICRNL|IGNPAR;
- termbuf.c_cflag |= HUPCL;
- termbuf.c_iflag &= ~IXOFF;
- #endif /* BSD42 */
- #endif /* USE_TERMIO */
- #endif /* HPUX */
- #endif /* CRAY */
- set_termbuf(); /* Set the tty modes, and make this our controlling tty. */
- if (t != 0)
- dup2(t, 0);
- if (t != 1)
- dup2(t, 1);
- if (t != 2)
- dup2(t, 2);
- if (t > 2)
- close(t);
- if (ttyfd > 2) {
- close(ttyfd);
- ttyfd = -1;
- }
- return(0);
- }
- #ifdef HAVE_PTYTRAP
- /*
- To be called to determine if a trap is pending on a pty
- if and only if select() cannot be used.
- */
- int
- pty_trap_pending(fd) int fd; {
- int pending;
- int rc;
- rc = ioctl(fd, TIOCTRAPSTATUS, (char *)&pending, sizeof(pending));
- if (rc == 0) {
- debug(F101,"pty_trap_pending()","",pending);
- return(pending);
- } else {
- debug(F111,"pty_trap_pending()","ioctl() failed",rc);
- return(-1);
- }
- }
- /*
- To be called after select() has returned indicating that an exception is
- waiting on a pty. It should be called with the file descriptor of the pty.
- Returns -1 on error; 0 if pty is still open; 1 if pty has closed.
- */
- int
- pty_trap_handler(fd) int fd; {
- struct request_info ri;
- memset(&ri,0,sizeof(ri));
- if (ioctl(fd,TIOCREQCHECK,(char *)&ri, sizeof(ri)) != 0) {
- debug(F111,"pty_trap_handler()","ioctl(TIOCREQCHECK) failed",errno);
- return(-1);
- }
- switch (ri.request) {
- case TIOCOPEN:
- debug(F110,"pty_trap_handler()","an open() call",0);
- break;
- case TIOCCLOSE:
- debug(F110,"pty_trap_handler()","a close() call",0);
- break;
- default:
- debug(F110,"pty_trap_handler()","an ioctl() call",0);
- ri.errno_error = EINVAL;
- }
- if (ioctl(fd, TIOCREQSET, (char *)&ri,sizeof(ri)) != 0) {
- debug(F111,"pty_trap_handler()","ioctl(TIOCREQSET) failed",errno);
- return(-1);
- }
- if (ri.request == TIOCCLOSE)
- return(1);
- else
- return(0);
- }
- #endif /* HAVE_PTYTRAP */
- VOID
- exec_cmd(s) char * s; {
- char *args[50];
- char *cp;
- int argi = 0;
- int quoting = 0;
- int in_token = 0; /* TRUE if we are reading a token */
- debug(F110,"exec_cmd()",s,0);
- args[0] = cp = s;
- while (*s && argi < 49) {
- if (quoting) {
- if (*s == '\' && *(s+1) == '"') { /* quoted quote */
- s++; /* get past " */
- *cp++ = *s++;
- } else if (*s == '"') { /* close quote */
- quoting = 0;
- } else
- *cp++ = *s++; /* suck up anything */
- } else if (*s == '"') { /* open quote */
- in_token = 1;
- quoting = 1;
- s++;
- } else if (isspace(*s)) {
- if (in_token) {
- *cp++ = ' ';
- argi++;
- args[argi] = cp;
- in_token = 0;
- }
- s++;
- } else {
- *cp++ = *s++;
- in_token = 1;
- }
- }
- if (args[argi][0]) {
- *cp++ = ' ';
- argi++;
- }
- args[argi] = (char *) 0; /* terminate argv */
- debug(F111,"exec_cmd()","calling execvp() - # of args",argi-1);
- execvp(args[0],args);
- }
- /* Get a pty, scan input lines. */
- int
- do_pty(cmd) char * cmd; {
- int ptynum;
- long retval;
- int syncpipe[2];
- int i, x;
- msg = 0; /* Message counter */
- pty_init(); /* Find an available pty to use. */
- if ((retval = pty_getpty(&ttyfd, Xline, 20)) != 0) {
- debug(F111,"do_pty()","pty_getpty() fails",retval);
- return(-1);
- }
- debug(F110,"do_pty() Xline",Xline,0);
- #ifdef SIGTTOU
- /*
- Ignoring SIGTTOU keeps the kernel from blocking us. we tweak the tty with
- an ioctl() (in ttioct() in /sys/tty.c in a BSD kernel)
- */
- signal(SIGTTOU, SIG_IGN);
- #endif /* SIGTTOU */
- /* Start up the command on the slave side of the terminal */
- if (pipe(syncpipe) < 0) {
- debug(F110,"do_pty()","pipe() fails",0);
- return(-1);
- }
- if ((i = fork()) < 0) {
- /* XXX - need to clean up the allocated pty */
- perror("Fork failure");
- msg++;
- debug(F111,"do_pty()","fork fails",errno);
- return(-1);
- }
- if (i) { /* Wait for child before writing to parent side of pty. */
- char c;
- #ifdef HAVE_PTYTRAP
- int on = 1;
- #endif /* HAVE_PTYTRAP */
- close(syncpipe[1]);
- if (read(syncpipe[0], &c, 1) == 0) { /* Slave side died */
- if (msg++ == 0)
- printf("?Initialization failurern");
- debug(F110,"do_pty()","Slave fails to initialize",0);
- close(syncpipe[0]);
- return(-1);
- }
- slavepid = i; /* So we can clean it up later */
- #ifdef HAVE_PTYTRAP
- /* HPUX does not allow the master to read end of file. */
- /* Therefore, we must determine that the slave has been */
- /* closed by trapping the call to close(). */
- errno = 0;
- x = ioctl(ttyfd, TIOCTRAP, (char *)&on);
- debug(F111,"do_pty ioctl(TIOCTRAP)",ckitoa(x),errno);
- #endif /* HAVE_PTYTRAP */
- debug(F111,"do_pty()","synchronized - slavepid",slavepid);
- close(syncpipe[0]);
- } else {
- char *p;
- debug(F110,"do_pty()","Slave starts",0);
- if (getptyslave() == 0) {
- #ifdef WANT_UTMP
- pty_update_utmp(PTY_USER_PROCESS,
- getpid(),
- "KERMIT",
- Xline,
- cmd,
- PTY_TTYSLOT_USABLE
- );
- #endif /* WANT_UTMP */
- /* Notify our parent we're ready to continue.*/
- debug(F110,"do_pty()","slave synchronizing",0);
- write(syncpipe[1],"y",1);
- close(syncpipe[0]);
- close(syncpipe[1]);
- exec_cmd(cmd);
- debug(F111,"do_pty()","exec_cmd() returns - why?",errno);
- }
- debug(F110,"do_pty()","getptyslave() fails - exiting",0);
- exit(1);
- }
- return(0);
- } /* end of do_pty() */
- VOID
- end_pty() {
- msg = 0; /* Message counter */
- if (Xline[0] && slavepid >= 0) {
- pty_cleanup(Xline,slavepid,1);
- Xline[0] = ' ';
- slavepid = -1;
- }
- }
- #endif /* NETPTY */