Make config file stuff somewhat clearer and easier to understand, and possibly easier to extend later. --- src/Makefile.am | 2 + src/main.c | 135 +++++-------------------- src/nm-config.c | 243 ++++++++++++++++++++++++++++++++++++++++++++ src/nm-config.h | 55 ++++++++++ src/settings/nm-settings.c | 22 ++-- src/settings/nm-settings.h | 2 +- 6 files changed, 335 insertions(+), 124 deletions(-) create mode 100644 src/nm-config.c create mode 100644 src/nm-config.h
diff --git a/src/Makefile.am b/src/Makefile.am index c8caefb..cbcfdc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -142,6 +142,8 @@ NetworkManager_SOURCES = \ nm-ip6-config.h \ nm-active-connection.h \ nm-active-connection.c \ + nm-config.h \ + nm-config.c \ main.c \ nm-policy.c \ nm-policy.h \ diff --git a/src/main.c b/src/main.c index a9ffd38..8d37bc9 100644 --- a/src/main.c +++ b/src/main.c @@ -50,14 +50,13 @@ #include "nm-vpn-manager.h" #include "nm-logging.h" #include "nm-policy-hosts.h" +#include "nm-config.h" #if !defined(NM_DIST_VERSION) # define NM_DIST_VERSION VERSION #endif #define NM_DEFAULT_PID_FILE LOCALSTATEDIR"/run/NetworkManager.pid" -#define NM_DEFAULT_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/NetworkManager.conf" -#define NM_OLD_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/nm-system-settings.conf" #define NM_DEFAULT_SYSTEM_STATE_FILE LOCALSTATEDIR"/lib/NetworkManager/NetworkManager.state" /* @@ -310,46 +309,6 @@ done: } static gboolean -parse_config_file (const char *filename, - char **plugins, - char **dhcp_client, - char ***dns_plugins, - char **log_level, - char **log_domains, - GError **error) -{ - GKeyFile *config; - gboolean success = FALSE; - - config = g_key_file_new (); - if (!config) { - g_set_error (error, 0, 0, - "Not enough memory to load config file."); - return FALSE; - } - - g_key_file_set_list_separator (config, ','); - if (!g_key_file_load_from_file (config, filename, G_KEY_FILE_NONE, error)) - goto out; - - *plugins = g_key_file_get_value (config, "main", "plugins", error); - if (*error) - goto out; - - *dhcp_client = g_key_file_get_value (config, "main", "dhcp", NULL); - *dns_plugins = g_key_file_get_string_list (config, "main", "dns", NULL, NULL); - - *log_level = g_key_file_get_value (config, "logging", "level", NULL); - *log_domains = g_key_file_get_value (config, "logging", "domains", NULL); - - success = TRUE; - -out: - g_key_file_free (config); - return success; -} - -static gboolean parse_state_file (const char *filename, gboolean *net_enabled, gboolean *wifi_enabled, @@ -469,10 +428,9 @@ main (int argc, char *argv[]) GOptionContext *opt_ctx = NULL; gboolean become_daemon = FALSE; gboolean g_fatal_warnings = FALSE; - char *pidfile = NULL, *state_file = NULL, *dhcp = NULL; - char *config = NULL, *plugins = NULL, *conf_plugins = NULL; + char *pidfile = NULL, *state_file = NULL; + char *config_path = NULL, *plugins = NULL; char *log_level = NULL, *log_domains = NULL; - char **dns = NULL; gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE, wimax_enabled = TRUE; gboolean success, show_version = FALSE; NMPolicy *policy = NULL; @@ -482,9 +440,9 @@ main (int argc, char *argv[]) NMSupplicantManager *sup_mgr = NULL; NMDHCPManager *dhcp_mgr = NULL; NMSettings *settings = NULL; + NMConfig *config; GError *error = NULL; gboolean wrote_pidfile = FALSE; - char *cfg_log_level = NULL, *cfg_log_domains = NULL; GOptionEntry options[] = { { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, "Print NetworkManager version and exit", NULL }, @@ -492,7 +450,7 @@ main (int argc, char *argv[]) { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL }, { "pid-file", 0, 0, G_OPTION_ARG_FILENAME, &pidfile, "Specify the location of a PID file", "filename" }, { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &state_file, "State file location", "/path/to/state.file" }, - { "config", 0, 0, G_OPTION_ARG_FILENAME, &config, "Config file location", "/path/to/config.file" }, + { "config", 0, 0, G_OPTION_ARG_FILENAME, &config_path, "Config file location", "/path/to/config.file" }, { "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, "List of plugins separated by ','", "plugin1,plugin2" }, { "log-level", 0, 0, G_OPTION_ARG_STRING, &log_level, "Log level: one of [ERR, WARN, INFO, DEBUG]", "INFO" }, { "log-domains", 0, 0, G_OPTION_ARG_STRING, &log_domains, @@ -554,58 +512,18 @@ main (int argc, char *argv[]) if (check_pidfile (pidfile)) exit (1); - /* Parse the config file */ - if (config) { - if (!parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error)) { - fprintf (stderr, "Config file %s invalid: (%d) %s\n", - config, - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); - exit (1); - } - } else { - gboolean parsed = FALSE; - - /* Even though we prefer NetworkManager.conf, we need to check the - * old nm-system-settings.conf first to preserve compat with older - * setups. In package managed systems dropping a NetworkManager.conf - * onto the system would make NM use it instead of nm-system-settings.conf, - * changing behavior during an upgrade. We don't want that. - */ - - /* Try deprecated nm-system-settings.conf first */ - if (g_file_test (NM_OLD_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) { - config = g_strdup (NM_OLD_SYSTEM_CONF_FILE); - parsed = parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error); - if (!parsed) { - fprintf (stderr, "Default config file %s invalid: (%d) %s\n", - config, - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); - g_free (config); - config = NULL; - g_clear_error (&error); - } - } - - /* Try the preferred NetworkManager.conf last */ - if (!parsed && g_file_test (NM_DEFAULT_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) { - config = g_strdup (NM_DEFAULT_SYSTEM_CONF_FILE); - parsed = parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error); - if (!parsed) { - fprintf (stderr, "Default config file %s invalid: (%d) %s\n", - config, - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); - g_free (config); - config = NULL; - g_clear_error (&error); - } - } + /* Read the config file and CLI overrides */ + config = nm_config_new (config_path, plugins, log_level, log_domains, &error); + if (config == NULL) { + fprintf (stderr, "Failed to read configuration: (%d) %s\n", + error ? error->code : -1, + (error && error->message) ? error->message : "unknown"); + exit (1); } + /* Logging setup */ - if (!nm_logging_setup (log_level ? log_level : cfg_log_level, - log_domains ? log_domains : cfg_log_domains, + if (!nm_logging_setup (nm_config_get_log_level (config), + nm_config_get_log_domains (config), &error)) { fprintf (stderr, _("%s. Please use --help to see a list of valid options.\n"), @@ -613,10 +531,6 @@ main (int argc, char *argv[]) exit (1); } - /* Plugins specified with '--plugins' override those of config file */ - plugins = plugins ? plugins : g_strdup (conf_plugins); - g_free (conf_plugins); - /* Parse the state file */ if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &wimax_enabled, &error)) { fprintf (stderr, "State file %s parsing failed: (%d) %s\n", @@ -683,8 +597,7 @@ main (int argc, char *argv[]) nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); success = FALSE; - if (config) - nm_log_info (LOGD_CORE, "Read config file %s", config); + nm_log_info (LOGD_CORE, "Read config file %s", nm_config_get_path (config)); main_loop = g_main_loop_new (NULL, FALSE); @@ -704,13 +617,15 @@ main (int argc, char *argv[]) goto done; } - dns_mgr = nm_dns_manager_get ((const char **) dns); + dns_mgr = nm_dns_manager_get (nm_config_get_dns_plugins (config)); if (!dns_mgr) { nm_log_err (LOGD_CORE, "failed to start the DNS manager."); goto done; } - settings = nm_settings_new (config, plugins, &error); + settings = nm_settings_new (nm_config_get_path (config), + nm_config_get_plugins (config), + &error); if (!settings) { nm_log_err (LOGD_CORE, "failed to initialize settings storage: %s", error && error->message ? error->message : "(unknown)"); @@ -744,7 +659,7 @@ main (int argc, char *argv[]) } /* Initialize DHCP manager */ - dhcp_mgr = nm_dhcp_manager_new (dhcp, &error); + dhcp_mgr = nm_dhcp_manager_new (nm_config_get_dhcp_client (config), &error); if (!dhcp_mgr) { nm_log_err (LOGD_CORE, "failed to start the DHCP manager: %s.", error->message); goto done; @@ -804,17 +719,15 @@ done: if (pidfile && wrote_pidfile) unlink (pidfile); + nm_config_free (config); + /* Free options */ g_free (pidfile); g_free (state_file); - g_free (config); + g_free (config_path); g_free (plugins); - g_free (dhcp); - g_strfreev (dns); g_free (log_level); g_free (log_domains); - g_free (cfg_log_level); - g_free (cfg_log_domains); nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error"); exit (success ? 0 : 1); diff --git a/src/nm-config.c b/src/nm-config.c new file mode 100644 index 0000000..f52f06f --- /dev/null +++ b/src/nm-config.c @@ -0,0 +1,243 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + */ + +#include <config.h> +#include <string.h> +#include <stdio.h> + +#include "nm-config.h" + +#define NM_DEFAULT_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/NetworkManager.conf" +#define NM_OLD_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/nm-system-settings.conf" + +struct NMConfig { + char *path; + char **plugins; + char *dhcp_client; + char **dns_plugins; + char *log_level; + char *log_domains; +}; + +/************************************************************************/ + +GQuark +nm_config_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-config-error"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_config_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* Not enough memory to parse the config file. */ + ENUM_ENTRY (NM_CONFIG_ERROR_NO_MEMORY, "NoMemory"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMConfigError", values); + } + return etype; +} + +/************************************************************************/ + +const char * +nm_config_get_path (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return config->path; +} + +const char ** +nm_config_get_plugins (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return (const char **) config->plugins; +} + +const char * +nm_config_get_dhcp_client (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return config->dhcp_client; +} + +const char ** +nm_config_get_dns_plugins (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return (const char **) config->dns_plugins; +} + +const char * +nm_config_get_log_level (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return config->log_level; +} + +const char * +nm_config_get_log_domains (NMConfig *config) +{ + g_return_val_if_fail (config != NULL, NULL); + + return config->log_domains; +} + +/************************************************************************/ + +static gboolean +fill_from_file (NMConfig *config, + const char *path, + const char *cli_plugins, + const char *cli_log_level, + const char *cli_log_domains, + GError **error) +{ + GKeyFile *kf; + gboolean success = FALSE; + + if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) { + g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND, "file not found"); + return FALSE; + } + + kf = g_key_file_new (); + if (!kf) { + g_set_error (error, NM_CONFIG_ERROR, NM_CONFIG_ERROR_NO_MEMORY, + "Not enough memory to load config file"); + return FALSE; + } + + g_key_file_set_list_separator (kf, ','); + if (g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, error)) { + config->path = g_strdup (path); + + /* CLI provided options override config file options */ + if (cli_plugins && strlen (cli_plugins)) + config->plugins = g_strsplit_set (cli_plugins, ",", 0); + else + config->plugins = g_key_file_get_string_list (kf, "main", "plugins", NULL, NULL); + + config->dhcp_client = g_key_file_get_value (kf, "main", "dhcp", NULL); + config->dns_plugins = g_key_file_get_string_list (kf, "main", "dns", NULL, NULL); + + if (cli_log_level && strlen (cli_log_level)) + config->log_level = g_strdup (cli_log_level); + else + config->log_level = g_key_file_get_value (kf, "logging", "level", NULL); + + if (cli_log_domains && strlen (cli_log_domains)) + config->log_domains = g_strdup (cli_log_domains); + else + config->log_domains = g_key_file_get_value (kf, "logging", "domains", NULL); + success = TRUE; + } + + g_key_file_free (kf); + return success; +} + +NMConfig * +nm_config_new (const char *cli_config_path, + const char *cli_plugins, + const char *cli_log_level, + const char *cli_log_domains, + GError **error) +{ + NMConfig *config; + GError *local = NULL; + + config = g_malloc0 (sizeof (*config)); + + if (cli_config_path) { + /* Bad user-specific config file path is a hard error */ + if (!fill_from_file (config, cli_config_path, cli_plugins, cli_log_level, cli_log_domains, error)) { + nm_config_free (config); + return NULL; + } + return config; + } + + /* Even though we prefer NetworkManager.conf, we need to check the + * old nm-system-settings.conf first to preserve compat with older + * setups. In package managed systems dropping a NetworkManager.conf + * onto the system would make NM use it instead of nm-system-settings.conf, + * changing behavior during an upgrade. We don't want that. + */ + + /* Try deprecated nm-system-settings.conf first */ + if (fill_from_file (config, NM_OLD_SYSTEM_CONF_FILE, cli_plugins, cli_log_level, cli_log_domains, &local)) + return config; + + if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) { + fprintf (stderr, "Default config file %s invalid: (%d) %s\n", + NM_OLD_SYSTEM_CONF_FILE, + local ? local->code : -1, + (local && local->message) ? local->message : "unknown"); + } + g_clear_error (&local); + + /* Try the standard config file location next */ + if (fill_from_file (config, NM_DEFAULT_SYSTEM_CONF_FILE, cli_plugins, cli_log_level, cli_log_domains, &local)) + return config; + + if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND) == FALSE) { + fprintf (stderr, "Default config file %s invalid: (%d) %s\n", + NM_DEFAULT_SYSTEM_CONF_FILE, + local ? local->code : -1, + (local && local->message) ? local->message : "unknown"); + } + + g_propagate_error (error, local); + return config; +} + +void +nm_config_free (NMConfig *config) +{ + g_return_if_fail (config != NULL); + + g_free (config->path); + g_strfreev (config->plugins); + g_free (config->dhcp_client); + g_strfreev (config->dns_plugins); + g_free (config->log_level); + g_free (config->log_domains); + + memset (config, 0, sizeof (*config)); + g_free (config); +} + diff --git a/src/nm-config.h b/src/nm-config.h new file mode 100644 index 0000000..fae344f --- /dev/null +++ b/src/nm-config.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2011 Red Hat, Inc. + */ + +#ifndef NM_CONFIG_H +#define NM_CONFIG_H + +#include <glib.h> +#include <glib-object.h> + +typedef struct NMConfig NMConfig; + +typedef enum { + NM_CONFIG_ERROR_NO_MEMORY = 0, +} NMConfigError; + +#define NM_CONFIG_ERROR (nm_config_error_quark ()) +GQuark nm_config_error_quark (void); +#define NM_TYPE_CONFIG_ERROR (nm_config_error_get_type ()) +GType nm_config_error_get_type (void); + + +NMConfig *nm_config_new (const char *cli_config_path, + const char *cli_plugins, + const char *cli_log_level, + const char *cli_log_domains, + GError **error); + +const char *nm_config_get_path (NMConfig *config); +const char **nm_config_get_plugins (NMConfig *config); +const char *nm_config_get_dhcp_client (NMConfig *config); +const char **nm_config_get_dns_plugins (NMConfig *config); +const char *nm_config_get_log_level (NMConfig *config); +const char *nm_config_get_log_domains (NMConfig *config); + +void nm_config_free (NMConfig *config); + +#endif /* NM_CONFIG_H */ + diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index cb094e9..f0bfc16 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -27,6 +27,7 @@ #include <unistd.h> #include <string.h> +#include <ctype.h> #include <gmodule.h> #include <net/ethernet.h> #include <netinet/ether.h> @@ -546,24 +547,23 @@ find_plugin (GSList *list, const char *pname) } static gboolean -load_plugins (NMSettings *self, const char *plugins, GError **error) +load_plugins (NMSettings *self, const char **plugins, GError **error) { GSList *list = NULL; - char **plist; - char **iter; + const char **iter; gboolean success = TRUE; - plist = g_strsplit (plugins, ",", 0); - if (!plist) - return FALSE; - - for (iter = plist; *iter; iter++) { + for (iter = plugins; *iter; iter++) { GModule *plugin; char *full_name, *path; - const char *pname = g_strstrip (*iter); + const char *pname = *iter; GObject *obj; GObject * (*factory_func) (void); + /* strip leading spaces */ + while (isblank (*pname)) + pname++; + /* keyfile plugin built in now */ if (!strcmp (pname, "keyfile")) continue; @@ -616,8 +616,6 @@ load_plugins (NMSettings *self, const char *plugins, GError **error) list = g_slist_append (list, obj); } - g_strfreev (plist); - g_slist_foreach (list, (GFunc) g_object_unref, NULL); g_slist_free (list); @@ -1494,7 +1492,7 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device) NMSettings * nm_settings_new (const char *config_file, - const char *plugins, + const char **plugins, GError **error) { NMSettings *self; diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 66d41cc..77485e1 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -77,7 +77,7 @@ typedef struct { GType nm_settings_get_type (void); NMSettings *nm_settings_new (const char *config_file, - const char *plugins, + const char **plugins, GError **error); typedef void (*NMSettingsForEachFunc) (NMSettings *settings, -- 1.7.6.2 _______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org http://mail.gnome.org/mailman/listinfo/networkmanager-list