#include <stddef.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.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 <mysql.h>

#include "dae.h"
#include "dbsql.h"

gboolean             tcp_new_connection           (GIOChannel     *source,  GIOCondition   condition, gpointer       data);
gboolean             tcp_client_activity          (GIOChannel     *source, GIOCondition   condition, gpointer       data);

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

char version[] = "$Id: gxdd.c,v 1.1 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 *fpgxdd;
aclist *trapfilter;
db_init dbs;

/****************/

typedef struct _dbblock {
	unsigned char version;
	unsigned int session;
	unsigned int action;
					/*host table*/
	char dns_name[64];
	char dname[64];
	char description[127];
					/*interface table*/
	int host;
	int snmp;
	char address[127];
	char iname[127];

}dbblock;

/*cache
this is a test, to cache IP/name pairs

*/

typedef struct _gcache{
	char iname[127];		/*interface name*/
	char address[127];
}gcache;

gcache cache[128]; /* approx 32000 bytes */


#include "dbsql.c"

int decodedb(char *pipestring, dbblock *block){
int pz = 5;

  memset(block, 0, sizeof(dbblock));

  if((pipestring[5] != '\1')) return 0; /*wrong version number*/
  pz += sizeof(char);

//  memcpy(&(trap->severity), &(pipestring[pz]),sizeof(int));          /*session*/
  pz +=sizeof(int);

 // memcpy(&(trap->timestamp), &(pipestring[pz]),sizeof(int));          /*trap timestamp from block*/
  pz += sizeof(int);

//  memcpy(&ip,&(pipestring[pz]),sizeof(struct in_addr));
//  strcpy(trap->IP,inet_ntoa(ip));
  pz += sizeof(int);

 // memcpy(&(trap->g),&(pipestring[pz]),sizeof(int));
  pz += sizeof(int);
//  memcpy(&(trap->s),&(pipestring[pz]),sizeof(int));
  pz += sizeof(int);


}

void
tcp_enable_reuseaddr (gint sock)
{
  gint tmp = 1;
  if (sock < 0)
    return;
  if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (gchar *)&tmp, 
                  sizeof (tmp)) == -1)
    perror ("Bah! Bad setsockopt ()\n");
}

void 
tcp_enable_nbio (gint fd)
{
  if (fcntl (fd, F_SETOWN, getpid()) == -1)
    perror ("fcntl (F_SETOWN) error\n");
  if (fcntl (fd, F_SETFL, FNDELAY) == -1)
    perror ("fcntl (F_SETFL, FNDELAY\n");
}

void 
tcp_socket_init (gint port)
{
  gint                s;
  struct sockaddr_in  addr;
  GIOChannel          *channel;

  if (port <= 0)
    return ;

  s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s == -1)
    return;
  tcp_enable_reuseaddr (s);
  memset (&addr, 0, sizeof (addr));
  addr.sin_family       = AF_INET;
  addr.sin_port         = htons ((u_short)port);
  addr.sin_addr.s_addr  = INADDR_ANY;
  if (bind (s, (struct sockaddr *)&addr, sizeof (addr)) == -1)
    {
      close (s);
      return ;
    }
  if (listen (s, 5) == -1)
    {
      close (s);
      return ;
    }
  channel = g_io_channel_unix_new (s);
  g_io_add_watch (channel, G_IO_IN, tcp_new_connection, NULL);
}

/**
 * tcp_new_connection 
 * Will accept a new connection and add the client to the list of clients.
 * actual client communication is handled elsewhere.
 **/
gboolean 
tcp_new_connection (GIOChannel *source, GIOCondition cond, gpointer data)
{
  gint               new;              /* new socket descriptor */
  gint               client;
  GIOChannel         *new_channel;
  struct sockaddr_in client_addr;

  if (cond == G_IO_IN)
    {
      if ( (new = accept (g_io_channel_unix_get_fd (source),
                          (struct sockaddr *)&client_addr, &client)) < 0)
        {
          g_warning ("Unable to accept new connection.");
          return FALSE;
        }
      new_channel = g_io_channel_unix_new (new);
      g_io_add_watch (new_channel, G_IO_IN, tcp_client_activity, NULL);
    }
  return TRUE;
}


/**
 * tcp_client_activity
 * Handles input from the clients and passes it off to the parser/dispatcher.
 * This will get the raw data from the socket, make sure there is a NULL 
 * terminator, and call the command dispatcher.
 **/
gboolean 
tcp_client_activity (GIOChannel *source, GIOCondition cond, gpointer data)
{
  char w1[100];
  char w2[100];
  char w3[100];
  gchar w4[200];
  gchar buf[1024];
  guint num_read = 0;
  db_host host;
  int len;

  if (cond == G_IO_IN)
    {
      if (g_io_channel_read (source, buf, sizeof (buf), &num_read) == G_IO_ERROR_NONE)
        {
          buf[num_read] = '\0';           /* Make sure its null terminated */
          g_print ("Read (%d)\"%s\" from the socket\n", num_read, buf);
          wordcpy(w1,buf,1);
	  if(!strcmp(w1,"gethostinfo")){ /*user wants to get dns_name for an IP*/
            wordcpy(host.name,buf,2);	/*this is IP address*/
            if(!db_ip2name_read_host(&host)){
              fprintf(stderr,"dns_name: %s\n", host.dns_name);
              sprintf(w4, "answer %s ", host.dns_name);
              len = strlen(w4);
              fprintf(stderr,"Writing '%s' of %d bytes\n", w4, len);
              if(g_io_channel_write(source, w4, len, &num_read) != G_IO_ERROR_NONE){
                fprintf(stderr,"Error sending result to client.\n");
              }
            }else{
              printf("database request error.\n");
            }
	  }
        }
    }
  return TRUE;
}

int main(){
char raw[4000];
char foo[1000],foo2[80];
int evdpysrvdsock;
GMainLoop    *loop;

/*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*/
  fpgxdd = logopen("gxdd.log");					/*start logging*/
//  unlink(enviroment.gxdd);			/*currently we are only listening on a file socket*/
//  if(!(evdpysrvdsock = createsocket(enviroment.gxdd,0))) _exit(0);	/*trap input socket*/
  fprintf(stderr, "connecting.\n");
  if(-1 == (dbs.sock = db_connect_db())) _exit(0);
  fprintf(stderr, "opening.\n");
  if(-1 == db_open_db("gxsnmp")){
    fprintf(stderr, "Open error\n");
    _exit(0);
  }
  fprintf(stderr, "Cache size is %d bytes. ( cache unimplemented )\n",sizeof(cache));
  fprintf(stderr, "gxdd started.\n");
  logstr(fpgxdd,"Evdpysrvd started.\n");

  tcp_socket_init (4000);
  loop = g_main_new (TRUE);
  while (g_main_is_running (loop)) g_main_run (loop);
  g_main_destroy (loop);
  return 0;
}
