#include <glib/gtypes.h> /* for 'gchar' */
#define G_LOG_DOMAIN ((const gchar *)"UDPForward")
+/**
+ * udpforward_printf_alloca:
+ * @format: Format string. See the sprintf() documentation.
+ * @args...: Arguments for @format. See the sprintf() documentation.
+ *
+ * Format the given format string @format as in sprintf().
+ * Output buffer is allocated automatically and it does not need to be deallocated
+ * manually as it is managed by g_alloca().
+ *
+ * @Returns: Formatted output string located in g_alloca() memory.
+ */
+#define udpforward_printf_alloca(format,args...) ({ \
+ gsize _udpforward_printf_alloca_size=udpforward_nv_printf_string_upper_bound((format) , ## args); \
+ gchar *_udpforward_printf_alloca_r=g_alloca(_udpforward_printf_alloca_size); \
+ g_snprintf(_udpforward_printf_alloca_r,_udpforward_printf_alloca_size,(format) , ## args); \
+ (const gchar *)_udpforward_printf_alloca_r; \
+ })
+#include <stdarg.h>
+#include <glib/gmessages.h> /* for g_printf_string_upper_bound() */
+static inline gsize udpforward_nv_printf_string_upper_bound(const gchar *format,...) G_GNUC_PRINTF(1,0) G_GNUC_UNUSED;
+static inline gsize udpforward_nv_printf_string_upper_bound(const gchar *format,...)
+{
+va_list ap;
+gsize r;
+
+ va_start(ap,format);
+ r=g_printf_string_upper_bound(format,ap);
+ va_end(ap);
+ return r;
+}
+
#endif /* !_UDPFORWARD_CONFIG_H */
])
+/* $Id$
+ * UDP forwarding utility
+ * Copyright (C) 2004 Jan Kratochvil <project-udpforward@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
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ *
+ * 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, Boston, MA 02111-1307 USA
+ */
+
+
+#include "config.h"
+
+#include <glib/gmessages.h>
+#include <popt.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <glib/gutils.h>
+#include <string.h>
+#include <setjmp.h>
+#include <unistd.h>
+#include <libgnome/gnome-program.h>
+#include <libgnomeui/gnome-ui-init.h>
+
+#include "ui-gnome.h"
+
+
+int optarg_verbose;
+static int optarg_text;
+
+static const struct poptOption popt_table[]={
+
+#define UDPFORWARD_POPT(shortname,longname,argInfoP,argP,valP,descripP,argDescripP) \
+ { \
+ longName: (longname), \
+ shortName: (shortname), \
+ argInfo: (argInfoP)|(!(valP) ? 0 : POPT_ARG_VAL), \
+ arg: (void *)argP, \
+ val: (valP), \
+ descrip: (descripP), \
+ argDescrip: (argDescripP), \
+ }
+
+ UDPFORWARD_POPT(0 ,"text" ,POPT_ARG_NONE ,&optarg_text ,0,
+ N_("Disable Gnome UI; --text must be first argument"),NULL),
+ UDPFORWARD_POPT('v',"verbose" ,POPT_ARG_NONE ,&optarg_verbose,0,N_("Display additional debug information"),NULL),
+
+#undef UDPFORWARD_POPT
+ POPT_TABLEEND
+ };
+
+static const struct poptOption popt_table_autohelp[]={
+ { NULL,'\0',POPT_ARG_INCLUDE_TABLE,(struct poptOption *)&popt_table,0,PACKAGE },
+ POPT_AUTOHELP
+ POPT_TABLEEND
+ };
+
+
+static jmp_buf gnome_init_atexit_jmpbuf;
+static gboolean gnome_init_atexit_disable;
+
+static void gnome_init_atexit_handler(void)
+{
+ if (gnome_init_atexit_disable)
+ return;
+
+ longjmp(gnome_init_atexit_jmpbuf,1);
+ g_assert_not_reached();
+ _exit(EXIT_FAILURE);
+}
+
+gboolean gnome_init_g_log_handler_hit;
+static void gnome_init_g_log_handler(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,gpointer user_data)
+{
+ gnome_init_g_log_handler_hit=TRUE;
+ g_log_default_handler(log_domain,log_level,message,user_data);
+}
+
+int main(int argc,char **argv)
+{
+poptContext context;
+int errint;
+gboolean is_interactive;
+gboolean no_gnome;
+
+#if 0
+ g_log_set_always_fatal(~(0
+ |G_LOG_LEVEL_MESSAGE
+ |G_LOG_LEVEL_INFO
+ |G_LOG_LEVEL_DEBUG
+ ));
+#endif
+
+ /* Initialize the i18n stuff */
+ setlocale(LC_ALL,"");
+ bindtextdomain(PACKAGE,LOCALEDIR);
+ textdomain(PACKAGE);
+
+ if (argv[1] && !strcmp(argv[1],"--text"))
+ optarg_text=1;
+
+ no_gnome=(optarg_text || !getenv("DISPLAY") || !*getenv("DISPLAY"));
+
+ if (no_gnome) {
+ context=poptGetContext(
+ PACKAGE, /* name */
+ argc,(/*en-const*/const char **)argv, /* argc,argv */
+ popt_table_autohelp, /* options */
+ POPT_CONTEXT_POSIXMEHARDER); /* flags; && !POPT_CONTEXT_KEEP_FIRST */
+ if (context==NULL) {
+ g_assert_not_reached(); /* argument recognization args_error */
+ return EXIT_FAILURE;
+ }
+ errint=poptReadDefaultConfig(context,
+ TRUE); /* useEnv */
+ if (errint!=0) {
+ g_assert_not_reached(); /* argument recognization args_error */
+ return EXIT_FAILURE;
+ }
+ errint=poptGetNextOpt(context);
+ if (errint!=-1) {
+ g_assert_not_reached(); /* some non-callbacked argument reached */
+ return EXIT_FAILURE;
+ }
+ if (poptPeekArg(context)) {
+ g_error(_("No arguments expected"));
+ return EXIT_FAILURE;
+ }
+ }
+ else {
+GnomeProgram *gnome_program;
+guint handler_id;
+
+ gnome_init_atexit_disable=FALSE;
+ g_atexit(gnome_init_atexit_handler);
+ gnome_init_g_log_handler_hit=FALSE;
+ handler_id=g_log_set_handler(
+ "Gtk", /* log_domain */
+ G_LOG_LEVEL_WARNING, /* log_levels */
+ gnome_init_g_log_handler, /* log_func */
+ NULL); /* user_data */
+ if (!setjmp(gnome_init_atexit_jmpbuf))
+ gnome_program=gnome_program_init(PACKAGE,VERSION,LIBGNOMEUI_MODULE,argc,argv,
+ GNOME_PARAM_POPT_TABLE,popt_table,
+ GNOME_PARAM_POPT_FLAGS,(int)POPT_CONTEXT_POSIXMEHARDER,
+ NULL);
+ else {
+ no_gnome=TRUE;
+ /* No message: (captive-install-acquire:3693): Gtk-WARNING **: cannot open display:
+ * was reported, probably only '--help' message was shown.
+ */
+ if (!gnome_init_g_log_handler_hit)
+ exit(EXIT_SUCCESS);
+ }
+ gnome_init_atexit_disable=TRUE;
+ g_log_remove_handler(
+ "Gtk", /* log_domain */
+ handler_id); /* handler_id */
+ }
+
+ is_interactive=(1
+/* && ! optarg_scan_path_list
+ && ! optarg_scan_disks_quick
+ && ! optarg_scan_disks
+ && ! optarg_microsoft_com */ );
+
+ /* Initialize UI here to catch all GLog errors below. */
+ if (is_interactive
+ && (no_gnome || !ui_gnome_init())
+/* && !ui_line_init()*/)
+ g_error(_("No UI interface could be initialized"));
+
+ if (!is_interactive)
+ /*scan_batch()*/;
+ else
+ ui_gnome_interactive();
+
+ return EXIT_SUCCESS;
+}
#include "ui-gnome.h" /* self */
#include <glib/gmessages.h>
#include "main.h"
+#include <libgnomeui/gnome-app.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+#include <errno.h>
+#include <libgnomeui/gnome-appbar.h>
+#include <gtk/gtkbutton.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtktogglebutton.h>
+#include <string.h>
+#include <gtk/gtkmain.h>
+
+
+/* Config: */
+#define PATHNAME_PID "/var/run/udpforward.pid"
+#define DAEMON_CHECK_INTERVAL_MS 500
+#define PORT_RANGE_BEGIN 2048
+#define PORT_RANGE_END 10240
static GnomeApp *App;
+static GtkButton *ButtonStart;
+static GtkButton *ButtonStop;
+static GtkHBox *PortHBox;
+static GnomeAppBar *AppBar;
+static GtkEntry *PortEntry;
+
+
+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)
+{
+gboolean daemon_running;
+ 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));
+ else
+ gnome_appbar_set_status(AppBar,_("No udpforward daemon currently running."));
+}
+
+static gboolean daemon_check_timeout_func(gpointer data /* unused */)
+{
+ state_start_stop();
+ return TRUE; /* continue running */
+}
+
+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)
+ return;
+ gtk_entry_set_text(PortEntry,
+ udpforward_printf_alloca("%d",(int)g_random_int_range(PORT_RANGE_BEGIN,PORT_RANGE_END)));
+}
+
+void on_AutostartCheckButton_toggled(GtkToggleButton *togglebutton,gpointer user_data)
+{
+ g_return_if_fail(GTK_IS_TOGGLE_BUTTON(togglebutton));
+}
+
+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)
+ return;
+}
+
+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)));
+}
+
+void on_ButtonHide_clicked(GtkButton *button,gpointer user_data)
+{
+ g_return_if_fail(GTK_IS_BUTTON(button));
+
+ gtk_main_quit();
+}
/* of "ui-gnome-interface.h": */
GtkWidget *create_App(void);
/* of "ui-gnome-support.h": */
GtkWidget *lookup_widget(GtkWidget *widget,const gchar *widget_name);
-void ui_gnome_init(void)
+gboolean ui_gnome_init(void)
{
App=GNOME_APP(create_App());
+
+ ButtonStart=GTK_BUTTON(lookup_widget(GTK_WIDGET(App),"ButtonStart"));
+ ButtonStop=GTK_BUTTON(lookup_widget(GTK_WIDGET(App),"ButtonStop"));
+ 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"));
+
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();
}
<property name="label" translatable="yes">Try random one</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_PortButtonRandom_clicked" last_modification_time="Sun, 09 May 2004 16:50:55 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_AutostartCheckButton_toggled" after="yes" last_modification_time="Sun, 09 May 2004 16:51:15 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_ButtonStart_clicked" last_modification_time="Sun, 09 May 2004 16:49:20 GMT"/>
<child>
- <widget class="GtkAlignment" id="alignment1">
+ <widget class="GtkAlignment" id="ButtonStartAlignment">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="yscale">0</property>
<child>
- <widget class="GtkHBox" id="hbox1">
+ <widget class="GtkHBox" id="ButtonStartHBox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
- <widget class="GtkImage" id="image1">
+ <widget class="GtkImage" id="ButtonStartImage">
<property name="visible">True</property>
<property name="stock">gtk-execute</property>
<property name="icon_size">4</property>
</child>
<child>
- <widget class="GtkLabel" id="label1">
+ <widget class="GtkLabel" id="ButtonStartLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">_Start</property>
<property name="use_underline">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_ButtonStop_clicked" last_modification_time="Sun, 09 May 2004 16:49:28 GMT"/>
<child>
- <widget class="GtkAlignment" id="alignment2">
+ <widget class="GtkAlignment" id="ButtonStopAlignment">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="yscale">0</property>
<child>
- <widget class="GtkHBox" id="hbox2">
+ <widget class="GtkHBox" id="ButtonStopHBox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
- <widget class="GtkImage" id="image2">
+ <widget class="GtkImage" id="ButtonStopImage">
<property name="visible">True</property>
<property name="stock">gtk-stop</property>
<property name="icon_size">4</property>
</child>
<child>
- <widget class="GtkLabel" id="label2">
+ <widget class="GtkLabel" id="ButtonStopLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">S_top</property>
<property name="use_underline">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_ButtonHide_clicked" last_modification_time="Sun, 09 May 2004 16:49:35 GMT"/>
<child>
- <widget class="GtkAlignment" id="alignment3">
+ <widget class="GtkAlignment" id="ButtonHideAlignment">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="yscale">0</property>
<child>
- <widget class="GtkHBox" id="hbox3">
+ <widget class="GtkHBox" id="ButtonHideHBox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
- <widget class="GtkImage" id="image3">
+ <widget class="GtkImage" id="ButtonHideImage">
<property name="visible">True</property>
<property name="stock">gtk-apply</property>
<property name="icon_size">4</property>
</child>
<child>
- <widget class="GtkLabel" id="label3">
+ <widget class="GtkLabel" id="ButtonHideLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">_Hide</property>
<property name="use_underline">True</property>
G_BEGIN_DECLS
-void ui_gnome_init(void);
+gboolean ui_gnome_init(void);
+void ui_gnome_interactive(void);
G_END_DECLS