home *** CD-ROM | disk | FTP | other *** search
- /* pty_termios.c - routines to allocate ptys - termios version
-
- Written by: Don Libes, NIST, 2/6/90
-
- Design and implementation of this program was paid for by U.S. tax
- dollars. Therefore it is public domain. However, the author and NIST
- would appreciate credit if this program or parts of it are used.
-
- */
-
- #include "exp_conf.h"
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifdef HAVE_SYSMACROS_H
- #include <sys/sysmacros.h>
- #endif
-
- #ifdef HAVE_PTYTRAP
- #include <sys/ptyio.h>
- #endif
-
- #include <sys/file.h>
-
- #ifdef HAVE_SYS_FCNTL_H
- # include <sys/fcntl.h>
- #else
- # include <fcntl.h>
- #endif
-
- #ifdef HAVE_PTMX
- # include <sys/stropts.h>
- #endif
-
- #include "exp_tty.h"
- #include "exp_rename.h"
- #include "exp_pty.h"
-
- void debuglog();
-
- extern int errno;
- extern char *sys_errlist[];
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
-
- #if defined(HAVE__GETPTY) || defined(HAVE_PTC) || defined(HAVE_PTC_PTS) || defined(HAVE_PTMX)
- static char *slave_name;
- #endif
-
- #if defined(HAVE_GETPTY)
- #include <sys/vty.h>
- static char master_name[MAXPTYNAMELEN];
- static char slave_name[MAXPTYNAMELEN];
- #endif
-
- #if !defined(HAVE_GETPTY) && !defined(HAVE_GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX)
- #ifdef HAVE_PTYM
- static char master_name[] = "/dev/ptym/ptyXX";
- static char slave_name[] = "/dev/pty/ttyXX";
- static char *slave_bank;
- static char *slave_num;
- #else
- static char master_name[] = "/dev/ptyXX";
- static char slave_name [] = "/dev/ttyXX";
- #endif
- #endif
-
- static char *tty_type; /* ptr to char [pt] denoting
- whether it is a pty or tty */
- static char *tty_bank; /* ptr to char [p-z] denoting
- which bank it is */
- static char *tty_num; /* ptr to char [0-f] denoting
- which number it is */
- static void
- pty_stty(s,name)
- char *s; /* args to stty */
- char *name; /* name of pty */
- {
- #define MAX_ARGLIST 10240
- char buf[MAX_ARGLIST]; /* overkill is easier */
-
- sprintf(buf,"stty %s < %s > %s",s,name,name);
- system(buf);
- }
-
- exp_tty exp_tty_original;
-
- int dev_tty; /* file descriptor to /dev/tty or -1 if none */
- int knew_dev_tty; /* true if we had our hands on /dev/tty at any time */
-
- #define GET_TTYTYPE 0
- #define SET_TTYTYPE 1
- static void
- ttytype(request,fd,ttycopy,ttyinit,s)
- int request;
- int fd;
- /* following are used only if request == SET_TTYTYPE */
- int ttycopy; /* true/false, copy from /dev/tty */
- int ttyinit; /* if true, initialize to sane state */
- char *s; /* stty args */
- {
- if (request == GET_TTYTYPE) {
- #ifdef POSIX
- if (-1 == tcgetattr(fd, &exp_tty_original)) {
- #else
- if (-1 == ioctl(fd, TCGETS, (char *)&exp_tty_original)) {
- #endif
- knew_dev_tty = FALSE;
- dev_tty = -1;
- }
- } else { /* type == SET_TTYTYPE */
- if (ttycopy && knew_dev_tty) {
- #ifdef POSIX
- (void) tcsetattr(fd, TCSADRAIN, &exp_tty_original);
- #else
- (void) ioctl(fd, TCSETS, (char *)&exp_tty_original);
- #endif
- }
-
- #ifdef __SABER__
- #undef DFLT_STTY
- #define DFLT_STTY "sane"
- #endif
- if (ttyinit) {
- /* overlay parms originally supplied by Makefile */
- debuglog("getptyslave: (default) stty %s\n",DFLT_STTY);
- pty_stty(DFLT_STTY,slave_name);
- }
-
- /* lastly, give user chance to override any terminal parms */
- if (s) {
- /* give user a chance to override any terminal parms */
- debuglog("getptyslave: (user-requested) stty %s\n",s);
- pty_stty(s,slave_name);
- }
- }
- }
-
- void
- init_pty()
- {
- #if !defined(HAVE_GETPTY) && !defined(HAVE_GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX)
- #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")];
- #else
- tty_bank = &master_name[strlen("/dev/pty")];
- tty_num = &master_name[strlen("/dev/ptyp")];
- tty_type = &slave_name[strlen("/dev/")];
- #endif
-
- #endif /* HAVE_PTYM */
-
-
- dev_tty = open("/dev/tty",O_RDWR);
- knew_dev_tty = (dev_tty != -1);
- if (knew_dev_tty) ttytype(GET_TTYTYPE,dev_tty,0,0,(char *)0);
- }
-
- #ifndef R_OK
- /* 3b2 doesn't define these according to jthomas@nmsu.edu. */
- #define R_OK 04
- #define W_OK 02
- #endif
-
- int
- getptymaster()
- {
- char *hex, *bank;
- struct stat stat_buf;
- int master = -1;
-
- #if defined(HAVE_PTMX)
- if ((master = open("/dev/ptmx", O_RDWR)) == -1) return(-1);
- if ((slave_name = ptsname(master)) == NULL || unlockpt(master) || grantpt(master)) {
- close(master);
- return(-1);
- }
- (void) ioctl(master,TIOCFLUSH,(char *)0);
-
- return(master);
- #endif
-
- #if defined(HAVE__GETPTY) /* SGI needs it this way */
- slave_name = _getpty(&master, O_RDWR, 0600, 0);
- if (slave_name == NULL)
- return (-1);
- return(master);
- #endif
-
- #if defined(HAVE_PTC) && !defined(HAVE__GETPTY) /* old SGI, version 3 */
- master = open("/dev/ptc", O_RDWR);
- if (master >= 0) {
- int ptynum;
-
- if (fstat(master, &stat_buf) < 0) {
- close(master);
- return(-1);
- }
- ptynum = minor(stat_buf.st_rdev);
- sprintf(slave_name,"/dev/ttyq%d",ptynum);
- }
- return(master);
- #endif
-
- #if defined(HAVE_GETPTY) && !defined(HAVE__GETPTY)
- master = getpty(master_name, slave_name, O_RDWR);
- /* is it really necessary to verify slave side is usable? */
- return master;
- #endif
-
- #if defined(HAVE_PTC_PTS)
- master = open("/dev/ptc",O_RDWR);
- if (master >= 0) {
- /* never fails */
- slave_name = ttyname(master);
- }
- return(master);
- #endif
-
- #if !defined(HAVE_GETPTY) && !defined(HAVE_GETPTY) && !defined(HAVE_PTC) && !defined(HAVE_PTC_PTS) && !defined(HAVE_PTMX)
- if (exp_pty_test_start() == -1) return -1;
-
- for (bank = "pqrstuvwxyzPQRSTUVWXYZ";*bank;bank++) {
- *tty_bank = *bank;
- *tty_num = '0';
- if (stat(master_name, &stat_buf) < 0) break;
- for (hex = "0123456789abcdef";*hex;hex++) {
- *tty_num = *hex;
- #ifdef HAVE_PTYM
- *slave_bank = *tty_bank;
- *slave_num = *tty_num;
- #else
- strcpy(slave_name,master_name);
- *tty_type = 't';
- #endif
- master = exp_pty_test(master_name,slave_name,*tty_bank,*tty_num);
- if (master >= 0) goto done;
- }
- }
- done:
- #ifdef HAVE_PTYTRAP
- /* Turn on trapping of close, open and */
- /* ioctl requests from the slave.*/
- {
- int enable = 1;
- ioctl(master, TIOCTRAP, &enable);
- }
- #endif /* HAVE_PTYTRAP */
-
- exp_pty_test_end();
- return(master);
- #endif
- }
-
- int
- getptyslave(ttycopy,ttyinit,stty_args)
- int ttycopy;
- int ttyinit;
- char *stty_args;
- {
- int slave;
- if (0 > (slave = open(slave_name, O_RDWR))) return(-1);
-
- #if defined(HAVE_PTMX)
- if (ioctl(slave, I_PUSH, "ptem")) {
- debuglog("ioctl(%s,I_PUSH,\"ptem\") = %s\n",sys_errlist[errno]);
- }
- if (ioctl(slave, I_PUSH, "ldterm")) {
- debuglog("ioctl(%s,I_PUSH,\"ldterm\") = %s\n",sys_errlist[errno]);
- }
- if (ioctl(slave, I_PUSH, "ttcompat")) {
- debuglog("ioctl(%s,I_PUSH,\"ttcompat\") = %s\n",sys_errlist[errno]);
- }
- #endif
-
- /* sanity check - if slave not 0, skip rest of this and return */
- /* to what will later be detected as an error in caller */
- if (0 != slave) return(slave);
-
- fcntl(0,F_DUPFD,1); /* duplicate 0 onto 1 to prepare for stty */
- ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args);
- (void) exp_pty_unlock();
- return(slave);
- }
-
- #ifdef HAVE_PTYTRAP
- #include <sys/ptyio.h>
- #include <sys/time.h>
-
- /* return 1 for failure, 0 for success */
- int
- exp_wait_for_slave_open(fd)
- int fd;
- {
- fd_set excep;
- struct timeval t;
- struct request_info ioctl_info;
- int rc;
-
- int maxfds = sysconf(_SC_OPEN_MAX);
-
- t.tv_sec = 30; /* 30 seconds */
- t.tv_usec = 0;
-
- FD_ZERO(&excep);
- FD_SET(fd,&excep);
-
- rc = select(maxfds,(fd_set *)0,(fd_set *)0,&excep,&t);
- if (rc != 1) {
- debuglog("spawned process never started, errno = %d\n",errno);
- return(1);
- }
- if (ioctl(fd,TIOCREQCHECK,&ioctl_info) < 0) {
- debuglog("ioctl(TIOCREQCHECK) failed, errno = %d\n",errno);
- return(1);
- }
- if (ioctl_info.request != TIOCOPEN) {
- debuglog("ioctl from slave is not OPEN?\n");
- }
- if (ioctl(fd, TIOCREQSET, &ioctl_info) < 0) {
- debuglog("ioctl(TIOCREQSET) failed, errno = %d\n",errno);
- return(1);
- }
- return(0);
- }
- #endif
-