
#define VERSION	"1.0.0"
#define I_IOCTL
#define I_ERRNO
#define I_SYS
#include "includes.h"

#include <signal.h>
#include <sys/stat.h>
#include <pwd.h>

#ifdef USE_TIOCNOTTY
#include <sys/ioctl.h>
#endif

int pty_pid;

int open_pty(char *prog) {
  int masterfd = -1,
  slavefd,
  c,
  i,
  pid;
  int pip[2];
#ifndef sgi
#define	SFIRST	(sizeof (slaveline) - 3)
#define	SSECOND	(sizeof (slaveline) - 2)
#ifdef __hpux
  char masterline[]="/dev/ptym/ptyXY";
  char slaveline[]="/dev/pty/ttyXY";
  char *first ="pqrstuv";
#else				/*  not hpux, and not sgi. */
  char masterline[]="/dev/ptyXY";
  char *first ="pqrstuvwzyz";
  char slaveline[]="/dev/ttyXY";
#endif
				/* Ok. Stuff for not sgi. */
#define	MFIRST	(sizeof (masterline) - 3)
#define	MSECOND	(sizeof (masterline) - 2)
  char *ptr = first;
#else
				/* And then finally, sgi stuff. */
  char *linetmp;
  char slaveline[20];
#endif
  
#ifndef sgi
  /* get a pseudo tty */
  ptr = first;
  for (c = *ptr; (c = *ptr); ++ptr) {
    struct stat statbuff;
    
    masterline[MFIRST] = c;
    masterline[MSECOND] = '0';
    
    if (stat (masterline, &statbuff) < 0)
      continue; /* no pty's on this bank availiable */

    for (i = 0; i < 16; ++i) {
      masterline[MSECOND] = "0123456789abcdef"[i];
      if ((masterfd = open (masterline, O_RDWR)) > 0)
	break;
    }
    if (i != 16) {
				/* Ok. now check to make sure we can */
				/* open the slave as well. */
      slaveline[SFIRST] = masterline[MFIRST];
      slaveline[SSECOND] = masterline[MSECOND];
      
      if ((slavefd = open (slaveline, O_RDWR)) < 0) {
	close(masterfd);
	continue;			/* unable to open slave pty */
      }
      break;
    }
    
  }

  if (!c)
    return -1;
  
#ifdef SUIDROOT
  if (fchmod (slavefd, 0622))
    return -2;
#endif
  
  close(slavefd);

#else /* sgi */
  
  linetmp = _getpty(&masterfd, O_RDWR, 0600, 0);
  
  if (linetmp == NULL)
    return -1; /* no pty's available */
  
  strcpy(slaveline, linetmp);
  
  /* Don't check slave - have to assume it's going to work */
  
#endif /* sgi */
  pipe(pip);
  if ((pid = fork ()) < 0)
    return -3; /* unable to fork */
  
  if (pid == 0) { /* child. */
    char  ** a, *b[2] = {0, };

    close(0);
    close(1);
    close(2);

    lose_ctty();
    
    if ((slavefd = open (slaveline, O_RDWR)) < 0) {
      /* make it control tty */
      exit(1);
    }
#ifdef USE_VHANGUP
    signal (SIGHUP, SIG_IGN);
    vhangup ();
    signal (SIGHUP, SIG_DFL);
#endif
    
    if ((slavefd = open (slaveline, O_RDWR)) < 0) {
      exit(1);
    }
    /*
     **	do a term setup here.
     */
    dup2 (slavefd, 0);
    dup2 (slavefd, 1);
    dup2 (slavefd, 2);
    for (slavefd = 3; slavefd < 64;++slavefd)
      close(slavefd);
    terminal_restore(0);
    /* find out what shell to run. */
    /* note: technically we should free a, but as we are 
     * in the child who will either exec or exit, we can 
     * neglect this.  croutons.
     */
    a = rebuild_arg(prog);
    if ( !a ) {
      a = b; 
    }
    if ( !a[0] )
      a[0] = getenv("SHELL");
    if (!a[0]) a[0] = "/bin/sh";
    printf ("Running on line %s\n", slaveline);
    printf ("Term %s running. about to exec %s...\n", VERSION, a[0]);
    close(pip[0]);
    write(pip[1],"a",1);
    close(pip[1]);
    execvp(a[0], a);
    
    printf ("Unable to exec %s.\n", a[0]);
    exit(1);
  }
				/* Wait for exec.. */
  close(pip[1]);
  read(pip[0], (char *) &i, 1);
  close(pip[0]);

  set_nonblock(masterfd);
  /*	ioctl(masterfd, TIOCPKY, &one); BSD pty packet mode. */
  pty_pid = pid;
  
  return masterfd;
}
