#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h> 

int ppppid, sshpid;

#ifndef PIDFILE
#define PIDFILE "/d2/borer/ptyfu.pid"
#endif

#ifndef SSH_PROG
#define SSH_PROG "/usr/pkg/bin/ssh"
#endif

#ifndef SSH_USER
#define SSH_USER "Porchard"
#endif

#ifndef PPPD_PROG
#define PPPD_PROG "/usr/sbin/pppd"
#endif

#ifndef PPPD_RC
#define PPPD_RC "/d2/borer/.ppprc"
#endif

void cleanup(int sig) {
  if (ppppid)
    kill(ppppid, SIGTERM);
  sleep(1);
  if (sshpid)
    kill(sshpid, SIGTERM);
  unlink(PIDFILE);
  exit(1);
}

void reaper(int sig) {
  int status;
  int deadpid = waitpid(-1, &status, WNOHANG);
  if (deadpid) {
    if (deadpid == ppppid) {
      fprintf(stderr, "pppd died\n");
      ppppid = 0;
    }
    if (deadpid == sshpid) {
      fprintf(stderr, "ssh died\n");
      sshpid = 0;
    }
  }
}

main(int argc, char **argv)
{
  sigset_t nosig;
  char ptybuf[64];
  int pty, tty;
  char *host;
  int mypid = getpid();
  FILE *pidfile;

  if (argc != 2) {
    fprintf (stderr, "Usage: %s host\n", argv[0]);
    exit (1);
  }

  host = argv[1];
  
  /* unholy pipefitting: pppd<-ssh->sshd->pppd */
  signal(SIGCHLD, reaper);
  signal(SIGINT, cleanup);
  signal(SIGTERM, cleanup);

  pidfile = fopen(PIDFILE, "w");
  if (pidfile == NULL) {
    perror(PIDFILE);
    exit(1);
  }
  fprintf(pidfile, "%d\n", mypid);
  fclose(pidfile);

  /* grab a pty.. */
  pty_allocate(&pty, &tty, ptybuf);

  printf("Grabbed %s\n", ptybuf);

  fflush(NULL);
  ppppid = fork();
  if (ppppid < 0) {
    perror("fork");
    cleanup(0);
  }

  if (ppppid == 0) {
    /* child.  start pppd... */
    dup2(tty, 0);
    dup2(tty, 1);
    close(pty);
    close(tty);
    sleep(10);
#ifdef SETUID
    setreuid(0,0);
    seteuid(0);
    setuid(0);
#endif    
    fprintf(stderr, "execing pppd...\n");
    execlp(PPPD_PROG, "pppd", ptybuf, "passive", "file", PPPD_RC, NULL);
    fprintf(stderr, "pppd finished?\n");
    _exit(1);
  }

  sshpid = fork();
  if (sshpid < 0) {
    perror("fork");
    cleanup(0);
  }

  if (sshpid == 0) {
    /* child.  start sshd... */
    dup2(pty, 0);
    dup2(pty, 1);
    close(pty);
    close(tty);

    fprintf(stderr, "execing ssh...\n");
    execlp(SSH_PROG, "ssh", host, "-v", "-x", "-l", SSH_USER, NULL);
    _exit(1);
  }
  close(tty);
  close(pty);
  while (sshpid || ppppid) {
    sigemptyset(&nosig);
    sigsuspend(&nosig);
    fprintf(stderr, "awake!\n");
  }
  cleanup(0);
}
