/*
 * Start off a new shell, or shell like program, after first configuring
 * its tty connection to a "standard" state
 *
 * Usage: startoff cols rows pgmname args...
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

#include <sys/types.h>
#if   !defined(apollo)
#include <sys/termios.h>
#else
#include <sgtty.h>
#endif

#define  MAX_ARGS    16

char *args[MAX_ARGS + 2];

int openpty(pty)
char *pty;
{
   int fd;

   fd = open(pty,2);
   if (fd < 0) {
      fprintf(stderr,"startoff: unable to open pseudo-tty %s\n",pty);
      sleep(3);
      exit(-2);
   }
   return fd;
}

void main(argc,argv)
int argc;
char *argv[];
{
   long i,cols,rows;
   int ttyfd;
   char *tty;
   char *ptr,*pgm;
   char *tkt_library;
   char buffer[128];
   char rbuf[32],lbuf[32];
   char tcapbuf[256],termbuf[256];
#if   defined(sparc)
   struct termios ttymodes;
   struct winsize ttysizes;
#endif
#if   defined(hpux)
   struct termios ttymodes;
   struct winsize ttysizes;
#endif
#if   defined(apollo)
   struct sgttyb ttymodes;
   struct tchars ttychars;
   struct ltchars ttylchars;
   int discipline = NTTYDISC;
   struct winsize ttysizes;
#endif

   if (argc < 4 || argc >= MAX_ARGS+6) {
      fprintf(stderr,"startoff: usage is: 'startoff cols rows <pgmname args...>\n");
      fprintf(stderr,"startoff: maximum of %d arguments.\n",MAX_ARGS);
      sleep(3);
      exit(-1);
   }
   cols = atoi(argv[1]);
   rows = atoi(argv[2]);
   tty = argv[3];
   tkt_library = argv[4];

   sprintf(rbuf,"LINES=%d",rows);
   putenv(rbuf);
   sprintf(lbuf,"COLUMNS=%d",cols);
   putenv(lbuf);
   putenv("TERM=tkt-ansi");
   sprintf(tcapbuf,"TERMCAP=%s/tkt-ansi.tcap",tkt_library);
   putenv(tcapbuf);
   sprintf(termbuf,"TERMINFO=%s",tkt_library);
   putenv(termbuf);

   signal(SIGINT,SIG_DFL);
   signal(SIGQUIT,SIG_DFL);

   setsid();
#if   defined(apollo)
   ttyfd = open("/dev/tty", 2, 0);
   if (ttyfd >= 0) {
      ioctl(ttyfd, TIOCNOTTY, (char *)0);
      close(ttyfd);
   }
#endif
   ttyfd = openpty(tty);
#if   !defined(apollo)
   ioctl(ttyfd,TIOCSCTTY,0);
#endif
   tcsetpgrp(ttyfd,getpid());

   dup2(ttyfd,0);
   dup2(ttyfd,1);
   dup2(ttyfd,2);
   for (i = 3; i <= ttyfd; i++)
      close(i);

#if   defined(sparc)
   ioctl(1,TCGETS,&ttymodes);
#endif
#if   defined(hpux)
   ioctl(1,TCGETATTR,&ttymodes);
#endif
#if   defined(apollo)
   ioctl(1,TIOCGETP,&ttymodes);
   ioctl(1,TIOCGETC,&ttychars);
   ioctl(1,TIOCGLTC,&ttylchars);
#endif
#if   !defined(apollo)
   ttymodes.c_cc[VINTR] = 3;  /* control c */
   ttymodes.c_cc[VERASE] = 8; /* control h */
   ttymodes.c_cc[VKILL] = 21; /* control u */
   ttymodes.c_iflag |= IGNPAR;
   ttymodes.c_iflag &= ~PARMRK;
   ttymodes.c_iflag &= ~INPCK;
   ttymodes.c_iflag &= ~INLCR;
   ttymodes.c_iflag &= ~IGNCR;
   ttymodes.c_iflag &= ~ISTRIP;
   ttymodes.c_iflag |= ICRNL;
#if   defined(sparc)
   ttymodes.c_iflag |= IMAXBEL;
#endif
   ttymodes.c_oflag &= ~ONLCR;
   ttymodes.c_oflag &= ~OCRNL;
   ttymodes.c_oflag |= ONLRET;
   ttymodes.c_cflag &= ~CBAUD;
   ttymodes.c_cflag |= B38400;
#if   defined(sparc)
   ttymodes.c_cflag &= ~CIBAUD;
   ttymodes.c_cflag |= B38400 << IBSHIFT;
#endif
   ttymodes.c_cflag &= ~CSIZE;
   ttymodes.c_cflag |= CS8;
   ttymodes.c_cflag &= ~PARENB;
   ttymodes.c_cflag |= HUPCL;
   ttymodes.c_cflag &= ~CLOCAL;
   ttymodes.c_lflag |= ECHO;
   ttymodes.c_lflag |= ECHOE;
   ttymodes.c_lflag |= ECHOK;
#if   defined(sparc)
   ttymodes.c_lflag |= ECHOKE;
   ttymodes.c_lflag |= ECHOCTL;
#endif
   ttymodes.c_lflag |= ISIG;
   ttymodes.c_lflag |= ICANON;
#else
   ttymodes.sg_flags &= ~CBREAK;
   ttymodes.sg_flags &= ~RAW;
   ttymodes.sg_flags |= ECHO;
   ttymodes.sg_flags |= CRMOD;
   ttymodes.sg_flags |= XTABS;
   ttymodes.sg_flags |= ANYP;
   ttymodes.sg_flags &= ~ALLDELAY;
   ttymodes.sg_flags |= CRTBS;
   ttymodes.sg_flags |= CRTERA;
   ttymodes.sg_flags |= CRTKIL;
   ttymodes.sg_ispeed = B9600;
   ttymodes.sg_ospeed = B9600;
   ttymodes.sg_erase = 8;     /* control h */
   ttymodes.sg_kill = 21;     /* control u */
   ttychars.t_intrc = 3;      /* control c */
#endif
#if   defined(sparc)
   ioctl(1,TCSETS,&ttymodes);
#endif
#if   defined(hpux)
   ioctl(1,TCSETATTR,&ttymodes);
#endif
#if   defined(apollo)
   ioctl(1,TIOCSETP,&ttymodes);
   ioctl(1,TIOCSETC,&ttychars);
   ioctl(1,TIOCSLTC,&ttylchars);
   ioctl(1,TIOCSETD,&discipline);
#endif
   ttysizes.ws_row = rows;
   ttysizes.ws_col = cols;
   ioctl(1,TIOCSWINSZ,&ttysizes);

   for (i = 5; i < argc; i++) {
      args[i - 5] = argv[i];
   }
   args[i - 5] = (char *)NULL;
   pgm = args[0];
   for (ptr = pgm; *ptr != '\0'; ptr++)
      /* do nothing */;
   while (ptr > pgm && *ptr != '/')
      ptr--;
   if (ptr > pgm && *ptr == '/')
      ptr++;
   sprintf(buffer,"-%s",ptr);
   args[0] = buffer;
   execv(pgm,args);
   fprintf(stderr,"startoff: unable to start up %s\n",pgm);
   sleep(3);
}
