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

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <glib.h>
#include "dae.h"

#define EVPOLL 300 /*poll time gap when polling event displays*/

char version[] = "$Id: evdpysrvd.c,v 1.18 1999/09/29 15:10:48 remlali Exp $"; /*usefull to 'strings' the binary*/

/*GLOBALS	*/
struct _xdpy{			/* Hold remote event display info*/
	char ip[80];		/* this is a file name when using AF_UNIX*/
	time_t lastpoll;	/* when did we last poll this evdpy*/
	int state;		/* state of evdpy */
}xdpy[40];			/*maximum numbers of connected xdpys, should be allocated instead of static.*/
glb_enviroment enviroment;
int currt;						/*holds current time() */
FILE *fpevdpysrvd;
aclist *trapfilter;
/****************/

int debug(){return 0;}

int xdpy_add(char *IP){	/*adds an remote display to the xdpy-struct*/
int i = 0;

  while(1){
    if(!strlen(xdpy[i].ip)){
      strcpy(xdpy[i].ip,IP);		/*add a new event display, and terminate list*/
      xdpy[i].state = 1;
      xdpy[i].lastpoll = currt;
      xdpy[++i].ip[0] = 0;
      return 0;
    }
    if(!strcmp(xdpy[i].ip,"NULL")){		/*add to a old empty slot*/
      strcpy(xdpy[i].ip,IP);
      xdpy[i].state = 1;
      xdpy[i].lastpoll = currt;
      return 0;
    }
    i++;
  }
}

int xdpy_del(char *IP){	/*adds an remote display to the xdpy-struct*/
int i = 0;

  while(1){
    if(!strlen(xdpy[i].ip)) return 0;	/*this is major cause it doesn't exists, */
    if(!strcmp(xdpy[i].ip,IP)){
      strcpy(xdpy[i].ip,"NULL");	/*mark this slot as empty*/
      return 1;
    }	
    i++;
  }
}

int main(){
char pipestring[400];
char foo[1000],foo2[80];
trapslot trap;
int evdpysrvdsock, nbytes;
int i, traplen;

/*daemonize*/
/*
  if(fork() != 0) _exit(0);
  if(setsid() == -1) _exit(0);
  if(fork() != 0) _exit(0);
  umask(777);
  if(chdir("/")<0) _exit(0);
  for(i=sysconf(_SC_OPEN_MAX),j=0;j<i;) close(j++);
  open("/dev/null",O_RDWR); dup(0); dup(0);
*/
/***********/
  load_enviroment();
  xdpy[0].ip[0] = 0;				/*initialize struct where event display data is held*/
  fpevdpysrvd = logopen("evdpysrvd.log");					/*start logging*/
  unlink(enviroment.evdpysrvd);
  if(!(evdpysrvdsock = createsocket(enviroment.evdpysrvd,0))) _exit(0);	/*trap input socket*/
  logstr(fpevdpysrvd,"Evdpysrvd started.\n");

start:
  currt = time(0);
  i = 0;
  while(1){							/* go through all registered displays and check if they are alive*/
    if(!strlen(xdpy[i].ip)) break;						/*end of array*/
    if(!strcmp(xdpy[i].ip,"NULL")) break;					/*unused slot*/
    if(((currt - xdpy[i].lastpoll)> EVPOLL) && xdpy[i].state == 1){		/*this evdpy hasn't been polled for a while*/
      snprintf(foo,1000,"gs. %d",i);					/*GetStatus*/
      sendsocket(evdpysrvdsock, xdpy[i].ip, foo);
      xdpy[i].state = 2;						/*pending state (evdpysrvd waiting for reply)*/
    }
    else if(((currt - xdpy[i].lastpoll) > EVPOLL ) && xdpy[i].state == 2){	/*this evdpy hasn't answered a poll*/
      strcpy(xdpy[i].ip,"NULL");					/*unregister this evdpy */
    }
    i++;
  }
		
  nbytes = recv(evdpysrvdsock,pipestring,400,0);
  if(nbytes < 0) goto start;
    if(!strncmp(pipestring,"kill",4)){
      unlink(enviroment.evdpysrvd);
      close(evdpysrvdsock);
      logstr(fpevdpysrvd,"Evdpysrvd stoped.\n");
      fclose(fpevdpysrvd);
      _exit(0);
    }
  if(!strncmp(pipestring,"open",4)){				/*register a new event display to receive a traps*/
    wordcpy(foo, pipestring, 2);				/*get source address ( IP / Socket  ) */
    xdpy_add(foo);
    snprintf(foo2,80,"Registered event display: %s\n",foo);
    logstr(fpevdpysrvd,foo2);
  }
  if(!strncmp(pipestring,"close",5)){				/*unregister a event display from receiving traps*/
    wordcpy(foo, pipestring, 2);				/*get sorce address ( IP / socket ) */
    xdpy_del(foo);						/*del old event display from receiveing traps*/
    snprintf(foo2,80,"Unregistered event display: %s\n",foo);
    logstr(fpevdpysrvd,foo2);
  }
  if(!strncmp(pipestring,"sr.",3)){				/*STatusReply*/
    i = atoi(wordcpy(foo,pipestring,2));			/*get xdpy struct index ( sent in GetStatus )*/
    xdpy[i].state = 1;					/*daemon is alive*/
    xdpy[i].lastpoll = currt;				/*set date when we last polled this machine*/
  }
  if(!strncmp(pipestring,"status",6)){                            /*answer a hello query to gxdhd*/
    strcpy(foo,"daemon evdpysrvd ");
    sendsocket(evdpysrvdsock, enviroment.gxdhd, foo);
    goto start;
  }
  if(!strncmp(pipestring,"TRAP#",5)){
    traplen = trap_decode(pipestring, &trap);
fprintf(stderr,"trap:%s %d %d\n", trap.IP, trap.g, trap.s);
    i = 0;
    while(1){
      if(!strlen(xdpy[i].ip)) break;			/*end of array*/
      if(!strcmp(xdpy[i].ip,"NULL")) break;		/*empty slot*/
      if(enviroment.evdpysrvd_log){
        snprintf(foo,1000,"Sending trap (%s,%d,%d) to display: %s\n",trap.oid,trap.g,trap.s,xdpy[i].ip);
        logstr(fpevdpysrvd,foo);
      }
      fprintf(stderr, "sending trap to %s\n", xdpy[i].ip);
      senddsocket(evdpysrvdsock, xdpy[i].ip, pipestring, traplen);		/*forward event to connected event display */
      i++;
    }
  }
  goto start;
}
