Blame pty_unicos.c

Packit a69f91
/* pty_unicos.c - routines to allocate ptys - for CRAY UNICOS 5.1 and 6.0 */
Packit a69f91
Packit a69f91
/*
Packit a69f91
Packit a69f91
Original by: Don Libes, NIST, 2/6/90
Packit a69f91
Hacked for Unicos 5.1 by: Frank Terhaar-Yonkers, US EPA,  1/10/91
Packit a69f91
Hacked for Unicos 6.0 by: Pete TerMaat, pete@willow.cray.com, 3/27/91
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 "expect_cf.h"
Packit a69f91
#include <stdio.h>
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
#ifdef HAVE_UNISTD_H
Packit a69f91
#include <unistd.h>
Packit a69f91
#else
Packit a69f91
extern int fork(), execl(), wait();
Packit a69f91
#endif
Packit a69f91
#include <errno.h>
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
#ifdef HAVE_SYS_FCNTL_H
Packit a69f91
#  include <sys/fcntl.h>
Packit a69f91
#else
Packit a69f91
#  include <fcntl.h>
Packit a69f91
#endif
Packit a69f91
/*#if CRAY>=60*/
Packit a69f91
#if defined(HAVE_TERMIOS)
Packit a69f91
# include <sys/termios.h>
Packit a69f91
#else
Packit a69f91
# include <sys/termio.h>
Packit a69f91
/*#endif /* 60 */*/
Packit a69f91
#endif /* defined(HAVE_TERMIOS) */
Packit a69f91
#if CRAY>=70 && defined(_CRAY2)
Packit a69f91
#include <sys/session.h>
Packit a69f91
#endif /* 70 */
Packit a69f91
#include <sys/pty.h>
Packit a69f91
#include <pwd.h>
Packit a69f91
#include <utmp.h>
Packit a69f91
#include <signal.h>
Packit a69f91
#include "exp_tty_in.h"
Packit a69f91
#include "exp_rename.h"
Packit a69f91
Packit a69f91
#ifdef HAVE_SYSCONF_H
Packit a69f91
#include <sys/sysconfig.h>
Packit a69f91
#endif
Packit a69f91
Packit a69f91
void expDiagLog();
Packit a69f91
Packit a69f91
#ifndef TRUE
Packit a69f91
#define TRUE 1
Packit a69f91
#define FALSE 0
Packit a69f91
#endif
Packit a69f91
Packit a69f91
#ifndef MAXHOSTNAMELEN
Packit a69f91
#define MAXHOSTNAMELEN 64
Packit a69f91
#endif /* MAXHOSTNAMELEN */
Packit a69f91
Packit a69f91
static char	linep[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
Packit a69f91
static char	linet[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
Packit a69f91
static int	lowpty;
Packit a69f91
static int	highpty;
Packit a69f91
static int	realuid;
Packit a69f91
static int	realgid;
Packit a69f91
static int 	*ptys;
Packit a69f91
static char myname[32];
Packit a69f91
static char hostname[MAXHOSTNAMELEN];
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
/*struct	termio exp_tty_original;*/
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;	/* true/false, copy from /dev/tty */
Packit a69f91
int ttyinit;	/* if true, initialize to sane state */
Packit a69f91
char *s;	/* stty args, used only if request == SET_TTYTYPE */
Packit a69f91
{
Packit a69f91
	if (request == GET_TTYTYPE) {
Packit a69f91
		if (-1 == ioctl(fd, TCGETA, (char *)&exp_tty_original)) {
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, TCSETA, (char *)&exp_tty_current);
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
		if (ttyinit) {
Packit a69f91
			/* overlay parms originally supplied by Makefile */
Packit a69f91
			pty_stty(DFLT_STTY,linet);
Packit a69f91
		}
Packit a69f91
Packit a69f91
		/* lastly, give user chance to override any terminal parms */
Packit a69f91
		if (s) {
Packit a69f91
			pty_stty(s,linet);
Packit a69f91
		}
Packit a69f91
	}
Packit a69f91
}
Packit a69f91
Packit a69f91
void
Packit a69f91
exp_init_pty()
Packit a69f91
{
Packit a69f91
	int npty;
Packit a69f91
	char *myline;
Packit a69f91
Packit a69f91
	lowpty=0;
Packit a69f91
#ifdef _SC_CRAY_NPTY
Packit a69f91
	highpty=sysconf(_SC_CRAY_NPTY);
Packit a69f91
#else
Packit a69f91
	highpty=128;
Packit a69f91
#endif /* _SC_CRAY_NPTY */
Packit a69f91
Packit a69f91
	ptys = (int *) malloc(sizeof(int)*(highpty+1));
Packit a69f91
	if (ptys == NULL) {
Packit a69f91
		fprintf(stderr,"exp_init_pty:  couldn't allocate pty array\n");
Packit a69f91
		exit(1);
Packit a69f91
	}
Packit a69f91
	for (npty = lowpty;npty <= highpty;npty++)
Packit a69f91
		ptys[npty] = 0;
Packit a69f91
Packit a69f91
 	realuid=getuid();	/* get REAL uid */
Packit a69f91
 	realgid=getgid();	/* get REAL uid */
Packit a69f91
Packit a69f91
	exp_dev_tty = open("/dev/tty",O_RDWR);
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
	 * Acquire (as root) current user name and host.
Packit a69f91
	 */
Packit a69f91
	(void) cuserid(myname);
Packit a69f91
	(void) gethostname(hostname,sizeof(hostname));
Packit a69f91
Packit a69f91
	/*
Packit a69f91
	 * Set the real and effective userids to root using 'setuid'.  Then
Packit a69f91
	 * set the real and effective userids to the actual user using
Packit a69f91
	 * 'setreuid'.  This allows using 'seteuid' to go back and forth from
Packit a69f91
	 * root and the actual userid.  Don't ask me why it works.
Packit a69f91
	 */
Packit a69f91
	setuid(0);
Packit a69f91
	setreuid(realuid,realuid);
Packit a69f91
}
Packit a69f91
Packit a69f91
/* returns fd of master end of pseudotty */
Packit a69f91
int
Packit a69f91
exp_getptymaster()
Packit a69f91
{
Packit a69f91
	struct stat sb;
Packit a69f91
	int master;
Packit a69f91
	int npty;
Packit a69f91
Packit a69f91
	exp_pty_error = 0;
Packit a69f91
Packit a69f91
	expDiagLog("exp_getptymaster:  lowpty=%d  highpty=%d\n",lowpty,highpty);
Packit a69f91
	for (npty = lowpty; npty <= highpty; npty++) {
Packit a69f91
		if (seteuid(0) == -1) {		/* we need to be root! */
Packit a69f91
			expDiagLog("exp_getptymaster:  seteuid root errno=%d\n",
Packit a69f91
				errno);
Packit a69f91
		}
Packit a69f91
		(void) sprintf(linep, "/dev/pty/%03d", npty);
Packit a69f91
		master = open(linep, O_RDWR);
Packit a69f91
Packit a69f91
		if (master < 0) {
Packit a69f91
			expDiagLog("exp_getptymaster:  open linep=%s errno=%d\n",
Packit a69f91
				linep,errno);
Packit a69f91
			continue;
Packit a69f91
		}
Packit a69f91
Packit a69f91
		(void) sprintf(linet, "/dev/ttyp%03d", npty);
Packit a69f91
		if(stat(linet, &sb) < 0) {
Packit a69f91
			expDiagLog("exp_getptymaster:  stat linet=%s errno=%d\n",
Packit a69f91
				linet,errno);
Packit a69f91
			(void) close(master);
Packit a69f91
			continue;
Packit a69f91
		}
Packit a69f91
		if (sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
Packit a69f91
                        if (chown(linet, realuid, realgid) == -1) {
Packit a69f91
				expDiagLog("exp_getptymaster:  chown linet=%s errno=%d\n",
Packit a69f91
					linet,errno);
Packit a69f91
			}
Packit a69f91
                        if (chmod(linet, 0600) == -1) {
Packit a69f91
				expDiagLog("exp_getptymaster:  chmod linet=%s errno=%d\n",
Packit a69f91
					linet,errno);
Packit a69f91
			}
Packit a69f91
                        (void)close(master);
Packit a69f91
                        master = open(linep, 2);
Packit a69f91
                        if (master < 0) {
Packit a69f91
				expDiagLog("exp_getptymaster:  reopen linep=%s errno=%d\n",
Packit a69f91
					linep,errno);
Packit a69f91
                                continue;
Packit a69f91
			}
Packit a69f91
                }
Packit a69f91
		if (seteuid(realuid) == -1) {	/* back to who we are! */
Packit a69f91
			expDiagLog("exp_getptymaster:  seteuid user errno=%d\n",
Packit a69f91
				errno);
Packit a69f91
		}
Packit a69f91
		if (access(linet, R_OK|W_OK) != 0) {
Packit a69f91
			expDiagLog("exp_getptymaster:  access linet=%s errno=%d\n",
Packit a69f91
				linet,errno);
Packit a69f91
			(void) close(master);
Packit a69f91
			continue;
Packit a69f91
		}
Packit a69f91
		expDiagLog("exp_getptymaster:  allocated %s\n",linet);
Packit a69f91
		ptys[npty] = -1;
Packit a69f91
		exp_pty_slave_name = linet;
Packit a69f91
		return(master);
Packit a69f91
	}
Packit a69f91
	if (seteuid(realuid) == -1) {		/* back to who we are! */
Packit a69f91
		expDiagLog("exp_getptymaster:  seteuid user errno=%d\n",errno);
Packit a69f91
	}
Packit a69f91
	return(-1);
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(linet, O_RDWR))) {
Packit a69f91
		expDiagLog("exp_getptyslave:  open linet=%s errno=%d\n",linet,errno);
Packit a69f91
		return(-1);
Packit a69f91
	}
Packit a69f91
Packit a69f91
	/* sanity check - if slave not 0, skip rest of this and return */
Packit a69f91
	/* to what will later be detected as an error in caller */
Packit a69f91
	if (0 != slave) {
Packit a69f91
		expDiagLog("exp_getptyslave:  slave fd not 0\n");
Packit a69f91
		 return(slave);
Packit a69f91
	}
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
	return(slave);
Packit a69f91
}
Packit a69f91
Packit a69f91
setptyutmp()
Packit a69f91
{
Packit a69f91
	struct utmp utmp;
Packit a69f91
Packit a69f91
	if (seteuid(0) == -1) {		/* Need to be root */
Packit a69f91
		expDiagLog("setptyutmp:  setuid root errno=%d\n",errno);
Packit a69f91
		return(-1);
Packit a69f91
	}
Packit a69f91
	(void) time(&utmp.ut_time);
Packit a69f91
	utmp.ut_type = USER_PROCESS;
Packit a69f91
	utmp.ut_pid = getpid();
Packit a69f91
	strncpy(utmp.ut_user,myname,sizeof(utmp.ut_user));
Packit a69f91
	strncpy(utmp.ut_host,hostname,sizeof(utmp.ut_host));
Packit a69f91
	strncpy(utmp.ut_line,linet+5,sizeof(utmp.ut_line));
Packit a69f91
	strncpy(utmp.ut_id,linet+8,sizeof(utmp.ut_id));
Packit a69f91
	if (pututline(&utmp) == NULL) {
Packit a69f91
		expDiagLog("setptyutmp:  pututline failed\n");
Packit a69f91
	}
Packit a69f91
	endutent();
Packit a69f91
	if (seteuid(realuid) == -1)
Packit a69f91
		expDiagLog("setptyutmp:  seteuid user errno=%d\n",errno);
Packit a69f91
	return(0);
Packit a69f91
}
Packit a69f91
Packit a69f91
setptypid(pid)
Packit a69f91
int pid;
Packit a69f91
{
Packit a69f91
        int npty;
Packit a69f91
Packit a69f91
        for (npty = lowpty; npty <= highpty; npty++) {
Packit a69f91
                if (ptys[npty] < 0) {
Packit a69f91
                        expDiagLog("setptypid:  ttyp%03d pid=%d\n",npty,pid);
Packit a69f91
                        ptys[npty] = pid;
Packit a69f91
                        break;
Packit a69f91
                }
Packit a69f91
        }
Packit a69f91
}
Packit a69f91
Packit a69f91
ttyp_reset()
Packit a69f91
{
Packit a69f91
        int npty;
Packit a69f91
Packit a69f91
        if (seteuid(0) == -1) {		/* we need to be root! */
Packit a69f91
                expDiagLog("ttyp_reset:  seteuid root errno=%d\n",errno);
Packit a69f91
        }
Packit a69f91
        for (npty = lowpty; npty <= highpty; npty++) {
Packit a69f91
                if (ptys[npty] <= 0)
Packit a69f91
                        continue;
Packit a69f91
Packit a69f91
                (void) sprintf(linet, "/dev/ttyp%03d", npty);
Packit a69f91
                expDiagLog("ttyp_reset:  resetting %s, killing %d\n",
Packit a69f91
			linet,ptys[npty]);
Packit a69f91
                if (chown(linet,0,0) == -1) {
Packit a69f91
                        expDiagLog("ttyp_reset: chown %s errno=%d\n",linet,errno);
Packit a69f91
                }
Packit a69f91
                if (chmod(linet, 0666) == -1) {
Packit a69f91
                        expDiagLog("ttyp_reset: chmod %s errno=%d\n",linet,errno);
Packit a69f91
                }
Packit a69f91
                resetptyutmp();
Packit a69f91
                if (kill(ptys[npty],SIGKILL) == -1) {
Packit a69f91
                        expDiagLog("ttyp_reset:  kill pid=%d errno=%d\n",
Packit a69f91
                                ptys[npty],errno);
Packit a69f91
                }
Packit a69f91
        }
Packit a69f91
        if (seteuid(realuid) == -1) {   /* Back to who we really are */
Packit a69f91
                expDiagLog("ttyp_reset:  seteuid user errno=%d\n",errno);
Packit a69f91
        }
Packit a69f91
}
Packit a69f91
Packit a69f91
void
Packit a69f91
exp_pty_exit()
Packit a69f91
{
Packit a69f91
	ttyp_reset();
Packit a69f91
}
Packit a69f91
Packit a69f91
resetptyutmp()
Packit a69f91
{
Packit a69f91
        struct utmp utmp;
Packit a69f91
Packit a69f91
        (void) setutent ();
Packit a69f91
        /* set up entry to search for */
Packit a69f91
        (void) strncpy(utmp.ut_id, linet + strlen(linet) - 4,
Packit a69f91
                 sizeof (utmp.ut_id));
Packit a69f91
        utmp.ut_type = USER_PROCESS;
Packit a69f91
Packit a69f91
        /* position to entry in utmp file */
Packit a69f91
        if(getutid(&utmp) == NULL) {
Packit a69f91
                expDiagLog("resetptyutmp:  no utmp entry for %s\n",linet);
Packit a69f91
                return(-1);     /* no utmp entry for this line ??? */
Packit a69f91
        }
Packit a69f91
Packit a69f91
        /* set up the new entry */
Packit a69f91
        strncpy(utmp.ut_name,"",sizeof(utmp.ut_name));
Packit a69f91
        strncpy(utmp.ut_host,"",sizeof(utmp.ut_host));
Packit a69f91
        time(&utmp.ut_time);
Packit a69f91
        utmp.ut_type = DEAD_PROCESS;
Packit a69f91
        utmp.ut_exit.e_exit = 0;
Packit a69f91
Packit a69f91
        /* write out the entry */
Packit a69f91
        pututline(&utmp);
Packit a69f91
Packit a69f91
        /* close the file */
Packit a69f91
        (void) endutent();
Packit a69f91
        return(0);
Packit a69f91
}