1/* pty_bsd.c - routines to allocate ptys - BSD version 2 3Written by: Don Libes, NIST, 2/6/90 4 5Design and implementation of this program was paid for by U.S. tax 6dollars. Therefore it is public domain. However, the author and NIST 7would appreciate credit if this program or parts of it are used. 8 9*/ 10 11#include <stdio.h> /* tmp for debugging */ 12#include <signal.h> 13 14#if defined(SIGCLD) && !defined(SIGCHLD) 15#define SIGCHLD SIGCLD 16#endif 17 18#include <sys/types.h> 19#include <sys/stat.h> 20/*** #include <sys/ioctl.h> ***/ 21#include <sys/file.h> 22#include <signal.h> 23#include <setjmp.h> 24#include "expect_cf.h" 25#include "exp_rename.h" 26#include "exp_tty_in.h" 27#include "exp_pty.h" 28 29void expDiagLog(); 30void expDiagLogU(); 31 32#ifndef TRUE 33#define TRUE 1 34#define FALSE 0 35#endif 36 37static char master_name[] = "/dev/ptyXX"; /* master */ 38static char slave_name[] = "/dev/ttyXX"; /* slave */ 39static char *tty_type; /* ptr to char [pt] denoting 40 whether it is a pty or tty */ 41static char *tty_bank; /* ptr to char [p-z] denoting 42 which bank it is */ 43static char *tty_num; /* ptr to char [0-f] denoting 44 which number it is */ 45char *exp_pty_slave_name; 46char *exp_pty_error; 47 48static void 49pty_stty(s,name) 50char *s; /* args to stty */ 51char *name; /* name of pty */ 52{ 53#define MAX_ARGLIST 10240 54 char buf[MAX_ARGLIST]; /* overkill is easier */ 55 RETSIGTYPE (*old)(); /* save old sigalarm handler */ 56 57#ifdef STTY_READS_STDOUT 58 sprintf(buf,"%s %s > %s",STTY_BIN,s,name); 59#else 60 sprintf(buf,"%s %s < %s",STTY_BIN,s,name); 61#endif 62 old = signal(SIGCHLD, SIG_DFL); 63 system(buf); 64 signal(SIGCHLD, old); /* restore signal handler */ 65} 66 67int exp_dev_tty; /* file descriptor to /dev/tty or -1 if none */ 68static int knew_dev_tty;/* true if we had our hands on /dev/tty at any time */ 69 70#ifdef TIOCGWINSZ 71static struct winsize winsize = {0, 0}; 72#endif 73#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) 74static struct ttysize winsize = {0, 0}; 75#endif 76 77exp_tty exp_tty_original; 78 79#define GET_TTYTYPE 0 80#define SET_TTYTYPE 1 81static void 82ttytype(request,fd,ttycopy,ttyinit,s) 83int request; 84int fd; 85 /* following are used only if request == SET_TTYTYPE */ 86int ttycopy; /* if true, copy from /dev/tty */ 87int ttyinit; /* if true, initialize to sane state */ 88char *s; /* stty args */ 89{ 90 static struct tchars tc; /* special characters */ 91 static struct ltchars lc; /* local special characters */ 92 static struct winsize win; /* window size */ 93 static int lb; /* local modes */ 94 static int l; /* line discipline */ 95 96 if (request == GET_TTYTYPE) { 97 if (-1 == ioctl(fd, TIOCGETP, (char *)&exp_tty_original) 98 || -1 == ioctl(fd, TIOCGETC, (char *)&tc) 99 || -1 == ioctl(fd, TIOCGETD, (char *)&l) 100 || -1 == ioctl(fd, TIOCGLTC, (char *)&lc) 101 || -1 == ioctl(fd, TIOCLGET, (char *)&lb) 102 || -1 == ioctl(fd, TIOCGWINSZ, (char *)&win)) { 103 knew_dev_tty = FALSE; 104 exp_dev_tty = -1; 105 } 106#ifdef TIOCGWINSZ 107 ioctl(fd,TIOCGWINSZ,&winsize); 108#endif 109#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ) 110 ioctl(fd,TIOCGSIZE,&winsize); 111#endif 112 } else { /* type == SET_TTYTYPE */ 113 if (ttycopy && knew_dev_tty) { 114 (void) ioctl(fd, TIOCSETP, (char *)&exp_tty_current); 115 (void) ioctl(fd, TIOCSETC, (char *)&tc); 116 (void) ioctl(fd, TIOCSLTC, (char *)&lc); 117 (void) ioctl(fd, TIOCLSET, (char *)&lb); 118 (void) ioctl(fd, TIOCSETD, (char *)&l); 119 (void) ioctl(fd, TIOCSWINSZ, (char *)&win); 120#ifdef TIOCSWINSZ 121 ioctl(fd,TIOCSWINSZ,&winsize); 122#endif 123#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ) 124 ioctl(fd,TIOCGSIZE,&winsize); 125#endif 126 } 127 128#ifdef __CENTERLINE__ 129#undef DFLT_STTY 130#define DFLT_STTY "sane" 131#endif 132 133/* Apollo Domain doesn't need this */ 134#ifdef DFLT_STTY 135 if (ttyinit) { 136 /* overlay parms originally supplied by Makefile */ 137 pty_stty(DFLT_STTY,slave_name); 138 } 139#endif 140 141 /* lastly, give user chance to override any terminal parms */ 142 if (s) { 143 pty_stty(s,slave_name); 144 } 145 } 146} 147 148void 149exp_init_pty() 150{ 151 tty_type = & slave_name[strlen("/dev/")]; 152 tty_bank = &master_name[strlen("/dev/pty")]; 153 tty_num = &master_name[strlen("/dev/ptyp")]; 154 155 exp_dev_tty = open("/dev/tty",O_RDWR); 156 157#if experimental 158 /* code to allocate force expect to get a controlling tty */ 159 /* even if it doesn't start with one (i.e., under cron). */ 160 /* This code is not necessary, but helpful for testing odd things. */ 161 if (exp_dev_tty == -1) { 162 /* give ourselves a controlling tty */ 163 int master = exp_getptymaster(); 164 fcntl(master,F_SETFD,1); /* close-on-exec */ 165 setpgrp(0,0); 166 close(0); 167 close(1); 168 exp_getptyslave(exp_get_var(exp_interp,"stty_init")); 169 close(2); 170 fcntl(0,F_DUPFD,2); /* dup 0 onto 2 */ 171 } 172#endif 173 174 knew_dev_tty = (exp_dev_tty != -1); 175 if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0); 176} 177 178/* returns fd of master end of pseudotty */ 179int 180exp_getptymaster() 181{ 182 int master = -1; 183 char *hex, *bank; 184 struct stat statbuf; 185 186 exp_pty_error = 0; 187 188 if (exp_pty_test_start() == -1) return -1; 189 190 for (bank = "pqrstuvwxyzPQRSTUVWXYZ";*bank;bank++) { 191 *tty_bank = *bank; 192 *tty_num = '0'; 193 if (stat(master_name, &statbuf) < 0) break; 194 for (hex = "0123456789abcdef";*hex;hex++) { 195 *tty_num = *hex; 196 197 /* generate slave name from master */ 198 strcpy(slave_name,master_name); 199 *tty_type = 't'; 200 201 master = exp_pty_test(master_name,slave_name, 202 *tty_bank,tty_num); 203 if (master >= 0) goto done; 204 } 205 } 206 done: 207 exp_pty_test_end(); 208 exp_pty_slave_name = slave_name; 209 return(master); 210} 211 212/* see comment in pty_termios.c */ 213/*ARGSUSED*/ 214void 215exp_slave_control(master,control) 216int master; 217int control; 218{ 219} 220 221int 222exp_getptyslave(ttycopy,ttyinit,stty_args) 223int ttycopy; 224int ttyinit; 225char *stty_args; 226{ 227 int slave; 228 229 if (0 > (slave = open(slave_name, O_RDWR))) return(-1); 230 231 if (0 == slave) { 232 /* if opened in a new process, slave will be 0 (and */ 233 /* ultimately, 1 and 2 as well) */ 234 235 /* duplicate 0 onto 1 and 2 to prepare for stty */ 236 fcntl(0,F_DUPFD,1); 237 fcntl(0,F_DUPFD,2); 238 } 239 240 ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args); 241 (void) exp_pty_unlock(); 242 return(slave); 243} 244 245void 246exp_pty_exit() 247{ 248 /* a stub so we can do weird things on the cray */ 249} 250