#include <unistd.h>
#include <stddef.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 <pthread.h>
#include <glib.h>
#include <EXTERN.h>
#include <perl.h>
#include <guile/gh.h>
#include <libguile.h>
#include "dae.h"
#define CTSFMASK 8191 /*corrthreadslot-flag-mask*/
#define MAXTRAPHOLD 3600 /*throw away traps in buffer after the've been there MAXTRAPHOLD seconds*/

char version[] = "$Id: corrd.c,v 1.17 1999/09/14 10:26:59 remlali Exp $"; /*usefull to 'strings' the binary*/

char pipestring[400];
int corrdsock;
trapslot trap;
FILE *forkfp;
FILE *fpcorrd;
glb_enviroment enviroment;
aclist *trapfilter; /*this is only needed by the libdae*/
int pstatus, traplen;
typedef struct _corrthreadslot{ /* each correlating thread will receive its own corrthreadslot */
  int pstatus;		/* status of thread when it terminates */
  int seconds;		/* how long, if wanted, to keep this trap in memory*/
  int flag;		/* flags about trap and so, mask is CTSFMASK */
    /* bit 0 - 0=running 1=finished , correlation done.
     * bit 1 - 0=no 1=yes, corrd can remove trap.
     * bit 2 - 
     * bit 3 - 
     * bit 4 - 0=block / 1=forward trap after finished.
    */
  trapslot trap;	/* trap to be correlated */
  int stype;		/* script type */
  char script[200];	/* scriptfile */
  char *scriptargs[2];   /* script arguments, stupid but simple */
  char args[2][200];
  PerlInterpreter *perl;		/*this is the interpreter*/
}corrthreadslot;

GList *corrthreads = 0; 						/* all corrthreadslots is saved in this list, for use by corrd */
//pthread_mutex_t mutex;
int scheme_ct = 0; 							/* this is set, whenever there is a new trap to be correlated*/
corrthreadslot *newthread; 						/*this is a pointer to the trap to be correlated*/
struct timespec delay;

#include "sev.c"

corr_slot *corr_lookup(corr_slot *corrdst, corr_slot *cortmp, trapslot *trap){
  for(;strlen(cortmp->mask);cortmp++){ 							/*go through corr.conf*/
    if(!strcmp(cortmp->mask,trap->IP) || !strcmp(cortmp->mask, "*")){			/*host match found*/
      strcpy(corrdst->file,cortmp->file);
      cortmp++;
      return cortmp;
    }
  }
  return 0;
}

int main(int argc, char **argv, char** env){	/*needs argument due to PERL , but we pass NULLs anyway*/
char foo[80];
corr_slot corrdst, *corrp, *cortmp;
int nbytes;
int l;
pthread_t sid;

/*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();
  fpcorrd = logopen("corrd.log");
  cortmp = corrp = load_corrconf();
  unlink(enviroment.corrd);
  if(!(corrdsock = createsocket(enviroment.corrd,0))) _exit(0);
  logstr(fpcorrd,"Corrd started.\n");

start:

  nbytes = recv(corrdsock,pipestring,400,0);

  if(nbytes < 0) goto start;
fprintf(stderr,"!");
  if(!strncmp(pipestring,"kill",4)){
    unlink(enviroment.corrd);
    close(corrdsock);
    logstr(fpcorrd,"Corrd stopped.\n");
    fclose(fpcorrd);
    _exit(0);
  }
  if(!strncmp(pipestring,"status",6)){				/*answer a hello query from gxstatus*/
    strcpy(foo,"daemon corrd ");
    sendsocket(corrdsock, enviroment.gxdhd, foo);       	/*forward event to event display server deamon*/
    goto start;
  }
  if(!strncmp(pipestring,"reload",6)){
    free(corrp);
    corrp = load_corrconf();
    logstr(fpcorrd,"Reloaded corr.conf.\n");
  }
  if(!strncmp(pipestring,"TRAP#",5)){
    trap_decode(pipestring, &trap);
    cortmp = corrp;
    while(cortmp = corr_lookup(&corrdst, cortmp, &trap)){
      newthread = g_new0(corrthreadslot, 1); 			/*create a new corrthreadslot */
      newthread->stype = 0;                                	/*default to shell script */
      if(strncmp(corrdst.file,"/",1)){	         		/*if no root-path is set, try interpret and assign */
        l = strlen(corrdst.file);
        if(!strncmp(corrdst.file+l-3, ".pl", 3)){
          newthread->stype = 1;
          sprintf(newthread->args[0],"%s/perl/%s",enviroment.base,corrdst.file);
          newthread->scriptargs[0] = newthread->args[0];
        }else if(!strncmp(corrdst.file+l-4, ".scm", 4)){
          newthread->stype = 2;
          sprintf(newthread->script,"%s/scheme/%s",enviroment.base,corrdst.file);
        } else {							/*undefined script type. Dont know what to do. */
          logstr(fpcorrd,"Couldn't exec correlation script: unknown script type without full path.\n");
          g_free(newthread);
          continue;
        }
      }else{                                          		/*scriptfile have full pathname, its a shellscript*/
        strcpy(newthread->script, "/bin/sh");
        strcpy(newthread->args[0], newthread->script);
        strcpy(newthread->args[1], corrdst.file);
        newthread->scriptargs[0] = newthread->args[0];
        newthread->scriptargs[1] = 0;
      }
      if(enviroment.corrd_log) logstr(fpcorrd,"Launching correlation script.\n");
      /*corrthreads = g_list_append(corrthreads, newthread);*/			/*save it in corrd's thread lookup table, for all traps*/
      pthread_create(&sid, 0, &do_script, newthread);
/*something checking sid here*/
//      exec_script(newthread);	                                    /*launch script*/
      g_free(newthread); /*REMOVE when we have threads, and a trap GList revision function, that throws away old traps*/
    }/*end of corr.conf while */
  }/*end of trap identify */
  goto start;
}
