/*
 * dip		A program for handling dialup IP connecions.
 *		This program handles the connections needed for dialup
 *		IP links, like SLIP or PPP.  It can handle both incoming
 *		and outgoing connections, using password security for
 *		incoming connections.  The outgoing connections use the
 *		system's dial(3) library if possible.
 *
 * Usage:	dip -i [-v]
 *              diplogin
 *		dip [-v] -k [-l tty]
 *		dip -t [-v]
 *		dip [-v] [-m mtu] [-p proto] [telno | script]
 *		diplogin [-v]
 *
 * Version:	@(#)main.c	3.3.7f-uri	08/18/94
 *
 * Author:      Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *		Copyright 1988-1993 MicroWalt Corporation
 *
 * Modified:    Uri Blumenthal <uri@watson.ibm.com>
 *              Copyright 1994 
 *
 *		This program is free software; you can redistribute it
 *		and/or  modify it under  the terms of  the GNU General
 *		Public  License as  published  by  the  Free  Software
 *		Foundation;  either  version 2 of the License, or  (at
 *		your option) any later version.
 */
#define GLOBAL
#include "dip.h"


#define VERSION	"3.3.7f-uri (18 Aug 94)"


char *Version = "@(#) dip " VERSION;


struct dip	mydip;			/* global DIP entry		*/
int		opt_v = 0;		/* debug flag			*/


/* Kill a running DIP process. */
static void
kill_dip(void)
{
  char buff[128];
  int pid;
  FILE *fp;

  fp = fopen(_PATH_DIP_PID, "r");
  if (fp == NULL) {
	fprintf(stderr, "DIP: cannot open %s: %s\n",
			_PATH_DIP_PID, strerror(errno));
	return;
  }
  (void) fgets(buff, 128, fp);
  pid = atoi(buff);
  seteuid(getuid());
  if (kill(pid, SIGQUIT)) {
	fprintf(stderr, "DIP: cannot kill process %d: %s\n",
			pid, strerror(errno));
	return;
  } else printf("DIP: process %d killed.\n", pid);
  seteuid(0);
  (void) fclose(fp);
  (void) unlink(_PATH_DIP_PID);
}


static void new_kill_dip(char *nam)
{
  char buf[128];
  int pid = 0;
  FILE *fp;
  int fu_read = 0;
#if 0
  struct stat   sbuf;
#endif

  if ((nam == (char *)0) || (nam[0] == '\0')) { 
    /* tty name was not given */
    if (opt_v == 1) 
       fprintf(stderr, "No tty name given, will use /etc/dip.pid...\n");
    kill_dip();
    return;
  }
   
  sprintf(buf, "%s/LCK..%s", _PATH_LOCKD, nam);

  fp = fopen(buf, "r");
  if (fp == (FILE *)0) {
	fprintf(stderr, "DIP: cannot open %s: %s\n",
			buf, strerror(errno));
	return;
  }
#if HAVE_V2_LOCKFILES
  fu_read = read(fileno(fd), &pid, sizeof(pid));
#else
  (void) fscanf(fp, "%d", &pid);
#endif
  (void) fclose(fp);
  seteuid(getuid());
  if (kill(pid, SIGQUIT)) {
	fprintf(stderr, "DIP: cannot kill process %d: %s\n",
			pid, strerror(errno));
	return;
  } else printf("DIP: process %d killed.\n", pid);
  seteuid(0);
  (void) unlink(buf);
}


/* Fill in the global DIP entry. */
static void
dip_init(void)
{
  struct passwd *pw;
  struct hostent *hp;

  if ((pw = getpwuid(getuid())) == (struct passwd *)NULL) {
	fprintf(stderr, "You do not exist.  Go away!\n");
	exit(-1);
  }
  memset((char *) &mydip, 0, sizeof(struct dip));
  strncpy(mydip.name, pw->pw_name, 16);
  strcpy(mydip.home, "/tmp");

  if (gethostname(mydip.local, 128) < 0) {
	perror("gethostname");
	exit(-1);
  }
  if ((hp = gethostbyname(mydip.local)) == (struct hostent *)NULL) {
	herror(mydip.local);
	strcpy(mydip.local, "");
	exit(-1);
  }
  strncpy(mydip.local, hp->h_name, 128);
  memcpy((char *) &mydip.loc_ip, (char *) hp->h_addr_list[0], hp->h_length);

  strcpy(mydip.protocol, DEF_PROT);
  mydip.protonr = get_prot(mydip.protocol);
  mydip.mtu = DEF_MTU;
}


static void
usage(void)
{
  fprintf(stderr, "Usage: dip -i [-v]\n");
  fprintf(stderr, "       diplogin [-v]\n");
  fprintf(stderr, "       dip [-v] -k [-l ttyname]\n");
  fprintf(stderr, "       dip -t [-v]\n");
  fprintf(stderr, "       dip [-v] [-m mtu] [-p proto] [telno | script]\n");
  exit(-1);
}


int
main(int argc, char *argv[])
{
  char path[128];
  FILE *fp;
  register int s;
  register char *sp;
  int opt_i, opt_k, opt_t;

  /* Setup. */
  dip_init();

  bzero(path, sizeof(path));
  opt_i = 0;
  opt_k = 0;
  opt_t = 0;

  /*
   * This is a kludge for bad "login" programs which cannot pass
   * arguments. Needless to say, this includes the SLS login(8)
   * program, and most BSD derivatives... -FvK
   */
  /*
   * Added "login" below, so diplogin can be called directly
   * from getty_ps... SJS
   */
  if ((sp = strrchr(argv[0], '/')) != NULL) *sp++ = '\0';
    else sp = argv[0];
  if ((*sp == '-') || !strcmp(sp, "diplogin") || !strcmp(sp, "login")) 
      opt_i = 1;

  /* Scan command line for any arguments. */
  opterr = 0;
  while ((s = getopt(argc, argv, "ikl:m:p:vt")) != EOF) switch(s) {
	case 'i':
		opt_i = 1;
		break;

	case 'k':
		opt_k = 1;
		break;

        case 'l':
		strcpy(path, optarg);
		break;

	case 'm':
		mydip.mtu = atoi(optarg);
		if (mydip.mtu <= 0 || mydip.mtu > 32767) usage();
		break;

	case 'p':
		strcpy(mydip.protocol, optarg);
		mydip.protonr = get_prot(mydip.protocol);
		if (mydip.protonr == 0) usage();
		break;

	case 't':
		opt_t = 1;
		break;

	case 'v':
		opt_v = 1;
		break;

	default:
		usage();
  }

  printf("DIP: Dialup IP Protocol Driver version %s\n", VERSION);
  printf("Written by Fred N. van Kempen, MicroWalt Corporation.\n\n");

  /* Are we called to kill off a DIP process? */
  if (opt_k == 1) {
    new_kill_dip(path);
    exit(0);
  }
  
  /* Verbose mode? -> print mydip values */
  if (opt_v == 1) {
    printf("DIP: name=%s home=%s\n",mydip.name,mydip.home);
    printf("     host=%s IP=%s\n",mydip.local,inet_ntoa(mydip.loc_ip));
    printf("     prot=%s MTU=%d\n\n",mydip.protocol,mydip.mtu);
  }

  /* Are we going to be a dialIN server? */
  if (opt_i == 1) {
    if (optind == argc) sp = mydip.name;
    else sp = argv[optind];
    do_login(sp, &argv[0]);
    /*NOTREACHED*/
  }

  /* Are we running in TEST mode? */
  if (opt_t == 1) {
    if (optind != argc) usage();
    do_command(stdin);
    /*NOTREACHED*/
  }

  /* No, so we are running in dialOUT mode. */
  if (optind != (argc - 1)) usage();
  strncpy(path, argv[optind], 128);
  if ((sp = strrchr(path, '/')) != (char *)NULL) sp++;
    else sp = path;
  if (strchr(sp, '.') == (char *)NULL) strcat(path, DIP_SFX);

  if ((fp = fopen(path, "r")) == (FILE *)NULL) {
	fprintf(stderr, "dip: %s: %s\n", path, strerror(errno));
	exit(-1);
  }
  (void) setbuf(fp, (char *)NULL);
  do_command(fp);

  /*NOTREACHED*/
  return(-1);
}
