From e18d04cf0fcea09debb5b219c574520c6ad00fd0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 26 Nov 2007 03:47:30 +0000 Subject: [PATCH] 2007-11-25 Dan Williams * system-settings/* - Rework structure and code to use GModule-loaded plugins and a plugin interface that plugins export to the system settings service git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3106 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 6 + configure.in | 3 + system-settings/Makefile.am | 42 +- system-settings/plugins/Makefile.am | 2 + system-settings/plugins/ifcfg/Makefile.am | 24 ++ .../{main.c => plugins/ifcfg/parser.c} | 282 +------------ system-settings/plugins/ifcfg/parser.h | 35 ++ system-settings/plugins/ifcfg/plugin.c | 191 +++++++++ system-settings/plugins/ifcfg/plugin.h | 50 +++ system-settings/{ => plugins/ifcfg}/shvar.c | 0 system-settings/{ => plugins/ifcfg}/shvar.h | 0 system-settings/src/Makefile.am | 43 ++ system-settings/{ => src}/dbus-settings.c | 0 system-settings/{ => src}/dbus-settings.h | 2 +- system-settings/src/main.c | 382 ++++++++++++++++++ .../src/nm-system-config-interface.c | 111 +++++ .../src/nm-system-config-interface.h | 77 ++++ .../{ => src}/nm-system-settings.conf | 0 18 files changed, 945 insertions(+), 305 deletions(-) create mode 100644 system-settings/plugins/Makefile.am create mode 100644 system-settings/plugins/ifcfg/Makefile.am rename system-settings/{main.c => plugins/ifcfg/parser.c} (56%) create mode 100644 system-settings/plugins/ifcfg/parser.h create mode 100644 system-settings/plugins/ifcfg/plugin.c create mode 100644 system-settings/plugins/ifcfg/plugin.h rename system-settings/{ => plugins/ifcfg}/shvar.c (100%) rename system-settings/{ => plugins/ifcfg}/shvar.h (100%) create mode 100644 system-settings/src/Makefile.am rename system-settings/{ => src}/dbus-settings.c (100%) rename system-settings/{ => src}/dbus-settings.h (98%) create mode 100644 system-settings/src/main.c create mode 100644 system-settings/src/nm-system-config-interface.c create mode 100644 system-settings/src/nm-system-config-interface.h rename system-settings/{ => src}/nm-system-settings.conf (100%) diff --git a/ChangeLog b/ChangeLog index 3228bd23bf..d6bbe6fdfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2007-11-25 Dan Williams + + * system-settings/* + - Rework structure and code to use GModule-loaded plugins and a plugin + interface that plugins export to the system settings service + 2007-11-21 Dan Williams * system-settings/* diff --git a/configure.in b/configure.in index 37e2fc9904..d2d687a8bf 100644 --- a/configure.in +++ b/configure.in @@ -274,6 +274,9 @@ libnm-glib/Makefile callouts/Makefile dispatcher-daemon/Makefile system-settings/Makefile +system-settings/src/Makefile +system-settings/plugins/Makefile +system-settings/plugins/ifcfg/Makefile test/Makefile test/test-common/Makefile initscript/Makefile diff --git a/system-settings/Makefile.am b/system-settings/Makefile.am index c2ec09b159..128b058a00 100644 --- a/system-settings/Makefile.am +++ b/system-settings/Makefile.am @@ -1,42 +1,2 @@ -INCLUDES = -I${top_srcdir} \ - -I${top_srcdir}/include \ - -I${top_srcdir}/libnm-util \ - -I${top_srcdir}/libnm-glib - -sbin_PROGRAMS = nm-system-settings - -nm_system_settings_SOURCES = \ - dbus-settings.c \ - dbus-settings.h \ - main.c \ - shvar.c \ - shvar.h - -nm_system_settings_CPPFLAGS = \ - $(DBUS_CFLAGS) \ - $(GTHREAD_CFLAGS) \ - -DDBUS_API_SUBJECT_TO_CHANGE \ - -DG_DISABLE_DEPRECATED \ - -DBINDIR=\"$(bindir)\" \ - -DSBINDIR=\"$(sbindir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DLOCALSTATEDIR=\"$(localstatedir)\" \ - -DNM_RUN_DIR=\"$(rundir)\" \ - -DGNOMELOCALEDIR=\"$(datadir)/locale\" - -nm_system_settings_LDADD = \ - $(DBUS_LIBS) \ - $(GTHREAD_LIBS) \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(top_builddir)/libnm-glib/libnm_glib.la - -nm_system_settings_LDFLAGS = -rdynamic - -dbusservicedir = $(DBUS_SYS_DIR) -dbusservice_DATA = nm-system-settings.conf - -EXTRA_DIST = \ - $(dbusservice_DATA) +SUBDIRS=src plugins diff --git a/system-settings/plugins/Makefile.am b/system-settings/plugins/Makefile.am new file mode 100644 index 0000000000..a0eb4d9e4e --- /dev/null +++ b/system-settings/plugins/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS=ifcfg + diff --git a/system-settings/plugins/ifcfg/Makefile.am b/system-settings/plugins/ifcfg/Makefile.am new file mode 100644 index 0000000000..a03730e3c5 --- /dev/null +++ b/system-settings/plugins/ifcfg/Makefile.am @@ -0,0 +1,24 @@ + +lib_LTLIBRARIES = libnm-settings-plugin-ifcfg.la + +libnm_settings_plugin_ifcfg_la_SOURCES = \ + shvar.c \ + shvar.h \ + parser.c \ + parser.h \ + plugin.c + +libnm_settings_plugin_ifcfg_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(GMODULE_CFLAGS) \ + -DG_DISABLE_DEPRECATED \ + -I${top_srcdir}/system-settings/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/libnm-util \ + -DSYSCONFDIR=\"$(sysconfdir)\" + +libnm_settings_plugin_ifcfg_la_LIBADD = \ + $(GLIB_LIBS) \ + $(GMODULE_LIBS) \ + $(top_builddir)/libnm-util/libnm-util.la + diff --git a/system-settings/main.c b/system-settings/plugins/ifcfg/parser.c similarity index 56% rename from system-settings/main.c rename to system-settings/plugins/ifcfg/parser.c index 72ea8ea569..e504b7c0c9 100644 --- a/system-settings/main.c +++ b/system-settings/plugins/ifcfg/parser.c @@ -27,39 +27,32 @@ #include -#include -#include - #include -#include #include #include #include #include -#include "dbus-settings.h" #include "shvar.h" +#include "parser.h" +#include "plugin.h" -#define SYSCONFDIR "/etc" -#define PROFILE_DIR SYSCONFDIR "/sysconfig/networking/profiles/" - -typedef struct Application +char * +parser_get_current_profile_name (void) { - DBusConnection *connection; - DBusGConnection *g_connection; - DBusGProxy *bus_proxy; - gboolean started; + shvarFile * file; + char * buf; - NMSysconfigSettings *settings; - char *profile_path; - GMainLoop *loop; -} Application; + if (!(file = svNewFile (SYSCONFDIR"/sysconfig/network"))) + return NULL; + buf = svGetValue (file, "CURRENT_PROFILE"); + if (!buf) + buf = strdup ("default"); + svCloseFile (file); -static gboolean dbus_init (Application *app); -static void dbus_cleanup (Application *app); -static gboolean start_dbus_service (Application *app); -static void destroy_cb (DBusGProxy *proxy, gpointer user_data); + return buf; +} static gboolean get_int (const char *str, int *value) @@ -73,9 +66,6 @@ get_int (const char *str, int *value) return TRUE; } -#define IFCFG_TAG "ifcfg-" -#define BAK_TAG ".bak" - static NMSetting * make_connection_setting (const char *file, shvarFile *ifcfg, const char *type) { @@ -111,23 +101,6 @@ error: return NULL; } -static char * -get_current_profile_name (void) -{ - shvarFile * file; - char * buf; - - if (!(file = svNewFile (SYSCONFDIR"/sysconfig/network"))) - return NULL; - - buf = svGetValue (file, "CURRENT_PROFILE"); - if (!buf) - buf = strdup ("default"); - svCloseFile (file); - - return buf; -} - #define SEARCH_TAG "search " #define NS_TAG "nameserver " @@ -140,7 +113,7 @@ read_profile_resolv_conf (NMSettingIP4Config *s_ip4) char **lines = NULL; char **line; - profile = get_current_profile_name (); + profile = parser_get_current_profile_name (); if (!profile) return; @@ -323,18 +296,15 @@ error: return NULL; } -static NMSysconfigConnectionSettings * -parse_file (Application *app, - const char *file, - char **err) +NMConnection * +parser_parse_file (const char *file, + char **err) { - NMSysconfigConnectionSettings *sys_connection = NULL; NMConnection *connection = NULL; shvarFile *parsed; char *type; char *nmc = NULL; - g_return_val_if_fail (app != NULL, NULL); g_return_val_if_fail (file != NULL, NULL); parsed = svNewFile(file); @@ -377,224 +347,10 @@ parse_file (Application *app, s_ip4 = make_ip4_setting (parsed); if (s_ip4) nm_connection_add_setting (connection, s_ip4); - -nm_connection_dump (connection); - sys_connection = nm_sysconfig_connection_settings_new (connection, app->g_connection); } done: svCloseFile (parsed); - return sys_connection; -} - -static gboolean -parse_files (gpointer data) -{ - Application *app = data; - gboolean added = FALSE; - GDir *dir; - const char *item; - - dir = g_dir_open (app->profile_path, 0, NULL); - if (!dir) { - g_warning ("Couldn't access network profile directory '%s'.", app->profile_path); - goto out; - } - - while ((item = g_dir_read_name (dir))) { - NMSysconfigConnectionSettings *connection; - char *err = NULL; - char *filename; - - if (strncmp (item, IFCFG_TAG, strlen (IFCFG_TAG))) - continue; - - filename = g_build_filename (app->profile_path, item, NULL); - if (!filename) - continue; - - g_print ("Parsing %s ... \n", filename); - - if ((connection = parse_file (app, filename, &err))) { - NMSettingConnection *s_con; - - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection->connection, NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); - g_assert (s_con->id); - - g_print (" adding connection '%s'\n", s_con->id); - nm_sysconfig_settings_add_connection (app->settings, connection); - added = TRUE; - } else { - g_print (" error: %s\n", err ? err : "(unknown)"); - } - - g_free (filename); - } - g_dir_close (dir); - -out: - if (!added) { - g_print ("Warning: No useable configurations found\n"); - g_main_loop_quit (app->loop); - } - - return FALSE; -} - -/* ------------------------------------------------------------------------- */ - -static gboolean -dbus_reconnect (gpointer user_data) -{ - Application *app = (Application *) user_data; - - if (dbus_init (app)) { - if (start_dbus_service (app)) { - g_message ("reconnected to the system bus."); - return TRUE; - } - } - - dbus_cleanup (app); - return FALSE; -} - -static void -dbus_cleanup (Application *app) -{ - if (app->g_connection) { - dbus_g_connection_unref (app->g_connection); - app->g_connection = NULL; - app->connection = NULL; - } - - if (app->bus_proxy) { - g_signal_handlers_disconnect_by_func (app->bus_proxy, destroy_cb, app); - g_object_unref (app->bus_proxy); - app->bus_proxy = NULL; - } - - app->started = FALSE; -} - -static void -destroy_cb (DBusGProxy *proxy, gpointer user_data) -{ - Application *app = (Application *) user_data; - - /* Clean up existing connection */ - g_warning ("disconnected by the system bus."); - dbus_cleanup (app); - - g_timeout_add (3000, dbus_reconnect, app); -} - -static gboolean -start_dbus_service (Application *app) -{ - int request_name_result; - GError *err = NULL; - - if (app->started) { - g_warning ("Service has already started."); - return FALSE; - } - - if (!dbus_g_proxy_call (app->bus_proxy, "RequestName", &err, - G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS, - G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE, - G_TYPE_INVALID, - G_TYPE_UINT, &request_name_result, - G_TYPE_INVALID)) { - g_warning ("Could not acquire the NetworkManagerSystemSettings service.\n" - " Message: '%s'", err->message); - g_error_free (err); - goto out; - } - - if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - g_warning ("Could not acquire the NetworkManagerSystemSettings service " - "as it is already taken. Return: %d", - request_name_result); - goto out; - } - - app->started = TRUE; - -out: - if (!app->started) - dbus_cleanup (app); - - return app->started; -} - -static gboolean -dbus_init (Application *app) -{ - GError *err = NULL; - - dbus_connection_set_change_sigpipe (TRUE); - - app->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); - if (!app->g_connection) { - g_warning ("Could not get the system bus. Make sure " - "the message bus daemon is running! Message: %s", - err->message); - g_error_free (err); - return FALSE; - } - - app->connection = dbus_g_connection_get_connection (app->g_connection); - dbus_connection_set_exit_on_disconnect (app->connection, FALSE); - - app->bus_proxy = dbus_g_proxy_new_for_name (app->g_connection, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus"); - if (!app->bus_proxy) { - g_warning ("Could not get the DBus object!"); - goto error; - } - - g_signal_connect (app->bus_proxy, "destroy", G_CALLBACK (destroy_cb), app); - return TRUE; - -error: - dbus_cleanup (app); - return FALSE; -} - -int -main (int argc, char **argv) -{ - Application *app = g_new0 (Application, 1); - char *profile; - - g_type_init (); - - profile = get_current_profile_name (); - app->profile_path = g_strdup_printf (PROFILE_DIR "%s/", profile); - if (!app->profile_path) { - g_warning ("Current network profile directory '%s' not found.", profile); - g_free (profile); - return 1; - } - g_free (profile); - - app->loop = g_main_loop_new (NULL, FALSE); - - if (!dbus_init (app)) - return -1; - - if (!start_dbus_service (app)) - return -1; - - app->settings = nm_sysconfig_settings_new (app->g_connection); - g_idle_add (parse_files, app); - - g_main_loop_run (app->loop); - - return 0; + return connection; } diff --git a/system-settings/plugins/ifcfg/parser.h b/system-settings/plugins/ifcfg/parser.h new file mode 100644 index 0000000000..cce32935c7 --- /dev/null +++ b/system-settings/plugins/ifcfg/parser.h @@ -0,0 +1,35 @@ +/* NetworkManager system settings service + * + * Søren Sandmann + * + * 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, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2007 Red Hat, Inc. + */ + +#ifndef _PARSER_H_ +#define _PARSER_H_ + +#include + +#define IFCFG_TAG "ifcfg-" +#define BAK_TAG ".bak" + + +NMConnection * parser_parse_file (const char *file, char **err); + +char * parser_get_current_profile_name (void); + +#endif /* _PARSER_H_ */ diff --git a/system-settings/plugins/ifcfg/plugin.c b/system-settings/plugins/ifcfg/plugin.c new file mode 100644 index 0000000000..bcebacf27f --- /dev/null +++ b/system-settings/plugins/ifcfg/plugin.c @@ -0,0 +1,191 @@ +/* NetworkManager system settings service + * + * Søren Sandmann + * + * 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, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2007 Red Hat, Inc. + */ + +#include +#include +#include +#include + +#include + +#include "plugin.h" +#include "parser.h" +#include "nm-system-config-interface.h" + +#define IFCFG_PLUGIN_NAME "ifcfg" +#define IFCFG_PLUGIN_INFO "(C) 2007 Red Hat, Inc. To report bugs please use the NetworkManager mailing list." + +static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); + +G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, + system_config_interface_init)) + +#define SC_PLUGIN_IFCFG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfgPrivate)) + + +typedef struct { + GSList *connections; +} SCPluginIfcfgPrivate; + + +#define PROFILE_DIR SYSCONFDIR "/sysconfig/networking/profiles/" + +static gboolean +parse_files (gpointer data) +{ + SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (data); + SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + char *profile = NULL; + char *profile_path = NULL; + gboolean added = FALSE; + GDir *dir; + const char *item; + + profile = parser_get_current_profile_name (); + profile_path = g_strdup_printf (PROFILE_DIR "%s/", profile); + if (!profile_path) { + PLUGIN_WARN (PLUGIN_NAME, "current network profile directory '%s' not found.", profile); + goto out; + } + g_free (profile); + + dir = g_dir_open (profile_path, 0, NULL); + if (!dir) { + PLUGIN_WARN (PLUGIN_NAME, "couldn't access network profile directory '%s'.", profile_path); + goto out; + } + + while ((item = g_dir_read_name (dir))) { + NMConnection *connection; + char *err = NULL; + char *filename; + + if (strncmp (item, IFCFG_TAG, strlen (IFCFG_TAG))) + continue; + + filename = g_build_filename (profile_path, item, NULL); + if (!filename) + continue; + + PLUGIN_PRINT (PLUGIN_NAME, "parsing %s ... ", filename); + + if ((connection = parser_parse_file (filename, &err))) { + NMSettingConnection *s_con; + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + g_assert (s_con); + g_assert (s_con->id); + priv->connections = g_slist_append (priv->connections, connection); + PLUGIN_PRINT (PLUGIN_NAME, " added connection '%s'", s_con->id); + g_signal_emit_by_name (NM_SYSTEM_CONFIG_INTERFACE (plugin), + "connection-added", + connection); + added = TRUE; + } else { + PLUGIN_PRINT (PLUGIN_NAME, " error: %s", err ? err : "(unknown)"); + } + + g_free (filename); + } + g_dir_close (dir); + +out: + g_free (profile_path); + return FALSE; +} + +static void +sc_plugin_ifcfg_init (SCPluginIfcfg *plugin) +{ +} + +static void +dispose (GObject *object) +{ + G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME: + g_value_set_string (value, IFCFG_PLUGIN_NAME); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO: + g_value_set_string (value, IFCFG_PLUGIN_INFO); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +sc_plugin_ifcfg_class_init (SCPluginIfcfgClass *req_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (req_class); + + g_type_class_add_private (req_class, sizeof (SCPluginIfcfgPrivate)); + + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME, + NM_SYSTEM_CONFIG_INTERFACE_NAME); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, + NM_SYSTEM_CONFIG_INTERFACE_INFO); +} + +static void +system_config_interface_init (NMSystemConfigInterface *system_config_interface_class) +{ + /* interface implementation */ +} + +G_MODULE_EXPORT GObject * +nm_system_config_factory (void) +{ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + static SCPluginIfcfg *singleton = NULL; + + g_static_mutex_lock (&mutex); + if (!singleton) { + singleton = SC_PLUGIN_IFCFG (g_object_new (SC_TYPE_PLUGIN_IFCFG, NULL)); + g_idle_add (parse_files, singleton); + } + g_object_ref (singleton); + g_static_mutex_unlock (&mutex); + + return G_OBJECT (singleton); +} diff --git a/system-settings/plugins/ifcfg/plugin.h b/system-settings/plugins/ifcfg/plugin.h new file mode 100644 index 0000000000..2698cfc123 --- /dev/null +++ b/system-settings/plugins/ifcfg/plugin.h @@ -0,0 +1,50 @@ +/* NetworkManager system settings service + * + * Søren Sandmann + * + * 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, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2007 Red Hat, Inc. + */ + +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + +#include + +#define PLUGIN_NAME "ifcfg" + +#define SC_TYPE_PLUGIN_IFCFG (sc_plugin_ifcfg_get_type ()) +#define SC_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfg)) +#define SC_PLUGIN_IFCFG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfgClass)) +#define SC_IS_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_PLUGIN_IFCFG)) +#define SC_IS_PLUGIN_IFCFG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SC_TYPE_PLUGIN_IFCFG)) +#define SC_PLUGIN_IFCFG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfgClass)) + +typedef struct _SCPluginIfcfg SCPluginIfcfg; +typedef struct _SCPluginIfcfgClass SCPluginIfcfgClass; + +struct _SCPluginIfcfg { + GObject parent; +}; + +struct _SCPluginIfcfgClass { + GObjectClass parent; +}; + +GType sc_plugin_ifcfg_get_type (void); + +#endif /* _PLUGIN_H_ */ + diff --git a/system-settings/shvar.c b/system-settings/plugins/ifcfg/shvar.c similarity index 100% rename from system-settings/shvar.c rename to system-settings/plugins/ifcfg/shvar.c diff --git a/system-settings/shvar.h b/system-settings/plugins/ifcfg/shvar.h similarity index 100% rename from system-settings/shvar.h rename to system-settings/plugins/ifcfg/shvar.h diff --git a/system-settings/src/Makefile.am b/system-settings/src/Makefile.am new file mode 100644 index 0000000000..dc7ea24cf9 --- /dev/null +++ b/system-settings/src/Makefile.am @@ -0,0 +1,43 @@ +INCLUDES = -I${top_srcdir} \ + -I${top_srcdir}/include \ + -I${top_srcdir}/libnm-util \ + -I${top_srcdir}/libnm-glib + +sbin_PROGRAMS = nm-system-settings + +nm_system_settings_SOURCES = \ + dbus-settings.c \ + dbus-settings.h \ + main.c \ + nm-system-config-interface.c \ + nm-system-config-interface.h + +nm_system_settings_CPPFLAGS = \ + $(DBUS_CFLAGS) \ + $(GTHREAD_CFLAGS) \ + $(GMODULE_CFLAGS) \ + -DDBUS_API_SUBJECT_TO_CHANGE \ + -DG_DISABLE_DEPRECATED \ + -DBINDIR=\"$(bindir)\" \ + -DSBINDIR=\"$(sbindir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DDATADIR=\"$(datadir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DLOCALSTATEDIR=\"$(localstatedir)\" \ + -DGNOMELOCALEDIR=\"$(datadir)/locale\" + +nm_system_settings_LDADD = \ + $(DBUS_LIBS) \ + $(GTHREAD_LIBS) \ + $(GMODULE_LIBS) \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(top_builddir)/libnm-glib/libnm_glib.la + +nm_system_settings_LDFLAGS = -rdynamic + +dbusservicedir = $(DBUS_SYS_DIR) +dbusservice_DATA = nm-system-settings.conf + +EXTRA_DIST = \ + $(dbusservice_DATA) + diff --git a/system-settings/dbus-settings.c b/system-settings/src/dbus-settings.c similarity index 100% rename from system-settings/dbus-settings.c rename to system-settings/src/dbus-settings.c diff --git a/system-settings/dbus-settings.h b/system-settings/src/dbus-settings.h similarity index 98% rename from system-settings/dbus-settings.h rename to system-settings/src/dbus-settings.h index 327cffe41c..eb0c43234c 100644 --- a/system-settings/dbus-settings.h +++ b/system-settings/src/dbus-settings.h @@ -49,7 +49,7 @@ struct _NMSysconfigConnectionSettingsClass NMConnectionSettingsClass parent_class; }; -GType nm_sysconfig_connection_settings_get_type (void); +GType nm_sysconfig_connection_settings_get_type (void); NMSysconfigConnectionSettings *nm_sysconfig_connection_settings_new (NMConnection *connection, DBusGConnection *g_conn); diff --git a/system-settings/src/main.c b/system-settings/src/main.c new file mode 100644 index 0000000000..5d72bc62bc --- /dev/null +++ b/system-settings/src/main.c @@ -0,0 +1,382 @@ +/* NetworkManager system settings service + * + * Søren Sandmann + * Dan Williams + * + * 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, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2007 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "dbus-settings.h" +#include "nm-system-config-interface.h" + +typedef struct Application +{ + DBusConnection *connection; + DBusGConnection *g_connection; + DBusGProxy *bus_proxy; + gboolean started; + + NMSysconfigSettings *settings; + GMainLoop *loop; + + GHashTable *plugins; +} Application; + + +static gboolean dbus_init (Application *app); +static void dbus_cleanup (Application *app); +static gboolean start_dbus_service (Application *app); +static void destroy_cb (DBusGProxy *proxy, gpointer user_data); + + +static GQuark +plugins_error_quark (void) +{ + static GQuark error_quark = 0; + + if (G_UNLIKELY (error_quark == 0)) + error_quark = g_quark_from_static_string ("plugins-error-quark"); + + return error_quark; +} + +static void +connection_added_cb (NMSystemConfigInterface *config, + NMConnection *connection, + Application *app) +{ + NMSysconfigConnectionSettings *exported; + + exported = nm_sysconfig_connection_settings_new (connection, app->g_connection); + if (!exported) { + g_warning ("%s: couldn't export the connection!", __func__); + return; + } + nm_sysconfig_settings_add_connection (app->settings, exported); +} + +static void +connection_removed_cb (NMSystemConfigInterface *config, + NMConnection *connection, + Application *app) +{ +} + +static void +connection_updated_cb (NMSystemConfigInterface *config, + NMConnection *connection, + Application *app) +{ +} + +static void +register_plugin (Application *app, NMSystemConfigInterface *plugin) +{ + g_signal_connect (plugin, "connection-added", (GCallback) connection_added_cb, app); + g_signal_connect (plugin, "connection-removed", (GCallback) connection_removed_cb, app); + g_signal_connect (plugin, "connection-updated", (GCallback) connection_updated_cb, app); +} + +static GHashTable * +load_plugins (Application *app, const char *plugins, GError **error) +{ + GHashTable *table; + char **plist; + char **pname; + + plist = g_strsplit (plugins, ",", 0); + if (!plist) + return NULL; + + table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + + for (pname = plist; *pname; pname++) { + GModule *plugin; + char *full_name; + char *path; + GObject *obj; + GObject * (*factory_func) (void); + + obj = g_hash_table_lookup (table, *pname); + if (obj) + continue; + + full_name = g_strdup_printf ("nm-settings-plugin-%s", *pname); + path = g_module_build_path (NULL, full_name); + + plugin = g_module_open (path, G_MODULE_BIND_LOCAL); + if (!plugin) { + g_set_error (error, plugins_error_quark (), 0, + "Could not find plugin '%s' as %s!", + *pname, path); + g_free (full_name); + g_free (path); + break; + } + + g_free (full_name); + g_free (path); + + if (!g_module_symbol (plugin, "nm_system_config_factory", (gpointer) (&factory_func))) { + g_set_error (error, plugins_error_quark (), 0, + "Could not find plugin '%s' factory function.", + *pname); + break; + } + + obj = (*factory_func) (); + if (!obj || !NM_IS_SYSTEM_CONFIG_INTERFACE (obj)) { + g_set_error (error, plugins_error_quark (), 0, + "Plugin '%s' returned invalid system config object.", + *pname); + break; + } + + g_module_make_resident (plugin); + g_object_set_data_full (obj, "plugin", plugin, (GDestroyNotify) g_module_close); + register_plugin (app, NM_SYSTEM_CONFIG_INTERFACE (obj)); + g_hash_table_insert (table, g_strdup (*pname), obj); + } + + g_strfreev (plist); + return table; +} + +static void +print_plugin_info (gpointer key, gpointer data, gpointer user_data) +{ + NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (data); + char *pname; + char *pinfo; + + g_object_get (G_OBJECT (plugin), + NM_SYSTEM_CONFIG_INTERFACE_NAME, + &pname, + NULL); + + g_object_get (G_OBJECT (plugin), + NM_SYSTEM_CONFIG_INTERFACE_INFO, + &pinfo, + NULL); + + g_print (" %s: %s\n", pname, pinfo); + g_free (pname); + g_free (pinfo); +} + +static gboolean +dbus_reconnect (gpointer user_data) +{ + Application *app = (Application *) user_data; + + if (dbus_init (app)) { + if (start_dbus_service (app)) { + g_message ("reconnected to the system bus."); + return TRUE; + } + } + + dbus_cleanup (app); + return FALSE; +} + +static void +dbus_cleanup (Application *app) +{ + if (app->g_connection) { + dbus_g_connection_unref (app->g_connection); + app->g_connection = NULL; + app->connection = NULL; + } + + if (app->bus_proxy) { + g_signal_handlers_disconnect_by_func (app->bus_proxy, destroy_cb, app); + g_object_unref (app->bus_proxy); + app->bus_proxy = NULL; + } + + app->started = FALSE; +} + +static void +destroy_cb (DBusGProxy *proxy, gpointer user_data) +{ + Application *app = (Application *) user_data; + + /* Clean up existing connection */ + g_warning ("disconnected by the system bus."); + dbus_cleanup (app); + + g_timeout_add (3000, dbus_reconnect, app); +} + +static gboolean +start_dbus_service (Application *app) +{ + int request_name_result; + GError *err = NULL; + + if (app->started) { + g_warning ("Service has already started."); + return FALSE; + } + + if (!dbus_g_proxy_call (app->bus_proxy, "RequestName", &err, + G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS, + G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE, + G_TYPE_INVALID, + G_TYPE_UINT, &request_name_result, + G_TYPE_INVALID)) { + g_warning ("Could not acquire the NetworkManagerSystemSettings service.\n" + " Message: '%s'", err->message); + g_error_free (err); + goto out; + } + + if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_warning ("Could not acquire the NetworkManagerSystemSettings service " + "as it is already taken. Return: %d", + request_name_result); + goto out; + } + + app->started = TRUE; + +out: + if (!app->started) + dbus_cleanup (app); + + return app->started; +} + +static gboolean +dbus_init (Application *app) +{ + GError *err = NULL; + + dbus_connection_set_change_sigpipe (TRUE); + + app->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + if (!app->g_connection) { + g_warning ("Could not get the system bus. Make sure " + "the message bus daemon is running! Message: %s", + err->message); + g_error_free (err); + return FALSE; + } + + app->connection = dbus_g_connection_get_connection (app->g_connection); + dbus_connection_set_exit_on_disconnect (app->connection, FALSE); + + app->bus_proxy = dbus_g_proxy_new_for_name (app->g_connection, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"); + if (!app->bus_proxy) { + g_warning ("Could not get the DBus object!"); + goto error; + } + + g_signal_connect (app->bus_proxy, "destroy", G_CALLBACK (destroy_cb), app); + return TRUE; + +error: + dbus_cleanup (app); + return FALSE; +} + +int +main (int argc, char **argv) +{ + Application *app = g_new0 (Application, 1); + GOptionContext *opt_ctx; + GError *error = NULL; + char *plugins = NULL; + + GOptionEntry entries[] = { + { "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, "List of plugins separated by ,", "plugin1,plugin2" }, + { NULL } + }; + + opt_ctx = g_option_context_new (NULL); + g_option_context_set_summary (opt_ctx, "Provides system network settings to NetworkManager."); + g_option_context_add_main_entries (opt_ctx, entries, NULL); + + if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) { + g_warning ("%s\n", error->message); + g_error_free (error); + return 1; + } + + g_option_context_free (opt_ctx); + + if (!plugins) { + g_warning ("'plugins' argument is required."); + return 1; + } + + g_type_init (); + + if (!g_module_supported ()) { + g_warning ("GModules are not supported on your platform!"); + return 1; + } + + app->loop = g_main_loop_new (NULL, FALSE); + + if (!dbus_init (app)) + return -1; + + if (!start_dbus_service (app)) + return -1; + + app->settings = nm_sysconfig_settings_new (app->g_connection); + + /* Load the plugins; fail if a plugin is not found. */ + app->plugins = load_plugins (app, plugins, &error); + if (error) { + g_hash_table_destroy (app->plugins); + g_warning ("Error: %d - %s", error->code, error->message); + return -1; + } + g_free (plugins); + g_print ("Loaded plugins:\n"); + g_hash_table_foreach (app->plugins, print_plugin_info, NULL); + g_print ("\n"); + + g_main_loop_run (app->loop); + + return 0; +} + diff --git a/system-settings/src/nm-system-config-interface.c b/system-settings/src/nm-system-config-interface.c new file mode 100644 index 0000000000..5b929bc2a7 --- /dev/null +++ b/system-settings/src/nm-system-config-interface.c @@ -0,0 +1,111 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * 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, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2007 Red Hat, Inc. + */ + +#include "nm-system-config-interface.h" + +static void +nm_system_config_interface_init (gpointer g_iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Properties */ + g_object_interface_install_property + (g_iface, + g_param_spec_string (NM_SYSTEM_CONFIG_INTERFACE_NAME, + "Name", + "Plugin name", + NULL, + G_PARAM_READABLE)); + + g_object_interface_install_property + (g_iface, + g_param_spec_string (NM_SYSTEM_CONFIG_INTERFACE_INFO, + "Info", + "Plugin information", + NULL, + G_PARAM_READABLE)); + + /* Signals */ + g_signal_new ("connection-added", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSystemConfigInterface, connection_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + g_signal_new ("connection-removed", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSystemConfigInterface, connection_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + g_signal_new ("connection-updated", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSystemConfigInterface, connection_updated), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + initialized = TRUE; +} + + +GType +nm_system_config_interface_get_type (void) +{ + static GType system_config_interface_type = 0; + + if (!system_config_interface_type) { + const GTypeInfo system_config_interface_info = { + sizeof (NMSystemConfigInterface), /* class_size */ + nm_system_config_interface_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + system_config_interface_type = g_type_register_static (G_TYPE_INTERFACE, + "NMSystemConfigInterface", + &system_config_interface_info, + 0); + + g_type_interface_add_prerequisite (system_config_interface_type, G_TYPE_OBJECT); + } + + return system_config_interface_type; +} + diff --git a/system-settings/src/nm-system-config-interface.h b/system-settings/src/nm-system-config-interface.h new file mode 100644 index 0000000000..7cbfc21eef --- /dev/null +++ b/system-settings/src/nm-system-config-interface.h @@ -0,0 +1,77 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * 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, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2007 Red Hat, Inc. + */ + +#ifndef NM_SYSTEM_CONFIG_INTERFACE_H +#define NM_SYSTEM_CONFIG_INTERFACE_H + +#include +#include +#include + +G_BEGIN_DECLS + +#define PLUGIN_PRINT(pname, fmt, args...) \ + { g_print (" " pname ": " fmt "\n", ##args); } + +#define PLUGIN_WARN(pname, fmt, args...) \ + { g_warning (" " pname ": " fmt, ##args); } + + +/* Plugin's factory function that returns a GObject that implements + * NMSystemConfigInterface. + */ +GObject * nm_system_config_factory (void); + + +#define NM_TYPE_SYSTEM_CONFIG_INTERFACE (nm_system_config_interface_get_type ()) +#define NM_SYSTEM_CONFIG_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE, NMSystemConfigInterface)) +#define NM_IS_SYSTEM_CONFIG_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE)) +#define NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE, NMSystemConfigInterface)) + + +#define NM_SYSTEM_CONFIG_INTERFACE_NAME "name" +#define NM_SYSTEM_CONFIG_INTERFACE_INFO "info" + +typedef enum { + NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST = 0x1000, + + NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME = NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST, + NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, +} NMSystemConfigInterfaceProp; + + +typedef struct _NMSystemConfigInterface NMSystemConfigInterface; + +struct _NMSystemConfigInterface { + GTypeInterface g_iface; + + /* Signals */ + void (*connection_added) (NMSystemConfigInterface *config, NMConnection *connection); + void (*connection_removed) (NMSystemConfigInterface *config, NMConnection *connection); + void (*connection_updated) (NMSystemConfigInterface *config, NMConnection *connection); +}; + +GType nm_system_config_interface_get_type (void); + + +G_END_DECLS + +#endif /* NM_SYSTEM_CONFIG_INTERFACE_H */ diff --git a/system-settings/nm-system-settings.conf b/system-settings/src/nm-system-settings.conf similarity index 100% rename from system-settings/nm-system-settings.conf rename to system-settings/src/nm-system-settings.conf