diff options
Diffstat (limited to 'src/service-dbus/util/serviceutil.c')
-rw-r--r-- | src/service-dbus/util/serviceutil.c | 290 |
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; +} |