/* API to connect and query database daemon gxdd
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>

#include <errno.h> /*alot junk here*/
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/un.h>
#include <netinet/in.h>   
#include <arpa/inet.h>
#include <unistd.h>

#include "g_sqldb.h"
#include "tables.h"
#include "debug.h"

#include "tables.c"

char version[] = "$Id: gxsnmpdb.c,v 1.4 1999/10/20 11:24:44 remlali Exp $"; /*usefull to 'strings' the binary*/

struct sockaddr_in ddserver;


/****************************************************************************
 * private functions to the API
 ***************************************************************************/

gchar *
db_timestamp ()
{
  gchar         * buf;
  struct tm     * tim;
  time_t          gm_time;
  buf     = g_malloc (20);
  gm_time = time (NULL);
  tim     = localtime (&gm_time);
  strftime (buf, 20, "%Y.%m.%d %H:%M:%S", tim);
  return buf;
}

int createsocket(const char *filename, int flag){
struct sockaddr_un name;
int sock;
size_t size;

  sock = socket(PF_UNIX, SOCK_DGRAM, 0);
  if(sock < 0){ 
    perror("socket()");
    return 0;
  }
  name.sun_family = AF_UNIX;
  strcpy(name.sun_path, filename);
  size = (offsetof (struct sockaddr_un, sun_path) + strlen(name.sun_path) + 1);
  if(bind(sock,(struct sockaddr *) &name, size) < 0){ 
    perror("bind()");
    return 0;
  }
  if(flag) fcntl(sock, F_SETFL, O_NONBLOCK);
  return sock;	
}

int sendsocket(int sock, char *dst, char *text){
struct sockaddr_un name;
size_t size;
int nbytes;

  name.sun_family = AF_UNIX;
  strcpy(name.sun_path, dst);
  size = strlen(name.sun_path) + sizeof( name.sun_family);
  nbytes = sendto(sock, text, strlen(text) + 1, 0, (struct sockaddr *) &name, size);
  return 0;
}
int senddsocket(int sock, char *dst, char *data, size_t len){
struct sockaddr_un name;
size_t size;
int nbytes;

  name.sun_family = AF_UNIX;
  strcpy(name.sun_path, dst);
  size = strlen(name.sun_path) + sizeof( name.sun_family);
  nbytes = sendto(sock, data, len + 1, 0, (struct sockaddr *) &name, size);
  return 0;
}

static char *dd_read(int sock, int *size){
char *bulk,*blk1=0;
int nbytes;
int s = 1001;
int n=0;

fprintf(stderr, "malloc()\n");
  if (!(bulk = (char *) malloc ((unsigned char)(2000)))) return -1;
fprintf(stderr, "memset()\n");
//  memset(bulk, '\0', 1000);
fprintf(stderr, "read()\n");
  *size = read(sock, bulk, 1000);
fprintf(stderr, "check readed data\n");
  if(*size == -1) return -1; /*FIX free bulk */
fprintf(stderr, "all done!\n");
  return bulk;

readagain:
        if (!(bulk = (char *) malloc ((unsigned char)(s)))) return -1;
        if(blk1){
                memcpy(bulk,blk1,n);
                free(blk1);	
        }
        blk1 = bulk;	
        nbytes = read(sock, bulk+n, 1000);
        n += nbytes;
        switch(nbytes){
                case -1:        /*error*/
			fprintf(stderr,"dd_read(): got error\n");
                        free(bulk);
			return -1;
                case 0:         /*no more to read*/
			fprintf(stderr,"done reading\n");
                        return bulk;
                default:        /*more to read*/
                        s += 1001;
                        goto readagain;
                        break;
        }
}

int dd_write(int sock, int datalen, char *data){
int nbytes;

  nbytes = write(sock, data, datalen + 1);
  if(nbytes < 0) return -1;
  return nbytes;
}

/***********
 * public API
 ***********/

void dd_disconnect(int sock){
  close(sock);
}

int dd_connect(char *IP){
int sock;

  sock = socket(PF_INET, SOCK_STREAM,0);
  if(sock < 0) return -1;
  ddserver.sin_family = AF_INET;
  ddserver.sin_port = 4000;
  ddserver.sin_addr.s_addr = inet_addr(IP);
  if(0 > connect(sock, (struct sockaddr *) &ddserver, sizeof(ddserver))) return -1;
  return sock;
}

/*********
 * functions not performing any tcp activity
 *********/


DB_host * 
host_create (void)
{
  DB_host * dbh;
  dbh           = g_new0 (DB_host, 1);
  if (dbh)
    {
      dbh->created  = g_strdup ("(not in database)");
      dbh->modified = g_strdup (dbh->created);
      return dbh;
    }
  return NULL;
}

/******************************************************************************
**
**  Function to destroy a DB_host object.  The rowid must be zero, which
**  marks it as being "not in the database"
**
******************************************************************************/

void
host_destroy (DB_host * dbh)
{
  if (dbh)
   {
     g_assert (dbh->rowid == 0);
     if (dbh->created)     g_free (dbh->created);
     if (dbh->modified)    g_free (dbh->modified);
     if (dbh->dns_name)    g_free (dbh->dns_name);
     if (dbh->name)        g_free (dbh->name);
     if (dbh->description) g_free (dbh->description);
     if (dbh->contact)     g_free (dbh->contact);
     g_free (dbh);
   }
}

/*********
 * functions contacting database daemon
 *********/

/******************************************************************************
**
**  Function to add a DB_host object to the database.  The rowid must be
**  zero, meaning that the item is not already in the database.
**
******************************************************************************/

gint
host_add (int sock, DB_host * dbh)
{
  char packet[1000];
  if (!(dbh))
    {
      return -1;
    }
  if (dbh->rowid != 0)
    {
      g_warning ("Attempting to re-add a host which is in the db.");
      return -1;
    }
/*  dbh->rowid = g_sqldb_highest_rowid (host_sqldb, "_rowid") + 1; */

/**********************************************************
  g_sqldb_row_add (host_sqldb, dbh); 
**********************************************************/
/*
fprintf(stderr,"setting data\n");

fprintf(stderr,"creating packet\n");
  strcpy(packet,"hostadd ");
  memcpy(packet+8, &host, sizeof(DB_host2));
fprintf(stderr,"sending packet\n");
  dd_write(sock, sizeof(DB_host2)+8, packet);
fprintf(stderr,"packet sent\n");
*/

/**********************************************************/
/*
  if (dbh->created) g_free (dbh->created);
  dbh->created  = db_timestamp ();

  if (dbh->modified) g_free (dbh->modified);
  dbh->modified = g_strdup (dbh->created);
*/

  return 0;
}

gint dd_host_ip2name(int sock, DB_host *host, gchar *IP){
gchar foo[200];
gint len;
gchar *ptr;
int rlen;

  sprintf(foo,"gethostname %s \n", IP);
  len = strlen(foo);
  dd_write(sock, len, foo);
  ptr = dd_read(sock, &rlen);
  fprintf(stderr, "null term\n");
  ptr[rlen] = 0; 
  fprintf(stderr, "setting host.dns_name pointer to data: %s\n", ptr);
  host->dns_name = ptr;
  fprintf(stderr, "free data\n");
  free(ptr);
  return 0;
}

