/* trap.d
 *
 */
#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"

char version[] = "$Id: trapd.c,v 1.22 1999/09/29 15:10:48 remlali Exp $"; /*usefull to 'strings' the binary*/
char trapd[] = "trapd";
glb_enviroment enviroment;
trapslot trap;			/*this is the incoming trap mem space*/
aclist *trapfilter;
char pipestring[4000];		/*minimum support of 484 bytes in a TRAP-PDU (rfc 1157)*/
FILE *fptrapd;

void debug(){};

int trap_command(char *cmd, char **args){	/*runs command using fork and system calls*/
pid_t pid;	

  if(!(pid = fork())){
    if(!(fork())) execv(cmd,args);
    _exit(0);
  }
  waitpid(pid,NULL,0);
  return 0;
}

void reload_config(){
  free(enviroment.traptab);
  load_trapconf();
  logstr(fptrapd,"Reloaded trap.conf.\n");
}

void coredump(){
pid_t pid;
  logstr(fptrapd,"Administratively coredumped.\n");
  if(!(pid = fork())){
    raise(SIGQUIT);
    _exit(0); /*precausious if SIGQUIT has other purpouses on other machines*/
  }
  waitpid(pid,NULL,0);
}

int main(){
int i, j, c, k, l, a, trapdsock, nbytes, *args[10];
char foo[80],foo2[80], eid[512], row[200], cmd[200];

/*follows are some temporary variables to parse new trap format:block*/
int traplen;	/* calculate length of incoming traps */
int severity;	/*hold where in trap block to insert severity */


/*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();
  fptrapd = logopen("trapd.log");
  load_trapconf();
  unlink(enviroment.trapd);
  if(!(trapdsock = createsocket(enviroment.trapd,0))) _exit(0);
  signal(SIGHUP, reload_config);
  signal(SIGINT, coredump);
  logstr(fptrapd,"Trapd started.\n");

start:
  memset(pipestring,'\0',4000);	/* due to a buggy block protocol, should now be safe to remove? */
  nbytes = recv(trapdsock,pipestring,400,0);

  if(!strncmp(pipestring,"kill",4)){
    close(trapdsock);
    unlink(enviroment.trapd);
    logstr(fptrapd,"Trapd stoped.\n");
    fclose(fptrapd);
    _exit(0);
  }
  if(!strncmp(pipestring,"status",6)){				/*answer a hello query from gxdhd */
    strcpy(eid,"daemon trapd ");
    sendsocket(trapdsock, enviroment.gxdhd, eid);
    goto start;
  }
  if(!strncmp(pipestring,"reload",6)){				/*reread trap.conf*/
    reload_config();
    goto start;
  }
  if(!strncmp(pipestring,"TRAP#",5)){
  memset(&trap, 0, sizeof(trapslot));
  severity = &severity;						/*set severity to non null value, obsolete?*/
  traplen = trap_decode(pipestring,&trap);
fprintf(stderr,"TRAP(%s,%s,%d,%d)\n",trap.IP,trap.oid, trap.g, trap.s);
  if(!trap_lookup(&trap)){					/*Do some action if trap is identified in trap.conf*/
    severity = 5 + sizeof(char);
    memcpy(&(pipestring[severity]),&trap.severity,sizeof(int));	/*set severity in trap block to forward*/
    if(strlen(trap.popup)){ 					/*POPUP a message to DISPLAY*/
      var_interpret(row, trap.popup, 200, &trap);
      if(enviroment.popup_date) args[0] = ctime((time_t *)&trap.timestamp);
      else args[0] = trapd;
      args[1] = row;
      args[2] = 0;
      trap_command(enviroment.popup_exec,args);
    }
    if(strlen(trap.script)){
      wordcpy(cmd,trap.script,1);				/*get command*/
      wordcpy(eid,trap.script,2);				/*get command arguments*/
      var_interpret(row,eid,200,&trap);
      j=0;i=0;
      args[j++] = trapd;					/*set program name, script's $0*/
      args[j++] = row;
      for(;9>j;i++){
        if(row[i] == '\0') break;
        if(row[i] == ' '){
          row[i] = '\0';
          args[j++] = &row[i+1];
        }
      }
      args[j] = 0;
      trap_command(cmd,args);
    }
    if(trap.eid){								/*launch an event from a mysql stored event_table, obsolete*/
      snprintf(eid,512,"ev %d",trap.eid);
      /*sendsocket(trapdsock, enviroment.actiond, eid);*/
    }
    if(trap.flag & 1){								/*bit 0 is forward to corrd*/
      senddsocket(trapdsock, enviroment.corrd, pipestring, traplen);       	/*forward event to corrd*/
    }
    if(trap.flag & 2){								/*bit 1 is forward to evdpysrvd*/
      senddsocket(trapdsock, enviroment.evdpysrvd, pipestring, traplen);       /*forward event to event display server deamon*/
    }
    if(trap.flag & 4){								/*bit 2 log trap*/
      snprintf(eid,512,"TRAP#%s#%s#%d#%d#%s#%s#%s#%s\n",trap.IP,trap.oid,trap.g,trap.s,trap.argdat[0],trap.argdat[1],trap.argdat[2],trap.argdat[3]);
      logstr(fptrapd,eid);
    }
  }else{							/*this code is for unknown traps */
    trap.severity = enviroment.severity;
    if(enviroment.trapd_unknown_traps){				/*may I forward unknown traps to evdpysrvd*/
      senddsocket(trapdsock, enviroment.evdpysrvd, pipestring, traplen);       /*forward event to event display server deamon*/
    }
    if(enviroment.trapd_log_unknown_traps){
      fprintf(stderr,"log unknown trap\n");
      snprintf(eid,512,"TRAP#%s#%s#%d#%d#%s#%s#%s#%s\n",trap.IP,trap.oid,trap.g,trap.s,trap.argdat[0],trap.argdat[1],trap.argdat[2],trap.argdat[3]);
      logstr(fptrapd,eid);
    }
  }
/*lets do some actions for both unknown and identified traps*/

  }/*end of strcmp pipestring == TRAP*/
  goto start;
}
