#include "sliplogin.h"
#include "scanfile.h"

#include <sys/time.h>
#include <pwd.h>
#include <unistd.h>

#ifndef ESLIP_TIMEOUT
#define ESLIP_TIMEOUT 180
#endif

extern int configure_msg;
void hup_handler(int s);

static char host[80];

#ifdef IOCTL_FLAGS
extern IOCTL_FLAGS* modes;
#endif

void timeout (signum) /* esliplogin: handle login timeout */
int signum;
{
    printf("login handshake timed out after %d seconds.", ESLIP_TIMEOUT);
    syslog(LOG_INFO, "login handshake timed out after %d seconds.",
	   ESLIP_TIMEOUT);
    FATAL(1);
}

void stripstr(char* s)
{
    int p = 0;
    while (p < strlen(s))
    {
	if (s[p] == 8)
	{
	    int n = p-1;
	    int d;
	    if (n<0) n = 0;
	    d = p+1-n;
	    p = n;
	    do {
		s[n] = s[n+d];
		n++;
	    } while (s[n+d-1]);
	} else
	  p++;
    }
}

#ifdef LINE_ACCESS
int access_time; 	    
	    
void access_timeout(int s)
{
    extern int HUP;
    extern void exit_sliplogin();
    
    syslog(LOG_NOTICE, "SLIP access for %s expired (%d minutes).\n",
	   host, access_time);
    HUP=SIGUSR2;
    exit_sliplogin();
}
#endif

char* esliplogin (info, name)
struct slipinfo* info; 
char* name;
{
    FILE* fp;
    char *pass;
    struct itimerval ti;

    int ok = 0;
    int try = 5;

    if (name[strlen(name)-1] == '-') {
	configure_msg = 0;
	name[strlen(name)-1] = 0;
    } else if (name[strlen(name)-1] == '+') {
	configure_msg = 1;
	name[strlen(name)-1] = 0;
    }
    
    ti.it_interval.tv_sec = ESLIP_TIMEOUT; ti.it_interval.tv_usec = 0;
    ti.it_value.tv_sec    = ESLIP_TIMEOUT; ti.it_value.tv_usec    = 0;
    if (setitimer(ITIMER_REAL, &ti, NULL))
      syslog(LOG_WARNING, "No timer available: %m");
    else
      signal(SIGALRM, timeout);
    
    do { 
	char fhost[80], fpass[80];
	int denied = 0;
	
	printf("host: "); fgets(host,80,stdin);
	host[strlen(host)-1] = 0;
	stripstr(host);

	if (!(fp = fopen(_PATH_PASSWD, "r"))) /* usually: /etc/slip.passwd */
	{
	    fprintf(stderr, "Password file %s not found!\n", _PATH_PASSWD);
	    syslog(LOG_ERR, "Password file %s not found!", _PATH_PASSWD);
	    FATAL(1);
	}
	while (!feof(fp) && !ok) /* search for login */
	{
	    fscanf(fp, "%s %s", &fhost, &fpass);
	    if (fhost[0] == '+') /* Look at NIS map ? */
	    {
		char *nisdomain, *outval;
		int   outvallen, status;
		
#ifdef linux	    
		if(__yp_check(NULL)!=1) {
		    syslog(LOG_ERR,"YP not running\n"); continue;
		}
#endif	    
		yp_get_default_domain(&nisdomain);
		if (!nisdomain) continue;
	    
		status=yp_match(nisdomain,"slip.passwd", info->loginname,
				strlen(info->loginname), &outval, &outvallen);
		if(status!=0)
		{
		    fprintf(stderr,"%s not in NIS map slip.passwd\n",
			    info->loginname);
		    continue; /* Read next line */
		}
		strncpy (fhost, outval, outvallen);
		fhost[outvallen] = 0;
	    }
	    ok = (strcmp (fhost, host) == 0);
	}
	fclose(fp);
	
	if (   ok
	    && (   strcmp(fpass, "Reserved") == 0
		|| strcmp(fpass, "Local") == 0
		|| strcmp(fpass, "Locked") == 0))
	{
	    fprintf(stderr, "SLIP access denied for '%s', Status: %s.\n",
		    host, fpass);
	    /* copy message to line */
	    if (fp = fopen(_PATH_DENY, "r"))
	    {
		char msg[80];
		while (!feof(fp))
		{
		    fgets (msg, sizeof(msg), fp);
		    fprintf(stderr, msg);
		}
	    } else
	      fprintf(stderr, "Information file %s does not exist.\n",
		      _PATH_DENY);

	    syslog(LOG_ERR, "SLIP access denied for '%s', Status: %s.\n",
		   host, fpass);
	    FATAL(1);
	}

	pass = getpass("Password:");
	stripstr(pass);
	ok = (ok && strcmp(pass, fpass) == 0);
	
	if (ok)
	{
	    /* disable timer */
	    ti.it_value.tv_sec = 0;
	    setitimer(ITIMER_REAL, &ti, NULL);
	    signal(SIGALRM, SIG_DFL);

	    /* check for slip.host entry */
	    info->loginname = host;
	    scan_sliphosts(info);

#ifdef LINE_ACCESS
	    if ((access_time = get_access ('S', host, access_timeout)) == 0)
	    {
		printf("SLIP access denied (Time / Line restrictions).\n");
		syslog(LOG_ERR, "SLIP access denied for %s (Time / Line restrictions)",
		       host);
		FATAL(1);
	    } else if (access_time < 9999)
	    {
		fprintf(stderr,"Limited access for a minimum of %d minutes.\n",
			access_time);
		syslog(LOG_NOTICE, "SLIP access for %s: %d minutes.\n",
		       host, access_time);
	    }
#endif
	    
	    if (   strcmp(name, "nslip") == 0		/* normal slip */
		|| strcmp(name+1, "nslip") == 0)
	    {
		if (configure_msg)
		  fprintf(stderr,"Disabling VJ header compression.\n");
		strcpy(info->sm_name, "normal");
#ifdef IOCTL_FLAGS
		info->sm_value &= ~SL_MODE_CSLIP;
		info->sm_value &= ~SL_MODE_AUTO;
#endif
	    } else
	    if (   strcmp(name, "cslip") == 0		/* compressed slip */
		|| strcmp(name+1, "cslip") == 0)
	    {
		if (configure_msg)
		  fprintf(stderr,"Enabling VJ header compression.\n");
		strcpy(info->sm_name, "compress");
#ifdef IOCTL_FLAGS
		info->sm_value |= SL_MODE_CSLIP;
		info->sm_value &= ~SL_MODE_AUTO;
#endif
	    } else
#ifndef ESLIP_AUTO	      
	      if (   strcmp(name, "aslip") == 0		/* auto enable slip */
		  || strcmp(name+1, "aslip") == 0)
#endif
	      {
		  if (configure_msg)
		    fprintf(stderr,"Auto enabling VJ header compression.\n");
		  strcpy(info->sm_name, "auto");
#ifdef IOCTL_FLAGS
		  info->sm_value |= SL_MODE_AUTO;
		  info->sm_value &= ~SL_MODE_CSLIP;
#endif
	      }
	    return;
	    
	} else {
	    try--;
	    fprintf(stderr,"SLIP Login incorrect (%d tries left).\n", try);
	    fprintf(stderr,"Remember: the hostname usually consists only of small letters,\n");
	    fprintf(stderr,"\twhile the password is case sensitiv!\n");
	    syslog(LOG_ERR, "Wrong SLIP Passwort for %s: %s", host, pass);
	}
    } while (try>0);
    exit(1);
}

