/*
**  Copyright (c) 1991 Bolt Beranek and Newman, Inc.
**  All rights reserved.
**
**  Redistribution and use in source and binary forms are permitted
**  provided that: (1) source distributions retain this entire copyright
**  notice and comment, and (2) distributions including binaries display
**  the following acknowledgement:  ``This product includes software
**  developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
**  documentation or other materials provided with the distribution and in
**  all advertising materials mentioning features or use of this software.
**  Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
**  to endorse or promote products derived from this software without
**  specific prior written permission.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
**  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
 * Copyright (c) 1992 Purdue University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by Purdue University.  The name of the University may not be used
 * to endorse or promote products derived * from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Note: this copyright applies to portions of this software developed
 * at Purdue beyond the software covered by the original copyright.
 */
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stream.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/dlpi.h>

#include "ppp.h"
#include "dp.h"
#include "dpio.h"
#include "dpd.h"

static char *WHERE = "dplogin";

static time_t starttime,
	      stoptime;
static dp_stats_t startds,	/* Packet/byte/error counts at start	*/
		  stopds;	/* Packet/byte/error counts at stop	*/
static long   duration;
static char *tty;
static REMOTE *RP;

extern void collect_child(),
	    collect_ppp(),
	    writelog();
extern int log_level;
void hangup();

main(argc, argv)
    int			argc;
    char		*argv[];
{
    char login[L_cuserid];
    REMOTE *rp;
    extern REMOTE *findlogin();
    char *configfile;
    char *ttyname();

    /*
     * Become root completely..
     */
    (void)setuid(geteuid());

    /* Set defaults. */
    setprogname(argv[0][0] == '-' ? argv[0]+1 : argv[0]);
    WHERE = progname; configfile = DP_CONFIG;

    if (cuserid(login) == NULL) {
	d_log(DLOG_GENERAL, WHERE, "Can't determine login name");
	exit(11);
    }
    if (tty = ttyname(0)) {
	if (strncmp(tty, "/dev/", sizeof("/dev/")-1) == 0)
	    tty += sizeof("/dev/")-1;
    }
    else {
	d_log(DLOG_GENERAL, WHERE, "Can't determine login tty");
	exit(12);
    }

    /*
     * Figure out where everything is located.
     */
    init_pathconf();

    /*
     * Read network and modem configuration.
     */
    if (!readconfig(configfile))
	exit(13);

    if (!(rp = findlogin(login))) {
	d_log(DLOG_GENERAL, WHERE, "Unknown login name \"%s\"", login);
	exit(14);
    }
    if (rp->LogLevel > log_level)
	log_level = rp->LogLevel;

    /*
     * Save stuff for hangup().
     */
    RP = rp;
    record_pid(rp->Device, getpid(), -1);

    if (opendp(rp, (ulong)0)) {
	d_log(DLOG_GENERAL, WHERE, "Can't open dp device");
	exit(15);
    }


    /*
     * This synchronizes the dial script on the other end..
     */
    (void)printf("PPP start\n"); 
    (void)fflush(stdout);
    /*
     * Make sure our kernel knows what's coming..
     */
    if_callstat(rp, DP_IN_PROGRESS);

    /*
     * Configure the appropriate activity timeouts for an incoming call.
     */
    (void)if_atimeouts(rp);

    /*
     * Initiate PPP.
     */
    if (start_ppp(rp, (char *)0, 1, rp->AsyncMap) < 0) {
	d_log(DLOG_GENERAL, WHERE, "Failed to start PPP to \"%s\"", rp->Sitename);
	exit(16);
    }

    (void)signal(SIGHUP, SIG_IGN);
    (void)signal(SIGTERM, SIG_IGN);
    (void)signal(SIGCHLD, collect_child);

    d_log(DLOG_GENERAL, WHERE, "PPP started to \"%s\"", rp->Sitename);

    (void)time(&starttime);
    getpacketcounts(rp, &startds);

    collect_ppp();

    hangup(0);
    /* NOTREACHED */
}

/*
**  Catch signal and exit.
*/
void
hangup(sig)
    int			sig;
{
    static char	WHERE[] = "hangup";
    long		totalpkts;

    /*
     * Now ignore the signals since we're shutting down.
     */
    (void)signal(SIGHUP, SIG_IGN);
    (void)signal(SIGTERM, SIG_IGN);
    (void)signal(SIGCHLD, SIG_IGN);
    if (sig)
	d_log(DLOG_ALL, WHERE, "Process %d got signal %d for \"%s\"",
	    getpid(), sig, RP->Device);

    unlock_pid();

    /*
     * Log the statistics
     */
    (void)time(&stoptime);
    duration = stoptime - starttime;

    getpacketcounts(RP, &stopds);
    stopds.dps_ibytes   -= startds.dps_ibytes;
    stopds.dps_ipackets -= startds.dps_ipackets;
    stopds.dps_ierrors  -= startds.dps_ierrors;
    stopds.dps_obytes   -= startds.dps_obytes;
    stopds.dps_opackets -= startds.dps_opackets;
    stopds.dps_oerrors  -= startds.dps_oerrors;

    writelog(RP->Sitename, tty, starttime, stoptime, &stopds,
	     (dl_unitdata_req_t *)0, (char *)0);

    totalpkts = stopds.dps_ipackets + stopds.dps_opackets;
    d_log(DLOG_INFO, WHERE, "Inbound interface \"%s\" up %ld seconds",
	RP->Device, duration);
    d_log(DLOG_DIAG, WHERE,
	"Inpackets = %ld, Outpackets = %ld, Average = %.2f packets/sec",
	stopds.dps_ipackets, stopds.dps_opackets,
	duration ? ((float)totalpkts) / ((float)duration) : 0);

    /*
     * All done, report that we made it.
     */
    d_log(DLOG_GENERAL, WHERE, "Disconnected \"%s\"", RP->Device);
    exit(0);
}
