summaryrefslogtreecommitdiffstats
path: root/src/service-dbus/util/serviceutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service-dbus/util/serviceutil.c')
-rw-r--r--src/service-dbus/util/serviceutil.c290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/service-dbus/util/serviceutil.c b/src/service-dbus/util/serviceutil.c
new file mode 100644
index 0000000..32bd76a
--- /dev/null
+++ b/src/service-dbus/util/serviceutil.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Vitezslav Crhonek <vcrhonek@redhat.com>
+ * Radek Novacek <rnovacek@redhat.com>
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <gio/gio.h>
+
+#include "serviceutil.h"
+
+#define MAX_SLIST_CNT 1000
+
+#define MANAGER_NAME "org.freedesktop.systemd1"
+#define MANAGER_OP "/org/freedesktop/systemd1"
+#define MANAGER_INTERFACE "org.freedesktop.systemd1.Manager"
+#define UNIT_INTERFACE "org.freedesktop.systemd1.Unit"
+#define SERVICE_INTERFACE "org.freedesktop.systemd1.Service"
+#define PROPERTY_INTERFACE "org.freedesktop.DBus.Properties"
+
+void service_free_slist(SList *slist)
+{
+ int i;
+
+ if (!slist)
+ return;
+
+ for(i = 0; i < slist->cnt; i++)
+ free(slist->name[i]);
+ free(slist->name);
+ free(slist);
+
+ return;
+}
+
+SList *service_find_all(void)
+{
+ GDBusProxy *manager_proxy = NULL;
+ GVariantIter *arr = NULL;
+ GVariant *result = NULL;
+ GError *error = NULL;
+ SList *slist = NULL;
+ gchar *primary_unit_name = NULL;
+ char *tmps = NULL;
+
+ g_type_init();
+
+ manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error);
+ if (!manager_proxy) {
+ g_error_free(error);
+ return NULL;
+ }
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(manager_proxy, "ListUnitFiles", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) {
+ g_error_free(error);
+ g_object_unref(manager_proxy);
+ return NULL;
+ }
+
+ slist = malloc(sizeof(SList));
+ if (!slist) return NULL;
+ slist->name = malloc(MAX_SLIST_CNT * sizeof(char *));
+ if (!slist->name) {
+ free(slist);
+ return NULL;
+ }
+ slist->cnt = 0;
+
+ g_variant_get(result, "(a(ss))", &arr);
+ while (g_variant_iter_loop(arr, "(ss)", &primary_unit_name, NULL)) {
+ if (strstr(primary_unit_name, ".service")) {
+ tmps = strdup(primary_unit_name);
+ if (!tmps)
+ continue;
+ slist->name[slist->cnt] = strndup(basename(tmps), strlen(basename(tmps)));
+ if (!slist->name[slist->cnt]) {
+ free(tmps);
+ continue;
+ }
+ free(tmps);
+ slist->cnt++;
+ }
+ }
+ g_variant_iter_free(arr);
+
+ g_object_unref(manager_proxy);
+ return slist;
+}
+
+
+int service_get_properties(
+ Service *svc,
+ const char *service)
+{
+ GDBusProxy *manager_proxy = NULL;
+ GDBusProxy *proxy = NULL;
+ GVariantIter *arr = NULL;
+ GVariant *result = NULL;
+ GVariant *result2 = NULL;
+ GError *error = NULL;
+ gchar *fragment_path = NULL, *unit_file_state = NULL;
+ gchar *unit, *value_str;
+ unsigned long value_long;
+
+ g_type_init();
+
+ svc->svName = strdup(service);
+ if (!svc->svName) return 0;
+
+ manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error);
+ if (!manager_proxy) goto error;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(manager_proxy, "ListUnitFiles", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto error;
+
+ svc->svEnabledDefault = NOT_APPLICABLE;
+ g_variant_get(result, "(a(ss))", &arr);
+ while (g_variant_iter_loop(arr, "(ss)", &fragment_path, &unit_file_state)) {
+ if (strstr(fragment_path, service) && strcmp(strstr(fragment_path, service), service) == 0) {
+ if (strncmp(unit_file_state, "enabled", 7) == 0)
+ svc->svEnabledDefault = ENABLED;
+ if (strncmp(unit_file_state, "disabled", 8) == 0)
+ svc->svEnabledDefault = DISABLED;
+ }
+ }
+ g_variant_iter_free(arr);
+ arr = NULL;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(manager_proxy, "LoadUnit", g_variant_new("(s)", service),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto error;
+
+ g_object_unref(manager_proxy);
+ manager_proxy = NULL;
+ g_variant_get(result, "(o)", &unit);
+
+ proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, unit, PROPERTY_INTERFACE, NULL, &error);
+ if (!proxy) goto error;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", UNIT_INTERFACE, "Description"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto error;
+
+ g_variant_get(result, "(v)", &result2);
+ g_variant_get(result2, "s", &value_str);
+ svc->svCaption = strdup(value_str);
+ if (!svc->svCaption) goto error;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", SERVICE_INTERFACE, "MainPID"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto error;
+
+ g_variant_get(result, "(v)", &result2);
+ g_variant_get(result2, "u", &value_long);
+ svc->pid = value_long;
+
+ error = NULL;
+ result = g_dbus_proxy_call_sync(proxy, "Get", g_variant_new("(ss)", UNIT_INTERFACE, "ActiveState"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) goto error;
+
+ g_variant_get(result, "(v)", &result2);
+ g_variant_get(result2, "s", &value_str);
+
+ if (!strcmp(value_str, "active")) {
+ svc->svOperationalStatus[0] = OS_OK;
+ svc->svOperationalStatusCnt = 1;
+ }
+ else if (!strcmp(value_str, "inactive")) {
+ svc->svOperationalStatus[0] = OS_COMPLETED;
+ svc->svOperationalStatus[1] = OS_OK;
+ svc->svOperationalStatusCnt = 2;
+ }
+ else if (!strcmp(value_str, "failed")) {
+ svc->svOperationalStatus[0] = OS_COMPLETED;
+ svc->svOperationalStatus[1] = OS_ERROR;
+ svc->svOperationalStatusCnt = 2;
+ }
+ else if (!strcmp(value_str, "activating")) {
+ svc->svOperationalStatus[0] = OS_STARTING;
+ svc->svOperationalStatusCnt = 1;
+ }
+ else if (!strcmp(value_str, "deactivating")) {
+ svc->svOperationalStatus[0] = OS_STOPPING;
+ svc->svOperationalStatusCnt = 1;
+ }
+
+ if (svc->pid) {
+ svc->svStarted = 1;
+ svc->svStatus = strdup("OK");
+ } else {
+ svc->svStarted = 0;
+ svc->svStatus = strdup("Stopped");
+ }
+ if (!svc->svStatus) goto error;
+
+ g_object_unref(proxy);
+ return 1;
+
+error:
+ if (svc->svName) free(svc->svName);
+ if (error) g_error_free(error);
+ if (manager_proxy) g_object_unref(manager_proxy);
+ if (proxy) g_object_unref(proxy);
+ if (svc->svCaption) free(svc->svCaption);
+
+ return 0;
+}
+
+unsigned int service_operation(
+ const char *service,
+ const char *method,
+ char *output,
+ int output_len)
+{
+ GDBusProxy *manager_proxy = NULL;
+ GVariant *result = NULL;
+ GError *error = NULL;
+ GVariantBuilder *builder;
+
+ g_type_init();
+
+ manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+ NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error);
+ if (!manager_proxy) {
+ g_error_free(error);
+ return -1;
+ }
+
+ error = NULL;
+ if (!strcasecmp(method, "EnableUnitFiles") || !strcasecmp(method, "DisableUnitFiles")) {
+ builder = g_variant_builder_new(G_VARIANT_TYPE ("as"));
+ g_variant_builder_add(builder, "s", service);
+ if (!strcasecmp(method, "EnableUnitFiles")) {
+ result = g_dbus_proxy_call_sync(manager_proxy, method, g_variant_new("(asbb)", builder, FALSE, TRUE),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ } else {
+ result = g_dbus_proxy_call_sync(manager_proxy, method, g_variant_new("(asb)", builder, FALSE),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ }
+ if (error) {
+ g_error_free(error);
+ g_object_unref(manager_proxy);
+ return -1;
+ }
+ } else {
+ result = g_dbus_proxy_call_sync(manager_proxy, method, g_variant_new("(ss)", service, "replace"),
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ if (error) {
+ g_error_free(error);
+ g_object_unref(manager_proxy);
+ return -1;
+ }
+ }
+
+ g_object_unref(manager_proxy);
+ return 0;
+}