/** * main: **/ int main (int argc, char *argv[]) { gboolean ret = TRUE; gboolean disable_timer = FALSE; gboolean version = FALSE; gboolean use_daemon = FALSE; gboolean timed_exit = FALSE; gboolean immediate_exit = FALSE; gboolean keep_environment = FALSE; gboolean do_logging = FALSE; gchar *backend_name = NULL; PkEngine *engine = NULL; PkConf *conf = NULL; PkSyslog *syslog = NULL; GError *error = NULL; GOptionContext *context; guint timer_id = 0; const GOptionEntry options[] = { { "backend", '\0', 0, G_OPTION_ARG_STRING, &backend_name, /* TRANSLATORS: a backend is the system package tool, e.g. yum, apt */ _("Packaging backend to use, e.g. dummy"), NULL }, { "daemonize", '\0', 0, G_OPTION_ARG_NONE, &use_daemon, /* TRANSLATORS: if we should run in the background */ _("Daemonize and detach from the terminal"), NULL }, { "disable-timer", '\0', 0, G_OPTION_ARG_NONE, &disable_timer, /* TRANSLATORS: if we should not monitor how long we are inactive for */ _("Disable the idle timer"), NULL }, { "version", '\0', 0, G_OPTION_ARG_NONE, &version, /* TRANSLATORS: show version */ _("Show version and exit"), NULL }, { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit, /* TRANSLATORS: exit after we've started up, used for user profiling */ _("Exit after a small delay"), NULL }, { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit, /* TRANSLATORS: exit straight away, used for automatic profiling */ _("Exit after the engine has loaded"), NULL }, { "keep-environment", '\0', 0, G_OPTION_ARG_NONE, &keep_environment, /* TRANSLATORS: don't unset environment variables, used for debugging */ _("Don't clear environment on startup"), NULL }, { NULL } }; setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #if (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 35) g_type_init (); #endif /* TRANSLATORS: describing the service that is running */ context = g_option_context_new (_("PackageKit service")); g_option_context_add_main_entries (context, options, NULL); g_option_context_add_group (context, pk_debug_get_option_group ()); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); if (version) { g_print ("Version %s\n", VERSION); goto exit_program; } #if GLIB_CHECK_VERSION(2,29,19) /* do stuff on ctrl-c */ g_unix_signal_add_full (G_PRIORITY_DEFAULT, SIGINT, pk_main_sigint_cb, loop, NULL); #else signal (SIGINT, pk_main_sigint_handler); #endif /* we need to daemonize before we get a system connection */ if (use_daemon && daemon (0, 0)) { g_print ("Could not daemonize: %s\n", g_strerror (errno)); goto exit_program; } /* don't let GIO start it's own session bus: http://bugzilla.gnome.org/show_bug.cgi?id=526454 */ setenv ("GIO_USE_VFS", "local", 1); /* we don't actually need to do this, except it rules out the * 'it works from the command line but not service activation' bugs */ #ifdef HAVE_CLEARENV g_debug ("keep_environment: %i\n", keep_environment); if (!keep_environment) clearenv (); #endif /* get values from the config file */ conf = pk_conf_new (); pk_conf_set_bool (conf, "KeepEnvironment", keep_environment); /* log the startup */ syslog = pk_syslog_new (); pk_syslog_add (syslog, PK_SYSLOG_TYPE_INFO, "daemon start"); /* do we log? */ do_logging = pk_conf_get_bool (conf, "TransactionLogging"); g_debug ("Log all transactions: %i", do_logging); /* after how long do we timeout? */ exit_idle_time = pk_conf_get_int (conf, "ShutdownTimeout"); g_debug ("daemon shutdown set to %i seconds", exit_idle_time); /* override the backend name */ if (backend_name != NULL) { pk_conf_set_string (conf, "DefaultBackend", backend_name); } /* resolve 'auto' to an actual name */ backend_name = pk_conf_get_string (conf, "DefaultBackend"); if (g_strcmp0 (backend_name, "auto") == 0) { ret = pk_main_set_auto_backend (conf, &error); if (!ret) { g_print ("Failed to resolve auto: %s", error->message); g_error_free (error); goto out; } } loop = g_main_loop_new (NULL, FALSE); /* create a new engine object */ engine = pk_engine_new (); g_signal_connect (engine, "quit", G_CALLBACK (pk_main_quit_cb), loop); /* load the backend */ ret = pk_engine_load_backend (engine, &error); if (!ret) { /* TRANSLATORS: cannot load the backend the user specified */ g_print ("Failed to load the backend: %s", error->message); g_error_free (error); goto out; } /* Only timeout and close the mainloop if we have specified it * on the command line */ if (timed_exit) g_timeout_add_seconds (20, (GSourceFunc) timed_exit_cb, loop); /* only poll when we are alive */ if (exit_idle_time != 0 && !disable_timer) { timer_id = g_timeout_add_seconds (5, (GSourceFunc) pk_main_timeout_check_cb, engine); g_source_set_name_by_id (timer_id, "[PkMain] main poll"); } /* immediatly exit */ if (immediate_exit) g_timeout_add (50, (GSourceFunc) timed_exit_cb, loop); /* run until quit */ g_main_loop_run (loop); out: /* log the shutdown */ pk_syslog_add (syslog, PK_SYSLOG_TYPE_INFO, "daemon quit"); if (timer_id > 0) g_source_remove (timer_id); if (loop != NULL) g_main_loop_unref (loop); g_object_unref (syslog); g_object_unref (conf); if (engine != NULL) g_object_unref (engine); g_free (backend_name); exit_program: return 0; }
/** * pk_backend_load: * * Responsible for initialising the external backend object. * * Typically this will involve taking database locks for exclusive package access. * This method should only be called from the engine, unless the backend object * is used in self-check code, in which case the lock and unlock will have to * be done manually. **/ gboolean pk_backend_load (PkBackend *backend, GError **error) { GModule *handle; gchar *path = NULL; gboolean ret = FALSE; gpointer func = NULL; gchar *backend_name = NULL; g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE); /* already loaded */ if (backend->priv->loaded) { g_set_error (error, 1, 0, "already set name to %s", backend->priv->name); goto out; } /* can we load it? */ backend_name = pk_conf_get_string (backend->priv->conf, "DefaultBackend"); g_debug ("Trying to load : %s", backend_name); path = pk_backend_build_library_path (backend, backend_name); handle = g_module_open (path, 0); if (handle == NULL) { g_set_error (error, 1, 0, "opening module %s failed : %s", backend_name, g_module_error ()); goto out; } /* then check for the new style exported functions */ ret = g_module_symbol (handle, "pk_backend_get_description", (gpointer *)&func); if (ret) { PkBackendDesc *desc; PkBackendGetCompatStringFunc backend_vfunc; desc = g_new0 (PkBackendDesc, 1); /* connect up exported methods */ g_module_symbol (handle, "pk_backend_cancel", (gpointer *)&desc->cancel); g_module_symbol (handle, "pk_backend_destroy", (gpointer *)&desc->destroy); g_module_symbol (handle, "pk_backend_download_packages", (gpointer *)&desc->download_packages); g_module_symbol (handle, "pk_backend_get_categories", (gpointer *)&desc->get_categories); g_module_symbol (handle, "pk_backend_get_depends", (gpointer *)&desc->get_depends); g_module_symbol (handle, "pk_backend_get_details", (gpointer *)&desc->get_details); g_module_symbol (handle, "pk_backend_get_distro_upgrades", (gpointer *)&desc->get_distro_upgrades); g_module_symbol (handle, "pk_backend_get_files", (gpointer *)&desc->get_files); g_module_symbol (handle, "pk_backend_get_filters", (gpointer *)&desc->get_filters); g_module_symbol (handle, "pk_backend_get_groups", (gpointer *)&desc->get_groups); g_module_symbol (handle, "pk_backend_get_mime_types", (gpointer *)&desc->get_mime_types); g_module_symbol (handle, "pk_backend_supports_parallelization", (gpointer *)&desc->supports_parallelization); g_module_symbol (handle, "pk_backend_get_packages", (gpointer *)&desc->get_packages); g_module_symbol (handle, "pk_backend_get_repo_list", (gpointer *)&desc->get_repo_list); g_module_symbol (handle, "pk_backend_get_requires", (gpointer *)&desc->get_requires); g_module_symbol (handle, "pk_backend_get_roles", (gpointer *)&desc->get_roles); g_module_symbol (handle, "pk_backend_get_update_detail", (gpointer *)&desc->get_update_detail); g_module_symbol (handle, "pk_backend_get_updates", (gpointer *)&desc->get_updates); g_module_symbol (handle, "pk_backend_initialize", (gpointer *)&desc->initialize); g_module_symbol (handle, "pk_backend_install_files", (gpointer *)&desc->install_files); g_module_symbol (handle, "pk_backend_install_packages", (gpointer *)&desc->install_packages); g_module_symbol (handle, "pk_backend_install_signature", (gpointer *)&desc->install_signature); g_module_symbol (handle, "pk_backend_refresh_cache", (gpointer *)&desc->refresh_cache); g_module_symbol (handle, "pk_backend_remove_packages", (gpointer *)&desc->remove_packages); g_module_symbol (handle, "pk_backend_repo_enable", (gpointer *)&desc->repo_enable); g_module_symbol (handle, "pk_backend_repo_set_data", (gpointer *)&desc->repo_set_data); g_module_symbol (handle, "pk_backend_resolve", (gpointer *)&desc->resolve); g_module_symbol (handle, "pk_backend_search_details", (gpointer *)&desc->search_details); g_module_symbol (handle, "pk_backend_search_files", (gpointer *)&desc->search_files); g_module_symbol (handle, "pk_backend_search_groups", (gpointer *)&desc->search_groups); g_module_symbol (handle, "pk_backend_search_names", (gpointer *)&desc->search_names); g_module_symbol (handle, "pk_backend_start_job", (gpointer *)&desc->job_start); g_module_symbol (handle, "pk_backend_stop_job", (gpointer *)&desc->job_stop); g_module_symbol (handle, "pk_backend_reset_job", (gpointer *)&desc->job_reset); g_module_symbol (handle, "pk_backend_update_packages", (gpointer *)&desc->update_packages); g_module_symbol (handle, "pk_backend_what_provides", (gpointer *)&desc->what_provides); g_module_symbol (handle, "pk_backend_upgrade_system", (gpointer *)&desc->upgrade_system); g_module_symbol (handle, "pk_backend_repair_system", (gpointer *)&desc->repair_system); /* get old static string data */ ret = g_module_symbol (handle, "pk_backend_get_author", (gpointer *)&backend_vfunc); if (ret) desc->author = backend_vfunc (backend); ret = g_module_symbol (handle, "pk_backend_get_description", (gpointer *)&backend_vfunc); if (ret) desc->description = backend_vfunc (backend); /* make available */ backend->priv->desc = desc; } else { g_module_close (handle); g_set_error (error, 1, 0, "could not find description in plugin %s, not loading", backend_name); goto out; } /* save the backend name and handle */ g_free (backend->priv->name); backend->priv->name = g_strdup (backend_name); backend->priv->handle = handle; /* initialize if we can */ if (backend->priv->desc->initialize != NULL) { backend->priv->during_initialize = TRUE; backend->priv->desc->initialize (backend); backend->priv->during_initialize = FALSE; } backend->priv->loaded = TRUE; out: g_free (path); g_free (backend_name); return ret; }
/** * main: **/ int main (int argc, char *argv[]) { DBusGConnection *system_connection; EggDbusMonitor *monitor; gboolean ret; gboolean disable_timer = FALSE; gboolean version = FALSE; gboolean use_daemon = FALSE; gboolean timed_exit = FALSE; gboolean immediate_exit = FALSE; gboolean do_logging = FALSE; gchar *backend_name = NULL; PkEngine *engine = NULL; PkBackend *backend = NULL; PkConf *conf = NULL; PkSyslog *syslog = NULL; GError *error = NULL; GOptionContext *context; const GOptionEntry options[] = { { "backend", '\0', 0, G_OPTION_ARG_STRING, &backend_name, /* TRANSLATORS: a backend is the system package tool, e.g. yum, apt */ _("Packaging backend to use, e.g. dummy"), NULL }, { "daemonize", '\0', 0, G_OPTION_ARG_NONE, &use_daemon, /* TRANSLATORS: if we should run in the background */ _("Daemonize and detach from the terminal"), NULL }, { "disable-timer", '\0', 0, G_OPTION_ARG_NONE, &disable_timer, /* TRANSLATORS: if we should not monitor how long we are inactive for */ _("Disable the idle timer"), NULL }, { "version", '\0', 0, G_OPTION_ARG_NONE, &version, /* TRANSLATORS: show version */ _("Show version and exit"), NULL }, { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit, /* TRANSLATORS: exit after we've started up, used for user profiling */ _("Exit after a small delay"), NULL }, { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit, /* TRANSLATORS: exit straight away, used for automatic profiling */ _("Exit after the engine has loaded"), NULL }, { NULL} }; setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); if (! g_thread_supported ()) g_thread_init (NULL); dbus_g_thread_init (); g_type_init (); /* TRANSLATORS: describing the service that is running */ context = g_option_context_new (_("PackageKit service")); g_option_context_add_main_entries (context, options, NULL); g_option_context_add_group (context, egg_debug_get_option_group ()); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); if (version) { g_print ("Version %s\n", VERSION); goto exit_program; } /* check if an instance is already running */ monitor = egg_dbus_monitor_new (); egg_dbus_monitor_assign (monitor, EGG_DBUS_MONITOR_SYSTEM, PK_DBUS_SERVICE); ret = egg_dbus_monitor_is_connected (monitor); g_object_unref (monitor); if (ret) { g_print ("Already running service which provides %s\n", PK_DBUS_SERVICE); goto exit_program; } /* do stuff on ctrl-c */ signal (SIGINT, pk_main_sigint_handler); /* we need to daemonize before we get a system connection */ if (use_daemon && daemon (0, 0)) { g_print ("Could not daemonize: %s\n", g_strerror (errno)); goto exit_program; } /* don't let GIO start it's own session bus: http://bugzilla.gnome.org/show_bug.cgi?id=526454 */ setenv ("GIO_USE_VFS", "local", 1); /* check dbus connections, exit if not valid */ system_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); if (error) { /* TRANSLATORS: fatal error, dbus is not running */ g_print ("%s: %s\n", _("Cannot connect to the system bus"), error->message); g_error_free (error); goto exit_program; } /* we don't actually need to do this, except it rules out the * 'it works from the command line but not service activation' bugs */ #ifdef HAVE_CLEARENV clearenv (); #endif /* get values from the config file */ conf = pk_conf_new (); /* log the startup */ syslog = pk_syslog_new (); pk_syslog_add (syslog, PK_SYSLOG_TYPE_INFO, "daemon start"); /* do we log? */ do_logging = pk_conf_get_bool (conf, "TransactionLogging"); egg_debug ("Log all transactions: %i", do_logging); if (do_logging) egg_debug_set_log_filename ("/var/log/PackageKit"); /* after how long do we timeout? */ exit_idle_time = pk_conf_get_int (conf, "ShutdownTimeout"); egg_debug ("daemon shutdown set to %i seconds", exit_idle_time); if (backend_name == NULL) { backend_name = pk_conf_get_string (conf, "DefaultBackend"); egg_debug ("using default backend %s", backend_name); } /* load our chosen backend */ backend = pk_backend_new (); ret = pk_backend_set_name (backend, backend_name); g_free (backend_name); /* all okay? */ if (!ret) egg_error ("cannot continue, backend invalid"); loop = g_main_loop_new (NULL, FALSE); /* create a new engine object */ engine = pk_engine_new (); g_signal_connect (engine, "quit", G_CALLBACK (pk_main_quit_cb), loop); if (!pk_object_register (system_connection, G_OBJECT (engine), &error)) { /* TRANSLATORS: cannot register on system bus, unknown reason -- geeky error follows */ g_print ("%s %s\n", _("Error trying to start:"), error->message); g_error_free (error); goto out; } /* Only timeout and close the mainloop if we have specified it * on the command line */ if (timed_exit) g_timeout_add_seconds (20, (GSourceFunc) timed_exit_cb, loop); /* only poll every 10 seconds when we are alive */ if (exit_idle_time != 0 && !disable_timer) g_timeout_add_seconds (5, (GSourceFunc) pk_main_timeout_check_cb, engine); /* immediatly exit */ if (immediate_exit) g_timeout_add (50, (GSourceFunc) timed_exit_cb, loop); /* run until quit */ g_main_loop_run (loop); out: /* log the shutdown */ pk_syslog_add (syslog, PK_SYSLOG_TYPE_INFO, "daemon quit"); g_main_loop_unref (loop); g_object_unref (syslog); g_object_unref (conf); g_object_unref (engine); g_object_unref (backend); exit_program: return 0; }