From 956e79652c48c440733b2443530f26c2081a6af8 Mon Sep 17 00:00:00 2001 From: Ralf Habacker Date: Sun, 18 Mar 2018 20:07:33 +0100 Subject: Add integration config file support. - non standard dbus session config bus - autolaunch dbus-daemon executable --- cmake/CMakeLists.txt | 6 +- cmake/dbus/CMakeLists.txt | 23 ++++++ cmake/doc/CMakeLists.txt | 1 + dbus/dbus-config-loader-expat.c | 164 ++++++++++++++++++++++++++++++++++++++++ dbus/dbus-config-parser.c | 72 ++++++++++++++++++ dbus/dbus-config-parser.h | 53 +++++++++++++ dbus/dbus-sysdeps-util-win.c | 7 ++ dbus/dbus-sysdeps-win.c | 132 +++++++++++++++++++++++++------- dbus/dbus-sysdeps.h | 1 + dbus/integration.conf.in | 16 ++++ doc/integration.dtd | 5 ++ 11 files changed, 452 insertions(+), 28 deletions(-) create mode 100644 dbus/dbus-config-loader-expat.c create mode 100644 dbus/dbus-config-parser.c create mode 100644 dbus/dbus-config-parser.h create mode 100644 dbus/integration.conf.in create mode 100644 doc/integration.dtd diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index c1f0f1659..8990adde9 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -147,6 +147,8 @@ endif() # analogous to AC_USE_SYSTEM_EXTENSIONS in configure.ac add_definitions(-D_GNU_SOURCE) +OPTION(DBUS_INTEGRATION_CONFIG "Enable file based integration configuration" OFF) + # do config checks INCLUDE(ConfigureChecks.cmake) @@ -507,8 +509,8 @@ if (DBUS_BUILD_TESTS) endif (WIN32) endif (DBUS_BUILD_TESTS) -set(DBUS_LIBRARIES dbus-1) -set(DBUS_INTERNAL_LIBRARIES dbus-internal) +set(DBUS_LIBRARIES dbus-1 expat) +set(DBUS_INTERNAL_LIBRARIES dbus-internal expat) set (DBUS_INTERNAL_ADD_LIBRARY_OPTIONS STATIC) set (DBUS_INTERNAL_CLIENT_DEFINITIONS "-DDBUS_COMPILATION") diff --git a/cmake/dbus/CMakeLists.txt b/cmake/dbus/CMakeLists.txt index 33f2be600..5945ad928 100644 --- a/cmake/dbus/CMakeLists.txt +++ b/cmake/dbus/CMakeLists.txt @@ -1,6 +1,10 @@ SET(DBUS_DIR ${CMAKE_SOURCE_DIR}/../dbus) configure_file(${DBUS_DIR}/dbus-arch-deps.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbus-arch-deps.h ) +if(DBUS_INTEGRATION_CONFIG) + configure_file(${DBUS_DIR}/integration.conf.in ${CMAKE_CURRENT_BINARY_DIR}/integration.conf ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/integration.conf DESTINATION share/dbus-1) +endif() add_definitions(-DDBUS_COMPILATION) @@ -255,6 +259,18 @@ if(WIN32) list(APPEND libdbus_SOURCES versioninfo.rc) endif() +if(DBUS_INTEGRATION_CONFIG) + set (DBUS_CONFIG_SOURCES + ${DBUS_DIR}/dbus-config-parser.c + ${DBUS_DIR}/dbus-config-loader-expat.c + ${DBUS_UTIL_SOURCES} + ) + set (DBUS_CONFIG_HEADERS + ${DBUS_DIR}/dbus-config-parser.h + ${DBUS_UTIL_HEADERS} + ) +endif() + if(MSVC_IDE) project_source_group(${GROUP_CODE} DBUS_LIB_SOURCES DBUS_LIB_HEADERS) project_source_group(${GROUP_CODE} DBUS_SHARED_SOURCES DBUS_SHARED_HEADERS) @@ -271,6 +287,8 @@ find_library(LIBSOCKET socket) add_library(dbus-1 SHARED ${libdbus_SOURCES} ${libdbus_HEADERS} + ${DBUS_CONFIG_SOURCES} + ${DBUS_CONFIG_HEADERS} ) if(WIN32) @@ -307,6 +325,11 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") set_target_properties(dbus-1 PROPERTIES LINK_FLAGS -Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/Version) endif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") +if(DBUS_INTEGRATION_CONFIG) + target_link_libraries(dbus-1 expat) + set_target_properties(dbus-1 PROPERTIES COMPILE_FLAGS -DDBUS_INTEGRATION_CONFIG) +endif() + install(TARGETS dbus-1 ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${dbusinclude_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dbus-1.0/dbus) install(FILES ${dbusinclude_ARCH_HEADERS} DESTINATION ${CMAKE_INSTALL_LIBDIR}/dbus-1.0/include/dbus) diff --git a/cmake/doc/CMakeLists.txt b/cmake/doc/CMakeLists.txt index f21e84e7a..e487cae48 100644 --- a/cmake/doc/CMakeLists.txt +++ b/cmake/doc/CMakeLists.txt @@ -166,6 +166,7 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/index.html DESTINATION share/doc/dbus) set (EXTRA_DIST ${CMAKE_SOURCE_DIR}/../doc/busconfig.dtd + ${CMAKE_SOURCE_DIR}/../doc/integration.dtd ${CMAKE_SOURCE_DIR}/../doc/introspect.dtd ${CMAKE_SOURCE_DIR}/../doc/introspect.xsl ) diff --git a/dbus/dbus-config-loader-expat.c b/dbus/dbus-config-loader-expat.c new file mode 100644 index 000000000..352d3d993 --- /dev/null +++ b/dbus/dbus-config-loader-expat.c @@ -0,0 +1,164 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-config-loader-expat.c expat XML loader + * + * Copyright (C) 2015-2018 Ralf Habacker + * + * Licensed under the Academic Free License version 2.1 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef XML_LARGE_SIZE +#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400 +#define XML_FMT_INT_MOD "I64" +#else +#define XML_FMT_INT_MOD "ll" +#endif +#else +#define XML_FMT_INT_MOD "l" +#endif + +typedef struct { + IntegrationConfigParser *parser; + DBusString content; + dbus_bool_t in_session_bus; + dbus_bool_t in_autolaunch; + DBusError *error; + dbus_bool_t failed; +} ExpatIntegrationParseContext; + +static void XMLCALL +integration_config_start_element (void *userData, const char *name, const char **atts) +{ + ExpatIntegrationParseContext *context = userData; + _dbus_string_set_length (&context->content, 0); + if (strcmp (name,"sessionbus") == 0) + context->in_session_bus = TRUE; + else if (strcmp (name,"autolaunch") == 0) + context->in_autolaunch = TRUE; +} + +static void XMLCALL +integration_config_end_element (void *userData, const char *name) +{ + ExpatIntegrationParseContext *context = userData; + + if (_dbus_string_get_length (&context->content) > 0) + { + if (context->in_session_bus && strcmp (name,"connect") == 0) + context->parser->session_bus_address = _dbus_strdup (_dbus_string_get_const_data (&context->content)); + else if (context->in_autolaunch && strcmp (name,"executable") == 0) + context->parser->autolaunch_executable = _dbus_strdup (_dbus_string_get_const_data (&context->content)); + _dbus_string_set_length (&context->content, 0); + } + if (strcmp (name,"sessionbus") == 0) + context->in_session_bus = FALSE; +} + +/* s is not 0 terminated. */ +static void +integration_config_CharacterDataHandler (void *userData, + const XML_Char *s, + int len) +{ + ExpatIntegrationParseContext *context = userData; + if (context->failed) + return; + + if (!_dbus_string_append_len (&context->content, + s, len)) + { + dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL); + context->failed = TRUE; + return; + } +} + +IntegrationConfigParser* +integration_config_load (const DBusString *file, + const IntegrationConfigParser *parent, + DBusError *error) +{ + IntegrationConfigParser *parser; + ExpatIntegrationParseContext context; + DBusString data; + const char *data_str; + XML_Parser expat = XML_ParserCreate(NULL); + + parser = NULL; + context.error = error; + context.failed = FALSE; + context.in_session_bus = FALSE; + + if (!_dbus_string_init (&context.content)) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return NULL; + } + + if (!_dbus_string_init (&data)) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto failed; + } + + if (!_dbus_file_get_contents (&data, file, error)) + { + _dbus_string_free (&data); + goto failed; + } + + data_str = _dbus_string_get_const_data (&data); + + context.parser = integration_config_parser_new (0,0,0); + + XML_SetUserData (expat, &context); + XML_SetElementHandler (expat, integration_config_start_element, integration_config_end_element); + XML_SetCharacterDataHandler (expat, integration_config_CharacterDataHandler); + if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE)) + { + if (context.error != NULL && + !dbus_error_is_set (context.error)) + { + enum XML_Error e; + + e = XML_GetErrorCode (expat); + if (e == XML_ERROR_NO_MEMORY) + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + else + dbus_set_error (error, DBUS_ERROR_FAILED, + "Error in file %s, line %ld, column %ld: %s\n", + _dbus_string_get_const_data (file), + XML_GetCurrentLineNumber (expat), + XML_GetCurrentColumnNumber (expat), + XML_ErrorString (e)); + } + } + _dbus_string_free (&data); + + XML_ParserFree (expat); + return context.parser; +failed: + XML_ParserFree (expat); + return 0; +} diff --git a/dbus/dbus-config-parser.c b/dbus/dbus-config-parser.c new file mode 100644 index 000000000..b0a9969b4 --- /dev/null +++ b/dbus/dbus-config-parser.c @@ -0,0 +1,72 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-config-parser.c integration config parser implementation + * + * Copyright (C) 2015-2018 Ralf Habacker + * + * Licensed under the Academic Free License version 2.1 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "dbus-config-parser.h" +#include "dbus-internals.h" + +IntegrationConfigParser* integration_config_parser_new (const DBusString *basedir, + dbus_bool_t is_toplevel, + const IntegrationConfigParser *parent) +{ + IntegrationConfigParser *parser = dbus_new0(IntegrationConfigParser,1); + if (parser == NULL) + return NULL; + + parser->session_bus_address = 0; + parser->refcount = 1; + return parser; +} + +IntegrationConfigParser *integration_config_parser_ref (IntegrationConfigParser *parser) +{ + _dbus_assert (parser->refcount > 0); + + parser->refcount += 1; + + return parser; +} + +void integration_config_parser_unref (IntegrationConfigParser *parser) +{ + _dbus_assert (parser->refcount > 0); + + parser->refcount -= 1; + + if (parser->refcount == 0) + { + if (parser->session_bus_address) + dbus_free(parser->session_bus_address); + dbus_free(parser); + } +} + +const char *integration_config_parser_get_session_bus_address (IntegrationConfigParser *parser) +{ + return parser->session_bus_address; +} + +const char *integration_config_parser_get_autolaunch_executable (IntegrationConfigParser *parser) +{ + return parser->autolaunch_executable; +} diff --git a/dbus/dbus-config-parser.h b/dbus/dbus-config-parser.h new file mode 100644 index 000000000..7ce9bc43c --- /dev/null +++ b/dbus/dbus-config-parser.h @@ -0,0 +1,53 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-config-parser.h integration config parser definitions + * + * Copyright (C) 2015-2018 Ralf Habacker + * + * Licensed under the Academic Free License version 2.1 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef DBUS_CONFIG_PARSER_H +#define DBUS_CONFIG_PARSER_H + +#include "dbus-string.h" +#include "dbus-errors.h" + +typedef struct { + char *session_bus_address; + char *autolaunch_executable; + int refcount; +} IntegrationConfigParser; + +IntegrationConfigParser* integration_config_parser_new (const DBusString *basedir, + dbus_bool_t is_toplevel, + const IntegrationConfigParser *parent); + +const char *integration_config_parser_get_session_bus_address (IntegrationConfigParser *parser); +const char *integration_config_parser_get_autolaunch_executable (IntegrationConfigParser *parser); + +void integration_config_parser_unref (IntegrationConfigParser *parser); + +IntegrationConfigParser *integration_config_parser_ref (IntegrationConfigParser *parser); + +IntegrationConfigParser* +integration_config_load (const DBusString *file, + const IntegrationConfigParser *parent, + DBusError *error); + + +#endif diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c index a5c3bba63..4a20b81cc 100644 --- a/dbus/dbus-sysdeps-util-win.c +++ b/dbus/dbus-sysdeps-util-win.c @@ -1674,3 +1674,10 @@ void _dbus_daemon_report_stopping (void) { } +#ifdef DBUS_INTEGRATION_CONFIG +dbus_bool_t +_dbus_get_integration_config_file (DBusString *str) +{ + return _dbus_get_config_file_name(str, "integration.conf"); +} +#endif diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 70200e7f0..97856e275 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -44,6 +44,9 @@ #include "dbus-list.h" #include "dbus-nonce.h" #include "dbus-credentials.h" +#ifdef DBUS_INTEGRATION_CONFIG +#include "dbus-config-parser.h" +#endif #include #include @@ -129,6 +132,42 @@ load_ex_ip_helper_procedures(void) return TRUE; } +#ifdef DBUS_INTEGRATION_CONFIG +static +IntegrationConfigParser *_dbus_fetch_integration_config_file (DBusError *error) +{ + DBusString integration_config_file; + static IntegrationConfigParser *parser = 0; + + if (parser) + return parser; + + if (!_dbus_string_init (&integration_config_file)) + { + _DBUS_SET_OOM (error); + return NULL; + } + + if (!_dbus_get_integration_config_file (&integration_config_file)) + { + _DBUS_SET_OOM (error); + return NULL; + } + + parser = integration_config_load (&integration_config_file, 0, error); + if (!parser) + { + _dbus_warn ("Could not load integration config file %s: %s\n", + _dbus_string_get_const_data (&integration_config_file), + error->message); + dbus_error_free (error); + _dbus_string_free (&integration_config_file); + return NULL; + } + return parser; +} +#endif + /** * get pid from localhost tcp connection using peer_port * This function is available on WinXP >= SP3 @@ -3158,42 +3197,66 @@ _dbus_get_autolaunch_address (const char *scope, DBusString *address, goto out; } - if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) - { - // Look in directory containing dbus shared library - HMODULE hmod; - char dbus_module_path[MAX_PATH]; - DWORD rc; + *dbus_exe_path = '\0'; - _dbus_verbose( "did not found dbus daemon executable on default search path, " - "trying path where dbus shared library is located"); +#ifdef DBUS_INTEGRATION_CONFIG + { + IntegrationConfigParser *parser = _dbus_fetch_integration_config_file (error); + if (parser) + { + const char *s; + integration_config_parser_ref (parser); + s = integration_config_parser_get_autolaunch_executable (parser); + if (s) + { + strcpy (dbus_exe_path, s); + _dbus_string_append (address, s); + _dbus_verbose( "got dbus daemon executable path '%s' from integration.conf"); + } + integration_config_parser_unref (parser); + } + // handle relative pathes + } +#endif - hmod = _dbus_win_get_dll_hmodule(); - rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path)); - if (rc <= 0) - { - dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name"); - retval = FALSE; - goto out; - } - else + if (!*dbus_exe_path) + { + if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) { - char *ext_idx = strrchr(dbus_module_path, '\\'); - if (ext_idx) - *ext_idx = '\0'; - if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) + // Look in directory containing dbus shared library + HMODULE hmod; + char dbus_module_path[MAX_PATH]; + DWORD rc; + + _dbus_verbose( "did not found dbus daemon executable on default search path, " + "trying path where dbus shared library is located"); + + hmod = _dbus_win_get_dll_hmodule(); + rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path)); + if (rc <= 0) { - dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable"); + dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name"); retval = FALSE; - fprintf (stderr, "please add the path to %s to your PATH environment variable\n", daemon_name); - fprintf (stderr, "or start the daemon manually\n\n"); goto out; } - _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path); + else + { + char *ext_idx = strrchr(dbus_module_path, '\\'); + if (ext_idx) + *ext_idx = '\0'; + if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile)) + { + dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable"); + retval = FALSE; + fprintf (stderr, "please add the path to %s to your PATH environment variable\n", daemon_name); + fprintf (stderr, "or start the daemon manually\n\n"); + goto out; + } + _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path); + } } } - // Create process ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); @@ -3414,7 +3477,24 @@ _dbus_lookup_session_address (dbus_bool_t *supported, DBusError *error) { /* Probably fill this in with something based on COM? */ +#ifdef DBUS_INTEGRATION_CONFIG + IntegrationConfigParser *parser = _dbus_fetch_integration_config_file (error); + if (parser) + { + const char *s; + integration_config_parser_ref (parser); + s = integration_config_parser_get_session_bus_address (parser); + if (s) + { + _dbus_string_append (address, s); + *supported = TRUE; + } + integration_config_parser_unref (parser); + *supported = FALSE; + } +#else *supported = FALSE; +#endif return TRUE; } diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 8642dda56..6ccf67ff5 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -450,6 +450,7 @@ dbus_bool_t _dbus_set_up_transient_session_servicedirs (DBusList **dirs, dbus_bool_t _dbus_get_system_config_file (DBusString *str); dbus_bool_t _dbus_get_session_config_file (DBusString *str); +dbus_bool_t _dbus_get_integration_config_file (DBusString *str); /** Opaque type for reading a directory listing */ typedef struct DBusDirIter DBusDirIter; diff --git a/dbus/integration.conf.in b/dbus/integration.conf.in new file mode 100644 index 000000000..c30f8ac56 --- /dev/null +++ b/dbus/integration.conf.in @@ -0,0 +1,16 @@ + + + + + + @DBUS_SESSION_BUS_CONNECT_ADDRESS@ + + + + + diff --git a/doc/integration.dtd b/doc/integration.dtd new file mode 100644 index 000000000..dec54bc0f --- /dev/null +++ b/doc/integration.dtd @@ -0,0 +1,5 @@ + + + + + -- cgit v1.2.3