summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2004-08-12 19:58:01 +0000
committerDan Williams <dcbw@redhat.com>2004-08-12 19:58:01 +0000
commit0895829142ef3b5ec45d48bcbae1966857ae043a (patch)
tree6d972038c9803a2add12d99ad9c6955ee9811b56
parentf9b8cb84d1f51e2c90f240b66aaa13b52893531d (diff)
downloadNetworkManager-0895829142ef3b5ec45d48bcbae1966857ae043a.tar.gz
2004-08-12 Dan Williams <dcbw@redhat.com>
* info-daemon/passphrase.glade - Set window title to " " * panel-applet/Makefile.am panel-applet/keyring.png - Deliver to correct place * panel-applet/NMWirelessApplet.[ch] - Add comments - Remove applet->have_active_device as its no longer used - (nmwa_load_theme): load keyring.png too - (error_dialog): remove - (show_warning_dialog): subsume functionality of error dialog too - (nmwa_destroy, nmwa_new): create and dispose of an application-wide GConfClient - (nmwa_handle_network_choice): add to deal with user clicking on an item from the networks menu - (nmwa_menu_item_activated): GtkMenuItem "activate" signal handler - (nmwa_button_clicked, nmwa_setup_widgets): create and populate the menu on startup and when we get broadcasts of changed wireless access points only, not when the user clicks on the button to display the menu (too long of a wait) - (nmwa_add_menu_item): Make active network bold, and place a keyring icon beside networks that are encrypted - (nmwa_dispose_menu, nmwa_menu_item_data_free): dispose of the data we place on each menu item with g_object_set_data() * panel-applet/NMWirelessAppletDbus.[ch] - (nmwa_dbus_get_bool): add method to return boolean value from dbus message - (nmwa_dbus_get_active_network): add (nmwa_dbus_get_string() wrapper to get active network) - (nmwa_dbus_add_networks_to_menu): clean up, only show one instance of each ESSID in the menu - (nmwa_dbus_set_network): force NetworkManager to use a particular network for wireless cards - (nmwa_dbus_init, nmwa_dbus_filter): Trap network appear/disappear and device activation/deactivation signals and rebuild the menu when they happen * src/NetworkManager.c - (main): use new nm_spawn_process() rather than system() * src/NetworkManagerDbus.c - (nm_dbus_devices_handle_request): don't compare AP structure addresses directly, but essids instead. Since we can now force best_aps to stick around, the AP structure to which dev->options.wireless.best_ap points to won't necessarily be in the device's device list if a scan has happened since the best_ap was frozen. Also add "setNetwork" method to freeze the best_ap. * src/NetworkManagerDevice.[ch] - (nm_device_activation_worker): Use new nm_spawn_process() call rather than system() - (nm_device_*_best_ap): add freeze/unfreeze/get_frozen functions, and don't really update the best_ap in nm_device_update_best_ap() if the best_ap is frozen AND in the device's ap list * src/NetworkManagerUtils.[ch] - (nm_spawn_process): add replacement for system() usage git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@48 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
-rw-r--r--ChangeLog54
-rw-r--r--info-daemon/passphrase.glade2
-rw-r--r--panel-applet/Makefile.am1
-rw-r--r--panel-applet/NMWirelessApplet.c305
-rw-r--r--panel-applet/NMWirelessApplet.h14
-rw-r--r--panel-applet/NMWirelessAppletDbus.c192
-rw-r--r--panel-applet/NMWirelessAppletDbus.h5
-rw-r--r--panel-applet/keyring.pngbin0 -> 3130 bytes
-rw-r--r--src/NetworkManager.c2
-rw-r--r--src/NetworkManagerAPList.c1
-rw-r--r--src/NetworkManagerDbus.c31
-rw-r--r--src/NetworkManagerDevice.c100
-rw-r--r--src/NetworkManagerDevice.h3
-rw-r--r--src/NetworkManagerUtils.c27
-rw-r--r--src/NetworkManagerUtils.h2
15 files changed, 619 insertions, 120 deletions
diff --git a/ChangeLog b/ChangeLog
index a3b05eaa67..8049adf8e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,57 @@
+2004-08-12 Dan Williams <dcbw@redhat.com>
+
+ * info-daemon/passphrase.glade
+ - Set window title to " "
+
+ * panel-applet/Makefile.am
+ panel-applet/keyring.png
+ - Deliver to correct place
+
+ * panel-applet/NMWirelessApplet.[ch]
+ - Add comments
+ - Remove applet->have_active_device as its no longer used
+ - (nmwa_load_theme): load keyring.png too
+ - (error_dialog): remove
+ - (show_warning_dialog): subsume functionality of error dialog too
+ - (nmwa_destroy, nmwa_new): create and dispose of an application-wide GConfClient
+ - (nmwa_handle_network_choice): add to deal with user clicking on an item from
+ the networks menu
+ - (nmwa_menu_item_activated): GtkMenuItem "activate" signal handler
+ - (nmwa_button_clicked, nmwa_setup_widgets): create and populate the menu on startup
+ and when we get broadcasts of changed wireless access points only, not when the
+ user clicks on the button to display the menu (too long of a wait)
+ - (nmwa_add_menu_item): Make active network bold, and place a keyring icon beside
+ networks that are encrypted
+ - (nmwa_dispose_menu, nmwa_menu_item_data_free): dispose of the data we place on each
+ menu item with g_object_set_data()
+
+ * panel-applet/NMWirelessAppletDbus.[ch]
+ - (nmwa_dbus_get_bool): add method to return boolean value from dbus message
+ - (nmwa_dbus_get_active_network): add (nmwa_dbus_get_string() wrapper to get active network)
+ - (nmwa_dbus_add_networks_to_menu): clean up, only show one instance of each ESSID in the menu
+ - (nmwa_dbus_set_network): force NetworkManager to use a particular network for wireless cards
+ - (nmwa_dbus_init, nmwa_dbus_filter): Trap network appear/disappear and device
+ activation/deactivation signals and rebuild the menu when they happen
+
+ * src/NetworkManager.c
+ - (main): use new nm_spawn_process() rather than system()
+
+ * src/NetworkManagerDbus.c
+ - (nm_dbus_devices_handle_request): don't compare AP structure addresses directly, but essids
+ instead. Since we can now force best_aps to stick around, the AP structure to which
+ dev->options.wireless.best_ap points to won't necessarily be in the device's device list
+ if a scan has happened since the best_ap was frozen. Also add "setNetwork" method
+ to freeze the best_ap.
+
+ * src/NetworkManagerDevice.[ch]
+ - (nm_device_activation_worker): Use new nm_spawn_process() call rather than system()
+ - (nm_device_*_best_ap): add freeze/unfreeze/get_frozen functions, and don't really update
+ the best_ap in nm_device_update_best_ap() if the best_ap is frozen AND in the device's
+ ap list
+
+ * src/NetworkManagerUtils.[ch]
+ - (nm_spawn_process): add replacement for system() usage
+
2004-08-11 Dan Williams <dcbw@redhat.com>
* panel-applet/NMWirelessApplet.[ch]
diff --git a/info-daemon/passphrase.glade b/info-daemon/passphrase.glade
index 273dd0cfbb..4f4737af9f 100644
--- a/info-daemon/passphrase.glade
+++ b/info-daemon/passphrase.glade
@@ -5,7 +5,7 @@
<widget class="GtkDialog" id="passphrase_dialog">
<property name="border_width">6</property>
- <property name="title" translatable="yes"></property>
+ <property name="title" translatable="yes"> </property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
<property name="modal">False</property>
diff --git a/panel-applet/Makefile.am b/panel-applet/Makefile.am
index a5d97c5489..50203ba29b 100644
--- a/panel-applet/Makefile.am
+++ b/panel-applet/Makefile.am
@@ -53,6 +53,7 @@ pixmap_DATA = no-link-0.png \
connect-1.png \
connect-2.png \
connect-3.png \
+ keyring.png \
$(NULL)
CLEANFILES = $(server_in_files) $(server_DATA) *.bak *.gladep
diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c
index 0e4858c717..3f19d4e612 100644
--- a/panel-applet/NMWirelessApplet.c
+++ b/panel-applet/NMWirelessApplet.c
@@ -40,6 +40,7 @@
#include <panel-applet.h>
#include <panel-applet-gconf.h>
#include <glade/glade.h>
+#include <gconf/gconf-client.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
@@ -63,6 +64,7 @@ static char * pixmap_names[] =
"connect-3.png",
};
+static char *glade_file;
/* Represents an access point */
typedef struct
@@ -71,12 +73,7 @@ typedef struct
gboolean encrypted;
} AccessPoint;
-static GladeXML *xml = NULL;
-static gchar *glade_file = NULL;
-
-static int nmwa_timeout_handler (NMWirelessApplet *applet);
static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet);
-static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet);
static const BonoboUIVerb nmwa_context_menu_verbs [] =
{
@@ -105,6 +102,14 @@ static GType nmwa_get_type (void)
return (type);
}
+
+/*
+ * nmwa_draw
+ *
+ * Actually update the applet's pixmap so that our panel icon reflects
+ * the state of the applet
+ *
+ */
static void nmwa_draw (NMWirelessApplet *applet)
{
const char *label_text;
@@ -117,6 +122,14 @@ static void nmwa_draw (NMWirelessApplet *applet)
}
}
+
+/*
+ * nmwa_update_state
+ *
+ * Figure out what the currently active device is from NetworkManager, its type,
+ * and what our icon on the panel should look like for each type.
+ *
+ */
static void nmwa_update_state (NMWirelessApplet *applet)
{
if (applet->nm_active)
@@ -131,7 +144,6 @@ static void nmwa_update_state (NMWirelessApplet *applet)
switch (type)
{
case (DEVICE_TYPE_WIRELESS_ETHERNET):
- applet->have_active_device = TRUE;
if (strcmp (status, "connected") == 0)
applet->pix_state = PIX_SIGNAL_4;
else if (strcmp (status, "connecting") == 0)
@@ -146,29 +158,40 @@ static void nmwa_update_state (NMWirelessApplet *applet)
case (DEVICE_TYPE_WIRED_ETHERNET):
default:
- applet->have_active_device = FALSE;
applet->pix_state = PIX_BROKEN;
break;
}
}
else
- {
- applet->have_active_device = FALSE;
applet->pix_state = PIX_BROKEN;
- }
if (active_device) dbus_free (active_device);
if (status) dbus_free (status);
}
else
- {
- applet->have_active_device = FALSE;
applet->pix_state = PIX_BROKEN;
- }
nmwa_draw (applet);
}
+
+/*
+ * nmwa_timeout_handler
+ *
+ * Called regularly to update the applet's state and icon in the panel
+ *
+ */
+static int nmwa_timeout_handler (NMWirelessApplet *applet)
+{
+ /* Try to get a connection to dbus if we don't already have one */
+ if (!applet->connection)
+ applet->connection = nmwa_dbus_init (applet);
+
+ nmwa_update_state (applet);
+
+ return (TRUE);
+}
+
static void nmwa_start_timeout (NMWirelessApplet *applet)
{
applet->timeout_handler_id = g_timeout_add (CFG_UPDATE_INTERVAL * 1000,
@@ -185,9 +208,10 @@ static void nmwa_cancel_timeout (NMWirelessApplet *applet)
static void nmwa_load_theme (NMWirelessApplet *applet)
{
- char *pixmapdir;
- char *pixmapname;
- int i;
+ char *pixmapdir;
+ char *pixmapname;
+ int i;
+ GError *error = NULL;
pixmapdir = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
"NMWirelessApplet/", FALSE, NULL);
@@ -200,37 +224,21 @@ static void nmwa_load_theme (NMWirelessApplet *applet)
g_free (pixmapname);
}
- g_free (pixmapdir);
-}
-
-
-static int nmwa_timeout_handler (NMWirelessApplet *applet)
-{
- /* Try to get a connection to dbus if we don't already have one */
- if (!applet->connection)
- applet->connection = nmwa_dbus_init (applet);
-
- nmwa_update_state (applet);
+ pixmapname = g_build_filename (G_DIR_SEPARATOR_S, pixmapdir, "keyring.png", NULL);
+ applet->key_pixbuf = gdk_pixbuf_new_from_file_at_size (pixmapname, 16, 16, &error);
+ g_free (pixmapname);
- return (TRUE);
+ g_free (pixmapdir);
}
-void show_error_dialog (gchar *mesg, ...)
-{
- GtkWidget *dialog;
- char *tmp;
- va_list ap;
-
- va_start (ap,mesg);
- tmp = g_strdup_vprintf (mesg,ap);
- dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, mesg, NULL);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- g_free (tmp);
- va_end (ap);
-}
-void show_warning_dialog (gchar *mesg, ...)
+/*
+ * show_warning_dialog
+ *
+ * pop up a warning or error dialog with certain text
+ *
+ */
+static void show_warning_dialog (gboolean error, gchar *mesg, ...)
{
GtkWidget *dialog;
char *tmp;
@@ -238,7 +246,8 @@ void show_warning_dialog (gchar *mesg, ...)
va_start (ap,mesg);
tmp = g_strdup_vprintf (mesg,ap);
- dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, mesg, NULL);
+ dialog = gtk_message_dialog_new (NULL, 0, error ? GTK_MESSAGE_ERROR : GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK, mesg, NULL);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free (tmp);
@@ -246,6 +255,12 @@ void show_warning_dialog (gchar *mesg, ...)
}
+/*
+ * nmwa_about_cb
+ *
+ * Display our about dialog
+ *
+ */
static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet)
{
GdkPixbuf *pixbuf;
@@ -290,12 +305,18 @@ static void nmwa_about_cb (BonoboUIComponent *uic, NMWirelessApplet *applet)
}
+/*
+ * nmwa_destroy
+ *
+ * Destroy the applet and clean up its data
+ *
+ */
static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data)
{
int i;
if (applet->menu)
- gtk_widget_destroy (applet->menu);
+ nmwa_dispose_menu (applet);
if (applet->timeout_handler_id > 0)
{
@@ -311,9 +332,18 @@ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data)
gtk_widget_destroy (applet->about_dialog);
applet->about_dialog = NULL;
}
+
+ if (applet->gconf_client)
+ g_object_unref (G_OBJECT (applet->gconf_client));
}
+/*
+ * nmwa_get_menu_pos
+ *
+ * When displaying the popup menu, figure out exactly where to put it on the screen
+ *
+ */
static void nmwa_get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
{
NMWirelessApplet *applet = data;
@@ -347,18 +377,65 @@ static void nmwa_get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_i
}
+/*
+ * nmwa_handle_network_choice
+ *
+ * Ask the user whether to add the network they have chosen to the trusted
+ * networks list, and then stuff the network into gconf in either the trusted
+ * or preferred networks list depending on their choice. This notifies
+ * NetworkInfoManager that the networks list has changed, and it notifies
+ * NetworkManager about those changes, triggering an AP switch.
+ */
+void nmwa_handle_network_choice (NMWirelessApplet *applet, char *network)
+{
+
+ g_return_if_fail (applet != NULL);
+ g_return_if_fail (network != NULL);
+
+fprintf( stderr, "Forcing network '%s'\n", network);
+ nmwa_dbus_set_network (applet->connection, network);
+}
+
+
+/*
+ * nmwa_menu_item_activated
+ *
+ * Signal function called when user clicks on a menu item
+ *
+ */
+void nmwa_menu_item_activated (GtkMenuItem *item, gpointer user_data)
+{
+ NMWirelessApplet *applet = (NMWirelessApplet *)user_data;
+ char *network;
+
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (applet != NULL);
+
+ if ((network = g_object_get_data (G_OBJECT (item), "network")))
+ nmwa_handle_network_choice (applet, network);
+}
+
+
+/*
+ * nmwa_button_clicked
+ *
+ * Pop up the wireless networks menu in response to a click on the applet
+ *
+ */
static void nmwa_button_clicked (GtkWidget *button, NMWirelessApplet *applet)
{
- if (applet->menu != NULL)
- {
- gtk_menu_popdown (GTK_MENU (applet->menu));
- g_object_unref(G_OBJECT(applet->menu));
- applet->menu = NULL;
- }
+ if (applet->menu && GTK_WIDGET_VISIBLE (applet->menu))
+ gtk_menu_popdown (GTK_MENU (applet->menu));
else
{
- applet->menu = nmwa_populate_menu (applet);
- gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL, nmwa_get_menu_pos, applet, 0, gtk_get_current_event_time());
+ if (applet->nm_active)
+ {
+ if (!applet->menu)
+ applet->menu = nmwa_populate_menu (applet);
+
+ gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL, nmwa_get_menu_pos,
+ applet, 0, gtk_get_current_event_time());
+ }
}
}
@@ -370,18 +447,84 @@ static void nmwa_button_clicked (GtkWidget *button, NMWirelessApplet *applet)
* Given a network, add it to our networks menu.
*
*/
-void nmwa_add_menu_item (char *network, gboolean current, gpointer user_data)
+void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag, gboolean current,
+ gboolean encrypted)
{
- GtkWidget *menu = (GtkWidget *)user_data;
GtkWidget *menu_item;
+ GtkWidget *label;
+ GtkWidget *hbox;
- g_return_if_fail (network != NULL);
+ g_return_if_fail (text != NULL);
g_return_if_fail (menu != NULL);
+fprintf( stderr, "text = %s\n", text);
+ menu_item = gtk_menu_item_new ();
+ hbox = gtk_hbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (menu_item), hbox);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new (text);
+ if (current)
+ {
+ char *markup = g_strdup_printf ("<span weight=\"bold\">%s</span>", text);
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ g_free (markup);
+ }
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 2);
+ gtk_widget_show (label);
+
+ if (encrypted)
+ {
+ GtkWidget *image;
+
+ if ((image = gtk_image_new_from_pixbuf (applet->key_pixbuf)))
+ {
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2);
+ gtk_widget_show (image);
+ }
+ }
+
+ g_object_set_data (G_OBJECT (menu_item), "network", g_strdup (tag));
+ g_signal_connect(G_OBJECT (menu_item), "activate", G_CALLBACK(nmwa_menu_item_activated), applet);
- menu_item = gtk_check_menu_item_new_with_label (network);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), current);
- gtk_widget_show (menu_item);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ gtk_widget_show (menu_item);
+}
+
+
+/*
+ * nmwa_menu_item_data_free
+ *
+ * Frees the "network" data tag on a menu item we've created
+ *
+ */
+static void nmwa_menu_item_data_free (GtkWidget *menu_item, gpointer user_data)
+{
+ char *tag;
+
+ g_return_if_fail (menu_item != NULL);
+
+ if ((tag = g_object_get_data (G_OBJECT (menu_item), "network")))
+ {
+ g_object_set_data (G_OBJECT (menu_item), "network", NULL);
+ g_free (tag);
+ }
+}
+
+
+/*
+ * nmwa_dispose_menu
+ *
+ * Destroy the menu and each of its items data tags
+ *
+ */
+void nmwa_dispose_menu (NMWirelessApplet *applet)
+{
+ g_return_if_fail (applet != NULL);
+
+ /* Free the "network" data on each menu item */
+ gtk_container_foreach (GTK_CONTAINER (applet->menu), nmwa_menu_item_data_free, NULL);
+ gtk_widget_destroy (applet->menu);
}
@@ -391,24 +534,27 @@ void nmwa_add_menu_item (char *network, gboolean current, gpointer user_data)
* Set up our networks menu from scratch
*
*/
-static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet)
+GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet)
{
GtkWidget *menu;
- GtkWidget *menu_item;
- int num_networks;
- char **networks;
- g_assert(applet->nm_active);
+ g_assert (applet->nm_active);
g_return_if_fail (applet != NULL);
menu = gtk_menu_new ();
-
- nmwa_dbus_add_networks_to_menu (applet->connection, menu);
+ nmwa_dbus_add_networks_to_menu (applet, menu);
return (menu);
}
+/*
+ * mnwa_setup_widgets
+ *
+ * Intialize the applet's widgets and packing, create the initial
+ * menu of networks.
+ *
+ */
static void nmwa_setup_widgets (NMWirelessApplet *applet)
{
GtkRequisition req;
@@ -467,7 +613,8 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet)
applet->current_pixbuf = NULL;
applet->about_dialog = NULL;
- applet->menu = NULL;
+ if (applet->nm_active)
+ applet->menu = nmwa_populate_menu (applet);
}
static void change_size_cb(PanelApplet *pa, gint s, NMWirelessApplet *applet)
@@ -517,17 +664,37 @@ static void change_background_cb(PanelApplet *a, PanelAppletBackgroundType type,
gtk_rc_style_unref (rc_style);
}
+
+/*
+ * nmwa_new
+ *
+ * Create the initial instance of our wireless applet
+ *
+ */
static GtkWidget * nmwa_new (NMWirelessApplet *applet)
{
panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR);
gtk_widget_hide(GTK_WIDGET(applet));
+ applet->gconf_client = gconf_client_get_default ();
+ if (!applet->gconf_client)
+ return (NULL);
+
+#if 0
+ applet->net_dialog = glade_xml_new(GLADEDIR"/network_chocie.glade", NULL, NULL);
+ if (!applet->net_dialog)
+ {
+ fprintf (stderr, "Could not open the network dialog glade file!\n");
+ g_object_unref (G_OBJECT (applet->gconf_client));
+ return (NULL);
+ }
+#endif
+
applet->pix_state = PIX_BROKEN;
applet->connection = nmwa_dbus_init(applet);
- applet->have_active_device = FALSE;
applet->nm_active = nmwa_dbus_nm_is_running(applet->connection);
-
+
nmwa_load_theme (applet);
nmwa_setup_widgets (applet);
diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h
index ccbcad2dbb..40bf6f6a95 100644
--- a/panel-applet/NMWirelessApplet.h
+++ b/panel-applet/NMWirelessApplet.h
@@ -25,6 +25,8 @@
#include <gnome.h>
#include <panel-applet.h>
#include <panel-applet-gconf.h>
+#include <gconf/gconf-client.h>
+#include <glade/glade.h>
typedef enum
{
@@ -48,7 +50,8 @@ typedef struct
DBusConnection *connection;
gboolean nm_active;
- gboolean have_active_device;
+ GConfClient *gconf_client;
+ GladeXML *net_dialog;
PixmapState pix_state;
/* contains pointers into the images GList.
@@ -56,6 +59,7 @@ typedef struct
GdkPixbuf *pixmaps[PIX_NUMBER];
/* pointer to the current used file name */
GdkPixbuf *current_pixbuf;
+ GdkPixbuf *key_pixbuf;
GtkWidget *pixmap;
GtkWidget *button;
@@ -67,11 +71,11 @@ typedef struct
} NMWirelessApplet;
-void nmwa_add_menu_item (char *network, gboolean current, gpointer user_data);
+void nmwa_add_menu_item (NMWirelessApplet *applet, GtkWidget *menu, char *text, char *tag,
+ gboolean current, gboolean encrypted);
-void show_warning_dialog (gchar *mesg, ...);
-
-void show_warning_dialog (gchar *mesg, ...);
+GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet);
+void nmwa_dispose_menu (NMWirelessApplet *applet);
#endif
diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c
index 70d8c11f56..8c5a7d9a8c 100644
--- a/panel-applet/NMWirelessAppletDbus.c
+++ b/panel-applet/NMWirelessAppletDbus.c
@@ -138,6 +138,54 @@ gint32 nmwa_dbus_get_int (DBusConnection *connection, const char *path, const ch
/*
+ * nmwa_dbus_get_bool
+ *
+ */
+gboolean nmwa_dbus_get_bool (DBusConnection *connection, const char *path, const char *method)
+{
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusError error;
+ gboolean val;
+
+ g_return_val_if_fail (connection != NULL, 0);
+ g_return_val_if_fail (path != NULL, 0);
+ g_return_val_if_fail (method != NULL, 0);
+
+ if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE, method)))
+ {
+ fprintf (stderr, "nmwa_dbus_get_int(): Couldn't allocate the dbus message\n");
+ return (0);
+ }
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
+ if (dbus_error_is_set (&error))
+ {
+ fprintf (stderr, "nmwa_dbus_get_int(): %s raised:\n %s\n\n", error.name, error.message);
+ dbus_message_unref (message);
+ return (0);
+ }
+
+ if (reply == NULL)
+ {
+ fprintf( stderr, "nmwa_dbus_get_int(): dbus reply message was NULL\n" );
+ dbus_message_unref (message);
+ return (0);
+ }
+
+ dbus_error_init (&error);
+ if (!dbus_message_get_args (reply, &error, DBUS_TYPE_BOOLEAN, &val, DBUS_TYPE_INVALID))
+ val = FALSE;
+
+ dbus_message_unref (reply);
+ dbus_message_unref (message);
+
+ return (val);
+}
+
+
+/*
* nmwa_dbus_get_double
*
*/
@@ -265,6 +313,32 @@ char * nmwa_dbus_get_active_device (DBusConnection *connection)
/*
+ * nmwa_dbus_get_active_network
+ *
+ * Returns the object_path of the currently active network of the active device.
+ *
+ */
+char * nmwa_dbus_get_active_network (DBusConnection *connection, char *dev_path)
+{
+ char *network;
+
+ if (!connection)
+ return (NULL);
+
+ if ((network = nmwa_dbus_get_string (connection, dev_path, "getActiveNetwork")))
+ {
+ if (strlen (network) < 1)
+ {
+ dbus_free (network);
+ network = NULL;
+ }
+ }
+
+ return (network);
+}
+
+
+/*
* nmwa_dbus_get_device_type
*
* Returns the object_path of the currently active device, if any.
@@ -311,62 +385,124 @@ char * nmwa_dbus_get_nm_status (DBusConnection *connection)
* Query NetworkManager for networks and add any to the networks menu
*
*/
-void nmwa_dbus_add_networks_to_menu (DBusConnection *connection, gpointer user_data)
+void nmwa_dbus_add_networks_to_menu (NMWirelessApplet *applet, GtkWidget *menu)
{
char *active_device;
char *active_network;
char **networks;
int num_items = 0;
+ int i;
- if (!connection)
+ g_return_if_fail (applet != NULL);
+ g_return_if_fail (applet->connection != NULL);
+ g_return_if_fail (menu != NULL);
+
+ if (!applet->connection)
{
- nmwa_add_menu_item ("No wireless networks found...", FALSE, user_data);
+ nmwa_add_menu_item (applet, menu, "No wireless networks found...", NULL, FALSE, FALSE);
return;
}
- if (!(active_device = nmwa_dbus_get_active_device (connection)))
+ if (!(active_device = nmwa_dbus_get_active_device (applet->connection)))
{
- nmwa_add_menu_item ("No network connection is present.", FALSE, user_data);
+ nmwa_add_menu_item (applet, menu, "No network connection is present.", NULL, FALSE, FALSE);
return;
}
- switch (nmwa_dbus_get_device_type (connection, active_device))
+ switch (nmwa_dbus_get_device_type (applet->connection, active_device))
{
case (DEVICE_TYPE_WIRED_ETHERNET):
- nmwa_add_menu_item ("A wired ethernet card is currently active.", FALSE, user_data);
+ nmwa_add_menu_item (applet, menu, "A wired ethernet card is currently active.", NULL, FALSE, FALSE);
return;
case (DEVICE_TYPE_WIRELESS_ETHERNET):
break;
default:
- nmwa_add_menu_item ("Some other network device is currently active.", FALSE, user_data);
+ nmwa_add_menu_item (applet, menu, "Some other network device is currently active.", NULL, FALSE, FALSE);
return;
}
+ active_network = nmwa_dbus_get_active_network (applet->connection, active_device);
+
/* Get each of the networks in turn and add them to the menu */
- if ((networks = nmwa_dbus_get_string_array (connection, active_device, "getNetworks", &num_items)))
+ if (!(networks = nmwa_dbus_get_string_array (applet->connection, active_device, "getNetworks", &num_items)))
+ {
+ dbus_free (active_device);
+ if (active_network)
+ dbus_free (active_network);
+ return;
+ }
+
+ if (strlen (networks[0]) == 0)
+ {
+ nmwa_add_menu_item (applet, menu, "No wireless networks found...", NULL, FALSE, FALSE);
+ dbus_free (active_device);
+ if (active_network)
+ dbus_free (active_network);
+ return;
+ }
+
+ for (i = 0; i < num_items; i++)
{
- if (strlen (networks[0]) == 0)
- nmwa_add_menu_item ("No wireless networks found...", FALSE, user_data);
- else
+ char *name = nmwa_dbus_get_string (applet->connection, networks[i], "getName");
+
+ if (name && strlen (name))
{
- int i;
- for (i = 0; i < num_items; i++)
+ gboolean found = FALSE;
+ int j;
+
+ /* Only show one menu item per network. NetworkManager really passes back a list
+ * of access points, and there may be more than one that have the same ESSID. Filter
+ * them here.
+ */
+ for (j = 0; j < i; j++)
+ if (found = (networks[j] && (strcmp (networks[i], networks[j]) == 0)))
+ break;
+
+ if (!found)
{
- char *name = nmwa_dbus_get_string (connection, networks[i], "getName");
- nmwa_add_menu_item (name, (strcmp (networks[i], active_network) == 0), user_data);
- dbus_free (name);
+ gboolean active = active_network ? (strcmp (networks[i], active_network) == 0) : FALSE;
+ gboolean encrypted = nmwa_dbus_get_bool (applet->connection, networks[i], "getEncrypted");
+
+ fprintf( stderr, "Adding '%s' active (%d), enc (%d)\n", name, active, encrypted);
+ nmwa_add_menu_item (applet, menu, name, name, active, encrypted);
}
}
- dbus_free_string_array (networks);
+ dbus_free (name);
}
+ dbus_free_string_array (networks);
+ dbus_free (active_network);
dbus_free (active_device);
}
/*
+ * nmwa_dbus_set_network
+ *
+ * Tell NetworkManager to use a specific network that the user picked.
+ *
+ */
+void nmwa_dbus_set_network (DBusConnection *connection, char *network)
+{
+ DBusMessage *message;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (network != NULL);
+
+ message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "setNetwork");
+ if (message)
+ {
+ dbus_message_append_args (message, DBUS_TYPE_STRING, network, DBUS_TYPE_INVALID);
+ dbus_connection_send (connection, message, NULL);
+ }
+ else
+ fprintf (stderr, "nm_dbus_get_network_priority(): Couldn't allocate the dbus message\n");
+}
+
+
+/*
* nmwa_dbus_nm_is_running
*
* Ask dbus whether or not NetworkManager is running
@@ -418,6 +554,19 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa
&& (strcmp (service, NM_DBUS_SERVICE) == 0))
applet->nm_active = FALSE;
}
+ else if ( dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkAppeared")
+ || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared")
+ || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive")
+ || dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive"))
+ {
+ if (applet->menu && !GTK_WIDGET_VISIBLE (applet->menu))
+ {
+ nmwa_dispose_menu (applet);
+ applet->menu = nmwa_populate_menu (applet);
+ }
+ else if (!applet->menu)
+ applet->menu = nmwa_populate_menu (applet);
+ }
else
handled = FALSE;
@@ -459,6 +608,13 @@ DBusConnection * nmwa_dbus_init (gpointer user_data)
"sender='" DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "'",
&error);
+ dbus_bus_add_match(connection,
+ "type='signal',"
+ "interface='" NM_DBUS_INTERFACE "',"
+ "path='" NM_DBUS_PATH "',"
+ "sender='" NM_DBUS_SERVICE "'",
+ &error);
+
return (connection);
}
diff --git a/panel-applet/NMWirelessAppletDbus.h b/panel-applet/NMWirelessAppletDbus.h
index ea290e4850..eaf4e89095 100644
--- a/panel-applet/NMWirelessAppletDbus.h
+++ b/panel-applet/NMWirelessAppletDbus.h
@@ -24,6 +24,7 @@
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
+#include "NMWirelessApplet.h"
/* Must match NetworkManager device types */
enum
@@ -37,7 +38,7 @@ DBusConnection * nmwa_dbus_init (gpointer user_data);
gboolean nmwa_dbus_nm_is_running (DBusConnection *connection);
-void nmwa_dbus_add_networks_to_menu (DBusConnection *connection, gpointer user_data);
+void nmwa_dbus_add_networks_to_menu (NMWirelessApplet *applet, GtkWidget *menu);
char * nmwa_dbus_get_active_device (DBusConnection *connection);
@@ -45,4 +46,6 @@ int nmwa_dbus_get_device_type (DBusConnection *connection, char *path);
char * nmwa_dbus_get_nm_status (DBusConnection *connection);
+void nmwa_dbus_set_network (DBusConnection *connection, char *network);
+
#endif
diff --git a/panel-applet/keyring.png b/panel-applet/keyring.png
new file mode 100644
index 0000000000..caade38ad3
--- /dev/null
+++ b/panel-applet/keyring.png
Binary files differ
diff --git a/src/NetworkManager.c b/src/NetworkManager.c
index 297107f171..89938486b8 100644
--- a/src/NetworkManager.c
+++ b/src/NetworkManager.c
@@ -624,7 +624,7 @@ int main( int argc, char *argv[] )
/* We run dhclient when we need to, and we don't want any stray ones
* lying around upon launch.
*/
- system ("killall dhclient");
+ nm_spawn_process ("/usr/bin/killall dhclient");
/* Wheeee!!! */
loop = g_main_loop_new (NULL, FALSE);
diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c
index 82eced5ddb..43f57e467f 100644
--- a/src/NetworkManagerAPList.c
+++ b/src/NetworkManagerAPList.c
@@ -440,6 +440,7 @@ void nm_ap_list_iter_free (NMAPListIter *iter)
g_return_if_fail (iter != NULL);
nm_ap_list_unlock (iter->list);
+ memset (iter, 0, sizeof (struct NMAPListIter));
g_free (iter);
}
diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c
index 5c5da4b1ce..987837ad5a 100644
--- a/src/NetworkManagerDbus.c
+++ b/src/NetworkManagerDbus.c
@@ -1069,7 +1069,8 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection,
if ((ap = nm_device_ap_list_get_ap_by_essid (dev, nm_device_get_essid (dev))))
{
- if ((ap == nm_device_get_best_ap (dev)) && (object_path = nm_device_get_path_for_ap (dev, ap)))
+ if ( (nm_null_safe_strcmp (nm_ap_get_essid (ap), nm_ap_get_essid (nm_device_get_best_ap (dev))) == 0)
+ && (object_path = nm_device_get_path_for_ap (dev, ap)))
{
dbus_message_append_args (reply_message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID);
g_free (object_path);
@@ -1168,6 +1169,34 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection,
reply_message = nm_dbus_nm_get_devices (connection, message, data);
else if (strcmp ("setKeyForNetwork", method) == 0)
nm_dbus_set_user_key_for_network (connection, message, data);
+ else if (strcmp ("setNetwork", method) == 0)
+ {
+ if (data->active_device && nm_device_is_wireless (data->active_device))
+ {
+ char *network;
+ DBusError error;
+
+ dbus_error_init (&error);
+ if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID))
+ {
+ NMAccessPoint *ap;
+
+ if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (data->active_device), network)))
+ {
+fprintf (stderr, "Forcing AP '%s'\n", nm_ap_get_essid (ap));
+ nm_device_freeze_best_ap (data->active_device);
+ nm_device_set_best_ap (data->active_device, ap);
+ nm_data_set_state_modified (data, TRUE);
+ }
+ dbus_free (network);
+ }
+ }
+ else
+ reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadDevice",
+ "A network can only be set when a wireless device is active.");
+
+ handled = TRUE;
+ }
else if (strcmp ("status", method) == 0)
{
reply_message = dbus_message_new_method_return (message);
diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c
index 4717af1f76..493c6c56a5 100644
--- a/src/NetworkManagerDevice.c
+++ b/src/NetworkManagerDevice.c
@@ -890,13 +890,13 @@ static gboolean nm_device_activate_wireless (NMDevice *dev)
*/
static gpointer nm_device_activation_worker (gpointer user_data)
{
+ NMDevice *dev = (NMDevice *)user_data;
unsigned char buf[500];
- unsigned char *iface;
unsigned char hostname[100] = "\0";
int host_err;
int dhclient_err;
+ char *iface;
FILE *pidfile;
- NMDevice *dev = (NMDevice *)user_data;
g_return_val_if_fail (dev != NULL, NULL);
g_return_val_if_fail (dev->app_data != NULL, NULL);
@@ -965,8 +965,7 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n
}
/* Kill the old default route */
- snprintf (buf, 500, "/sbin/ip route del default");
- system (buf);
+ nm_spawn_process ("/sbin/ip route del default");
/* Find and kill the previous dhclient process for this interface */
iface = nm_device_get_iface (dev);
@@ -985,7 +984,7 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n
n_pid = atoi (s_pid);
if (n_pid > 0)
- kill (n_pid, 9);
+ kill (n_pid, SIGTERM);
}
/* If we don't have a "best" ap, don't try to get a DHCP address or restart the name service cache */
@@ -996,14 +995,10 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n
/* Unfortunately, dhclient can take a long time to get a dhcp address
* (for example, bad WEP key so it can't actually talk to the AP).
- * We are essentially blocked until it returns.
- * FIXME: fork() NetworkManager to do the dhclient stuff, and if our
- * state changes during the dhclient stuff, we can kill() the
- * forked process running dhclient.
*/
snprintf (buf, 500, "/sbin/dhclient -1 -q -lf /var/lib/dhcp/dhclient-%s.leases -pf /var/run/dhclient-%s.pid -cf /etc/dhclient-%s.conf %s\n",
iface, iface, iface, iface);
- dhclient_err = system (buf);
+ dhclient_err = nm_spawn_process (buf);
/* Set the hostname back to what it was before so that X11 doesn't
* puke when the hostname changes, and so users can actually launch stuff.
@@ -1011,15 +1006,6 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 1.5\n", n
if (host_err >= 0)
sethostname (hostname, strlen (hostname));
- /* If we were told to quit activation, stop the thread and return */
- if (dev->quit_activation)
- {
-fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 2\n", nm_device_get_iface (dev));
- dev->just_activated = FALSE;
- nm_device_unref (dev);
- return (NULL);
- }
-
if (dhclient_err != 0)
{
/* Interfaces cannot be down if they are the active interface,
@@ -1036,9 +1022,17 @@ fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 2\n", nm_
nm_device_bring_up (dev);
}
+ /* If we were told to quit activation, stop the thread and return */
+ if (dev->quit_activation)
+ {
+fprintf( stderr, "nm_device_activation_worker(%s): activation canceled 2\n", nm_device_get_iface (dev));
+ dev->just_activated = FALSE;
+ nm_device_unref (dev);
+ return (NULL);
+ }
+
/* Restart the nameservice caching daemon to make apps aware of new DNS servers */
- snprintf (buf, 500, "/sbin/service nscd restart");
- system (buf);
+ nm_spawn_process ("/sbin/service nscd restart");
}
/* If we were told to quit activation, stop the thread and return */
@@ -1135,11 +1129,11 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added)
{
/* Remove routing table entries */
snprintf (buf, 500, "/sbin/ip route flush dev %s", iface);
- system (buf);
+ nm_spawn_process (buf);
/* Remove ip address */
snprintf (buf, 500, "/sbin/ip address flush dev %s", iface);
- system (buf);
+ nm_spawn_process (buf);
dev->ip4_address = 0;
@@ -1317,6 +1311,38 @@ void nm_device_set_best_ap (NMDevice *dev, NMAccessPoint *ap)
/*
+ * Freeze/unfreeze best ap
+ *
+ * If the user explicitly picks a network to associate with, we don't
+ * change the active network until it goes out of range.
+ *
+ */
+void nm_device_freeze_best_ap (NMDevice *dev)
+{
+ g_return_if_fail (dev != NULL);
+ g_return_if_fail (nm_device_is_wireless (dev));
+
+ dev->options.wireless.freeze_best_ap = TRUE;
+}
+
+void nm_device_unfreeze_best_ap (NMDevice *dev)
+{
+ g_return_if_fail (dev != NULL);
+ g_return_if_fail (nm_device_is_wireless (dev));
+
+ dev->options.wireless.freeze_best_ap = FALSE;
+}
+
+gboolean nm_device_get_best_ap_frozen (NMDevice *dev)
+{
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (nm_device_is_wireless (dev), FALSE);
+
+ return (dev->options.wireless.freeze_best_ap);
+}
+
+
+/*
* nm_device_get_path_for_ap
*
* Return the object path for an access point.
@@ -1377,7 +1403,33 @@ void nm_device_update_best_ap (NMDevice *dev)
if (!(ap_list = nm_device_ap_list_get (dev)))
return;
- /* Check the trusted list first */
+ /* Iterate over the device's ap list to make sure the current
+ * "best" ap is still in the device's ap list (so that if its
+ * not, we can "unfreeze" the best ap if its been frozen already).
+ * If it is, we don't change the best ap here.
+ */
+ if (nm_device_get_best_ap_frozen (dev))
+ {
+ g_mutex_lock (dev->options.wireless.best_ap_mutex);
+ best_ap = nm_device_get_best_ap (dev);
+
+ /* If its in the device's ap list still, don't change the
+ * best ap, since its frozen.
+ */
+ if ( best_ap
+ && !nm_ap_list_get_ap_by_essid (dev->app_data->invalid_ap_list, nm_ap_get_essid (best_ap))
+ && nm_device_ap_list_get_ap_by_essid (dev, nm_ap_get_essid (best_ap)))
+ {
+ g_mutex_unlock (dev->options.wireless.best_ap_mutex);
+ return;
+ }
+
+ /* Otherwise, its gone away and we don't care about it anymore */
+ nm_device_unfreeze_best_ap (dev);
+ g_mutex_unlock (dev->options.wireless.best_ap_mutex);
+ }
+
+ /* Check the trusted list then */
if (!(iter = nm_ap_list_iter_new (ap_list)))
return;
while ((ap = nm_ap_list_iter_next (iter)))
diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h
index f4d497e2a0..6e09840b20 100644
--- a/src/NetworkManagerDevice.h
+++ b/src/NetworkManagerDevice.h
@@ -75,6 +75,9 @@ NMAccessPoint *nm_device_get_best_ap (NMDevice *dev);
void nm_device_set_best_ap (NMDevice *dev, NMAccessPoint *ap);
void nm_device_update_best_ap (NMDevice *dev);
gboolean nm_device_need_ap_switch (NMDevice *dev);
+void nm_device_freeze_best_ap (NMDevice *dev);
+void nm_device_unfreeze_best_ap (NMDevice *dev);
+gboolean nm_device_get_best_ap_frozen (NMDevice *dev);
char * nm_device_get_path_for_ap (NMDevice *dev, NMAccessPoint *ap);
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 018ee6200e..d8acdf4071 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -172,3 +172,30 @@ void nm_dispose_scan_results (wireless_scan *result_list)
}
}
+
+/*
+ * nm_spawn_process
+ *
+ * Wrap g_spawn_sync in a usable manner
+ *
+ */
+int nm_spawn_process (char *args)
+{
+ gint num_args;
+ char **argv;
+ int exit_status;
+
+ g_return_val_if_fail (args != NULL, -1);
+
+ if (g_shell_parse_argv (args, &num_args, &argv, NULL))
+ {
+ if (g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, NULL))
+ {
+ g_strfreev (argv);
+ return (exit_status);
+ }
+ g_strfreev (argv);
+ }
+
+ return (-1);
+}
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 946af2ff2e..48508c969a 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -48,4 +48,6 @@ gboolean nm_ethernet_address_is_valid (struct ether_addr *test_addr);
void nm_dispose_scan_results (wireless_scan *result_list);
+int nm_spawn_process (char *args);
+
#endif