static void on_unit_proxy_ready (GObject *object, GAsyncResult *res, gpointer user_data) { Services *services = user_data; gs_unref_object GDBusProxy *unit = g_dbus_proxy_new_for_bus_finish (res, NULL); if (unit) { const gchar *name, *description, *load_state, *active_state, *sub_state, *file_state; gs_unref_variant GVariant *n = g_dbus_proxy_get_cached_property (unit, "Id"); gs_unref_variant GVariant *d = g_dbus_proxy_get_cached_property (unit, "Description"); gs_unref_variant GVariant *l = g_dbus_proxy_get_cached_property (unit, "LoadState"); gs_unref_variant GVariant *a = g_dbus_proxy_get_cached_property (unit, "ActiveState"); gs_unref_variant GVariant *s = g_dbus_proxy_get_cached_property (unit, "SubState"); gs_unref_variant GVariant *f = g_dbus_proxy_get_cached_property (unit, "UnitFileState"); g_variant_get (n, "&s", &name); g_variant_get (d, "&s", &description); g_variant_get (l, "&s", &load_state); g_variant_get (a, "&s", &active_state); g_variant_get (s, "&s", &sub_state); g_variant_get (f, "&s", &file_state); cockpit_services_emit_service_update (COCKPIT_SERVICES (services), g_variant_new ("(ssssss)", name, description, load_state, active_state, sub_state, file_state)); } }
static void on_get_unit_file_state_done (GObject *object, GAsyncResult *res, gpointer user_data) { GetServiceInfoData *data = user_data; GError *error = NULL; gs_unref_variant GVariant *result = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); if (error) { end_invocation_take_gerror (data->invocation, error); g_free (data); return; } const gchar *state; g_variant_get (result, "(&s)", &state); GVariantBuilder bob; g_variant_builder_init (&bob, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&bob, "{sv}", "Id", g_variant_new_string (data->name)); g_variant_builder_add (&bob, "{sv}", "IsTemplate", g_variant_new_boolean (TRUE)); g_variant_builder_add (&bob, "{sv}", "UnitFileState", g_variant_new_string (state)); cockpit_services_complete_get_service_info (COCKPIT_SERVICES (data->services), data->invocation, g_variant_builder_end (&bob)); g_free (data->name); g_free (data); }
/** * services_new: * @daemon: A #Daemon. * * Create a new #Services instance. * * Returns: A #Services object. Free with g_object_unref(). */ CockpitServices * services_new (Daemon *daemon) { g_return_val_if_fail (IS_DAEMON (daemon), NULL); return COCKPIT_SERVICES (g_object_new (TYPE_SERVICES, "daemon", daemon, NULL)); }
static void on_unit_files_changed_signal (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { Services *services = user_data; cockpit_services_emit_service_update_all (COCKPIT_SERVICES (services)); }
static void on_service_action_done (GObject *object, GAsyncResult *res, gpointer user_data) { ServiceActionData *data = user_data; GError *error = NULL; gs_unref_variant GVariant *result = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); if (error) { end_invocation_take_gerror (data->invocation, error); g_free (data); return; } if (data->flags & FOR_FILES) { gboolean carries_install_info; gs_unref_variant GVariant *changes; if (data->flags & INSTALL_INFO) g_variant_get (result, "(b@a(sss))", &carries_install_info, &changes); else g_variant_get (result, "(@a(sss))", &changes); if ((data->flags & INSTALL_INFO) && !carries_install_info) { g_dbus_method_invocation_return_error (data->invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "Service has not been designed to be enabled or disabled."); g_free (data); return; } g_dbus_proxy_call (data->services->systemd, "Reload", NULL, G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, on_reload_done, data); } else { cockpit_services_complete_service_action (COCKPIT_SERVICES (data->services), data->invocation); g_free (data); } }
static gboolean handle_service_action (CockpitServices *object, GDBusMethodInvocation *invocation, const gchar *arg_name, const gchar *arg_action) { GError *error; Services *services = SERVICES (object); const gchar *argv[6]; int i; gint status; const gchar *method = arg_action; gboolean force = FALSE; if (g_str_has_prefix (arg_action, "force-")) { force = TRUE; method = arg_action + strlen ("force-"); } i = 0; argv[i++] = "pkexec"; argv[i++] = "systemctl"; if (force) argv[i++] = "--force"; argv[i++] = method; argv[i++] = arg_name; argv[i++] = NULL; error = NULL; if (g_spawn_sync (NULL, (gchar**)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &status, &error)) g_spawn_check_exit_status (status, &error); if (error) end_invocation_take_gerror (invocation, error); else cockpit_services_complete_service_action (COCKPIT_SERVICES (services), invocation); return TRUE; }
static void on_reload_done (GObject *object, GAsyncResult *res, gpointer user_data) { ServiceActionData *data = user_data; GError *error = NULL; GVariant *result = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); if (error) { end_invocation_take_gerror (data->invocation, error); g_free (data); return; } g_variant_unref (result); cockpit_services_complete_service_action (COCKPIT_SERVICES (data->services), data->invocation); g_free (data); }
static void on_get_all_done_for_info (GObject *object, GAsyncResult *res, gpointer user_data) { GetServiceInfoData *data = user_data; GError *error = NULL; gs_unref_variant GVariant *reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), res, &error); if (error) { end_invocation_take_gerror (data->invocation, error); g_free (data); return; } gs_unref_variant GVariant *props; g_variant_get (reply, "(@a{sv})", &props); GVariantBuilder bob; g_variant_builder_init (&bob, G_VARIANT_TYPE("a{sv}")); copy_entry (&bob, props, "Id"); copy_entry (&bob, props, "Description"); copy_entry (&bob, props, "LoadState"); copy_entry (&bob, props, "ActiveState"); copy_entry (&bob, props, "SubState"); copy_entry (&bob, props, "UnitFileState"); copy_entry (&bob, props, "ExecMainStartTimestamp"); copy_entry (&bob, props, "ExecMainExitTimestamp"); copy_entry (&bob, props, "ActiveEnterTimestamp"); copy_entry (&bob, props, "ActiveExitTimestamp"); copy_entry (&bob, props, "InactiveEnterTimestamp"); copy_entry (&bob, props, "InactiveExitTimestamp"); copy_entry (&bob, props, "ConditionTimestamp"); copy_entry (&bob, props, "SourcePath"); copy_entry (&bob, props, "FragmentPath"); copy_entry (&bob, props, "LoadError"); copy_entry (&bob, props, "ConditionResult"); copy_entry (&bob, props, "StatusText"); copy_entry (&bob, props, "DefaultControlGroup"); const gchar *id = NULL, *cgroup = NULL; uint32_t main_pid = 0, exec_main_pid = 0, control_pid = 0; g_variant_lookup (props, "Id", "&s", &id); g_variant_lookup (props, "DefaultControlGroup", "&s", &cgroup); g_variant_lookup (props, "ExecMainPid", "u", &exec_main_pid); g_variant_lookup (props, "MainPid", "u", &main_pid); g_variant_lookup (props, "ControlPid", "u", &control_pid); if (cgroup) { pid_t extra_pids[3]; int n_extra_pids = 0; if (main_pid > 0) extra_pids[n_extra_pids++] = main_pid; if (exec_main_pid > 0) extra_pids[n_extra_pids++] = exec_main_pid; if (control_pid > 0) extra_pids[n_extra_pids++] = control_pid; GVariant *c = collect_cgroup_and_extra_by_spec (cgroup, FALSE, TRUE, extra_pids, n_extra_pids); if (c) g_variant_builder_add (&bob, "{sv}", "Processes", c); } cockpit_services_complete_get_service_info (COCKPIT_SERVICES (data->services), data->invocation, g_variant_builder_end (&bob)); g_free (data); }
static void on_list_files_done (GObject *object, GAsyncResult *res, gpointer user_data) { ListServicesData *data = user_data; GError *error = NULL; data->files = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); if (error) { end_invocation_take_gerror (data->invocation, error); g_variant_unref (data->units); g_free (data); return; } data->result = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, listed_service_free); gs_free_variant_iter GVariantIter *unit_iter = NULL; const gchar *name, *description, *load_state, *active_state, *sub_state, *file_state; g_variant_get (data->units, "(a*)", &unit_iter); while (g_variant_iter_next (unit_iter, "(&s&s&s&s&s&s&ou&s&o)", &name, &description, &load_state, &active_state, &sub_state, NULL, // follow unit NULL, // object path NULL, // job id NULL, // job type NULL)) // job object path { if (!g_hash_table_lookup (data->result, name)) { ListedService *s = listed_service_new (); s->name = name; s->description = description; s->load_state = load_state; s->active_state = active_state; s->sub_state = sub_state; s->file_state = ""; g_hash_table_insert (data->result, (void *)name, s); } } gs_free_variant_iter GVariantIter *file_iter = NULL; g_variant_get (data->files, "(a*)", &file_iter); while (g_variant_iter_next (file_iter, "(&s&s)", &name, &file_state)) { gchar *base = g_path_get_basename (name); ListedService *s = g_hash_table_lookup (data->result, base); if (s) s->file_state = file_state; else { ListedService *s = listed_service_new (); s->name = base; s->description = get_service_description (name); s->load_state = ""; s->active_state = ""; s->sub_state = ""; s->file_state = file_state; s->needs_free = TRUE; g_hash_table_insert (data->result, (void *)base, s); } } GVariantBuilder bob; g_variant_builder_init (&bob, G_VARIANT_TYPE("a(ssssss)")); g_hash_table_foreach (data->result, add_listed_service_to_builder, &bob); cockpit_services_complete_list_services (COCKPIT_SERVICES (data->services), data->invocation, g_variant_builder_end (&bob)); g_variant_unref (data->units); g_variant_unref (data->files); g_hash_table_destroy (data->result); g_free (data); }