diff --git a/src/sysprofd/ipc-service-impl.c b/src/sysprofd/ipc-service-impl.c new file mode 100644 index 00000000..d8ef8d76 --- /dev/null +++ b/src/sysprofd/ipc-service-impl.c @@ -0,0 +1,135 @@ +/* ipc-service-impl.c + * + * Copyright 2019 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define G_LOG_DOMAIN "ipc-service-impl" + +#include "config.h" + +#include "ipc-service-impl.h" + +struct _IpcServiceImpl +{ + IpcServiceSkeleton parent_instance; +}; + +static gboolean +ipc_service_impl_handle_list_processes (IpcService *service, + GDBusMethodInvocation *invocation) +{ + g_autoptr(GDir) dir = NULL; + g_autoptr(GArray) pids = NULL; + const gchar *name; + + g_assert (IPC_IS_SERVICE_IMPL (service)); + g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation)); + + if (!(dir = g_dir_open ("/proc/", 0, NULL))) + { + g_dbus_method_invocation_return_error (g_steal_pointer (&invocation), + G_DBUS_ERROR, + G_DBUS_ERROR_FILE_NOT_FOUND, + "Failed to access /proc"); + return TRUE; + } + + pids = g_array_new (FALSE, FALSE, sizeof (gint32)); + + while ((name = g_dir_read_name (dir))) + { + if (g_ascii_isalnum (*name)) + { + gchar *endptr = NULL; + gint64 val = g_ascii_strtoll (name, &endptr, 10); + + if (endptr != NULL && *endptr == 0 && val < G_MAXINT && val >= 0) + { + gint32 v32 = val; + g_array_append_val (pids, v32); + } + } + } + + ipc_service_complete_list_processes (service, + g_steal_pointer (&invocation), + g_variant_new_fixed_array (G_VARIANT_TYPE_INT32, + pids->data, + pids->len, + sizeof (gint32))); + + return TRUE; +} + +static gboolean +ipc_service_impl_handle_get_proc_file (IpcService *service, + GDBusMethodInvocation *invocation, + const gchar *path) +{ + g_autofree gchar *canon = NULL; + g_autofree gchar *contents = NULL; + gsize len; + + g_assert (IPC_IS_SERVICE_IMPL (service)); + g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation)); + + canon = g_canonicalize_filename (path, "/proc/"); + + if (!g_str_has_prefix (canon, "/proc/")) + g_dbus_method_invocation_return_error (g_steal_pointer (&invocation), + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "File is not within /proc/"); + else if (!g_file_get_contents (canon, &contents, &len, NULL)) + g_dbus_method_invocation_return_error (g_steal_pointer (&invocation), + G_DBUS_ERROR, + G_DBUS_ERROR_FILE_NOT_FOUND, + "Failed to locate the file"); + else + ipc_service_complete_get_proc_file (service, + g_steal_pointer (&invocation), + contents); + + return TRUE; +} + +static void +init_service_iface (IpcServiceIface *iface) +{ + iface->handle_list_processes = ipc_service_impl_handle_list_processes; + iface->handle_get_proc_file = ipc_service_impl_handle_get_proc_file; +} + +G_DEFINE_TYPE_WITH_CODE (IpcServiceImpl, ipc_service_impl, IPC_TYPE_SERVICE_SKELETON, + G_IMPLEMENT_INTERFACE (IPC_TYPE_SERVICE, init_service_iface)) + +static void +ipc_service_impl_class_init (IpcServiceImplClass *klass) +{ +} + +static void +ipc_service_impl_init (IpcServiceImpl *self) +{ +} + +IpcService * +ipc_service_impl_new (void) +{ + return g_object_new (IPC_TYPE_SERVICE_IMPL, NULL); +} diff --git a/src/sysprofd/ipc-service-impl.h b/src/sysprofd/ipc-service-impl.h new file mode 100644 index 00000000..b56c6a6a --- /dev/null +++ b/src/sysprofd/ipc-service-impl.h @@ -0,0 +1,33 @@ +/* ipc-service-impl.h + * + * Copyright 2019 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include "ipc-service.h" + +G_BEGIN_DECLS + +#define IPC_TYPE_SERVICE_IMPL (ipc_service_impl_get_type()) + +G_DECLARE_FINAL_TYPE (IpcServiceImpl, ipc_service_impl, IPC, SERVICE_IMPL, IpcServiceSkeleton) + +IpcService *ipc_service_impl_new (void); + +G_END_DECLS diff --git a/src/sysprofd/meson.build b/src/sysprofd/meson.build index 9fb793ee..4ddc8565 100644 --- a/src/sysprofd/meson.build +++ b/src/sysprofd/meson.build @@ -1,10 +1,15 @@ if get_option('with_sysprofd') == 'bundled' +ipc_service_src = gnome.gdbus_codegen('ipc-service', + sources: 'org.gnome.Sysprof3.Service.xml', + interface_prefix: 'org.gnome.Sysprof3.', + namespace: 'Ipc', +) + sysprofd_sources = [ 'sysprofd.c', - 'sd-bus-helper.c', - 'sd-bus-helper.h', - '../libsysprof/sysprof-kallsyms.c', + 'ipc-service-impl.c', + ipc_service_src, ] pkglibexecdir = join_paths(get_option('prefix'), get_option('libexecdir')) @@ -12,6 +17,8 @@ pkglibexecdir = join_paths(get_option('prefix'), get_option('libexecdir')) sysprofd_deps = [ dependency('libsystemd', version: '>=222'), dependency('glib-2.0', version: glib_req_version), + dependency('gio-2.0', version: glib_req_version), + dependency('gio-unix-2.0', version: glib_req_version), ] sysprofd = executable('sysprofd', sysprofd_sources, @@ -19,9 +26,6 @@ sysprofd = executable('sysprofd', sysprofd_sources, install: true, install_dir: pkglibexecdir, pie: true, - include_directories: [include_directories('.'), - '../libsysprof', - libsysprof_capture_include_dirs], ) sysprofdconf = configuration_data() diff --git a/src/sysprofd/org.gnome.Sysprof2.xml b/src/sysprofd/org.gnome.Sysprof2.xml deleted file mode 100644 index b22de4fa..00000000 --- a/src/sysprofd/org.gnome.Sysprof2.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/sysprofd/org.gnome.Sysprof3.Service.xml b/src/sysprofd/org.gnome.Sysprof3.Service.xml new file mode 100644 index 00000000..0f6d6b4d --- /dev/null +++ b/src/sysprofd/org.gnome.Sysprof3.Service.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/sysprofd/sd-bus-helper.c b/src/sysprofd/sd-bus-helper.c deleted file mode 100644 index 1444a073..00000000 --- a/src/sysprofd/sd-bus-helper.c +++ /dev/null @@ -1,188 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd 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. - - systemd 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 systemd; If not, see . -***/ - -#include -#include - -#include "sd-bus-helper.h" - -/* - * Various macros to simplify lifing code from sd-bus. - */ -#define assert_return(expr,val) do { if (!(expr)) return (val); } while (0) -#define _cleanup_(f) __attribute__((cleanup(f))) -#define STRV_FOREACH_PAIR(x, y, l) \ - for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) - -/* - * To support systemd 222, we need a couple helpers that were added - * in 229. If we update code from systemd in the future, we can probably - * drop these helpres. - */ - -static void -_sd_bus_message_unrefp (sd_bus_message **m) -{ - if (m && *m) - { - sd_bus_message_unref (*m); - *m = NULL; - } -} - -static void -_sd_bus_creds_unrefp (sd_bus_creds **c) -{ - if (c && *c) - { - sd_bus_creds_unref (*c); - *c = NULL; - } -} - -/* - * Begin verbatim code from systemd. Please try to keep this in sync until - * systemd exposes helpers for polkit integration. - */ -static int -check_good_user (sd_bus_message *m, - uid_t good_user) -{ - _cleanup_(_sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; - uid_t sender_uid; - int r; - - assert (m); - - if (good_user == UID_INVALID) - return 0; - - r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds); - if (r < 0) - return r; - - /* Don't trust augmented credentials for authorization */ - assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM); - - r = sd_bus_creds_get_euid(creds, &sender_uid); - if (r < 0) - return r; - - return sender_uid == good_user; -} - -int -bus_test_polkit (sd_bus_message *call, - int capability, - const char *action, - const char **details, - uid_t good_user, - bool *_challenge, - sd_bus_error *e) -{ - int r; - - assert (call); - assert (action); - - /* Tests non-interactively! */ - - r = check_good_user(call, good_user); - if (r != 0) - return r; - - r = sd_bus_query_sender_privilege(call, capability); - if (r < 0) - return r; - else if (r > 0) - return 1; - else { - _cleanup_(_sd_bus_message_unrefp) sd_bus_message *request = NULL; - _cleanup_(_sd_bus_message_unrefp) sd_bus_message *reply = NULL; - int authorized = false, challenge = false; - const char *sender, **k, **v; - - sender = sd_bus_message_get_sender(call); - if (!sender) - return -EBADMSG; - - r = sd_bus_message_new_method_call(sd_bus_message_get_bus (call), - &request, - "org.freedesktop.PolicyKit1", - "/org/freedesktop/PolicyKit1/Authority", - "org.freedesktop.PolicyKit1.Authority", - "CheckAuthorization"); - if (r < 0) - return r; - - r = sd_bus_message_append(request, - "(sa{sv})s", - "system-bus-name", 1, "name", "s", sender, - action); - if (r < 0) - return r; - - r = sd_bus_message_open_container(request, 'a', "{ss}"); - if (r < 0) - return r; - - STRV_FOREACH_PAIR(k, v, details) { - r = sd_bus_message_append(request, "{ss}", *k, *v); - if (r < 0) - return r; - } - - r = sd_bus_message_close_container(request); - if (r < 0) - return r; - - r = sd_bus_message_append(request, "us", 0, NULL); - if (r < 0) - return r; - - r = sd_bus_call(sd_bus_message_get_bus(call), request, 0, e, &reply); - if (r < 0) { - /* Treat no PK available as access denied */ - if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) { - sd_bus_error_free(e); - return -EACCES; - } - - return r; - } - - r = sd_bus_message_enter_container(reply, 'r', "bba{ss}"); - if (r < 0) - return r; - - r = sd_bus_message_read(reply, "bb", &authorized, &challenge); - if (r < 0) - return r; - - if (authorized) - return 1; - - if (_challenge) { - *_challenge = challenge; - return 0; - } - } - - return -EACCES; -} diff --git a/src/sysprofd/sd-bus-helper.h b/src/sysprofd/sd-bus-helper.h deleted file mode 100644 index 58e2b9b8..00000000 --- a/src/sysprofd/sd-bus-helper.h +++ /dev/null @@ -1,36 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd 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. - - systemd 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 systemd; If not, see . -***/ - -#ifndef SD_BUS_HELPER_H -#define SD_BUS_HELPER_H - -#include -#include - -#define UID_INVALID ((uid_t)-1) - -int bus_test_polkit (sd_bus_message *call, - int capability, - const char *action, - const char **details, - uid_t good_user, - bool *_challenge, - sd_bus_error *e); - -#endif /* SD_BUS_HELPER_H */ diff --git a/src/sysprofd/sysprofd.c b/src/sysprofd/sysprofd.c index d876feac..fc944582 100644 --- a/src/sysprofd/sysprofd.c +++ b/src/sysprofd/sysprofd.c @@ -1,6 +1,6 @@ /* sysprofd.c * - * Copyright 2016 Christian Hergert + * Copyright 2019 Christian Hergert * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,413 +14,110 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later */ +#define G_LOG_DOMAIN "sysprofd" + #include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include -#include "sd-bus-helper.h" +#include "ipc-service.h" +#include "ipc-service-impl.h" -#include "sysprof-kallsyms.h" +#define BUS_NAME "org.gnome.Sysprof3" +#define OBJECT_PATH "/org/gnome/Sysprof3" +#define NAME_ACQUIRE_DELAY_SECS 3 -#define BUS_TIMEOUT_USEC (1000000L * 10L) +static GMainLoop *main_loop; +static gboolean name_acquired; +static gint exit_status = EXIT_SUCCESS; -#if 0 -#define GOTO(l) do { \ - fprintf (stderr, "GOTO: %s:%d: " #l "\n", __FUNCTION__, __LINE__); \ - goto l; \ -} while (0) -#else -#define GOTO(l) goto l -#endif - -static int -sysprofd_get_kernel_symbols (sd_bus_message *msg, - void *user_data, - sd_bus_error *error) +static void +name_acquired_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) { - g_autoptr(SysprofKallsyms) kallsyms = NULL; - sd_bus_message *reply = NULL; - const gchar *name; - guint64 addr; - guint8 type; - bool challenge = false; - int r; - - assert (msg); - assert (error); - - /* Authorize peer */ - r = bus_test_polkit (msg, - CAP_SYS_ADMIN, - "org.gnome.sysprof2.get-kernel-symbols", - NULL, - UID_INVALID, - &challenge, - error); - - if (r <= 0) - fprintf (stderr, "GetKernelSymbols() Failure: %s\n", error->message); - - if (r < 0) - return r; - else if (r == 0) - return -EACCES; - - if (!(kallsyms = sysprof_kallsyms_new (NULL))) - { - sd_bus_error_set (error, - SD_BUS_ERROR_FILE_NOT_FOUND, - "Failed to open /proc/kallsyms"); - return -ENOENT; - } - - r = sd_bus_message_new_method_return (msg, &reply); - if (r < 0) - return r; - - r = sd_bus_message_open_container (reply, 'a', "(tys)"); - if (r < 0) - return r; - - while (sysprof_kallsyms_next (kallsyms, &name, &addr, &type)) - sd_bus_message_append (reply, "(tys)", addr, type, name); - - r = sd_bus_message_close_container (reply); - if (r < 0) - return r; - - r = sd_bus_send (NULL, reply, NULL); - sd_bus_message_unref (reply); - - return r; + g_message ("Acquired Bus Name: %s", name); + name_acquired = TRUE; } -static int -_perf_event_open (struct perf_event_attr *attr, - pid_t pid, - int cpu, - int group_fd, - unsigned long flags) +static void +name_lost_cb (GDBusConnection *connection, + const gchar *name, + gpointer user_data) { - assert (attr != NULL); - - /* Quick sanity check */ - if (attr->sample_period < 100000 && attr->type != PERF_TYPE_TRACEPOINT) - return -EINVAL; - - return syscall (__NR_perf_event_open, attr, pid, cpu, group_fd, flags); + /* Exit if we lost the name */ + if (g_strcmp0 (name, BUS_NAME) == 0) + { + g_message ("Lost Bus Name: %s, exiting.", name); + name_acquired = FALSE; + g_main_loop_quit (main_loop); + } } -static int -sysprofd_perf_event_open (sd_bus_message *msg, - void *user_data, - sd_bus_error *error) +static gboolean +wait_for_acquire_timeout_cb (gpointer data) { - struct perf_event_attr attr = { 0 }; - sd_bus_message *reply = NULL; - uint64_t flags = 0; - int disabled = 0; - int32_t wakeup_events = 149; - int32_t cpu = -1; - int32_t pid = -1; - bool challenge = false; - int32_t type = 0; - uint64_t sample_period = 0; - uint64_t sample_type = 0; - uint64_t config = 0; - int clockid = CLOCK_MONOTONIC_RAW; - int comm = 0; - int mmap_ = 0; - int task = 0; - int exclude_idle = 0; - int fd = -1; - int use_clockid = 0; - int sample_id_all = 0; - int r; - - assert (msg); - - r = sd_bus_message_enter_container (msg, SD_BUS_TYPE_ARRAY, "{sv}"); - if (r < 0) - return r; - - for (;;) + if (!name_acquired) { - const char *name = NULL; - - r = sd_bus_message_enter_container (msg, SD_BUS_TYPE_DICT_ENTRY, "sv"); - if (r < 0) - return r; - - if (r == 0) - break; - - r = sd_bus_message_read (msg, "s", &name); - if (r < 0) - goto cleanup; - - r = sd_bus_message_enter_container (msg, SD_BUS_TYPE_VARIANT, NULL); - if (r < 0) - goto cleanup; - - if (strcmp (name, "disabled") == 0) - { - r = sd_bus_message_read (msg, "b", &disabled); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "wakeup_events") == 0) - { - r = sd_bus_message_read (msg, "u", &wakeup_events); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "sample_id_all") == 0) - { - r = sd_bus_message_read (msg, "b", &sample_id_all); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "clockid") == 0) - { - r = sd_bus_message_read (msg, "i", &clockid); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "comm") == 0) - { - r = sd_bus_message_read (msg, "b", &comm); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "exclude_idle") == 0) - { - r = sd_bus_message_read (msg, "b", &exclude_idle); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "mmap") == 0) - { - r = sd_bus_message_read (msg, "b", &mmap_); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "config") == 0) - { - r = sd_bus_message_read (msg, "t", &config); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "sample_period") == 0) - { - r = sd_bus_message_read (msg, "t", &sample_period); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "sample_type") == 0) - { - r = sd_bus_message_read (msg, "t", &sample_type); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "task") == 0) - { - r = sd_bus_message_read (msg, "b", &task); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "type") == 0) - { - r = sd_bus_message_read (msg, "u", &type); - if (r < 0) - GOTO (cleanup); - } - else if (strcmp (name, "use_clockid") == 0) - { - r = sd_bus_message_read (msg, "b", &use_clockid); - if (r < 0) - GOTO (cleanup); - } - - r = sd_bus_message_exit_container (msg); - if (r < 0) - goto cleanup; - - sd_bus_message_exit_container (msg); - if (r < 0) - goto cleanup; - - cleanup: - if (r < 0) - return r; + exit_status = EXIT_FAILURE; + g_critical ("Failed to acquire name on bus after %d seconds, exiting.", + NAME_ACQUIRE_DELAY_SECS); + g_main_loop_quit (main_loop); } - r = sd_bus_message_exit_container (msg); - if (r < 0) - return r; - - r = sd_bus_message_read (msg, "iit", &pid, &cpu, &flags); - if (r < 0) - return r; - - if (pid < -1 || cpu < -1) - return -EINVAL; - - r = sd_bus_message_new_method_return (msg, &reply); - if (r < 0) - return r; - - /* Authorize peer */ - r = bus_test_polkit (msg, - CAP_SYS_ADMIN, - "org.gnome.sysprof2.perf-event-open", - NULL, - UID_INVALID, - &challenge, - error); - if (r < 0) - return r; - else if (r == 0) - return -EACCES; - - attr.comm = !!comm; - attr.config = config; - attr.disabled = disabled; - attr.exclude_idle = !!exclude_idle; - attr.mmap = !!mmap_; - attr.sample_id_all = sample_id_all; - attr.sample_period = sample_period; - attr.sample_type = sample_type; - attr.task = !!task; - attr.type = type; - attr.wakeup_events = wakeup_events; - -#ifdef HAVE_PERF_CLOCKID - if (!use_clockid || clockid < 0) - attr.clockid = CLOCK_MONOTONIC_RAW; - else - attr.clockid = clockid; - attr.use_clockid = use_clockid; -#endif - - attr.size = sizeof attr; - - fd = _perf_event_open (&attr, pid, cpu, -1, 0); - if (fd < 0) - { - fprintf (stderr, - "Failed to open perf event stream: %s\n", - strerror (errno)); - return -EINVAL; - } - - sd_bus_message_append_basic (reply, SD_BUS_TYPE_UNIX_FD, &fd); - r = sd_bus_send (NULL, reply, NULL); - sd_bus_message_unref (reply); - - close (fd); - - return r; + return G_SOURCE_REMOVE; } -static const sd_bus_vtable sysprofd_vtable[] = { - SD_BUS_VTABLE_START (0), - SD_BUS_METHOD ("PerfEventOpen", "a{sv}iit", "h", sysprofd_perf_event_open, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD ("GetKernelSymbols", "", "a(tys)", sysprofd_get_kernel_symbols, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_VTABLE_END -}; - -int -main (int argc, - char *argv[]) +gint +main (gint argc, + gchar *argv[]) { - sd_bus_slot *slot = NULL; - sd_bus *bus = NULL; - int r; + g_autoptr(GDBusConnection) bus = NULL; + g_autoptr(GError) error = NULL; + GBusType bus_type = G_BUS_TYPE_SYSTEM; - /* Connect to the system bus */ - r = sd_bus_default_system (&bus); - if (r < 0) - { - fprintf (stderr, - "Failed to connect to system bus: %s\n", - strerror (-r)); - goto failure; - } + g_set_prgname ("sysprofd"); + g_set_application_name ("sysprofd"); - /* Install our object */ - r = sd_bus_add_object_vtable (bus, - &slot, - "/org/gnome/Sysprof2", - "org.gnome.Sysprof2", - sysprofd_vtable, - NULL); - if (r < 0) - { - fprintf (stderr, - "Failed to install object on bus: %s\n", - strerror (-r)); - goto failure; - } + if (g_getenv ("SYSPROFD_USE_SESSION_BUS")) + bus_type = G_BUS_TYPE_SESSION; - /* Request our well-known name on the bus */ - r = sd_bus_request_name (bus, "org.gnome.Sysprof2", 0); - if (r < 0) - { - fprintf (stderr, - "Failed to register name on the bus: %s\n", - strerror (-r)); - goto failure; - } + main_loop = g_main_loop_new (NULL, FALSE); - for (;;) + if ((bus = g_bus_get_sync (bus_type, NULL, &error))) { - /* Process requests */ - r = sd_bus_process (bus, NULL); - if (r < 0) + g_autoptr(IpcService) service = ipc_service_impl_new (); + + if (g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (service), + bus, + OBJECT_PATH, + &error)) { - fprintf (stderr, - "Failed to process bus: %s\n", - strerror (-r)); - goto failure; + g_bus_own_name_on_connection (bus, + BUS_NAME, + (G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | + G_BUS_NAME_OWNER_FLAGS_REPLACE), + name_acquired_cb, + name_lost_cb, + NULL, + NULL); + g_timeout_add_seconds (NAME_ACQUIRE_DELAY_SECS, + wait_for_acquire_timeout_cb, + NULL); + g_main_loop_run (main_loop); + g_main_loop_unref (main_loop); + + return exit_status; } - - /* If we processed a request, continue processing */ - if (r > 0) - continue; - - /* Wait for the next request to process */ - r = sd_bus_wait (bus, BUS_TIMEOUT_USEC); - if (r < 0) - { - fprintf (stderr, - "Failed to wait on bus: %s\n", - strerror (-r)); - goto failure; - } - - /* - * If we timed out, we can expire, we will be auto-started by - * systemd or dbus on the next activation request. - */ - if (r == 0) - break; } -failure: - sd_bus_slot_unref (slot); - sd_bus_unref (bus); + g_error ("Failed to setup system bus: %s", error->message); - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + g_main_loop_unref (main_loop); + + return EXIT_FAILURE; }