/*
 * GXSNMP - An snmp managment application
 * Copyright (C) 1998 Gregory McLean
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc.,  59 Temple Place - Suite 330, Cambridge, MA 02139, USA.
 *
 * The events & traps graphical interface
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gnome.h>
#include <stddef.h>	/*six row downs is needed by soc.c*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

#include "config.h"
#include "events.h"
#include "dae.h"

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

static GnomeUIInfo tools_menu_fail;			/*if load of gxevents.conf fails, set Tools menu to empty*/
GnomeUIInfo *toolsmenu;			/* if load success, we alloc space and fill her up */
FILE *tmpfp;
char line[400];
char line2[200];
char foo[200];
int traplistcur = 0;		/*current pointer of first trap in traplist */
GtkWidget *tvw_win;
GtkWidget *tvw_vbox;
GtkWidget *tvw_table;
GtkWidget *fileacl;
GtkWidget *subfileacl;
trapslot eventsel;		/*current selected event in eventlist*/
char textoid[400];		/*for eventsel*/
char aclfile[200];		/*holds current loaded trapfilter, from widget ( temporary )*/
aclist *trapfilter = 0;		/*this is main displays trapfilter */
int ddsock = 0;                 /*if ddsock is zero, we can't use database*/

struct _sub_window{
  int stat;			/*0=endoflist, 1=empty, 2=used*/
  GtkWidget *sublist;		/*List to append trap to*/
  GtkWidget *win;		/*main window, used when closing sub window*/
  aclist *acl;			/*loaded trapfilter*/
}sub_window[10];		/*Maximum of 10 concurrently sub windows open*/

typedef struct _menutoollist {
  char name[80];		/*name that appear in Menu*/
  char cmd[200];		/*command to interpret*/
} menutoollist;

menutoollist *menutools;
  

GdkVisual *visual;
GdkColormap *colormap;

GdkColor black  =  { 0x0000,0x0000,0x0000,0x0000};		/*text*/
GdkColor red    =  { 0x0000,0xffff,0x0000,0x0000};		/*critical*/
GdkColor yellow =  { 0x0000,0xffff,0xffff,0x0000};		/*Alarm*/
GdkColor amber  =  { 0x0000,0xaaaa,0xaaaa,0x0000};		/*Warning*/
GdkColor green  =  { 0x0000,0x0000,0xffff,0x0000};		/*Informative*/
GdkColor white  =  { 0x0000,0xffff,0xffff,0xffff};              /*Unknown*/

/*
 * Local functions
 */
void prune_trap();
void fileacl_select();
void fileacl_hide();
void fileacl_load(GtkWidget *, GtkFileSelection *);
void subfileacl_select();
void subfileacl_hide();
void subfileacl_load(GtkWidget *, GtkFileSelection *);
static void     event_close_button_cb        (GtkWidget   *widget, gpointer    data);
static void     event_refresh_button_cb      (GtkWidget   *widget, gpointer    data);
static gint     event_panel_delete_cb        (GtkWidget   *widget, GdkEvent    *e, gpointer    data);
static void     fill_event_panel             (void);
static void     update_event_panel           (app_event    *event);
static void	tvw_open();
static void	tvw_close();
static void	sub_open();
static void	sub_close();

enum {
  EVENT_ID_IDX,
    EVENT_LV_IDX,
    EVENT_ST_IDX,
    EVENT_TS_IDX,
    EVENT_DS_IDX
};
/*
 * Local Variables
 */
int trapid = 0;								/*uniq ID*/
glb_enviroment enviroment;
static char pipestring[401];
static char mydpyfile[40];
static int mydpysock;
static gchar *titles[] =
{
  "Event ID",
  "Category",
  "Status",
  "Timestamp",
  "Summary",
  "Description",0
};

static int         col_sizes[6];
static event_panel *ev_panel = NULL;
static GList       *event_list = NULL;
/*
 * Menus 
 */
static GnomeUIInfo file_menu[] = {
  { GNOME_APP_UI_ITEM, N_("Save"), NULL,
    NULL, NULL, NULL, 
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE, 0, 0, NULL },
  { GNOME_APP_UI_ITEM, N_("Save as..."), NULL, 
    NULL, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },
  { GNOME_APP_UI_SEPARATOR },
  { GNOME_APP_UI_ITEM, N_("Print"), NULL,
    NULL, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PRINT, 0, 0, NULL },
  { GNOME_APP_UI_SEPARATOR },
  { GNOME_APP_UI_ITEM, N_("Close"), NULL, event_close_button_cb, 
    NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },
  { GNOME_APP_UI_ITEM, N_("Exit"), NULL, event_close_button_cb,
    NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },
  { GNOME_APP_UI_ENDOFINFO },
};

static GnomeUIInfo edit_menu[] = {
  { GNOME_APP_UI_ITEM, N_("Load filter"), NULL,
    fileacl_select, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },

  { GNOME_APP_UI_ITEM, N_("Prune trap"), NULL,
    prune_trap, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },

  { GNOME_APP_UI_ITEM, N_("View trap"), NULL,
    tvw_open, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },

  { GNOME_APP_UI_ITEM, N_("Open filtered trap window"), NULL,
    subfileacl_select, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BLANK, 0, 0, NULL },

  { GNOME_APP_UI_ENDOFINFO },
};

static GnomeUIInfo *tools_menu;					/*run-time loaded from gxevents.conf, numerical is wc -l gxevents.conf*/

GnomeUIInfo event_panel_menu[] = {
  { GNOME_APP_UI_SUBTREE, N_("File"), NULL, file_menu, NULL, NULL, 
    GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL },
  { GNOME_APP_UI_SUBTREE, N_("Edit"), NULL, edit_menu, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL },
  { GNOME_APP_UI_SUBTREE, N_("Tools"), NULL, 0, NULL, NULL,		/*slot 2 MUST be Tools menu, moreinfo is overwritten when loading gxevents.conf*/
    GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL },
  { GNOME_APP_UI_ENDOFINFO },
};

void quit_cb(){
  snprintf(line,400,"close %s",mydpyfile);
  sendsocket(mydpysock, enviroment.evdpysrvd, line);	/*tell evdpysrvd to disconnect trap receive pipe*/
  unlink(mydpyfile);
  printf("gxevents: unregistered to evdpysrvd.\n");
  dd_disconnect(ddsock);
  exit(0);
}

void menutools_interpret(GtkWidget *mti, gchar *text){ /* Execute a command from Tools menu*/
gchar cmd[200];
gchar ioo[80];
gchar *iarg[10];
int i=0,j=0;
pid_t pid;

  var_interpret(cmd, text, 200, &eventsel);
  wordcpy(ioo,cmd,1);
  iarg[j++] = ioo;
  for(;9>j;i++){
    if(cmd[i] == '\0') break;
    if(cmd[i] == ' '){
      cmd[i] = '\0';
      iarg[j++] = &cmd[i+1];
    }
  }
  iarg[j] = 0;
  if(!(pid = fork())){
    if(!(fork())) execv(ioo,iarg);
      _exit(0);
    }
  waitpid(pid,NULL,0);
}

/***MENU CALLBACKS************************/
GtkWidget *gui_generic(GtkWidget *table, char *text,int type, int x, int y, void *callback, void *data, int data2 ){
GtkWidget *lab;
GtkWidget *wid;

  lab = gtk_label_new(text);
  gtk_table_attach (GTK_TABLE (table), lab, 1, 2, y, y+1, GTK_SHRINK, GTK_SHRINK, 2, 1);
  gtk_widget_show(lab);
  if(type == 1){
    wid = gtk_entry_new_with_max_length(data2);
    gtk_signal_connect(GTK_OBJECT(wid), "activate", GTK_SIGNAL_FUNC(callback), wid);
    gtk_table_attach(GTK_TABLE (table), wid, 2, 3, y, y+1, GTK_SHRINK, GTK_SHRINK, 2, 1);
    gtk_entry_set_text(GTK_ENTRY(wid), (char *)data);
    gtk_widget_show(wid);
    return wid;
  }else if (type == 2){
    wid = gtk_toggle_button_new();
    gtk_table_attach (GTK_TABLE (table), wid, 2, 3, y, y+1, GTK_SHRINK, GTK_SHRINK, 2, 1);
    gtk_signal_connect_object(GTK_OBJECT(wid), "clicked", GTK_SIGNAL_FUNC(callback),GTK_OBJECT(wid));
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wid), data2);
    gtk_widget_show(wid);
  }else if (type == 3){
    wid = gtk_button_new_with_label(text);
    gtk_table_attach (GTK_TABLE (table), wid, x, y, x+1, y+1, GTK_SHRINK , GTK_SHRINK, 2, 1);
    gtk_signal_connect(GTK_OBJECT(wid), "clicked",GTK_SIGNAL_FUNC(callback),(gpointer) "savecfg");
  }else if (type == 4); /*only a label*/
  return 0;
}

void eventlist_cb(GtkWidget *eventlist, gint row, gint column, GdkEventButton *event){
gchar *field;
int a;
  GList     *item;
  app_event *data;

  gtk_clist_get_text(GTK_CLIST(eventlist), row, 0, &field);
  a = atoi(field);						/*get eventid*/
  item = g_list_first (event_list);
  while (item)							/*search up using eventid in app_events*/
    {
      data = (app_event *)item->data;
      if (data)
	if ( (data->eventid) == a)				/*ok, we've found the app_event*/
	  {
            strcpy(eventsel.IP,data->IP);			/*fill in current selected event ( in main event window ) */
            strcpy(eventsel.oid,data->oid);
            eventsel.g = data->g;
            eventsel.s = data->s;
            eventsel.severity = data->category;
            eventsel.timestamp = data->timestamp;
            gtk_clist_get_text(GTK_CLIST(eventlist), row, 6, &field);
            strcpy(eventsel.argoid[0], field);			/*argoid holds whole argument string*/
            break;
          }
      item = g_list_next (item);
    }
}

void tvw_close(GtkWidget *tvw){
  gtk_widget_destroy(tvw);
}

void tvw_open(){ /* send selected trap to a own window */
GtkWidget *foo;

  eventsel.name[0] = 0; 				/*define some trapslot_clear() instead*/
  trap_lookup(&eventsel);

  tvw_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  tvw_vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_add(GTK_CONTAINER(tvw_win), tvw_vbox);
  gtk_widget_show(tvw_vbox);

  snprintf(line,400,"Object ID: %s",eventsel.oid);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  textoid[0] = 0;
  oid2text(textoid, eventsel.oid);
  snprintf(line,400,"Object ID: %s",textoid);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  snprintf(line,400,"Generic: %d",eventsel.g);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  snprintf(line,400,"Specific: %d",eventsel.s);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  snprintf(line,400,"Name: %s",eventsel.name);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  snprintf(line,400,"Source: %s",eventsel.IP);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  snprintf(line,400,"Severity: %d",eventsel.severity);
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  foo = gtk_label_new(eventsel.argoid[0]);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  snprintf(line,400,"Date: %s", ctime((time_t *)&eventsel.timestamp));
  foo = gtk_label_new(line);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  foo = gtk_button_new_with_label("Dismiss");
  gtk_signal_connect(GTK_OBJECT(foo), "clicked",GTK_SIGNAL_FUNC(tvw_close),NULL);
  gtk_misc_set_alignment (GTK_MISC (foo), 0, 0);
  gtk_box_pack_start (GTK_BOX (tvw_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  gtk_widget_show_all(tvw_win);
}

void sub_close(GtkWidget *win){ /*I wonder if win is the dismiss button widget, then for(;;) beneith is unecessery*/
int a=0;
 
  for(;sub_window[a].stat;a++){
    if(sub_window[a].win == win){
      gtk_widget_destroy(win);
      sub_window[a].stat = 1; 				/*this slot is set to empty*/
      if(sub_window[a].acl) g_free(sub_window[a].acl); /*hmm doesn't g_free check if zero?*/
    }
  }
}

void sub_open(struct _sub_window *subw){ /* open a sub trap display */
GtkWidget *sub_vbox;
GtkWidget *foo;
GtkWidget *mywin;

  subw->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  sub_vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_add(GTK_CONTAINER(subw->win), sub_vbox);
  gtk_widget_show(sub_vbox);

  foo = gtk_label_new("Loaded filter: test");
  gtk_box_pack_start (GTK_BOX (sub_vbox), foo, FALSE, FALSE, 0);

  subw->sublist = gtk_clist_new(1);
  /*gtk_signal_connect(GTK_OBJECT(subw->sublist), "select_row",GTK_SIGNAL_FUNC(xxx_cb),NULL);*/
  gtk_clist_set_selection_mode(GTK_CLIST(subw->sublist),GTK_SELECTION_SINGLE);
  gtk_clist_column_titles_hide(GTK_CLIST(subw->sublist));
  gtk_clist_set_column_width(GTK_CLIST(subw->sublist),0,200);

  mywin = gtk_scrolled_window_new(0, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mywin),  GTK_POLICY_ALWAYS,  GTK_POLICY_AUTOMATIC);
  gtk_container_add (GTK_CONTAINER (mywin), subw->sublist);
  gtk_box_pack_start (GTK_BOX (sub_vbox), mywin, FALSE, FALSE, 0);

  foo = gtk_button_new_with_label("Dismiss");
  gtk_signal_connect(GTK_OBJECT(foo), "clicked",GTK_SIGNAL_FUNC(sub_close),NULL);
  gtk_box_pack_start (GTK_BOX (sub_vbox), foo, FALSE, FALSE, 0);
  gtk_widget_show(foo);

  gtk_widget_show_all(subw->win);
}

void prune_trap(){ /*This callback will prune the selected trap ( add it into current loaded acl ) */
aclist acl;

  if(!aclfile) return;							/*no trapfilter loaded*/
  acl.action = 13;							/*add 'deny oid+g+s'*/
  acl.g = eventsel.g;
  acl.s = eventsel.s;
  strcpy(acl.oid,eventsel.oid);
  acl_add_filter(acl, aclfile);
  /*reload trapfilter*/
  if(trapfilter) g_free(trapfilter);
  else fprintf(stderr,"APP_ERR: no trapfilter loaded, but aclfile is set\n");
  trapfilter = load_acl(aclfile);					/*load event display filter (trapfilter )*/
}
/***************************/

static void create_panel()
{
GtkWidget   *button;
GtkWidget   *scrolled;
GtkWidget   *w_frame;
GtkWidget   *vbox;
GtkWidget   *bar;
GtkWidget   *table;
GtkWidget   *button_box;
GtkWidget   *pixmap;
int         a, i, tmp, w_size;
gint        char_size;

  ev_panel = (event_panel *)g_malloc (sizeof (event_panel));
  ev_panel->window = gnome_app_new ("GXSNMP", _("Events"));

  gtk_signal_connect (GTK_OBJECT (ev_panel->window),
		      "delete_event",
		      GTK_SIGNAL_FUNC (event_panel_delete_cb),
		      NULL);

  vbox = gtk_vbox_new (FALSE, 4);
  table = gtk_table_new (3, 3, FALSE);
  gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 3);
  tmp = gdk_text_width (vbox->style->font, "1", 1);
  tmp = tmp * 18;
  w_size = 0;
  char_size = gdk_string_width (table->style->font, "xW") / 2;

  for (i=0; i< 6; i++){
      titles[i] = strdup(gettext(titles[i]));
      col_sizes[i] = strlen (titles[i]) * char_size;
  }

  ev_panel->clist =  gtk_clist_new_with_titles (6, titles);
  gtk_object_set_data (GTK_OBJECT (ev_panel->window), "event_clist", 
		       ev_panel->clist);

  gtk_clist_column_titles_passive (GTK_CLIST (ev_panel->clist));
  for (i = 0; i < 6; i++){
      gtk_clist_set_column_width (GTK_CLIST (ev_panel->clist), i, (col_sizes[i] + (col_sizes[i] / 2)));
      w_size += (col_sizes[i] + (col_sizes[i] / 2));
  }

  gtk_clist_set_selection_mode (GTK_CLIST (ev_panel->clist),  GTK_SELECTION_BROWSE);
  gtk_signal_connect(GTK_OBJECT(ev_panel->clist), "select_row",GTK_SIGNAL_FUNC(eventlist_cb),NULL);
  scrolled = gtk_scrolled_window_new (NULL, NULL);

  visual = gdk_visual_get_best();			/* initialize all list colors */
  colormap = gtk_widget_get_colormap(scrolled);
  gdk_color_alloc(colormap, &black);
  gdk_color_alloc(colormap, &red);
  gdk_color_alloc(colormap, &yellow);
  gdk_color_alloc(colormap, &amber);
  gdk_color_alloc(colormap, &green);
  gdk_color_alloc(colormap, &white);

  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), 
			GTK_POLICY_ALWAYS, 
			GTK_POLICY_AUTOMATIC);
  gtk_container_add (GTK_CONTAINER (scrolled), ev_panel->clist);
  gtk_table_attach (GTK_TABLE (table), scrolled, 0, 1, 0, 4,
		    GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 1);
  bar = gtk_vseparator_new ();
  gtk_table_attach (GTK_TABLE (table), bar, 1, 2, 0, 4,
		    GTK_FILL, GTK_FILL | GTK_EXPAND, 2, 1);
  button = gtk_button_new_with_label (_("Acknowledge"));
  gtk_object_set_data (GTK_OBJECT (ev_panel->window), "ack_button", button);
  gtk_widget_set_sensitive (button, FALSE);
  gtk_table_attach (GTK_TABLE (table), button, 
		    2, 3, 0, 1,
		    GTK_FILL | GTK_SHRINK, GTK_SHRINK, 1, 1);
  button = gtk_button_new_with_label (_("Delete"));
  gtk_object_set_data (GTK_OBJECT (ev_panel->window), "del_button", button);
  gtk_widget_set_sensitive (button, FALSE);
 /*
   * FIXME: need a way to determine the size of the buttons
   */
  w_size += (90 * 2);
  gtk_table_attach (GTK_TABLE (table), button,
		    2, 3, 1, 2,
		    GTK_FILL | GTK_SHRINK, GTK_SHRINK, 1, 1);
  bar = gtk_hseparator_new ();
  gtk_box_pack_start (GTK_BOX (vbox), bar, FALSE, FALSE, 2);
  w_frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER (w_frame), 2);
  gtk_box_pack_start (GTK_BOX (vbox), w_frame, FALSE, FALSE, 1);
  button_box = gtk_hbutton_box_new ();
  gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box),
			     GTK_BUTTONBOX_SPREAD);
  gtk_button_box_set_spacing (GTK_BUTTON_BOX (button_box), 2);
  gtk_button_box_set_child_size (GTK_BUTTON_BOX (button_box), 85, 20);
  gtk_container_border_width (GTK_CONTAINER (button_box), 2);
  gtk_container_add (GTK_CONTAINER (w_frame), button_box);

  button = gnome_stock_button (GNOME_STOCK_BUTTON_CLOSE);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (event_close_button_cb),
		      NULL);
  gtk_container_add (GTK_CONTAINER (button_box), button);
  pixmap = gnome_stock_pixmap_widget (ev_panel->window,
				      GNOME_STOCK_PIXMAP_REFRESH);
  button = gnome_pixmap_button (pixmap, _("Refresh"));
  gtk_signal_connect (GTK_OBJECT (button), "clicked", 
		      GTK_SIGNAL_FUNC (event_refresh_button_cb),
		      NULL);
  gtk_container_add (GTK_CONTAINER (button_box), button);

  fileacl = gtk_file_selection_new("Load Access Control List");
  gtk_signal_connect (GTK_OBJECT (fileacl), "destroy", (GtkSignalFunc) fileacl_hide, &fileacl);
  gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileacl)->ok_button), "clicked", (GtkSignalFunc) fileacl_load, fileacl );
  gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (fileacl)->cancel_button), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT (fileacl));

  subfileacl = gtk_file_selection_new("Load Access Control List");
  gtk_signal_connect (GTK_OBJECT (subfileacl), "destroy", (GtkSignalFunc) subfileacl_hide, &subfileacl);
  gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (subfileacl)->ok_button), "clicked", (GtkSignalFunc) subfileacl_load, subfileacl );
  gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (subfileacl)->cancel_button), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT (subfileacl));

/***** RUN-TIME LOAD THE TOOLS_MENU ********/

  tools_menu_fail.type = GNOME_APP_UI_ENDOFINFO; 

  strcpy(line,enviroment.base); /*sorry for putting file parsing here*/
  strcat(line,"/conf/gxevents.conf");
  if(!(tmpfp = fopen(line,"r"))){
    fprintf(stderr, "Can't access gxevents.conf file\n");
    event_panel_menu[2].moreinfo = &tools_menu_fail;
  }else{
    while(fgets(line,200,tmpfp)) i++;
    i++; i++; i++; 					/*last slot + some extra for safety*/
    if (!(toolsmenu = (GnomeUIInfo *) malloc((unsigned)(i*(sizeof(GnomeUIInfo)))))){
      fprintf(stderr, "Can't alloc enough space to hold your gxevents.conf setup\n");
      fclose(tmpfp);
      event_panel_menu[2].moreinfo = &tools_menu_fail;
    }else{
      if (!(menutools = (menutoollist *) malloc((unsigned)(i*(sizeof(menutoollist)))))){         
        fprintf(stderr, "Can't alloc enough space to hold your gxevents.conf setup\n");
        fclose(tmpfp);                                                                 
        event_panel_menu[2].moreinfo = &tools_menu_fail;
      }else{                                           
        fseek(tmpfp,0,SEEK_SET);
        for(a=0;fgets(line,200,tmpfp);){					/*lets build some menus*/
          if(line[0] == '#') continue;
          wordcpy(foo,line,1);							/*fetch name */
          wordcpy(line2,line,2);						/*fetch command */
          strcpy(menutools[a].name, foo);					/*set table that interpreter uses*/
          strcpy(menutools[a].cmd, line2);
          toolsmenu[a].type = GNOME_APP_UI_ITEM;
          toolsmenu[a].label = menutools[a].name;
          toolsmenu[a].hint = NULL;
          toolsmenu[a].moreinfo = menutools_interpret;
          toolsmenu[a].user_data = menutools[a].cmd;				/*bind command to set as argument to menutools_interpret()*/
          toolsmenu[a].unused_data = NULL;
          toolsmenu[a].pixmap_type = GNOME_APP_PIXMAP_STOCK;
          toolsmenu[a].pixmap_info = GNOME_STOCK_MENU_BLANK;
          toolsmenu[a].accelerator_key = 0;
          toolsmenu[a].ac_mods = 0;
          toolsmenu[a].widget = NULL;
          a++;
        }
      toolsmenu[a].type = GNOME_APP_UI_ENDOFINFO;
      tools_menu = toolsmenu;
      event_panel_menu[2].moreinfo = tools_menu;
      }
    }
  }
/*******************************************/

  gnome_app_set_contents (GNOME_APP (ev_panel->window), vbox);
  gnome_app_create_menus(GNOME_APP (ev_panel->window), 
			  event_panel_menu);
  gtk_widget_set_usize (ev_panel->window, w_size, 200);
  gtk_widget_show_all (ev_panel->window);
}

/* 
 * Callback wrapper functions
 */

void fileacl_select(){	/*shows up the ACL file selection box*/
  gtk_widget_show_all(fileacl);
}
void fileacl_hide(){  /*hides ACL file selection box*/
  gtk_widget_hide(fileacl);
}
void fileacl_load(GtkWidget *w, GtkFileSelection *fs){ /*only used by main trap display */
  strcpy(aclfile,gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
  if(trapfilter) free(trapfilter);						/*free old trapfilter*/
  trapfilter = load_acl(aclfile);						/*load event display filter*/
  fileacl_hide();
}
/*
 * sub window callbacks
 */
void subfileacl_select(){	/*shows up the ACL file selection box*/
  gtk_widget_show_all(subfileacl);
}
void subfileacl_hide(){  /*hides ACL file selection box*/
  gtk_widget_hide(subfileacl);
}
void subfileacl_load(GtkWidget *w, GtkFileSelection *fs){ /*creates a new sub_window slot and loads filter */
int a=0;
  subfileacl_hide();		                      /*thank you, selection box*/
  for(;sub_window[a].stat;a++);                      /*lets find a empty slot*/
  strcpy(aclfile,gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));  /*retreive what access control file to use file to load*/
  sub_window[a].acl = load_acl(aclfile);	      /*load sub windows filter*/
  sub_window[a].stat = 2;                             /*set this sub window to state: used*/
  sub_open(&sub_window[a]);                            /*create widgets*/
}


/* widget callbacks*/

static void event_close_button_cb (GtkWidget *widget, gpointer data)
{
  hide_event_panel ();
  quit_cb();
}

static void event_refresh_button_cb (GtkWidget *widget, gpointer data)
{
  fprintf(stderr,"this button is unsigned");
}

static gint event_panel_delete_cb (GtkWidget *widget, GdkEvent *e, gpointer data)
{
  destroy_event_panel();
  quit_cb();
  return 0;
}

/*
 * List management functions.
 */

static void fill_event_panel ()
{
  GList     *item;
  app_event *data;

  if (g_list_length <= 0)
      return;
  else
    {
      item = g_list_first (event_list);
      while (item)
	{
	  data = (app_event *)item->data;
	  if (data)
	    update_event_panel (data);
	  item = g_list_next (item);
	}
    }

}

int add_event (app_event *event)
{
  GList     *item;
  app_event  *cp,*low=0,*data;
  int a ,b;

  cp = (app_event *)g_malloc (sizeof (app_event));
  memcpy (cp, event, sizeof (app_event));		/*make a copy of incoming event*/
  cp->eventid = ++trapid;
  event_list = g_list_append (event_list, cp);
  b = g_list_length(event_list);
  while(b > enviroment.gxevents_max_traps){		/*adjust list to maximum amount of list items*/
    gtk_clist_remove(GTK_CLIST (ev_panel->clist), 0);	/*remove oldest entry in list*/
    item = g_list_first (event_list);			/*update g_list*/
    a = 65535;						/*maximum possible amount of list items ever*/
    while (item)
      {
        data = (app_event *)item->data;
        if (data)
          if (a > (data->eventid)){ 
            a = data->eventid;
            low = data;
          }
        item = g_list_next (item);
      }
    event_list = g_list_remove(event_list, low);
    g_free(low);
    b--;
  }
  update_event_panel(cp);
  return 1;
}

int remove_event (int eventid)
{
  GList     *item;
  app_event *data;

  item = g_list_first (event_list);
  while (item)
    {
      data = (app_event *)item->data;
      if (data)
	if ( (data->eventid) == eventid)
	  {
	    event_list = g_list_remove (event_list, data);
	    g_free (data);
	    return 1;
	  }
      item = g_list_next (item);
    }
  return -1;
}

/*
 * Exported standard panel functions.
 */
void open_event_panel ()
{
  if (!ev_panel)
    create_panel ();
  else
    if (!GTK_WIDGET_VISIBLE (ev_panel->window))
      gtk_widget_show (ev_panel->window);
  reset_event_panel ();
}

void destroy_event_panel ()
{
  if (ev_panel)
    {
      gtk_widget_destroy (ev_panel->window);
      g_free (ev_panel);
      ev_panel = NULL;
    }
	quit_cb();
}

void hide_event_panel ()
{
  if (ev_panel)
    {
      if (GTK_WIDGET_VISIBLE (ev_panel->window))
	{
	  gtk_widget_hide (ev_panel->window);
	}
    }
}

void reset_event_panel ()
{
  /* do any refresh of the panel that is needed, this is called when
   * the panel is opened.
   */
  gtk_clist_clear (GTK_CLIST (ev_panel->clist));
  fill_event_panel ();
}

/*
 * misc functions
 */
static void update_event_panel (app_event *event)
{
  char    t_buf[80];
  gchar    *list_item[7];
  int row;
  GdkColor *color;

  if (ev_panel)
    {
      if (GTK_WIDGET_VISIBLE (ev_panel->window))
	{
	  snprintf (t_buf, sizeof (t_buf), "%d", event->eventid);
	  list_item[EVENT_ID_IDX] = g_strdup (t_buf);
	  switch (event->category)
	    {
	    case 64:
	      list_item[EVENT_LV_IDX] = g_strdup (_("Critical"));
              color = &red;
	      break;
	    case 48:
	      list_item[EVENT_LV_IDX] = g_strdup (_("Alarm"));
              color = &yellow;
	      break;
	    case 32:
	      list_item[EVENT_LV_IDX] = g_strdup (_("Warning"));
              color = &amber;
	      break;
	    case 16:
	      list_item[EVENT_LV_IDX] = g_strdup (_("Informative"));
              color = &green;
	      break;
	    case 0:
	      list_item[EVENT_LV_IDX] = g_strdup (_("Unknown"));
              color = &white;
	      break;


	    default:
	      list_item[EVENT_LV_IDX] = g_strdup ("");
              color = &green;
	      break;
	    }
	  list_item[EVENT_ST_IDX] = g_strdup ("");
	  list_item[EVENT_TS_IDX] = g_strdup (ctime (&event->timestamp));
	  list_item[EVENT_DS_IDX] = g_strdup (event->summary);
	  list_item[5] = g_strdup (event->description);
	  row = gtk_clist_append (GTK_CLIST (ev_panel->clist), list_item);
          gtk_clist_set_foreground(GTK_CLIST (ev_panel->clist), row, &black );
          gtk_clist_set_background(GTK_CLIST (ev_panel->clist), row, color);
	}
    }
}
/*
 * Alarm panel
 */

int main(int argc, char *argv[]){
aclist acl;
static int nbytes;
app_event trap_event;
char    buf[200], buf2[1000],foo1[300];
trapslot trap;
int k,known;
gchar *listitems[2]; 						/* this is for new trap windows */
time_t tk;
char *hostname;
int ddsize;

  load_enviroment();
  load_trapconf();						/*hold trap.conf loaded into enviroment.traptab */
  aclfile[0] = 0;

/* connect to evdpysrvd and open a pipe */
  sprintf(mydpyfile,"/tmp/gxevents_socket_%u",time(0));
  unlink(mydpyfile);
  if(!(mydpysock = createsocket(mydpyfile,1))) return 1;	/*create a nonblocking connection to evdpysrvd*/
  printf("Using socket file %s\n",mydpyfile);
  aclfile[0] = 0;						/*set aclfile to state none loaded*/

  gnome_init("gxevents","0.0.11",argc,argv);
  open_event_panel();

  snprintf(buf,200,"open %s",mydpyfile);			/*open trap receive pipe to evdpysrvd*/
  sendsocket(mydpysock, enviroment.evdpysrvd, buf);
  printf("gxevents: registered to evdpysrvd.\n");
  init_mib(); 							/*FIX: check if fail*/

  sub_window[0].sublist = 0; 					/*null terminate sub window list*/
  if(-1 == (ddsock = dd_connect("130.100.31.195"))){              /* do without database access if we fail*/
    printf("WARNING: no database access.\n");
    ddsock = 0;
  }

start:

  if(gtk_events_pending()) gtk_main_iteration();
  pipestring[0] = 0;
  nbytes = recv(mydpysock,pipestring,400,0);
  if(nbytes != -1){
    if(!strncmp(pipestring,"gs.",3)){				/*hello received*/
      //fprintf(stderr,"(Keepalive_respond)");
      wordcpy(foo1,pipestring,2);				/*get evdpy struct ID*/
      snprintf(buf,200,"sr. %s",foo1);				/*make an answer*/
      sendsocket(mydpysock, enviroment.evdpysrvd, buf);	/*send alive response*/
      goto start;
    }
    trap_decode(pipestring,&trap);
    strcpy(acl.ip, trap.IP);
    /*strcpy(acl.ipm, trap.IPM);*/
    /*acl.severity = trap.severity;*/
    strcpy(acl.oid,trap.oid);
    trap_event.g = acl.g = trap.g;
    trap_event.s = acl.s = trap.s;
    trap_event.noid[0] = 0;
    if(oid2text(trap_event.noid, trap.oid)) strcpy(trap_event.noid, trap.oid); /*translate OID, if fail, give OID as is */
    for(k=0;sub_window[k].stat;k++){ /*go through all subwindows to see if anyone wants a trap!*/
      if(!sub_window[k].acl){ /*this shouldn't happend*/
        printf("APP_ERR: no access control list loaded to a sub window trap display\n");
        break;
      }
      if(!test_acl(acl, sub_window[k].acl)) continue;			/*check if event is allowed by filter*/
      snprintf(buf2,1000,"%s %s %d %d", trap.IP, trap_event.noid, trap.g, trap.s);	/*testing sub window*/
      listitems[0] = buf2;
      listitems[1] = 0;
      gtk_clist_append(GTK_CLIST(sub_window[k].sublist), listitems);
    }
    if(!test_acl(acl, trapfilter)) goto start;					/*check if event is allowed by filter*/
    known = 0;
    if(!trap_lookup(&trap)) known = 1;  				/*check if event is specified in trap.conf */
    trap_event.category = trap.severity;
    trap_event.sub_category = 0;
    trap_event.stat = 0;
    trap_event.timestamp = trap.timestamp;

    trap_event.hostname[0] = 0;								/*fill in trap_event.hostname using database access*/
    if(ddsock && enviroment.gxevents_lookup){			/*this part should go in a API*/
      sprintf(foo1, "gethostinfo %s ", trap.IP);
      fprintf(stderr,"Sending:(%s)\n", foo1);
      if(!(-1 == dd_write(ddsock, strlen(foo1), foo1))){
        fprintf(stderr,"Reading.\n");
        if(!(-1 == (hostname = dd_read(ddsock, &ddsize)))){
          hostname[ddsize] = 0;
          if(!strcmp(wordcpy(buf,hostname,1),"answer")){
            wordcpy(buf,hostname,2);
            strcpy(trap_event.hostname, buf);
            free(hostname);
            fprintf(stderr,"hostname: %s\n", trap_event.hostname);
          }
        }
      }
    }
      
    strcpy(trap_event.IP,trap.IP);
    if(trap_event.hostname) strcpy(foo1,trap_event.hostname);
    else strcpy(foo1, trap_event.IP);
    strcpy(trap_event.oid,trap.oid);							/* used by eventselection */
    if(known) snprintf(buf,200,"%s %s", foo1, trap.name);				/* if trap is defined in trap.conf, good */
    else snprintf(buf,200,"%s %s",foo1, trap_event.noid);
    trap_event.summary = buf;
	
    buf2[0] = 0;	
    strcat(buf2, "ARG: ");
    for(k=0;4>k;k++){
      strcat(buf2, " name: ");
      oid2text(trap.argoid[k], trap.argoid[k]);
      strcat(buf2, trap.argoid[k]);
      strcat(buf2, " data: ");
      strcat(buf2, trap.argdat[k]);
    }
/*fprintf(stderr,"ARGS(%s)\n",buf2);*/
    trap_event.description = buf2;			/* description holds traps all arguments */

    add_event(&trap_event);
  }
  goto start;
}
