Blame pty_sgttyb.c

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
}