Exemplo n.º 1
0
/*
 * main
 *
 */
int
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 *log_level = NULL, *log_domains = NULL;
	char **dns = NULL;
	gboolean success;
	BMPolicy *policy = NULL;
	BMDBusManager *dbus_mgr = NULL;
	GError *error = NULL;
	gboolean wrote_pidfile = FALSE;
	char *cfg_log_level = NULL, *cfg_log_domains = NULL;

	GOptionEntry options[] = {
		{ "no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL },
		{ "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" },
		{ "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,
		        "Log domains separated by ',': any combination of [NONE,HW,BT,USER_SET,SYS_SET,SUSPEND,CORE,DEVICE]",
		        "HW" },
		{NULL}
	};

	if (getuid () != 0) {
		fprintf (stderr, "You must be root to run BarcodeManager!\n");
		exit (1);
	}

	if (!g_module_supported ()) {
		fprintf (stderr, "GModules are not supported on your platform!\n");
		exit (1);
	}

	bindtextdomain (GETTEXT_PACKAGE, BMLOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

	/* Parse options */
	opt_ctx = g_option_context_new ("");
	g_option_context_set_translation_domain (opt_ctx, "UTF-8");
	g_option_context_set_ignore_unknown_options (opt_ctx, FALSE);
	g_option_context_set_help_enabled (opt_ctx, TRUE);
	g_option_context_add_main_entries (opt_ctx, options, NULL);

	g_option_context_set_summary (opt_ctx,
		"BarcodeManager monitors all barcode scanners automatically.");

	success = g_option_context_parse (opt_ctx, &argc, &argv, NULL);
	g_option_context_free (opt_ctx);

	if (!success) {
		fprintf (stderr, _("Invalid option.  Please use --help to see a list of valid options.\n"));
		exit (1);
	}

	/* Make GIO ignore the remote VFS service; otherwise it tries to use the
	 * session bus to contact the remote service, and NM shouldn't ever be
	 * talking on the session bus.  See rh #588745
	 */
	setenv ("GIO_USE_VFS", "local", 1);

	pidfile = pidfile ? pidfile : g_strdup (BM_DEFAULT_PID_FILE);
	state_file = state_file ? state_file : g_strdup (BM_DEFAULT_SYSTEM_STATE_FILE);

	/* check pid file */
	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 BarcodeManager.conf, we need to check the
		 * old bm-system-settings.conf first to preserve compat with older
		 * setups.  In package managed systems dropping a BarcodeManager.conf
		 * onto the system would make NM use it instead of bm-system-settings.conf,
		 * changing behavior during an upgrade.  We don't want that.
		 */

		/* Try deprecated bm-system-settings.conf first */
		if (g_file_test (BM_OLD_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) {
			config = g_strdup (BM_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 BarcodeManager.conf last */
		if (!parsed && g_file_test (BM_DEFAULT_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) {
			config = g_strdup (BM_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);
			}
		}
	}
	/* Logging setup */
	if (!bm_logging_setup (log_level ? log_level : cfg_log_level,
	                       log_domains ? log_domains : cfg_log_domains,
	                       &error)) {
		fprintf (stderr,
		         _("%s.  Please use --help to see a list of valid options.\n"),
		         error->message);
		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, &error)) {
		fprintf (stderr, "State file %s parsing failed: (%d) %s\n",
		         state_file,
		         error ? error->code : -1,
		         (error && error->message) ? error->message : "unknown");
		/* Not a hard failure */
	}
	g_clear_error (&error);

	/* Tricky: become_daemon is FALSE by default, so unless it's TRUE because
	 * of a CLI option, it'll become TRUE after this
	 */
	become_daemon = !become_daemon;
	if (become_daemon) {
		if (daemon (0, 0) < 0) {
			int saved_errno;

			saved_errno = errno;
			fprintf (stderr, "Could not daemonize: %s [error %u]\n",
			         g_strerror (saved_errno),
			         saved_errno);
			exit (1);
		}
		if (write_pidfile (pidfile))
			wrote_pidfile = TRUE;
	}

	if (g_fatal_warnings) {
		GLogLevelFlags fatal_mask;

		fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
		fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
		g_log_set_always_fatal (fatal_mask);
	}

	/*
	 * Set the umask to 0022, which results in 0666 & ~0022 = 0644.
	 * Otherwise, if root (or an su'ing user) has a wacky umask, we could
	 * write out an unreadable resolv.conf.
	 */
	umask (022);

	g_type_init ();
	if (!g_thread_supported ())
		g_thread_init (NULL);
	dbus_g_thread_init ();

#ifndef HAVE_DBUS_GLIB_DISABLE_LEGACY_PROP_ACCESS
#error HAVE_DBUS_GLIB_DISABLE_LEGACY_PROP_ACCESS not defined
#endif

#if HAVE_DBUS_GLIB_DISABLE_LEGACY_PROP_ACCESS
	/* Ensure that non-exported properties don't leak out, and that the
	 * introspection 'access' permissions are respected.
	 */
	dbus_glib_global_set_disable_legacy_property_access ();
#endif

	setup_signals ();

	bm_logging_start (become_daemon);

	bm_log_info (LOGD_CORE, "BarcodeManager (version " BM_DIST_VERSION ") is starting...");
	success = FALSE;

	if (config)
		bm_log_info (LOGD_CORE, "Read config file %s", config);

	main_loop = g_main_loop_new (NULL, FALSE);

	/* Initialize our DBus service & connection */
	dbus_mgr = bm_dbus_manager_get ();

	manager = bm_manager_get (config, plugins, state_file, &error);
	if (manager == NULL) {
		bm_log_err (LOGD_CORE, "failed to initialize the barcode manager: %s",
		          error && error->message ? error->message : "(unknown)");
		goto done;
	}

    policy = bm_policy_new (manager);
    if (policy == NULL) {
        bm_log_err (LOGD_CORE, "failed to initialize the policy.");
        goto done;
    }

	/* Start our DBus service */
	if (!bm_dbus_manager_start_service (dbus_mgr)) {
		bm_log_err (LOGD_CORE, "failed to start the dbus service.");
		goto done;
	}

	bm_manager_start (manager);

	success = TRUE;

	/* Told to quit before getting to the mainloop by the signal handler */
	if (quit_early == TRUE)
		goto done;

	g_main_loop_run (main_loop);

done:
    if (policy)
		bm_policy_destroy (policy);

	if (manager)
		g_object_unref (manager);

	bm_logging_shutdown ();

	if (pidfile && wrote_pidfile)
		unlink (pidfile);

	/* Free options */
	g_free (pidfile);
	g_free (state_file);
	g_free (config);
	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);

	bm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error");
	exit (success ? 0 : 1);
}
Exemplo n.º 2
0
/*
 * main
 *
 */
int
main (int argc, char *argv[])
{
	gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE;
	gboolean success = FALSE;
	NMConfig *config;
	GError *error = NULL;
	gboolean wrote_pidfile = FALSE;
	char *bad_domains = NULL;
	NMConfigCmdLineOptions *config_cli;

	nm_g_type_init ();

	/* Known to cause a possible deadlock upon GDBus initialization:
	 * https://bugzilla.gnome.org/show_bug.cgi?id=674885 */
	g_type_ensure (G_TYPE_SOCKET);
	g_type_ensure (G_TYPE_DBUS_CONNECTION);
	g_type_ensure (NM_TYPE_BUS_MANAGER);

	_nm_utils_is_manager_process = TRUE;

	main_loop = g_main_loop_new (NULL, FALSE);

	config_cli = nm_config_cmd_line_options_new ();
	do_early_setup (&argc, &argv, config_cli);

	if (global_opt.g_fatal_warnings)
		_set_g_fatal_warnings ();

	if (global_opt.show_version) {
		fprintf (stdout, NM_DIST_VERSION "\n");
		exit (0);
	}

	nm_main_utils_ensure_root ();

	nm_main_utils_ensure_not_running_pidfile (global_opt.pidfile);

	/* Ensure state directory exists */
	if (g_mkdir_with_parents (NMSTATEDIR, 0755) != 0) {
		fprintf (stderr, "Cannot create '%s': %s", NMSTATEDIR, strerror (errno));
		exit (1);
	}

	nm_main_utils_ensure_rundir ();

	/* When running from the build directory, determine our build directory
	 * base and set helper paths in the build tree */
	if (global_opt.run_from_build_dir) {
		char *path, *slash;
		int g;

		/* exe is <basedir>/src/.libs/lt-NetworkManager, so chop off
		 * the last three components */
		path = realpath ("/proc/self/exe", NULL);
		g_assert (path != NULL);
		for (g = 0; g < 3; ++g) {
			slash = strrchr (path, '/');
			g_assert (slash != NULL);
			*slash = '\0';
		}

		/* don't free these strings, we need them for the entire
		 * process lifetime */
		nm_dhcp_helper_path = g_strdup_printf ("%s/src/dhcp-manager/nm-dhcp-helper", path);

		g_free (path);
	}

	if (!nm_logging_setup (global_opt.opt_log_level,
	                       global_opt.opt_log_domains,
	                       &bad_domains,
	                       &error)) {
		fprintf (stderr,
		         _("%s.  Please use --help to see a list of valid options.\n"),
		         error->message);
		exit (1);
	} else if (bad_domains) {
		fprintf (stderr,
		         _("Ignoring unrecognized log domain(s) '%s' passed on command line.\n"),
		         bad_domains);
		g_clear_pointer (&bad_domains, g_free);
	}

	/* Read the config file and CLI overrides */
	config = nm_config_setup (config_cli, NULL, &error);
	nm_config_cmd_line_options_free (config_cli);
	config_cli = NULL;
	if (config == NULL) {
		fprintf (stderr, _("Failed to read configuration: (%d) %s\n"),
		         error ? error->code : -1,
		         (error && error->message) ? error->message : _("unknown"));
		exit (1);
	}

	_init_nm_debug (nm_config_get_debug (config));

	/* Initialize logging from config file *only* if not explicitly
	 * specified by commandline.
	 */
	if (global_opt.opt_log_level == NULL && global_opt.opt_log_domains == NULL) {
		if (!nm_logging_setup (nm_config_get_log_level (config),
		                       nm_config_get_log_domains (config),
		                       &bad_domains,
		                       &error)) {
			fprintf (stderr, _("Error in configuration file: %s.\n"),
			         error->message);
			exit (1);
		} else if (bad_domains) {
			fprintf (stderr,
			         _("Ignoring unrecognized log domain(s) '%s' from config files.\n"),
			         bad_domains);
			g_clear_pointer (&bad_domains, g_free);
		}
	}

	if (global_opt.become_daemon && !nm_config_get_is_debug (config)) {
		if (daemon (0, 0) < 0) {
			int saved_errno;

			saved_errno = errno;
			fprintf (stderr, _("Could not daemonize: %s [error %u]\n"),
			         g_strerror (saved_errno),
			         saved_errno);
			exit (1);
		}
		wrote_pidfile = nm_main_utils_write_pidfile (global_opt.pidfile);
	}

	/* Set up unix signal handling - before creating threads, but after daemonizing! */
	nm_main_utils_setup_signals (main_loop);

	nm_logging_syslog_openlog (nm_config_get_is_debug (config)
	                           ? "debug"
	                           : nm_config_data_get_value_cached (NM_CONFIG_GET_DATA_ORIG,
	                                                              NM_CONFIG_KEYFILE_GROUP_LOGGING,
	                                                              NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND,
	                                                              NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY));

	nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting...");

	/* Parse the state file */
	if (!parse_state_file (global_opt.state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) {
		nm_log_err (LOGD_CORE, "State file %s parsing failed: (%d) %s",
		            global_opt.state_file,
		            error ? error->code : -1,
		            (error && error->message) ? error->message : _("unknown"));
		/* Not a hard failure */
	}
	g_clear_error (&error);

	nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config)));
	nm_config_data_log (nm_config_get_data (config), "CONFIG: ");
	nm_log_dbg (LOGD_CORE, "WEXT support is %s",
#if HAVE_WEXT
	             "enabled"
#else
	             "disabled"
#endif
	             );

	nm_auth_manager_setup (nm_config_get_auth_polkit (config));

	nm_manager_setup (global_opt.state_file,
	                  net_enabled,
	                  wifi_enabled,
	                  wwan_enabled);

	if (!nm_bus_manager_get_connection (nm_bus_manager_get ())) {
		nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available");
	} else {
		/* Start our DBus service */
		if (!nm_bus_manager_start_service (nm_bus_manager_get ())) {
			nm_log_err (LOGD_CORE, "failed to start the dbus service.");
			goto done;
		}
	}

	/* Set up platform interaction layer */
	nm_linux_platform_setup ();

	NM_UTILS_KEEP_ALIVE (config, NM_PLATFORM_GET, "NMConfig-depends-on-NMPlatform");

	nm_dispatcher_init ();

	g_signal_connect (nm_manager_get (), NM_MANAGER_CONFIGURE_QUIT, G_CALLBACK (manager_configure_quit), config);

	if (!nm_manager_start (nm_manager_get (), &error)) {
		nm_log_err (LOGD_CORE, "failed to initialize: %s", error->message);
		goto done;
	}

	/* Make sure the loopback interface is up. If interface is down, we bring
	 * it up and kernel will assign it link-local IPv4 and IPv6 addresses. If
	 * it was already up, we assume is in clean state.
	 *
	 * TODO: it might be desirable to check the list of addresses and compare
	 * it with a list of expected addresses (one of the protocol families
	 * could be disabled). The 'lo' interface is sometimes used for assigning
	 * global addresses so their availability doesn't depend on the state of
	 * physical interfaces.
	 */
	nm_log_dbg (LOGD_CORE, "setting up local loopback");
	nm_platform_link_set_up (NM_PLATFORM_GET, 1, NULL);

	success = TRUE;

	if (configure_and_quit == FALSE)
		g_main_loop_run (main_loop);

	nm_manager_stop (nm_manager_get ());

done:
	if (global_opt.pidfile && wrote_pidfile)
		unlink (global_opt.pidfile);

	nm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error");
	exit (success ? 0 : 1);
}