diff --git a/CMakeLists.txt b/CMakeLists.txt index 6579fb856caf984cb85cf239ba1b7c7f05a44a13..6e38fde6ecb11ffcb6bd829764ebc281bbffe883 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,13 +30,13 @@ set(PROJECT_DISTCONFIGURE_PARAMS -DENABLE_VALA_BINDINGS=ON -DENABLE_INSTALLED_TESTS=ON -DENABLE_GTK_DOC=ON - -DENABLE_DBUS_SESSION_TOOL=ON -DWITH_PRIVATE_DOCS=ON ) # ****************************** # D-Bus versioning # ****************************** +# Actual name can be modified with DBUS_SERVICES_PREFIX option set(ADDRESS_BOOK_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook9") set(CALENDAR_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.Calendar7") set(SOURCES_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.Sources5") @@ -170,6 +170,15 @@ ensure_default_value(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share") ensure_default_value(LOCALE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/locale") ensure_default_value(SYSCONF_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/etc") +add_printable_variable(DBUS_SERVICES_PREFIX "Prefix for D-Bus services, usually left empty, without trailing dot" "") + +if(NOT ("${DBUS_SERVICES_PREFIX}" STREQUAL "")) + set(ADDRESS_BOOK_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${ADDRESS_BOOK_DBUS_SERVICE_NAME}") + set(CALENDAR_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${CALENDAR_DBUS_SERVICE_NAME}") + set(SOURCES_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${SOURCES_DBUS_SERVICE_NAME}") + set(USER_PROMPTER_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${USER_PROMPTER_DBUS_SERVICE_NAME}") +endif(NOT ("${DBUS_SERVICES_PREFIX}" STREQUAL "")) + # ****************************** # Special directories # ****************************** @@ -980,12 +989,6 @@ if(ENABLE_VALA_BINDINGS) endif(ENABLE_VALA_BINDINGS) -# ****************************** -# D-Bus session tool, a Flatpak helper -# ****************************** - -add_printable_option(ENABLE_DBUS_SESSION_TOOL "Build evolution-dbus-session tool" OFF) - # Generate the ${PROJECT_NAME}-config.h file CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.in ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-config.h) diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 796e02b6f39bac0b9c401d1333f1f72051e8a34d..e13c25f4f0a465b52a03b6daab184de68916222a 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,6 +1,2 @@ add_subdirectory(addressbook-export) add_subdirectory(list-sources) - -if(ENABLE_DBUS_SESSION_TOOL) - add_subdirectory(evolution-dbus-session) -endif(ENABLE_DBUS_SESSION_TOOL) diff --git a/src/tools/evolution-dbus-session/CMakeLists.txt b/src/tools/evolution-dbus-session/CMakeLists.txt deleted file mode 100644 index 2f063589377130b77130fca99de2ed38d1401bab..0000000000000000000000000000000000000000 --- a/src/tools/evolution-dbus-session/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -set(SOURCES - evolution-dbus-session.c -) - -add_executable(evolution-dbus-session - ${SOURCES} -) - -target_compile_definitions(evolution-dbus-session PRIVATE - -DG_LOG_DOMAIN=\"evolution-dbus-session\" -) - -target_compile_options(edataserver PUBLIC - ${GNOME_PLATFORM_CFLAGS} -) - -target_include_directories(evolution-dbus-session PUBLIC - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}/src - ${CMAKE_SOURCE_DIR}/src - ${CMAKE_CURRENT_BINARY_DIR} - ${GNOME_PLATFORM_INCLUDE_DIRS} -) - -target_link_libraries(evolution-dbus-session - ${GNOME_PLATFORM_LDFLAGS} -) - -install(TARGETS evolution-dbus-session - DESTINATION ${privlibexecdir} -) diff --git a/src/tools/evolution-dbus-session/evolution-dbus-session.c b/src/tools/evolution-dbus-session/evolution-dbus-session.c deleted file mode 100644 index f0c8e638c2554379dc1850a34a600006660ff511..0000000000000000000000000000000000000000 --- a/src/tools/evolution-dbus-session/evolution-dbus-session.c +++ /dev/null @@ -1,823 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com) - * - * This program 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. - * - * 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 Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#include "evolution-data-server-config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DBUS_CALL_TIMEOUT -1 /* as set by D-Bus settings */ - -static void -object_manager_object_added_cb (GDBusObjectManager *manager, - GDBusObject *object, - gpointer user_data); -static void -object_manager_object_removed_cb (GDBusObjectManager *manager, - GDBusObject *object, - gpointer user_data); - -typedef struct _ProxyData { - gchar *iface_name; - gchar *path; - - /* The original D-Bus session part */ - GDBusProxy *proxy; - GDBusObjectManager *object_manager; - GSList *sigids; /* GUINT_TO_POINTER(sigid) */ - - /* The new D-Bus session part */ - GDBusConnection *regs_connection; - guint ownid; - GSList *regids; /* GUINT_TO_POINTER(regid) */ - GSList *object_manager_pds; /* ProxyData *, when object_manager is not NULL */ -} ProxyData; - -static void -proxy_data_free (gpointer ptr) -{ - ProxyData *pd = ptr; - - if (pd) { - if (pd->object_manager) - g_signal_handlers_disconnect_by_data (pd->object_manager, pd); - - g_slist_free_full (pd->object_manager_pds, proxy_data_free); - - if (pd->regs_connection && !g_dbus_connection_is_closed (pd->regs_connection)) { - GSList *link; - - for (link = pd->regids; link; link = g_slist_next (link)) { - guint regid = GPOINTER_TO_UINT (link->data); - - g_dbus_connection_unregister_object (pd->regs_connection, regid); - } - - if (pd->object_manager) { - GList *objects, *llink; - - objects = g_dbus_object_manager_get_objects (pd->object_manager); - - for (llink = objects; llink; llink = g_list_next (llink)) { - GDBusObject *object = llink->data; - - object_manager_object_removed_cb (pd->object_manager, object, pd); - } - - g_list_free_full (objects, g_object_unref); - } - } - - if (pd->ownid) { - g_bus_unown_name (pd->ownid); - pd->ownid = 0; - } - - if (pd->proxy && pd->sigids) { - GDBusConnection *connection; - - connection = g_dbus_proxy_get_connection (pd->proxy); - - if (connection && !g_dbus_connection_is_closed (connection)) { - GSList *link; - - for (link = pd->sigids; link; link = g_slist_next (link)) { - guint sigid = GPOINTER_TO_UINT (link->data); - - g_dbus_connection_signal_unsubscribe (connection, sigid); - } - } - } - - g_clear_object (&pd->proxy); - g_clear_object (&pd->object_manager); - g_clear_object (&pd->regs_connection); - g_slist_free (pd->regids); - g_slist_free (pd->sigids); - g_free (pd->iface_name); - g_free (pd->path); - g_free (pd); - } -} - -/* encoded_string :== iface_name + ":" + path */ -static ProxyData * -proxy_data_new (const gchar *encoded_string) -{ - ProxyData *pd; - gchar **strv; - GError *error = NULL; - - strv = g_strsplit (encoded_string, ":", -1); - g_return_val_if_fail (strv != NULL, NULL); - if (!strv[0] || !strv[1] || strv[2]) { - g_warning ("Unexpected proxy data string format: '%s'", encoded_string); - g_strfreev (strv); - return NULL; - } - - pd = g_new0 (ProxyData, 1); - pd->iface_name = g_strdup (strv[0]); /* like "org.freedesktop.portal.Desktop" */ - pd->path = g_strdup (strv[1]); /* like "/org/freedesktop/portal/desktop" */ - pd->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, NULL, - pd->iface_name, pd->path, pd->iface_name, NULL, &error); - - if (!pd->proxy) { - g_warning ("Failed to open proxy for interface '%s' at path '%s': %s", pd->iface_name, pd->path, error ? error->message : "Unknown error"); - proxy_data_free (pd); - pd = NULL; - } - - g_clear_error (&error); - g_strfreev (strv); - - return pd; -} - -static void -handle_method_call_cb (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ -#ifdef G_OS_UNIX - GDBusMessage *message; - GUnixFDList *in_fd_list, *out_fd_list = NULL; -#endif - ProxyData *pd = user_data; - GVariant *result; - GError *error = NULL; - - g_return_if_fail (pd != NULL); - -#ifdef G_OS_UNIX - message = g_dbus_method_invocation_get_message (invocation); - in_fd_list = g_dbus_message_get_unix_fd_list (message); - - result = g_dbus_connection_call_with_unix_fd_list_sync (g_dbus_proxy_get_connection (pd->proxy), - g_dbus_proxy_get_name (pd->proxy), - object_path, - interface_name, - method_name, - parameters, - NULL, - G_DBUS_CALL_FLAGS_NONE, - DBUS_CALL_TIMEOUT, - in_fd_list, - &out_fd_list, - NULL, &error); -#else - result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (pd->proxy), - g_dbus_proxy_get_name (pd->proxy), - object_path, - interface_name, - method_name, - parameters, - NULL, - G_DBUS_CALL_FLAGS_NONE, - DBUS_CALL_TIMEOUT, - NULL, &error); -#endif - - if (result) { - #ifdef G_OS_UNIX - if (out_fd_list) { - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, result, out_fd_list); - g_object_unref (out_fd_list); - } else { - g_dbus_method_invocation_return_value (invocation, result); - } - #else - g_dbus_method_invocation_return_value (invocation, result); - #endif - g_variant_unref (result); - } else { - g_dbus_method_invocation_return_gerror (invocation, error); - } - - g_clear_error (&error); -} - -static GVariant * -handle_get_property_cb (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - ProxyData *pd = user_data; - - g_return_val_if_fail (pd != NULL, NULL); - - return g_dbus_connection_call_sync (g_dbus_proxy_get_connection (pd->proxy), - g_dbus_proxy_get_name (pd->proxy), - object_path, - "org.freedesktop.DBus.Properties", - "Get", - g_variant_new ("(ss)", interface_name, property_name), - G_VARIANT_TYPE ("(s)"), - G_DBUS_CALL_FLAGS_NONE, - DBUS_CALL_TIMEOUT, - NULL, error); -} - -static gboolean -handle_set_property_cb (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GVariant *value, - GError **error, - gpointer user_data) -{ - ProxyData *pd = user_data; - GVariant *result; - GError *local_error = NULL; - - g_return_val_if_fail (pd != NULL, FALSE); - - result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (pd->proxy), - g_dbus_proxy_get_name (pd->proxy), - object_path, - "org.freedesktop.DBus.Properties", - "Set", - g_variant_new ("(ssv)", interface_name, property_name, value), - NULL, - G_DBUS_CALL_FLAGS_NONE, - DBUS_CALL_TIMEOUT, - NULL, &local_error); - - if (result) - g_variant_unref (result); - - if (local_error) - g_propagate_error (error, local_error); - - return local_error != NULL; -} - -static void -handle_signal_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - ProxyData *pd = user_data; - GError *error = NULL; - - g_return_if_fail (pd != NULL); - - if (!g_dbus_connection_emit_signal (pd->regs_connection, NULL, object_path, - interface_name, signal_name, parameters, &error)) { - g_clear_error (&error); - } -} - -static void -proxy_data_reg_interfaces_for_object_path (ProxyData *pd, - GDBusConnection *connection, - const gchar *object_path) -{ - const GDBusInterfaceVTable interface_vtable = { - handle_method_call_cb, - handle_get_property_cb, - handle_set_property_cb - }; - GDBusNodeInfo *introspection_data; - GVariant *result; - const gchar *xml_data; - guint regid; - gint ii; - gboolean is_object_manager = FALSE; - GError *error = NULL; - - g_return_if_fail (pd != NULL); - g_return_if_fail (pd->proxy != NULL); - g_return_if_fail (connection != NULL); - - result = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (pd->proxy), - g_dbus_proxy_get_name (pd->proxy), - object_path, - "org.freedesktop.DBus.Introspectable", - "Introspect", - NULL, - G_VARIANT_TYPE ("(s)"), - G_DBUS_CALL_FLAGS_NONE, - DBUS_CALL_TIMEOUT, - NULL, &error); - - if (!result) { - g_warning ("Failed to get introspected data for '%s': %s", g_dbus_proxy_get_name (pd->proxy), error ? error->message : "Unknown error"); - g_clear_error (&error); - return; - } - - g_variant_get (result, "(&s)", &xml_data); - introspection_data = g_dbus_node_info_new_for_xml (xml_data, NULL); - g_variant_unref (result); - - if (!introspection_data) { - g_warning ("Failed to parse introspected data for '%s': %s", g_dbus_proxy_get_name (pd->proxy), error ? error->message : "Unknown error"); - g_clear_error (&error); - return; - } - - pd->regs_connection = g_object_ref (connection); - - for (ii = 0; introspection_data->interfaces && introspection_data->interfaces[ii]; ii++) { - GDBusInterfaceInfo *iface_info = introspection_data->interfaces[ii]; - - if (!iface_info) - continue; - - regid = g_dbus_connection_register_object (pd->regs_connection, object_path, - iface_info, - &interface_vtable, - pd, - NULL, - &error); - - if (regid) { - pd->regids = g_slist_prepend (pd->regids, GUINT_TO_POINTER (regid)); - - if (iface_info->signals) { - gint jj; - - for (jj = 0; iface_info->signals[jj]; jj++) { - guint sigid; - - sigid = g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (pd->proxy), NULL, - iface_info->name, - iface_info->signals[jj]->name, - object_path, - NULL, G_DBUS_SIGNAL_FLAGS_NONE, - handle_signal_cb, pd, NULL); - - if (sigid) - pd->sigids = g_slist_prepend (pd->sigids, GUINT_TO_POINTER (sigid)); - } - } - - if (g_strcmp0 (iface_info->name, "org.freedesktop.DBus.ObjectManager") == 0) { - is_object_manager = TRUE; - - pd->object_manager = g_dbus_object_manager_client_new_sync (g_dbus_proxy_get_connection (pd->proxy), - G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, - g_dbus_proxy_get_name (pd->proxy), - object_path, - NULL, NULL, NULL, NULL, &error); - - if (pd->object_manager) { - GList *objects, *link; - - g_signal_connect (pd->object_manager, "object-added", - G_CALLBACK (object_manager_object_added_cb), pd); - g_signal_connect (pd->object_manager, "object-removed", - G_CALLBACK (object_manager_object_removed_cb), pd); - - objects = g_dbus_object_manager_get_objects (pd->object_manager); - for (link = objects; link; link = g_list_next (link)) { - GDBusObject *object = link->data; - - object_manager_object_added_cb (pd->object_manager, object, pd); - } - - g_list_free_full (objects, g_object_unref); - } else { - g_clear_error (&error); - } - } - } else { - g_clear_error (&error); - } - } - - if (!is_object_manager && introspection_data->nodes) { - for (ii = 0; introspection_data->nodes[ii]; ii++) { - GDBusNodeInfo *node_info = introspection_data->nodes[ii]; - - if (node_info && node_info->path) { - gchar *path; - - if (node_info->path[0] == '/') - path = g_strdup (node_info->path); - else - path = g_strconcat (object_path, "/", node_info->path, NULL); - - if (g_variant_is_object_path (path)) - proxy_data_reg_interfaces_for_object_path (pd, connection, path); - - g_free (path); - } - } - } - - g_dbus_node_info_unref (introspection_data); -} - -static void -proxy_data_reg_interfaces (ProxyData *pd, - GDBusConnection *connection) -{ - g_return_if_fail (pd != NULL); - g_return_if_fail (pd->proxy != NULL); - g_return_if_fail (pd->regs_connection == NULL); - g_return_if_fail (connection != NULL); - - proxy_data_reg_interfaces_for_object_path (pd, connection, g_dbus_proxy_get_object_path (pd->proxy)); -} - -static void -bus_name_acquired_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - ProxyData *pd = user_data; - - g_return_if_fail (pd != NULL); - - proxy_data_reg_interfaces (pd, connection); -} - -static void -bus_name_lost_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - ProxyData *pd = user_data; - - g_return_if_fail (pd != NULL); -} - -static void -object_manager_object_added_cb (GDBusObjectManager *manager, - GDBusObject *object, - gpointer user_data) -{ - ProxyData *parent_pd = user_data, *child_pd; - gchar *encoded_string; - - encoded_string = g_strconcat (parent_pd->iface_name, ":", g_dbus_object_get_object_path (object), NULL); - child_pd = proxy_data_new (encoded_string); - g_free (encoded_string); - - if (child_pd) { - proxy_data_reg_interfaces (child_pd, parent_pd->regs_connection); - parent_pd->object_manager_pds = g_slist_prepend (parent_pd->object_manager_pds, child_pd); - } -} - -static void -object_manager_object_removed_cb (GDBusObjectManager *manager, - GDBusObject *object, - gpointer user_data) -{ - ProxyData *parent_pd = user_data; - GSList *link; - const gchar *obj_path; - - obj_path = g_dbus_object_get_object_path (object); - for (link = parent_pd->object_manager_pds; link; link = g_slist_next (link)) { - ProxyData *child_pd = link->data; - - if (child_pd && g_strcmp0 (child_pd->path, obj_path) == 0) { - proxy_data_free (child_pd); - parent_pd->object_manager_pds = g_slist_remove (parent_pd->object_manager_pds, child_pd); - break; - } - } -} - -static gpointer -main_loop_thread (gpointer user_data) -{ - GMainLoop *main_loop = user_data; - - g_main_loop_run (main_loop); - - return NULL; -} - -/* Adapted from glib's gtestdbus.c */ -static gchar * -write_config_file (const GSList *service_dirs) -{ - GString *contents; - gint fd; - GSList *link; - gchar *path = NULL; - GError *error = NULL; - - fd = g_file_open_tmp ("evolution-bus-tunnel-XXXXXX", &path, &error); - if (fd <= 0) { - g_warning ("Failed to create tmp file for D-Bus configuration: %s", error ? error->message : "Unknown error"); - g_clear_error (&error); - return NULL; - } - - contents = g_string_new (NULL); - g_string_append (contents, - "\n" - " session\n" - " unix:tmpdir=/tmp\n"); - - for (link = (GSList *) service_dirs; link; link = g_slist_next (link)) { - const gchar *dir_path = link->data; - - g_string_append_printf (contents," %s\n", dir_path); - } - - g_string_append (contents, - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"); - - close (fd); - if (!g_file_set_contents (path, contents->str, contents->len, &error)) { - g_warning ("Failed to write file '%s': %s", path, error ? error->message : "Unknown error"); - g_clear_error (&error); - g_free (path); - return NULL; - } - - g_string_free (contents, TRUE); - - return path; -} - -/* Adapted from glib's gtestdbus.c */ -static gboolean -start_daemon (const GSList *service_dirs, - GPid *pbus_pid, - gint *pbus_stdout_fd, - gchar **pbus_address) -{ - const gchar *argv[] = {"dbus-daemon", "--print-address", "--config-file=foo", NULL}; - gchar *config_path; - gchar *config_arg; - GIOChannel *channel; - gint stdout_fd2; - gsize termpos; - GError *error = NULL; - - /* Write config file and set its path in argv */ - config_path = write_config_file (service_dirs); - config_arg = g_strdup_printf ("--config-file=%s", config_path); - argv[2] = config_arg; - - /* Spawn dbus-daemon */ - g_spawn_async_with_pipes (NULL, (gchar **) argv, NULL, - G_SPAWN_SEARCH_PATH, NULL, NULL, pbus_pid, - NULL, pbus_stdout_fd, NULL, &error); - if (error) { - g_warning ("Failed to start D-Bus daemon: %s", error->message); - g_clear_error (&error); - g_free (config_path); - g_free (config_arg); - return FALSE; - } - - /* Read bus address from daemon' stdout. We have to be careful to avoid - * closing the FD, as it is passed to any D-Bus service activated processes, - * and if we close it, they will get a SIGPIPE and die when they try to write - * to their stdout. */ - stdout_fd2 = dup (*pbus_stdout_fd); - g_assert_cmpint (stdout_fd2, >=, 0); - channel = g_io_channel_unix_new (stdout_fd2); - - g_io_channel_read_line (channel, pbus_address, NULL, &termpos, &error); - if (error) { - g_warning ("Failed to read new D-Bus daemon address: %s", error->message); - g_io_channel_shutdown (channel, FALSE, NULL); - g_io_channel_unref (channel); - g_clear_error (&error); - g_free (config_path); - g_free (config_arg); - return FALSE; - } - - (*pbus_address)[termpos] = '\0'; - - /* Cleanup */ - g_io_channel_shutdown (channel, FALSE, &error); - if (error) { - g_debug ("Failed to shutdown io channel: %s", error->message); - g_clear_error (&error); - } - g_io_channel_unref (channel); - - /* Don't use g_file_delete since it calls into gvfs */ - if (g_unlink (config_path) != 0) - g_warning ("Failed to remove config file '%s'", config_path); - - g_free (config_path); - g_free (config_arg); - - g_unsetenv ("DBUS_STARTER_ADDRESS"); - g_unsetenv ("DBUS_STARTER_BUS_TYPE"); - g_setenv ("DBUS_SESSION_BUS_ADDRESS", *pbus_address, TRUE); - - return TRUE; -} - -/* Adapted from glib's gtestdbus.c */ -static void -stop_daemon (GPid *pbus_pid, - gint *pbus_stdout_fd, - gchar **pbus_address) -{ - kill (*pbus_pid, SIGTERM); - g_spawn_close_pid (*pbus_pid); - *pbus_pid = 0; - - close (*pbus_stdout_fd); - *pbus_stdout_fd = -1; - - g_free (*pbus_address); - *pbus_address = NULL; -} - -static void -print_help (void) -{ - printf ("Usage: evolution-dbus-session --exec exec [ --service-dir dir ] [ --iface name:path ]\n"); - printf (" --help ... shows this help and exits\n"); - printf (" --exec exec ... a program to run in a dedicated D-Bus session\n"); - printf (" --service-dir dir ... adds a dir as a service directory for the new D-Bus session\n"); - printf (" --iface name:path ... adds an interface name and its D-Bus path to proxy into the new D-Bus session\n"); - printf ("\n"); - printf (" Both --service-dir and --iface arguments are optional and can be specified multiple times.\n"); -} - -gint -main (gint argc, - gchar *argv[]) -{ - GPid bus_pid = 0; - gint bus_stdout_fd = -1, ii, res = 0; - gchar *bus_address = NULL; - GSList *service_dirs = NULL; - GSList *pds = NULL; /* ProxyData * */ - const gchar *to_exec = NULL; - - if (argc == 1) { - print_help (); - return 0; - } - - for (ii = 1; ii < argc; ii++) { - if (g_str_equal (argv[ii], "--help")) { - print_help (); - g_slist_free_full (pds, proxy_data_free); - g_slist_free (service_dirs); - return 0; - } else if (g_str_equal (argv[ii], "--exec")) { - if (ii + 1 >= argc) { - g_printerr ("Missing value for %s\n", argv[ii]); - return 1; - } - - ii++; - to_exec = argv[ii]; - } else if (g_str_equal (argv[ii], "--service-dir")) { - if (ii + 1 >= argc) { - g_printerr ("Missing value for %s\n", argv[ii]); - return 2; - } - - ii++; - service_dirs = g_slist_prepend (service_dirs, argv[ii]); - } else if (g_str_equal (argv[ii], "--iface")) { - ProxyData *pd; - - if (ii + 1 >= argc) { - g_printerr ("Missing value for %s\n", argv[ii]); - return 3; - } - - ii++; - pd = proxy_data_new (argv[ii]); - if (pd) { - pds = g_slist_prepend (pds, pd); - } - } else { - g_printerr ("Unknown argument '%s'\n", argv[ii]); - return 4; - } - } - - if (!pds) { - g_printerr ("No --iface defined or cannot connect to any, exiting\n"); - g_slist_free_full (pds, proxy_data_free); - g_slist_free (service_dirs); - return 5; - } - - if (!to_exec) { - g_printerr ("No --exec defined, exiting\n"); - g_slist_free_full (pds, proxy_data_free); - g_slist_free (service_dirs); - return 6; - } - - /* Preserve order as specified on the command line */ - pds = g_slist_reverse (pds); - service_dirs = g_slist_reverse (service_dirs); - - if (start_daemon (service_dirs, &bus_pid, &bus_stdout_fd, &bus_address)) { - GThread *thread; - GMainLoop *main_loop; - GDBusConnection *connection; - GError *error = NULL; - - connection = g_dbus_connection_new_for_address_sync (bus_address, - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, NULL, NULL, &error); - if (connection) { - GSList *link; - - for (link = pds; link; link = g_slist_next (link)) { - ProxyData *pd = link->data; - - if (!pd) - continue; - - pd->ownid = g_bus_own_name_on_connection (connection, - pd->iface_name, - G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, - bus_name_acquired_cb, - bus_name_lost_cb, - pd, NULL); - } - - main_loop = g_main_loop_new (NULL, FALSE); - - thread = g_thread_new (NULL, main_loop_thread, main_loop); - - if (system (to_exec) == -1) - g_warning ("Failed to execute '%s'", to_exec); - - if (!g_dbus_connection_is_closed (connection) && - !g_dbus_connection_close_sync (connection, NULL, &error)) { - g_warning ("Failed to close connection: %s", error ? error->message : "Unknown error"); - g_clear_error (&error); - } - - g_slist_free_full (pds, proxy_data_free); - pds = NULL; - - stop_daemon (&bus_pid, &bus_stdout_fd, &bus_address); - g_main_loop_quit (main_loop); - g_thread_join (thread); - - g_main_loop_unref (main_loop); - g_clear_object (&connection); - } else { - g_warning ("Failed to create connection for dedicated server address '%s': %s", - bus_address, error ? error->message : "Unknown error"); - g_clear_error (&error); - } - } else { - res = 7; - } - - g_slist_free_full (pds, proxy_data_free); - g_slist_free (service_dirs); - - return res; -}