Fixed GnomeUI segfault on the config file update.
[udpgate.git] / src / ui-gnome.c
index 38a8786..79546bb 100644 (file)
@@ -1,6 +1,6 @@
 /* $Id$
  * Gnome user interface
- * Copyright (C) 2004 Jan Kratochvil <project-udpforward@jankratochvil.net>
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
  * 
  * 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
 #include <gtk/gtktogglebutton.h>
 #include <string.h>
 #include <gtk/gtkmain.h>
+#include <libgnomeui/gnome-app-util.h>
+
+#include "network.h"
+#include "packet.h"
 
 
 /* Config: */
-#define PATHNAME_PID "/var/run/udpforward.pid"
-#define DAEMON_CHECK_INTERVAL_MS 500
+#define DAEMON_CHECK_INTERVAL_MS 100
 #define PORT_RANGE_BEGIN 2048
 #define PORT_RANGE_END 10240
 
@@ -50,52 +53,32 @@ static GtkButton *ButtonStop;
 static GtkHBox *PortHBox;
 static GnomeAppBar *AppBar;
 static GtkEntry *PortEntry;
+static GtkEntry *HostIPEntry;
 
 
-static pid_t daemon_pid;
-
-static gboolean is_daemon_running(void)
-{
-FILE *f;
-char buf[LINE_MAX],*got;
-int pid_int;
-
-       daemon_pid=(pid_t)-1;
-       if (!(f=fopen(PATHNAME_PID,"r")))
-               goto err;
-       got=fgets(buf,sizeof(buf),f);
-       fclose(f);      /* FIXME: error ignored */
-       if (got!=buf) {
-err_unlink:
-               unlink(PATHNAME_PID);
-err:
-               return FALSE;
-               }
-       pid_int=atoi(buf);
-       if (pid_int<=1)
-               goto err_unlink;
-       if (kill((pid_t)pid_int,0)) {
-               if (errno==ESRCH)
-                       goto err_unlink;
-               goto err;
-               }
-       daemon_pid=(pid_t)pid_int;
-       return TRUE;
-}
-
 static void state_start_stop(void)
 {
+pid_t daemon_pid;
 gboolean daemon_running;
+static gboolean last_daemon_running,last_daemon_running_set=FALSE;
+
+       daemon_pid=is_daemon_running();
+       daemon_running=((pid_t)-1!=daemon_pid);
+
+       /* Cache the result; maybe not needed. */
+       if (last_daemon_running_set && last_daemon_running==daemon_running)
+               return;
+       last_daemon_running=daemon_running;
+       last_daemon_running_set=TRUE;
 
-       daemon_running=is_daemon_running();
        gtk_widget_set_sensitive(GTK_WIDGET(ButtonStart),!daemon_running);
        gtk_widget_set_sensitive(GTK_WIDGET(ButtonStop) , daemon_running);
        gtk_widget_set_sensitive(GTK_WIDGET(PortHBox)   ,!daemon_running);
        if (daemon_running)
                gnome_appbar_set_status(AppBar,
-                               udpforward_printf_alloca(_("udpforward daemon running as PID %d."),(int)daemon_pid));
+                               udpgate_printf_alloca(_("udpgate daemon running as PID %d."),(int)daemon_pid));
        else
-               gnome_appbar_set_status(AppBar,_("No udpforward daemon currently running."));
+               gnome_appbar_set_status(AppBar,_("No udpgate daemon currently running."));
 }
 
 static gboolean daemon_check_timeout_func(gpointer data /* unused */)
@@ -109,10 +92,10 @@ void on_PortButtonRandom_clicked(GtkButton *button,gpointer user_data)
        g_return_if_fail(GTK_IS_BUTTON(button));
 
        state_start_stop();
-       if ((pid_t)-1!=daemon_pid)
+       if ((pid_t)-1!=is_daemon_running())
                return;
        gtk_entry_set_text(PortEntry,
-                       udpforward_printf_alloca("%d",(int)g_random_int_range(PORT_RANGE_BEGIN,PORT_RANGE_END)));
+                       udpgate_printf_alloca("%d",(int)g_random_int_range(PORT_RANGE_BEGIN,PORT_RANGE_END)));
 }
 
 void on_AutostartCheckButton_toggled(GtkToggleButton *togglebutton,gpointer user_data)
@@ -124,33 +107,70 @@ void on_ButtonStart_clicked(GtkButton *button,gpointer user_data)
 {
        g_return_if_fail(GTK_IS_BUTTON(button));
 
-       state_start_stop();
-       if ((pid_t)-1!=daemon_pid)
+       if (!optarg_port_set_string(gtk_entry_get_text(PortEntry)))
                return;
+       network_start(optarg_port);
 }
 
 void on_ButtonStop_clicked(GtkButton *button,gpointer user_data)
 {
-int errno_save;
-
        g_return_if_fail(GTK_IS_BUTTON(button));
 
-       state_start_stop();
-       if ((pid_t)-1==daemon_pid)
-               return;
-       errno=0;
-       kill(daemon_pid,SIGKILL);
-       errno_save=errno;
-       if (errno_save) 
-               g_warning(udpforward_printf_alloca(_("Unable to stop the daemon at PID %d: %s"),
-                               (int)daemon_pid,strerror(errno_save)));
+       network_stop();
 }
 
 void on_ButtonHide_clicked(GtkButton *button,gpointer user_data)
 {
        g_return_if_fail(GTK_IS_BUTTON(button));
 
-       gtk_main_quit();
+       /* update config file */
+       optarg_port_set_string(gtk_entry_get_text(PortEntry));
+
+       /* Do not: gtk_main_quit();
+        * as 'App' widget will quit our gtk_main() automatically.
+        */
+       gtk_widget_destroy(GTK_WIDGET(App));
+}
+
+static void ui_gnome_network_notify_hostip(guint32 hostip_guint32)
+{
+       if (!hostip_guint32) {
+               if (is_daemon_running()==(pid_t)-1)
+                       gtk_entry_set_text(HostIPEntry,_("(unknown; Start the daemon)"));
+               else
+                       gtk_entry_set_text(HostIPEntry,_("(unknown; detecting...)"));
+               }
+       else {
+               gtk_entry_set_text(HostIPEntry,HOSTIP_GUINT32_TO_STRING(hostip_guint32));
+               }
+}
+
+static guint ui_gnome_g_log_handler_handler_id;
+static void ui_gnome_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
+{
+GtkWidget *dialog;
+
+       /**/ if (log_level & G_LOG_LEVEL_ERROR)
+               dialog=gnome_app_error(App,message);
+       else if (log_level & (G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING))
+               dialog=gnome_app_warning(App,message);
+       else
+               dialog=gnome_app_message(App,message);
+
+       gtk_window_set_modal(GTK_WINDOW(dialog),TRUE);
+       g_signal_connect((gpointer)dialog,"close",G_CALLBACK(gtk_main_quit),NULL);
+       gtk_main();
+       /* 'dialog' gets destroyed automatically */
+}
+
+static void ui_gnome_interactive(void)
+{
+       gtk_main();
+       network_notify_hostip=NULL;
+       g_log_remove_handler(
+                       G_LOG_DOMAIN,   /* log_domain; "Captive" */
+                       ui_gnome_g_log_handler_handler_id);     /* handler_id */
+       network_detach();
 }
 
 /* of "ui-gnome-interface.h": */
@@ -167,16 +187,30 @@ gboolean ui_gnome_init(void)
        PortHBox=GTK_HBOX(lookup_widget(GTK_WIDGET(App),"PortHBox"));
        AppBar=GNOME_APPBAR(lookup_widget(GTK_WIDGET(App),"AppBar"));
        PortEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"PortEntry"));
+       HostIPEntry=GTK_ENTRY(lookup_widget(GTK_WIDGET(App),"HostIPEntry"));
+
+       /* ui_gnome_g_log_handler() needs 'App'. */
+       ui_gnome_g_log_handler_handler_id=g_log_set_handler(
+                       G_LOG_DOMAIN,   /* log_domain; "Captive" */
+                       (G_LOG_LEVEL_MASK|G_LOG_FLAG_FATAL)&~(0
+                                       |G_LOG_LEVEL_MESSAGE
+                                       |G_LOG_LEVEL_INFO
+                                       |G_LOG_LEVEL_DEBUG),    /* log_levels */
+                       ui_gnome_g_log_handler, /* log_func */
+                       NULL);  /* user_data */
+
+       ui_gnome_network_notify_hostip(0);
+       gtk_entry_set_text(PortEntry,udpgate_printf_alloca("%d",(int)optarg_port));
 
        gtk_widget_show_all(GTK_WIDGET(App));
        g_timeout_add(
                        DAEMON_CHECK_INTERVAL_MS,       /* interval */
                        daemon_check_timeout_func,      /* function */
                        NULL);  /* data; unused */
-       return TRUE;
-}
 
-void ui_gnome_interactive(void)
-{
-       gtk_main();
+       network_notify_hostip=ui_gnome_network_notify_hostip;
+
+       ui_interactive=ui_gnome_interactive;
+
+       return TRUE;
 }