/* Copyright 1990, Daniel J. Bernstein. All rights reserved. */

#include "file.h"
#include "config.h"
#include "pty.h"
#include "tty.h"
#include "err.h"
#include "sig.h"
#include "slave.h"
#include "logs.h"

void slave(fnsty,arg)
char *fnsty;
char **arg;
{
 sig_ignore(SIGTTOU);
 sig_ignore(SIGTTIN);

 if (fdtty > -1)
  {
   (void) tty_dissoc(fdtty); /* must succeed */
   (void) close(fdtty);
  }
 if (fdre > -1)
   (void) close(fdre);
 (void) close(fdin);
 (void) close(fdout);
 (void) close(fdmty);
 (void) close(fdsty);
 (void) close(0);
 (void) close(1);
 if (flagsameerr < 2)
   (void) close(2);
 if (flagsameerr < 1)
  {
   (void) close(3);
   for (fdout = getdtablesize();fdout > 3;fdout--)
     (void) close(fdout);
  }

 if (open(fnsty,O_RDONLY) != 0)
   fatalerrp(1,"pty: fatal: cannot reopen pty for input",errno);
 if (open(fnsty,O_WRONLY) != 1)
     fatalerrp(1,"pty: fatal: cannot reopen pty for output",errno);
 if (flagsameerr < 2)
   if (open(fnsty,(flagxerrwo ? O_WRONLY : O_RDWR)) != 2)
     fatalerrp(1,"pty: fatal: cannot reopen pty for stderr",errno);
 if (flagsameerr < 1)
   if (open("/dev/tty",O_RDWR) != 3)
     fatalerrp(1,"pty: fatal: cannot reopen pty for /dev/tty",errno);

 if ((fdtty = open("/dev/tty",O_RDWR)) == -1)
   fatalerrp(1,"pty: fatal: cannot reopen pty for temporary /dev/tty",errno);

 if (setpgrp(0,getpid()) == -1)
   fatalerr(1,"pty: fatal: cannot set process group\n");
 if (tty_setpgrp(fdtty,getpid()) == -1)
   fatalerrp(1,"pty: fatal: cannot set pty process group",errno);
 if (tty_setmodes(fdtty,&tmopty) == -1)
   fatalerr(1,"pty: fatal: cannot set pty modes\n");
 if (flagxexcl)
   if (tty_setexcl(fdtty) == -1)
     fatalerr(1,"pty: fatal: cannot set exclusive use on pty\n");

 (void) fchmod(0,USEDPTYMODE);

 if (flagxchown)
   (void) fchown(0,uid,PTYGROUP);

 (void) close(fdtty);

 date = now(); /* could use original date instead */

 if (flagxutmp)
  {
   if (flagverbose)
     warnerr2("%s","pty: writing utmp entry\n");
   if (utmp(fnsty + PTYUTMP_OFFSET,username,PTYUTMP_HOST,date) == -1)
     warnerr2("pty: warning: cannot write %s utmp entry\n",fnsty);
  }

 if (flagxwtmp)
  {
   if (flagverbose)
     warnerr2("%s","pty: writing wtmp entry\n");
   if (wtmp(fnsty + PTYWTMP_OFFSET,username,PTYWTMP_HOST,date) == -1)
     warnerr2("pty: warning: cannot write %s wtmp entry\n",fnsty);
  }

 if (setreuid(uid,uid) == -1)
   /* We absolutely refuse to exec while setuid. */
   fatalerrp(1,"pty: fatal: cannot setreuid",errno);

 sig_restore();
 if (flagverbose)
   warnerr2("pty: executing program %s\n",arg[0]);
 (void) execvp(arg[0],arg);
 fatalerr2p(1,"pty: fatal: cannot execute %s",arg[0],errno);
 /*NOTREACHED*/
}
