|
Packit |
a69f91 |
/* pty_bsd.c - routines to allocate ptys - BSD version
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Written by: Don Libes, NIST, 2/6/90
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Design and implementation of this program was paid for by U.S. tax
|
|
Packit |
a69f91 |
dollars. Therefore it is public domain. However, the author and NIST
|
|
Packit |
a69f91 |
would appreciate credit if this program or parts of it are used.
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include <stdio.h> /* tmp for debugging */
|
|
Packit |
a69f91 |
#include <signal.h>
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#if defined(SIGCLD) && !defined(SIGCHLD)
|
|
Packit |
a69f91 |
#define SIGCHLD SIGCLD
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include <sys/types.h>
|
|
Packit |
a69f91 |
#include <sys/stat.h>
|
|
Packit |
a69f91 |
/*** #include <sys/ioctl.h> ***/
|
|
Packit |
a69f91 |
#include <sys/file.h>
|
|
Packit |
a69f91 |
#include <signal.h>
|
|
Packit |
a69f91 |
#include <setjmp.h>
|
|
Packit |
a69f91 |
#include "expect_cf.h"
|
|
Packit |
a69f91 |
#include "exp_rename.h"
|
|
Packit |
a69f91 |
#include "exp_tty_in.h"
|
|
Packit |
a69f91 |
#include "exp_pty.h"
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void expDiagLog();
|
|
Packit |
a69f91 |
void expDiagLogU();
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifndef TRUE
|
|
Packit |
a69f91 |
#define TRUE 1
|
|
Packit |
a69f91 |
#define FALSE 0
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static char master_name[] = "/dev/ptyXX"; /* master */
|
|
Packit |
a69f91 |
static char slave_name[] = "/dev/ttyXX"; /* slave */
|
|
Packit |
a69f91 |
static char *tty_type; /* ptr to char [pt] denoting
|
|
Packit |
a69f91 |
whether it is a pty or tty */
|
|
Packit |
a69f91 |
static char *tty_bank; /* ptr to char [p-z] denoting
|
|
Packit |
a69f91 |
which bank it is */
|
|
Packit |
a69f91 |
static char *tty_num; /* ptr to char [0-f] denoting
|
|
Packit |
a69f91 |
which number it is */
|
|
Packit |
a69f91 |
char *exp_pty_slave_name;
|
|
Packit |
a69f91 |
char *exp_pty_error;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
pty_stty(s,name)
|
|
Packit |
a69f91 |
char *s; /* args to stty */
|
|
Packit |
a69f91 |
char *name; /* name of pty */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
#define MAX_ARGLIST 10240
|
|
Packit |
a69f91 |
char buf[MAX_ARGLIST]; /* overkill is easier */
|
|
Packit |
a69f91 |
RETSIGTYPE (*old)(); /* save old sigalarm handler */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef STTY_READS_STDOUT
|
|
Packit |
a69f91 |
sprintf(buf,"%s %s > %s",STTY_BIN,s,name);
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
sprintf(buf,"%s %s < %s",STTY_BIN,s,name);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
old = signal(SIGCHLD, SIG_DFL);
|
|
Packit |
a69f91 |
system(buf);
|
|
Packit |
a69f91 |
signal(SIGCHLD, old); /* restore signal handler */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int exp_dev_tty; /* file descriptor to /dev/tty or -1 if none */
|
|
Packit |
a69f91 |
static int knew_dev_tty;/* true if we had our hands on /dev/tty at any time */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef TIOCGWINSZ
|
|
Packit |
a69f91 |
static struct winsize winsize = {0, 0};
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
|
|
Packit |
a69f91 |
static struct ttysize winsize = {0, 0};
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_tty exp_tty_original;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#define GET_TTYTYPE 0
|
|
Packit |
a69f91 |
#define SET_TTYTYPE 1
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
ttytype(request,fd,ttycopy,ttyinit,s)
|
|
Packit |
a69f91 |
int request;
|
|
Packit |
a69f91 |
int fd;
|
|
Packit |
a69f91 |
/* following are used only if request == SET_TTYTYPE */
|
|
Packit |
a69f91 |
int ttycopy; /* if true, copy from /dev/tty */
|
|
Packit |
a69f91 |
int ttyinit; /* if true, initialize to sane state */
|
|
Packit |
a69f91 |
char *s; /* stty args */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
static struct tchars tc; /* special characters */
|
|
Packit |
a69f91 |
static struct ltchars lc; /* local special characters */
|
|
Packit |
a69f91 |
static struct winsize win; /* window size */
|
|
Packit |
a69f91 |
static int lb; /* local modes */
|
|
Packit |
a69f91 |
static int l; /* line discipline */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (request == GET_TTYTYPE) {
|
|
Packit |
a69f91 |
if (-1 == ioctl(fd, TIOCGETP, (char *)&exp_tty_original)
|
|
Packit |
a69f91 |
|| -1 == ioctl(fd, TIOCGETC, (char *)&tc)
|
|
Packit |
a69f91 |
|| -1 == ioctl(fd, TIOCGETD, (char *)&l)
|
|
Packit |
a69f91 |
|| -1 == ioctl(fd, TIOCGLTC, (char *)&lc)
|
|
Packit |
a69f91 |
|| -1 == ioctl(fd, TIOCLGET, (char *)&lb)
|
|
Packit |
a69f91 |
|| -1 == ioctl(fd, TIOCGWINSZ, (char *)&win)) {
|
|
Packit |
a69f91 |
knew_dev_tty = FALSE;
|
|
Packit |
a69f91 |
exp_dev_tty = -1;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#ifdef TIOCGWINSZ
|
|
Packit |
a69f91 |
ioctl(fd,TIOCGWINSZ,&winsize);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
|
|
Packit |
a69f91 |
ioctl(fd,TIOCGSIZE,&winsize);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
} else { /* type == SET_TTYTYPE */
|
|
Packit |
a69f91 |
if (ttycopy && knew_dev_tty) {
|
|
Packit |
a69f91 |
(void) ioctl(fd, TIOCSETP, (char *)&exp_tty_current);
|
|
Packit |
a69f91 |
(void) ioctl(fd, TIOCSETC, (char *)&tc);
|
|
Packit |
a69f91 |
(void) ioctl(fd, TIOCSLTC, (char *)&lc);
|
|
Packit |
a69f91 |
(void) ioctl(fd, TIOCLSET, (char *)&lb);
|
|
Packit |
a69f91 |
(void) ioctl(fd, TIOCSETD, (char *)&l);
|
|
Packit |
a69f91 |
(void) ioctl(fd, TIOCSWINSZ, (char *)&win);
|
|
Packit |
a69f91 |
#ifdef TIOCSWINSZ
|
|
Packit |
a69f91 |
ioctl(fd,TIOCSWINSZ,&winsize);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ)
|
|
Packit |
a69f91 |
ioctl(fd,TIOCGSIZE,&winsize);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef __CENTERLINE__
|
|
Packit |
a69f91 |
#undef DFLT_STTY
|
|
Packit |
a69f91 |
#define DFLT_STTY "sane"
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* Apollo Domain doesn't need this */
|
|
Packit |
a69f91 |
#ifdef DFLT_STTY
|
|
Packit |
a69f91 |
if (ttyinit) {
|
|
Packit |
a69f91 |
/* overlay parms originally supplied by Makefile */
|
|
Packit |
a69f91 |
pty_stty(DFLT_STTY,slave_name);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* lastly, give user chance to override any terminal parms */
|
|
Packit |
a69f91 |
if (s) {
|
|
Packit |
a69f91 |
pty_stty(s,slave_name);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_init_pty()
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
tty_type = & slave_name[strlen("/dev/")];
|
|
Packit |
a69f91 |
tty_bank = &master_name[strlen("/dev/pty")];
|
|
Packit |
a69f91 |
tty_num = &master_name[strlen("/dev/ptyp")];
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_dev_tty = open("/dev/tty",O_RDWR);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#if experimental
|
|
Packit |
a69f91 |
/* code to allocate force expect to get a controlling tty */
|
|
Packit |
a69f91 |
/* even if it doesn't start with one (i.e., under cron). */
|
|
Packit |
a69f91 |
/* This code is not necessary, but helpful for testing odd things. */
|
|
Packit |
a69f91 |
if (exp_dev_tty == -1) {
|
|
Packit |
a69f91 |
/* give ourselves a controlling tty */
|
|
Packit |
a69f91 |
int master = exp_getptymaster();
|
|
Packit |
a69f91 |
fcntl(master,F_SETFD,1); /* close-on-exec */
|
|
Packit |
a69f91 |
setpgrp(0,0);
|
|
Packit |
a69f91 |
close(0);
|
|
Packit |
a69f91 |
close(1);
|
|
Packit |
a69f91 |
exp_getptyslave(exp_get_var(exp_interp,"stty_init"));
|
|
Packit |
a69f91 |
close(2);
|
|
Packit |
a69f91 |
fcntl(0,F_DUPFD,2); /* dup 0 onto 2 */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
knew_dev_tty = (exp_dev_tty != -1);
|
|
Packit |
a69f91 |
if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* returns fd of master end of pseudotty */
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_getptymaster()
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int master = -1;
|
|
Packit |
a69f91 |
char *hex, *bank;
|
|
Packit |
a69f91 |
struct stat statbuf;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_pty_error = 0;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_pty_test_start() == -1) return -1;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (bank = "pqrstuvwxyzPQRSTUVWXYZ";*bank;bank++) {
|
|
Packit |
a69f91 |
*tty_bank = *bank;
|
|
Packit |
a69f91 |
*tty_num = '0';
|
|
Packit |
a69f91 |
if (stat(master_name, &statbuf) < 0) break;
|
|
Packit |
a69f91 |
for (hex = "0123456789abcdef";*hex;hex++) {
|
|
Packit |
a69f91 |
*tty_num = *hex;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* generate slave name from master */
|
|
Packit |
a69f91 |
strcpy(slave_name,master_name);
|
|
Packit |
a69f91 |
*tty_type = 't';
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
master = exp_pty_test(master_name,slave_name,
|
|
Packit |
a69f91 |
*tty_bank,tty_num);
|
|
Packit |
a69f91 |
if (master >= 0) goto done;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
done:
|
|
Packit |
a69f91 |
exp_pty_test_end();
|
|
Packit |
a69f91 |
exp_pty_slave_name = slave_name;
|
|
Packit |
a69f91 |
return(master);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* see comment in pty_termios.c */
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_slave_control(master,control)
|
|
Packit |
a69f91 |
int master;
|
|
Packit |
a69f91 |
int control;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_getptyslave(ttycopy,ttyinit,stty_args)
|
|
Packit |
a69f91 |
int ttycopy;
|
|
Packit |
a69f91 |
int ttyinit;
|
|
Packit |
a69f91 |
char *stty_args;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int slave;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (0 > (slave = open(slave_name, O_RDWR))) return(-1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (0 == slave) {
|
|
Packit |
a69f91 |
/* if opened in a new process, slave will be 0 (and */
|
|
Packit |
a69f91 |
/* ultimately, 1 and 2 as well) */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* duplicate 0 onto 1 and 2 to prepare for stty */
|
|
Packit |
a69f91 |
fcntl(0,F_DUPFD,1);
|
|
Packit |
a69f91 |
fcntl(0,F_DUPFD,2);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
ttytype(SET_TTYTYPE,slave,ttycopy,ttyinit,stty_args);
|
|
Packit |
a69f91 |
(void) exp_pty_unlock();
|
|
Packit |
a69f91 |
return(slave);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_pty_exit()
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
/* a stub so we can do weird things on the cray */
|
|
Packit |
a69f91 |
}
|