diff options
32 files changed, 891 insertions, 1718 deletions
@@ -1,3 +1,10 @@ +2003-09-29 Havoc Pennington <hp@pobox.com> + + * Merge dbus-object-names branch. To see the entire patch + do cvs diff -r DBUS_OBJECT_NAMES_BRANCHPOINT -r dbus-object-names, + it's huuuuge though. + To revert, I tagged DBUS_BEFORE_OBJECT_NAMES_MERGE. + 2003-09-28 Havoc Pennington <hp@pobox.com> * HACKING: update to reflect new server @@ -733,6 +740,88 @@ * dbus/dbus-protocol.h: add DBUS_TYPE_OBJECT_ID +2003-09-28 Havoc Pennington <hp@pobox.com> + + * real 0.13 release + +2003-09-28 Havoc Pennington <hp@pobox.com> + + * doc/Makefile.am (dbus-specification.html): testing a funky hack + to work with Debian db2html + +2003-09-28 Havoc Pennington <hp@pobox.com> + + * configure.in: 0.13 + + * doc/Makefile.am (dbus-test-plan.html): accept nonexistence of + stylesheet-images for benefit of Debian + + Change back to using filesystem-linked sockets for the system + bus, so only root can create the default system bus address. + + * bus/system.conf.in: change to use + DBUS_SYSTEM_BUS_DEFAULT_ADDRESS + + * dbus/Makefile.am (INCLUDES): remove DBUS_SYSTEM_BUS_PATH define + from here. + + * configure.in: define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS + here, and AC_DEFINE DBUS_SYSTEM_PATH + +2003-08-09 Anders Carlsson <andersca@codefactory.se> + + * doc/TODO: + * doc/busconfig.dtd: + Add busconfig DTD. + +2003-08-09 Anders Carlsson <andersca@codefactory.se> + + * doc/dbus-specification.sgml: + Add activation reply values. + +2003-08-05 Havoc Pennington <hp@redhat.com> + + * configure.in: 0.12 + +2003-08-05 Anders Carlsson <andersca@codefactory.se> + + * glib/dbus-gmain.c: (watch_fd_new), (watch_fd_ref), + (watch_fd_unref), (dbus_gsource_check), (dbus_gsource_dispatch), + (add_watch), (remove_watch), (create_source): + Refcount fds, fixes some reentrancy issues. + +2003-07-30 Havoc Pennington <hp@redhat.com> + + * dbus/dbus-bus.c (init_connections_unlocked): fix default system + bus address to be abstract if we have abstract sockets + + * NEWS: update + +2003-07-28 Havoc Pennington <hp@redhat.com> + + * bus/messagebus.in: fix to avoid processname/servicename + confusion, from Michael Kearey + https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=100965 + +2003-07-23 Havoc Pennington <hp@pobox.com> + + * dbus/dbus-message.c (dbus_message_iter_get_named): + fix from Andy Hanton to remove broken "+1" + +2003-07-16 Havoc Pennington <hp@pobox.com> + + * tools/dbus-launch.c (babysit): close stdout/stderr in the + babysitter process, as suggested by Thomas Leonard, so + an "eval `dbus-launch --exit-with-session`" will actually + return + +2003-07-16 Havoc Pennington <hp@pobox.com> + + * configure.in: print out EXPANDED_* variables in the summary at + the end; clean up the code that computes EXPANDED_ variables and + get the ones using exec_prefix right. Should make things work + when you build without --prefix + 2003-06-29 Havoc Pennington <hp@pobox.com> * mono/Test.cs (class Test): fire up a main loop and run it @@ -1,3 +1,40 @@ +D-BUS 0.13 +=== + +This is probably the last release before landing the large API changes +on the "dbus-object-names" branch. + +- fix system bus to always use filesystem socket; anyone + can create any abstract socket, which isn't secure + since if you can crash the system bus you'd be able + to replace it. +- add DTD for configuration file +- improve specification a bit + +D-BUS 0.12 +=== + +- fix "service messagebus status" on Red Hat +- fix demarshaling of DBUS_TYPE_NAMED +- fix "eval `dbus-launch --exit-with-session`" to exit properly +- fix build without --prefix +- useless fooling with Mono bindings +- useless fooling with gcj bindings +- fix srcdir != builddir +- fix various compiler warnings and other issues +- add get/set data to DBusMessage +- fix headers for C++ +- OS X build fixes +- abstract domain sockets support (Linux only) +- add dbus-cleanup-sockets utility for people + not using linux +- be consistent about defaulting to --session/--system + with command line tools +- merge in policies from included config files +- fix build on non-x86 +- docs updates +- lots of other bugfixes + D-BUS 0.11 === diff --git a/bus/messagebus.in b/bus/messagebus.in index e4a16967..7a358764 100755 --- a/bus/messagebus.in +++ b/bus/messagebus.in @@ -16,27 +16,31 @@ # Source function library. . @EXPANDED_SYSCONFDIR@/rc.d/init.d/functions +# so we can rearrange this easily +processname=dbus-daemon-1 +servicename=messagebus + RETVAL=0 start() { echo -n $"Starting system message bus: " - daemon --check messagebus dbus-daemon-1 --system + daemon --check $servicename $processname --system RETVAL=$? echo - [ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/messagebus + [ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename } stop() { echo -n $"Stopping system message bus: " - ## we don't want to kill all the per-user dbus-daemon-1, we want + ## we don't want to kill all the per-user $processname, we want ## to use the pid file *only*; because we use the fake nonexistent - ## program name "messagebus" that should be safe-ish - killproc messagebus -TERM + ## program name "$servicename" that should be safe-ish + killproc $servicename -TERM RETVAL=$? echo if [ $RETVAL -eq 0 ]; then - rm -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/messagebus + rm -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename rm -f @DBUS_SYSTEM_PID_FILE@ fi } @@ -50,7 +54,7 @@ case "$1" in stop ;; status) - status messagebus + status $processname RETVAL=$? ;; restart) @@ -58,7 +62,7 @@ case "$1" in start ;; condrestart) - if [ -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/messagebus ]; then + if [ -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename ]; then stop start fi diff --git a/bus/system.conf.in b/bus/system.conf.in index 122ea1b6..8e2dbda9 100644 --- a/bus/system.conf.in +++ b/bus/system.conf.in @@ -30,7 +30,7 @@ means use abstract namespace, don't really create filesystem file; only Linux supports this. Use path=/whatever on other systems.) --> - <listen>unix:@DBUS_PATH_OR_ABSTRACT@=@DBUS_SYSTEM_SOCKET@</listen> + <listen>@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@</listen> <policy context="default"> <!-- Deny everything then punch holes --> diff --git a/configure.in b/configure.in index 6cf4accb..9665cb03 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ AC_PREREQ(2.52) AC_INIT(dbus/dbus.h) -AM_INIT_AUTOMAKE(dbus, 0.11) +AM_INIT_AUTOMAKE(dbus, 0.13) AM_CONFIG_HEADER(config.h) @@ -715,6 +715,9 @@ fi AM_CONDITIONAL(DBUS_DOCS_ENABLED, test x$enable_docs = xyes) AC_MSG_RESULT(yes) +#### Have to go $localstatedir->$prefix/var->/usr/local/var +#### someone please fix this a better way... + #### find the actual value for $prefix that we'll end up with ## (I know this is broken and should be done in the Makefile, but ## that's a major pain and almost nobody actually seems to care) @@ -725,35 +728,39 @@ else REAL_PREFIX=$prefix fi -#### Have to go $localstatedir->$prefix/var->/usr/local/var -#### someone please fix this a better way... -LOCALSTATEDIR_TMP="$localstatedir" +## temporarily change prefix and exec_prefix old_prefix=$prefix prefix=$REAL_PREFIX + +if test "x$exec_prefix" = xNONE ; then + REAL_EXEC_PREFIX=$REAL_PREFIX +else + REAL_EXEC_PREFIX=$exec_prefix +fi +old_exec_prefix=$exec_prefix +exec_prefix=$REAL_EXEC_PREFIX + +## eval everything +LOCALSTATEDIR_TMP="$localstatedir" EXPANDED_LOCALSTATEDIR=`eval echo $LOCALSTATEDIR_TMP` -prefix=$old_prefix AC_SUBST(EXPANDED_LOCALSTATEDIR) SYSCONFDIR_TMP="$sysconfdir" -old_prefix=$prefix -prefix=$REAL_PREFIX EXPANDED_SYSCONFDIR=`eval echo $SYSCONFDIR_TMP` -prefix=$old_prefix AC_SUBST(EXPANDED_SYSCONFDIR) BINDIR_TMP="$bindir" -old_prefix=$prefix -prefix=$REAL_PREFIX EXPANDED_BINDIR=`eval echo $BINDIR_TMP` -prefix=$old_prefix AC_SUBST(EXPANDED_BINDIR) -old_exec_prefix=${exec_prefix} -test "x$exec_prefix" = xNONE && eval exec_prefix=${prefix} -eval EXPANDED_LIBDIR=${libdir} -exec_prefix=${old_exec_prefix} +LIBDIR_TMP="$libdir" +EXPANDED_LIBDIR=`eval echo $LIBDIR_TMP` AC_SUBST(EXPANDED_LIBDIR) +## put prefix and exec_prefix back +prefix=$old_prefix +exec_prefix=$old_exec_prefix + #### Check our operating system operating_system=unknown if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then @@ -781,6 +788,13 @@ else fi AC_SUBST(DBUS_SYSTEM_SOCKET) +AC_DEFINE_UNQUOTED(DBUS_SYSTEM_SOCKET,"$DBUS_SYSTEM_SOCKET",[The name of the socket the system bus listens on by default]) + +## system bus only listens on local domain sockets, and never +## on an abstract socket (so only root can create the socket) +DBUS_SYSTEM_BUS_DEFAULT_ADDRESS="unix:path=$DBUS_SYSTEM_SOCKET" +AC_SUBST(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS) +AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS, "$DBUS_SYSTEM_BUS_DEFAULT_ADDRESS",[The default D-BUS address of the system bus]) #### Set up the pid file if ! test -z "$with_system_pid_file"; then @@ -915,6 +929,11 @@ echo " ============== prefix: ${prefix} + exec_prefix: ${exec_prefix} + libdir: ${EXPANDED_LIBDIR} + bindir: ${EXPANDED_BINDIR} + sysconfdir: ${EXPANDED_SYSCONFDIR} + localstatedir: ${EXPANDED_LOCALSTATEDIR} source code location: ${srcdir} compiler: ${CC} cflags: ${CFLAGS} @@ -961,6 +980,7 @@ echo " Init scripts style: ${with_init_scripts} Abstract socket names: ${have_abstract_sockets} System bus socket: ${DBUS_SYSTEM_SOCKET} + System bus address: ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS} System bus PID file: ${DBUS_SYSTEM_PID_FILE} Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR} 'make check' socket dir: ${TEST_SOCKET_DIR} diff --git a/dbus/Makefile.am b/dbus/Makefile.am index f377b2a8..dc49ec81 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -1,6 +1,5 @@ -INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION \ - -DDBUS_SYSTEM_BUS_PATH=\""@DBUS_SYSTEM_SOCKET@"\" +INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION dbusincludedir=$(includedir)/dbus-1.0/dbus dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index a8b9e452..0c9f58e1 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -33,13 +33,14 @@ * @ingroup DBus * @brief Functions for communicating with the message bus * - * - * @todo get rid of most of these; they should be done - * with DBusGProxy and the Qt equivalent, i.e. the same - * way any other interface would be used. + * @todo right now the default address of the system bus is hardcoded, + * so if you change it in the global config file suddenly you have to + * set DBUS_SYSTEM_BUS_ADDRESS env variable. Might be nice if the + * client lib somehow read the config file, or if the bus on startup + * somehow wrote out its address to a well-known spot, but might also + * not be worth it. */ - /** * @defgroup DBusBusInternals Message bus APIs internals * @ingroup DBusInternals @@ -52,6 +53,10 @@ * Block of message-bus-related data we attach to each * #DBusConnection used with these convenience functions. * + * + * @todo get rid of most of these; they should be done + * with DBusGProxy and the Qt equivalent, i.e. the same + * way any other interface would be used. */ typedef struct { @@ -146,7 +151,7 @@ init_connections_unlocked (void) { /* Use default system bus address if none set in environment */ bus_connection_addresses[DBUS_BUS_SYSTEM] = - _dbus_strdup ("unix:path=" DBUS_SYSTEM_BUS_PATH); + _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS); if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL) return FALSE; } diff --git a/dbus/dbus-message-handler.c b/dbus/dbus-message-handler.c new file mode 100644 index 00000000..f38e5100 --- /dev/null +++ b/dbus/dbus-message-handler.c @@ -0,0 +1,363 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-message-handler.c Sender/receiver of messages. + * + * Copyright (C) 2002, 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-internals.h" +#include "dbus-message-handler.h" +#include "dbus-list.h" +#include "dbus-threads.h" +#include "dbus-test.h" +#include "dbus-connection-internal.h" + +/** + * @defgroup DBusMessageHandlerInternals DBusMessageHandler implementation details + * @ingroup DBusInternals + * @brief DBusMessageHandler private implementation details. + * + * The guts of DBusMessageHandler and its methods. + * + * @{ + */ + +_DBUS_DEFINE_GLOBAL_LOCK (message_handler); + +/** + * @brief Internals of DBusMessageHandler + * + * Object that can send and receive messages. + */ +struct DBusMessageHandler +{ + DBusAtomic refcount; /**< reference count */ + + DBusHandleMessageFunction function; /**< handler function */ + void *user_data; /**< user data for function */ + DBusFreeFunction free_user_data; /**< free the user data */ + + DBusList *connections; /**< connections we're registered with */ +}; + +/** + * Add this connection to the list used by this message handler. + * When the message handler goes away, the connection + * will be notified. + * + * @param handler the message handler + * @param connection the connection + * @returns #FALSE if not enough memory + */ +dbus_bool_t +_dbus_message_handler_add_connection (DBusMessageHandler *handler, + DBusConnection *connection) +{ + dbus_bool_t res; + + _DBUS_LOCK (message_handler); + /* This is a bit wasteful - we just put the connection in the list + * once per time it's added. :-/ + */ + if (!_dbus_list_prepend (&handler->connections, connection)) + res = FALSE; + else + res = TRUE; + + _DBUS_UNLOCK (message_handler); + + return res; +} + +/** + * Reverses the effect of _dbus_message_handler_add_connection(). + * @param handler the message handler + * @param connection the connection + */ +void +_dbus_message_handler_remove_connection (DBusMessageHandler *handler, + DBusConnection *connection) +{ + _DBUS_LOCK (message_handler); + if (!_dbus_list_remove (&handler->connections, connection)) + _dbus_warn ("Function _dbus_message_handler_remove_connection() called when the connection hadn't been added\n"); + _DBUS_UNLOCK (message_handler); +} + + +/** + * Handles the given message, by dispatching the handler function + * for this DBusMessageHandler, if any. + * + * @param handler the handler + * @param connection the connection that received the message + * @param message the message + * + * @returns what to do with the message + */ +DBusHandlerResult +_dbus_message_handler_handle_message (DBusMessageHandler *handler, + DBusConnection *connection, + DBusMessage *message) +{ + DBusHandleMessageFunction function; + void *user_data; + + _DBUS_LOCK (message_handler); + function = handler->function; + user_data = handler->user_data; + _DBUS_UNLOCK (message_handler); + + /* This function doesn't ref handler/connection/message + * since that's done in dbus_connection_dispatch(). + */ + if (function != NULL) + return (* function) (handler, connection, message, user_data); + else + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; +} + +/** @} */ + +/** + * @defgroup DBusMessageHandler DBusMessageHandler + * @ingroup DBus + * @brief Message processor + * + * A DBusMessageHandler is an object that can send and receive + * messages. Typically the handler is registered with one or + * more DBusConnection objects and processes some types of + * messages received from the connection. + * + * @{ + */ + +/** + * @typedef DBusMessageHandler + * + * Opaque data type representing a message handler. + */ + +/** + * Creates a new message handler. The handler function + * may be #NULL for a no-op handler or a handler to + * be assigned a function later. + * + * @param function function to call to handle a message + * @param user_data data to pass to the function + * @param free_user_data function to call to free the user data + * @returns a new DBusMessageHandler or #NULL if no memory. + */ +DBusMessageHandler* +dbus_message_handler_new (DBusHandleMessageFunction function, + void *user_data, + DBusFreeFunction free_user_data) +{ + DBusMessageHandler *handler; + + handler = dbus_new (DBusMessageHandler, 1); + + if (handler == NULL) + return NULL; + + handler->refcount.value = 1; + handler->function = function; + handler->user_data = user_data; + handler->free_user_data = free_user_data; + handler->connections = NULL; + + return handler; +} + +/** + * Increments the reference count on a message handler. + * + * @param handler the handler + */ +void +dbus_message_handler_ref (DBusMessageHandler *handler) +{ + _dbus_return_if_fail (handler != NULL); + + _dbus_atomic_inc (&handler->refcount); +} + +/** + * Decrements the reference count on a message handler, + * freeing the handler if the count reaches 0. + * + * @param handler the handler + */ +void +dbus_message_handler_unref (DBusMessageHandler *handler) +{ + dbus_bool_t last_unref; + + _dbus_return_if_fail (handler != NULL); + + last_unref = (_dbus_atomic_dec (&handler->refcount) == 1); + + if (last_unref) + { + DBusList *link; + + if (handler->free_user_data) + (* handler->free_user_data) (handler->user_data); + + link = _dbus_list_get_first_link (&handler->connections); + while (link != NULL) + { + DBusConnection *connection = link->data; + + _dbus_connection_handler_destroyed_locked (connection, handler); + + link = _dbus_list_get_next_link (&handler->connections, link); + } + + _dbus_list_clear (&handler->connections); + + dbus_free (handler); + } +} + +/** + * Gets the user data for the handler (the same user data + * passed to the handler function.) + * + * @param handler the handler + * @returns the user data + */ +void* +dbus_message_handler_get_data (DBusMessageHandler *handler) +{ + void* user_data; + + _dbus_return_val_if_fail (handler != NULL, NULL); + + _DBUS_LOCK (message_handler); + user_data = handler->user_data; + _DBUS_UNLOCK (message_handler); + return user_data; +} + +/** + * Sets the user data for the handler (the same user data + * to be passed to the handler function). Frees any previously-existing + * user data with the previous free_user_data function. + * + * @param handler the handler + * @param user_data the user data + * @param free_user_data free function for the data + */ +void +dbus_message_handler_set_data (DBusMessageHandler *handler, + void *user_data, + DBusFreeFunction free_user_data) +{ + DBusFreeFunction old_free_func; + void *old_user_data; + + _dbus_return_if_fail (handler != NULL); + + _DBUS_LOCK (message_handler); + old_free_func = handler->free_user_data; + old_user_data = handler->user_data; + + handler->user_data = user_data; + handler->free_user_data = free_user_data; + _DBUS_UNLOCK (message_handler); + + if (old_free_func) + (* old_free_func) (old_user_data); + +} + +/** + * Sets the handler function. Call dbus_message_handler_set_data() + * to set the user data for the function. + * + * @param handler the handler + * @param function the function + */ +void +dbus_message_handler_set_function (DBusMessageHandler *handler, + DBusHandleMessageFunction function) +{ + _dbus_return_if_fail (handler != NULL); + + _DBUS_LOCK (message_handler); + handler->function = function; + _DBUS_UNLOCK (message_handler); +} + +/** @} */ + +#ifdef DBUS_BUILD_TESTS +static DBusHandlerResult +test_handler (DBusMessageHandler *handler, + DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; +} + +static void +free_test_data (void *data) +{ + /* does nothing */ +} + +/** + * @ingroup DBusMessageInternals + * Unit test for DBusMessageHandler. + * + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_message_handler_test (const char *test_data_dir) +{ + DBusMessageHandler *handler; + +#define TEST_DATA ((void*) 0xcafebabe) + + handler = dbus_message_handler_new (test_handler, + TEST_DATA, + free_test_data); + + _dbus_assert (handler != NULL); + _dbus_assert (handler->function == test_handler); + + if (dbus_message_handler_get_data (handler) != TEST_DATA) + _dbus_assert_not_reached ("got wrong data"); + + dbus_message_handler_set_data (handler, NULL, NULL); + if (dbus_message_handler_get_data (handler) != NULL) + _dbus_assert_not_reached ("got wrong data after set"); + + dbus_message_handler_set_function (handler, NULL); + _dbus_assert (handler->function == NULL); + + dbus_message_handler_ref (handler); + dbus_message_handler_unref (handler); + dbus_message_handler_unref (handler); + + return TRUE; +} +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-message-handler.h b/dbus/dbus-message-handler.h new file mode 100644 index 00000000..dac015ac --- /dev/null +++ b/dbus/dbus-message-handler.h @@ -0,0 +1,59 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-message-handler.h Sender/receiver of messages. + * + * Copyright (C) 2002 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION) +#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef DBUS_MESSAGE_HANDLER_H +#define DBUS_MESSAGE_HANDLER_H + +#include <dbus/dbus-macros.h> +#include <dbus/dbus-types.h> +#include <dbus/dbus-connection.h> + +DBUS_BEGIN_DECLS; + +typedef DBusHandlerResult (* DBusHandleMessageFunction) (DBusMessageHandler *handler, + DBusConnection *connection, + DBusMessage *message, + void *user_data); + +DBusMessageHandler* dbus_message_handler_new (DBusHandleMessageFunction function, + void *user_data, + DBusFreeFunction free_user_data); + + +void dbus_message_handler_ref (DBusMessageHandler *handler); +void dbus_message_handler_unref (DBusMessageHandler *handler); + + +void* dbus_message_handler_get_data (DBusMessageHandler *handler); +void dbus_message_handler_set_data (DBusMessageHandler *handler, + void *data, + DBusFreeFunction free_user_data); +void dbus_message_handler_set_function (DBusMessageHandler *handler, + DBusHandleMessageFunction function); + +DBUS_END_DECLS; + +#endif /* DBUS_MESSAGE_HANDLER_H */ diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index fe56e011..19457468 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -2638,7 +2638,7 @@ dbus_message_iter_get_named (DBusMessageIter *iter, return FALSE; if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order, - pos + 1, NULL, value, len)) + pos, NULL, value, len)) { dbus_free (_name); return FALSE; diff --git a/doc/Makefile.am b/doc/Makefile.am index 891c0209..5bd9fb1e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -10,16 +10,23 @@ if DBUS_DOCS_ENABLED all-local: dbus-specification.html dbus-test-plan.html endif +## Debian db2html outputs to stdout, so we collect stdout and use +## it if we didn't get the proper output + dbus-specification.html: dbus-specification.sgml - $(DB2HTML) -o . --nochunks $< && \ - rm -r $(srcdir)/dbus-specification/stylesheet-images && \ - (if test -d $(srcdir)/dbus-specification ; then \ + rm -f $@ && \ + $(DB2HTML) -o . --nochunks $< > $@.stdout && \ + (test -e $@ && rm -f $@.stdout || mv $@.stdout $@) && \ + rm -rf $(srcdir)/dbus-specification/stylesheet-images && \ + (if test -d $(srcdir)/dbus-specification ; then \ rmdir $(srcdir)/dbus-specification ; fi) dbus-test-plan.html: dbus-test-plan.sgml - $(DB2HTML) -o . --nochunks $< && \ - rm -r $(srcdir)/dbus-test-plan/stylesheet-images && \ - (if test -d $(srcdir)/dbus-test-plan ; then \ + rm -f $@ && \ + $(DB2HTML) -o . --nochunks $< > $@.stdout && \ + (test -e $@ && rm -f $@.stdout || mv $@.stdout $@) && \ + rm -rf $(srcdir)/dbus-test-plan/stylesheet-images && \ + (if test -d $(srcdir)/dbus-test-plan ; then \ rmdir $(srcdir)/dbus-test-plan ; fi) maintainer-clean-local: @@ -45,8 +45,6 @@ after the message bus has processed your message but before the service has replied, it would be nice if the message bus sent you an error reply. - - write a DTD for the dbus-daemon-1 configuration file - - build and install the Doxygen manual in Makefile when --enable-docs - if you send the same message to multiple connections, the serial number diff --git a/doc/busconfig.dtd b/doc/busconfig.dtd new file mode 100644 index 00000000..97c0b82e --- /dev/null +++ b/doc/busconfig.dtd @@ -0,0 +1,52 @@ +<!ELEMENT busconfig (user | + type | + fork | + listen | + pidfile | + includedir | + servicedir | + auth | + include | + policy | + limit)*> + +<!ELEMENT user (#PCDATA)> +<!ELEMENT listen (#PCDATA)> +<!ELEMENT includedir (#PCDATA)> +<!ELEMENT servicedir (#PCDATA)> +<!ELEMENT auth (#PCDATA)> +<!ELEMENT type (#PCDATA)> +<!ELEMENT pidfile (#PCDATA)> +<!ELEMENT fork EMPTY> + +<!ELEMENT include (#PCDATA)> +<!ATTLIST include + ignore_missing (yes|no) "yes"> + +<!ELEMENT policy (allow|deny)*> +<!ATTLIST policy + context (default|mandatory) #IMPLIED + user CDATA #IMPLIED + group CDATA #IMPLIED> + +<!ELEMENT allow EMPTY> +<!ATTLIST allow + user CDATA #IMPLIED + send CDATA #IMPLIED + receive CDATA #IMPLIED + own CDATA #IMPLIED + send_to CDATA #IMPLIED + receive_from CDATA #IMPLIED> + +<!ELEMENT deny EMPTY> +<!ATTLIST deny + user CDATA #IMPLIED + send CDATA #IMPLIED + receive CDATA #IMPLIED + own CDATA #IMPLIED + send_to CDATA #IMPLIED + receive_from CDATA #IMPLIED> + +<!ELEMENT limit (#PCDATA)> +<!ATTLIST limit name CDATA #REQUIRED> + diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml index c772b3e5..696c3f45 100644 --- a/doc/dbus-specification.sgml +++ b/doc/dbus-specification.sgml @@ -1972,22 +1972,44 @@ <row> <entry>0</entry> <entry>UINT32</entry> - <entry>Result code; DBUS_ACTIVATION_REPLY_ACTIVATED if - the service was activated successfully or - DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE if the service is - already active.</entry> + <entry>Return value</entry> </row> </tbody> </tgroup> </informaltable> - </para> - <para> Tries to launch the executable associated with a service. For more information, see <xref linkend="message-bus-activation">. [FIXME need semantics in much more detail here; for example, if I activate a service then send it a message, is the message queued for the new service or is there a race] </para> + <para> + The return value can be one of the following values: + <informaltable> + <tgroup cols=3> + <thead> + <row> + <entry>Identifier</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_ACTIVATION_REPLY_ACTIVATED</entry> + <entry>0x0</entry> + <entry>The service was activated successfully.</entry> + </row> + <row> + <entry>DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE</entry> + <entry>0x1</entry> + <entry>The service is already active.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> <sect3 id="bus-messages-out-of-memory"> diff --git a/glib/dbus-gmain.c b/glib/dbus-gmain.c index 54a2d462..68ba22d7 100644 --- a/glib/dbus-gmain.c +++ b/glib/dbus-gmain.c @@ -60,14 +60,53 @@ struct DBusGSource { GSource source; /**< the parent GSource */ - GList *poll_fds; /**< descriptors we're watching */ - GHashTable *watches; /**< hash of DBusWatch objects */ + GList *watch_fds; /**< descriptors we're watching */ GMainContext *context; /**< the GMainContext to use, NULL for default */ void *connection_or_server; /**< DBusConnection or DBusServer */ }; +typedef struct +{ + int refcount; + + GPollFD poll_fd; + DBusWatch *watch; + + unsigned int removed : 1; +} WatchFD; + +static WatchFD * +watch_fd_new (void) +{ + WatchFD *watch_fd; + + watch_fd = g_new0 (WatchFD, 1); + watch_fd->refcount = 1; + + return watch_fd; +} + +static void +watch_fd_ref (WatchFD *watch_fd) +{ + watch_fd->refcount += 1; +} + +static void +watch_fd_unref (WatchFD *watch_fd) +{ + watch_fd->refcount -= 1; + + if (watch_fd->refcount == 0) + { + g_assert (watch_fd->removed); + + g_free (watch_fd); + } +} + static dbus_int32_t connection_slot = -1; static dbus_int32_t server_slot = -1; @@ -124,13 +163,13 @@ dbus_gsource_check (GSource *source) DBusGSource *dbus_source = (DBusGSource *)source; GList *list; - list = dbus_source->poll_fds; + list = dbus_source->watch_fds; while (list) { - GPollFD *poll_fd = list->data; + WatchFD *watch_fd = list->data; - if (poll_fd->revents != 0) + if (watch_fd->poll_fd.revents != 0) return TRUE; list = list->next; @@ -160,35 +199,35 @@ dbus_gsource_dispatch (GSource *source, DBusGSource *dbus_source = (DBusGSource *)source; GList *copy, *list; - /* We need to traverse a copy of the list, since it can change in - dbus_watch_handle(). */ - copy = g_list_copy (dbus_source->poll_fds); - + /* Make a copy of the list and ref all WatchFDs */ + copy = g_list_copy (dbus_source->watch_fds); + g_list_foreach (copy, (GFunc)watch_fd_ref, NULL); + list = copy; while (list) { - GPollFD *poll_fd = list->data; + WatchFD *watch_fd = list->data; - if (poll_fd->revents != 0) + if (!watch_fd->removed && watch_fd->poll_fd.revents != 0) { - DBusWatch *watch = g_hash_table_lookup (dbus_source->watches, poll_fd); guint condition = 0; - if (poll_fd->revents & G_IO_IN) + if (watch_fd->poll_fd.revents & G_IO_IN) condition |= DBUS_WATCH_READABLE; - if (poll_fd->revents & G_IO_OUT) + if (watch_fd->poll_fd.revents & G_IO_OUT) condition |= DBUS_WATCH_WRITABLE; - if (poll_fd->revents & G_IO_ERR) + if (watch_fd->poll_fd.revents & G_IO_ERR) condition |= DBUS_WATCH_ERROR; - if (poll_fd->revents & G_IO_HUP) + if (watch_fd->poll_fd.revents & G_IO_HUP) condition |= DBUS_WATCH_HANGUP; - dbus_watch_handle (watch, condition); + dbus_watch_handle (watch_fd->watch, condition); } list = list->next; } + g_list_foreach (copy, (GFunc)watch_fd_unref, NULL); g_list_free (copy); return TRUE; @@ -238,7 +277,7 @@ static dbus_bool_t add_watch (DBusWatch *watch, gpointer data) { - GPollFD *poll_fd; + WatchFD *watch_fd; DBusGSource *dbus_source; guint flags; @@ -246,23 +285,24 @@ add_watch (DBusWatch *watch, return TRUE; dbus_source = data; - - poll_fd = g_new (GPollFD, 1); - poll_fd->fd = dbus_watch_get_fd (watch); - poll_fd->events = 0; + + watch_fd = watch_fd_new (); + watch_fd->poll_fd.fd = dbus_watch_get_fd (watch); + watch_fd->poll_fd.events = 0; flags = dbus_watch_get_flags (watch); - dbus_watch_set_data (watch, poll_fd, NULL); + dbus_watch_set_data (watch, watch_fd, (DBusFreeFunction)watch_fd_unref); if (flags & DBUS_WATCH_READABLE) - poll_fd->events |= G_IO_IN; + watch_fd->poll_fd.events |= G_IO_IN; if (flags & DBUS_WATCH_WRITABLE) - poll_fd->events |= G_IO_OUT; - poll_fd->events |= G_IO_ERR | G_IO_HUP; + watch_fd->poll_fd.events |= G_IO_OUT; + watch_fd->poll_fd.events |= G_IO_ERR | G_IO_HUP; - g_source_add_poll ((GSource *)dbus_source, poll_fd); + watch_fd->watch = watch; + + g_source_add_poll ((GSource *)dbus_source, &watch_fd->poll_fd); - dbus_source->poll_fds = g_list_prepend (dbus_source->poll_fds, poll_fd); - g_hash_table_insert (dbus_source->watches, poll_fd, watch); + dbus_source->watch_fds = g_list_prepend (dbus_source->watch_fds, watch_fd); return TRUE; } @@ -272,21 +312,22 @@ remove_watch (DBusWatch *watch, gpointer data) { DBusGSource *dbus_source = data; - GPollFD *poll_fd; + WatchFD *watch_fd; - poll_fd = dbus_watch_get_data (watch); - if (poll_fd == NULL) + watch_fd = dbus_watch_get_data (watch); + if (watch_fd == NULL) return; /* probably a not-enabled watch that was added */ + + watch_fd->removed = TRUE; + watch_fd->watch = NULL; - dbus_source->poll_fds = g_list_remove (dbus_source->poll_fds, poll_fd); - g_hash_table_remove (dbus_source->watches, poll_fd); - g_source_remove_poll ((GSource *)dbus_source, poll_fd); + dbus_source->watch_fds = g_list_remove (dbus_source->watch_fds, watch_fd); + + g_source_remove_poll ((GSource *)dbus_source, &watch_fd->poll_fd); dbus_watch_set_data (watch, NULL, NULL); /* needed due to watch_toggled * breaking add/remove symmetry */ - - g_free (poll_fd); } static void @@ -390,7 +431,6 @@ create_source (void *connection_or_server, source = g_source_new (funcs, sizeof (DBusGSource)); dbus_source = (DBusGSource *)source; - dbus_source->watches = g_hash_table_new (NULL, NULL); dbus_source->connection_or_server = connection_or_server; dbus_source->context = context; diff --git a/test/glib/test-dbus-glib.c b/glib/test-dbus-glib.c index beda0a7a..d963ee3d 100644 --- a/test/glib/test-dbus-glib.c +++ b/glib/test-dbus-glib.c @@ -30,10 +30,8 @@ main (int argc, char **argv) dbus_connection_setup_with_g_main (connection, NULL); - message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, - DBUS_PATH_ORG_FREEDESKTOP_DBUS, - DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, - "Hello"); + message = dbus_message_new (DBUS_MESSAGE_HELLO, + DBUS_SERVICE_DBUS); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); @@ -44,7 +42,7 @@ main (int argc, char **argv) return 1; } - g_print ("reply received\n"); + g_print ("reply name: %s\n", dbus_message_get_name (reply)); g_main_loop_run (loop); diff --git a/test/glib/test-profile.c b/glib/test-profile.c index 23547a1f..f213c676 100644 --- a/test/glib/test-profile.c +++ b/glib/test-profile.c @@ -21,11 +21,6 @@ * */ -/* FIXME this test is wacky since both client and server keep - * sending each other method calls, but nobody sends - * a DBUS_MESSAGE_TYPE_METHOD_RETURN - */ - #include <config.h> #include <glib.h> #include "dbus-glib.h" @@ -34,10 +29,7 @@ #define N_CLIENT_THREADS 1 #define N_ITERATIONS 1000 #define PAYLOAD_SIZE 30 -#define ECHO_PATH "/org/freedesktop/EchoTest" -#define ECHO_INTERFACE "org.freedesktop.EchoTest" -#define ECHO_METHOD "EchoProfile" - +#define ECHO_MESSAGE "org.freedesktop.DBus.Test.EchoProfile" static const char *address; static unsigned char *payload; @@ -46,8 +38,7 @@ send_echo_message (DBusConnection *connection) { DBusMessage *message; - message = dbus_message_new_method_call (NULL, ECHO_PATH, - ECHO_INTERFACE, ECHO_METHOD); + message = dbus_message_new (ECHO_MESSAGE, NULL); dbus_message_append_args (message, DBUS_TYPE_STRING, "Hello World!", DBUS_TYPE_INT32, 123456, @@ -63,21 +54,20 @@ send_echo_message (DBusConnection *connection) } static DBusHandlerResult -client_filter (DBusConnection *connection, +client_filter (DBusMessageHandler *handler, + DBusConnection *connection, DBusMessage *message, void *user_data) { int *iterations = user_data; - if (dbus_message_is_signal (message, - DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnected")) + if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) { g_printerr ("Client thread disconnected\n"); exit (1); } - else if (dbus_message_is_method_call (message, - ECHO_INTERFACE, ECHO_METHOD)) + else if (dbus_message_has_name (message, + ECHO_MESSAGE)) { *iterations += 1; if (*iterations >= N_ITERATIONS) @@ -86,10 +76,9 @@ client_filter (DBusConnection *connection, exit (0); } send_echo_message (connection); - return DBUS_HANDLER_RESULT_HANDLED; } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } static void* @@ -98,6 +87,7 @@ thread_func (void *data) DBusError error; GMainContext *context; GMainLoop *loop; + DBusMessageHandler *handler; DBusConnection *connection; int iterations; @@ -114,9 +104,14 @@ thread_func (void *data) iterations = 1; + handler = dbus_message_handler_new (client_filter, + &iterations, NULL); + if (!dbus_connection_add_filter (connection, - client_filter, &iterations, NULL)) + handler)) g_error ("no memory"); + + /* FIXME we leak the handler */ context = g_main_context_new (); loop = g_main_loop_new (context, FALSE); @@ -138,38 +133,40 @@ thread_func (void *data) } static DBusHandlerResult -server_filter (DBusConnection *connection, +server_filter (DBusMessageHandler *handler, + DBusConnection *connection, DBusMessage *message, void *user_data) { - if (dbus_message_is_signal (message, - DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnected")) + if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) { g_printerr ("Server thread disconnected\n"); exit (1); } - else if (dbus_message_is_method_call (message, - ECHO_INTERFACE, - ECHO_METHOD)) + else if (dbus_message_has_name (message, + ECHO_MESSAGE)) { send_echo_message (connection); - return DBUS_HANDLER_RESULT_HANDLED; } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } static void new_connection_callback (DBusServer *server, DBusConnection *new_connection, void *user_data) -{ +{ + DBusMessageHandler *handler; + dbus_connection_ref (new_connection); dbus_connection_setup_with_g_main (new_connection, NULL); + + handler = dbus_message_handler_new (server_filter, + NULL, NULL); if (!dbus_connection_add_filter (new_connection, - server_filter, NULL, NULL)) + handler)) g_error ("no memory"); @@ -185,7 +182,7 @@ main (int argc, char *argv[]) int i; g_thread_init (NULL); - dbus_g_thread_init (); + dbus_gthread_init (); dbus_error_init (&error); server = dbus_server_listen ("unix:tmpdir="DBUS_TEST_SOCKET_DIR, diff --git a/test/glib/test-thread-client.c b/glib/test-thread-client.c index 122c839a..02ebdf67 100644 --- a/test/glib/test-thread-client.c +++ b/glib/test-thread-client.c @@ -19,10 +19,7 @@ thread_func (gpointer data) while (1) { - message = dbus_message_new_method_call (NULL, - "/org/freedesktop/ThreadTest", - "org.freedesktop.ThreadTest", - "TestMethod"); + message = dbus_message_new ("org.freedesktop.ThreadTest", NULL); dbus_message_append_iter_init (message, &iter); @@ -66,7 +63,7 @@ main (int argc, char *argv[]) int i; g_thread_init (NULL); - dbus_g_thread_init (); + dbus_gthread_init (); if(argc < 2) { diff --git a/test/glib/test-thread-server.c b/glib/test-thread-server.c index dd560328..00044a79 100644 --- a/test/glib/test-thread-server.c +++ b/glib/test-thread-server.c @@ -25,8 +25,13 @@ thread_test_data_free (ThreadTestData *data) g_free (data); } +static DBusMessageHandler *disconnect_handler; +static DBusMessageHandler *filter_handler; +static dbus_int32_t handler_slot = -1; + static DBusHandlerResult -filter_test_message (DBusConnection *connection, +handle_test_message (DBusMessageHandler *handler, + DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -37,10 +42,6 @@ filter_test_message (DBusConnection *connection, char *str, *expected_str; GString *counter_str; int i; - - if (!dbus_message_is_method_call (message, "org.freedesktop.ThreadTest", - "TestMethod")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_iter_init (message, &iter); @@ -123,29 +124,39 @@ filter_test_message (DBusConnection *connection, g_string_free (counter_str, TRUE); out: - return DBUS_HANDLER_RESULT_HANDLED; + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; +} + +static DBusHandlerResult +handle_filter (DBusMessageHandler *handler, + DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } static DBusHandlerResult -filter_disconnect (DBusConnection *connection, +handle_disconnect (DBusMessageHandler *handler, + DBusConnection *connection, DBusMessage *message, void *user_data) { - if (!dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnected")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - g_print ("connection disconnected\n"); dbus_connection_unref (connection); - - return DBUS_HANDLER_RESULT_HANDLED; + + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; } + static void new_connection_callback (DBusServer *server, DBusConnection *new_connection, void *user_data) { + const char *test_messages[] = { "org.freedesktop.ThreadTest" }; + const char *disconnect_messages[] = { "org.freedesktop.Local.Disconnect" }; + DBusMessageHandler *test_message_handler; ThreadTestData * data; g_print ("new_connection_callback\n"); @@ -155,13 +166,28 @@ new_connection_callback (DBusServer *server, data = thread_test_data_new (); - if (!dbus_connection_add_filter (new_connection, - filter_test_message, data, - (DBusFreeFunction) thread_test_data_free)) + test_message_handler = + dbus_message_handler_new (handle_test_message, + data, (DBusFreeFunction)thread_test_data_free); + + if (!dbus_connection_register_handler (new_connection, + test_message_handler, + test_messages, 1)) + goto nomem; + + if (!dbus_connection_set_data (new_connection, + handler_slot, + test_message_handler, + (DBusFreeFunction)dbus_message_handler_unref)) + goto nomem; + + if (!dbus_connection_register_handler (new_connection, + disconnect_handler, + disconnect_messages, 1)) goto nomem; if (!dbus_connection_add_filter (new_connection, - filter_disconnect, NULL, NULL)) + filter_handler)) goto nomem; return; @@ -178,7 +204,7 @@ main (int argc, char *argv[]) DBusError error; g_thread_init (NULL); - dbus_g_thread_init (); + dbus_gthread_init (); if (argc < 2) { @@ -195,6 +221,19 @@ main (int argc, char *argv[]) dbus_error_free (&error); return 1; } + + if (!dbus_connection_allocate_data_slot (&handler_slot)) + g_error ("no memory for data slot"); + + filter_handler = + dbus_message_handler_new (handle_filter, NULL, NULL); + if (filter_handler == NULL) + g_error ("no memory for handler"); + + disconnect_handler = + dbus_message_handler_new (handle_disconnect, NULL, NULL); + if (disconnect_handler == NULL) + g_error ("no memory for handler"); dbus_server_set_new_connection_function (server, new_connection_callback, diff --git a/test/glib/test-thread.h b/glib/test-thread.h index 8c78fba2..8c78fba2 100644 --- a/test/glib/test-thread.h +++ b/glib/test-thread.h diff --git a/python/.cvsignore b/python/.cvsignore deleted file mode 100644 index 8902bbe5..00000000 --- a/python/.cvsignore +++ /dev/null @@ -1,8 +0,0 @@ -*.pyc -*.pyo -Makefile -Makefile.in -build -*.la -*.lo -*.o
\ No newline at end of file diff --git a/python/Makefile.am b/python/Makefile.am deleted file mode 100644 index 792dc477..00000000 --- a/python/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -INCLUDES=-I$(top_builddir) -I$(top_builddir)/glib $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_GLIB_TOOL_CFLAGS) $(PYTHON_INCLUDES) - -dbusdir = $(pythondir) -dbus_PYTHON = dbus.py - -dbusbindingsdir = $(pythondir) -dbusbindings_LTLIBRARIES = dbus_bindings.la - -dbus_bindings_la_LDFLAGS = -module -avoid-version -fPIC -export-symbols-regex initdbus_bindings -dbus_bindings_la_LIBADD = $(top_builddir)/dbus/libdbus-1.la $(top_builddir)/glib/libdbus-glib-1.la -dbus_bindings_la_SOURCES = dbus_bindings.c - -EXTRA_DIST = \ - dbus_bindings.pyx.in \ - extract.py \ - setup.py \ - test.py - -CLEANFILES = \ - dbus_bindings.pyx \ - dbus_bindings.c - - -dbus_bindings.pyx: dbus_bindings.pyx.in extract.py - -$(PYTHON) extract.py dbus_bindings.pyx.in -I$(top_builddir) > dbus_bindings.pyx - -dbus_bindings.c: dbus_bindings.pyx - -pyrexc dbus_bindings.pyx diff --git a/python/dbus.py b/python/dbus.py deleted file mode 100644 index c7ab5dd3..00000000 --- a/python/dbus.py +++ /dev/null @@ -1,267 +0,0 @@ - -"""Module for high-level communication over the FreeDesktop.org Bus (DBus) - -DBus allows you to share and access remote objects between processes -running on the desktop, and also to access system services (such as -the print spool). - -To use DBus, first get a Bus object, which provides a connection to one -of a few standard dbus-daemon instances that might be running. From the -Bus you can get a RemoteService. A service is provided by an application or -process connected to the Bus, and represents a set of objects. Once you -have a RemoteService you can get a RemoteObject that implements a specific interface -(an interface is just a standard group of member functions). Then you can call -those member functions directly. - -You can think of a complete method call as looking something like: - -Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org') - -This communicates over the SESSION Bus to the org.gnome.Evolution process to call the -Forward method of the /org/gnome/Evolution/Inbox object (which provides the -org.gnome.Evolution.MailFolder interface) with two string arguments. - -For example, the dbus-daemon itself provides a service and some objects: - -# Get a connection to the desktop-wide SESSION bus -bus = dbus.Bus(dbus.Bus.TYPE_SESSION) - -# Get the service provided by the dbus-daemon named org.freedesktop.DBus -dbus_service = bus.get_service('org.freedesktop.DBus') - -# Get a reference to the desktop bus' standard object, denoted -# by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus -# implements the 'org.freedesktop.DBus' interface -dbus_object = dbus_service.get_object('/org/freedesktop/DBus', - 'org.freedesktop.DBus') - -# One of the member functions in the org.freedesktop.DBus interface -# is ListServices(), which provides a list of all the other services -# registered on this bus. Call it, and print the list. -print(dbus_object.ListServices()) -""" - -import dbus_bindings - -class Bus: - """A connection to a DBus daemon. - - One of three possible standard buses, the SESSION, SYSTEM, - or ACTIVATION bus - """ - TYPE_SESSION = dbus_bindings.BUS_SESSION - TYPE_SYSTEM = dbus_bindings.BUS_SYSTEM - TYPE_ACTIVATION = dbus_bindings.BUS_ACTIVATION - - def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True): - self._connection = dbus_bindings.bus_get(bus_type) - - self._connection.add_filter(self._signal_func) - self._match_rule_to_receivers = { } - if (glib_mainloop): - self._connection.setup_with_g_main() - - def get_service(self, service_name="org.freedesktop.Broadcast"): - """Get one of the RemoteServices connected to this Bus. service_name - is just a string of the form 'com.widgetcorp.MyService' - """ - return RemoteService(self._connection, service_name) - - def add_signal_receiver(self, receiver, interface=None, service=None, path=None): - match_rule = self._get_match_rule(interface, service, path) - - if (not self._match_rule_to_receivers.has_key(match_rule)): - self._match_rule_to_receivers[match_rule] = [ ] - self._match_rule_to_receivers[match_rule].append(receiver) - - dbus_bindings.bus_add_match(self._connection, match_rule) - - def get_connection(self): - """Get the dbus_bindings.Connection object associated with this Bus""" - return self._connection - - def _get_match_rule(self, interface, service, path): -## if (interface): -## match_rule = match_rule + ",interface='%s'" % (interface) -## if (service): -## match_rule = match_rule + ",service='%s'" % (service) -## if (path): -## match_rule = match_rule + ",path='%s'" % (path) - # FIXME: use the service here too!!! - return "type='signal',interface='%s',path='%s'" % (interface, path) - - def _signal_func(self, connection, message): - if (message.get_type() != dbus_bindings.MESSAGE_TYPE_SIGNAL): - return - - interface = message.get_interface() - service = message.get_sender() - path = message.get_path() - member = message.get_member() - - match_rule = self._get_match_rule(interface, service, path) - - if (self._match_rule_to_receivers.has_key(match_rule)): - receivers = self._match_rule_to_receivers[match_rule] - args = [interface, member, service, path] - for receiver in receivers: - receiver(*args) - - -class RemoteObject: - """A remote Object. - - A RemoteObject is provided by a RemoteService on a particular Bus. RemoteObjects - have member functions, and can be called like normal Python objects. - """ - def __init__(self, connection, service_name, object_path, interface): - self._connection = connection - self._service_name = service_name - self._object_path = object_path - self._interface = interface - - def __getattr__(self, member): - if member == '__call__': - return object.__call__ - else: - return RemoteMethod(self._connection, self._service_name, - self._object_path, self._interface, member) - - -class RemoteMethod: - """A remote Method. - - Typically a member of a RemoteObject. Calls to the - method produce messages that travel over the Bus and are routed - to a specific Service. - """ - def __init__(self, connection, service_name, object_path, interface, method_name): - self._connection = connection - self._service_name = service_name - self._object_path = object_path - self._interface = interface - self._method_name = method_name - - def __call__(self, *args): - message = dbus_bindings.MethodCall(self._object_path, self._interface, self._method_name) - message.set_destination(self._service_name) - - # Add the arguments to the function - iter = message.get_iter() - for arg in args: - iter.append(arg) - - reply_message = self._connection.send_with_reply_and_block(message, 5000) - - args_tuple = reply_message.get_args_list() - if len(args_tuple) == 0: - return - elif len(args_tuple) == 1: - return args_tuple[0] - else: - return args_tuple - -class Service: - """A base class for exporting your own Services across the Bus - - Just inherit from Service, providing the name of your service - (e.g. org.designfu.SampleService). - """ - def __init__(self, service_name, bus=None): - self._service_name = service_name - - if bus == None: - # Get the default bus - self._bus = Bus() - else: - self._bus = bus - - dbus_bindings.bus_acquire_service(self._bus.get_connection(), service_name) - - def get_bus(self): - """Get the Bus this Service is on""" - return self._bus - - def get_service_name(self): - """Get the name of this service""" - return self._service_name - -class Object: - """A base class for exporting your own Objects across the Bus. - - Just inherit from Object and provide a list of methods to share - across the Bus. These will appear as member functions of your - ServiceObject. - """ - def __init__(self, object_path, methods_to_share, service): - self._object_path = object_path - self._service = service - self._bus = service.get_bus() - self._connection = self._bus.get_connection() - - self._method_name_to_method = self._build_method_dictionary(methods_to_share) - - self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb) - - def broadcast_signal(self, interface, signal_name): - message = dbus_bindings.Signal(self._object_path, interface, signal_name) - #FIXME: need to set_sender, but it always disconnects when we do this - #message.set_sender(self._service.get_service_name()) - self._connection.send(message) - - def _unregister_cb(self, connection): - print ("Unregister") - - def _message_cb(self, connection, message): - target_method_name = message.get_member() - target_method = self._method_name_to_method[target_method_name] - args = message.get_args_list() - - try: - retval = target_method(*args) - except Exception, e: - if e.__module__ == '__main__': - # FIXME: is it right to use .__name__ here? - error_name = e.__class__.__name__ - else: - error_name = e.__module__ + '.' + str(e.__class__.__name__) - error_contents = str(e) - reply = dbus_bindings.Error(message, error_name, error_contents) - else: - reply = dbus_bindings.MethodReturn(message) - if retval != None: - iter = reply.get_iter() - iter.append(retval) - - self._connection.send(reply) - - def _build_method_dictionary(self, methods): - method_dict = {} - for method in methods: - if method_dict.has_key(method.__name__): - print ('WARNING: registering DBus Object methods, already have a method named %s' % (method.__name__)) - method_dict[method.__name__] = method - return method_dict - -class RemoteService: - """A remote service providing objects. - - A service is typically a process or application that provides - remote objects, but can also be the broadcast service that - receives signals from all applications on the Bus. - """ - - def __init__(self, connection, service_name): - self._connection = connection - self._service_name = service_name - - def get_object(self, object_path, interface): - """Get an object provided by this Service that implements a - particular interface. object_path is a string of the form - '/com/widgetcorp/MyService/MyObject1'. interface looks a lot - like a service_name (they're often the same) and is of the form, - 'com.widgetcorp.MyInterface', and mostly just defines the - set of member functions that will be present in the object. - """ - return RemoteObject(self._connection, self._service_name, object_path, interface) - diff --git a/python/dbus_bindings.pyx.in b/python/dbus_bindings.pyx.in deleted file mode 100644 index 4ae056c5..00000000 --- a/python/dbus_bindings.pyx.in +++ /dev/null @@ -1,917 +0,0 @@ -# -*- Mode: Python -*- - -#include "dbus_h_wrapper.h" - -cdef extern from "stdlib.h": - cdef void *malloc(size_t size) - cdef void free(void *ptr) - -cdef extern from "dbus-glib.h": - ctypedef struct GMainContext - cdef void dbus_connection_setup_with_g_main (DBusConnection *connection, - GMainContext *context) - cdef void dbus_server_setup_with_g_main (DBusServer *server, - GMainContext *context) - -cdef extern from "Python.h": - void Py_XINCREF (object) - void Py_XDECREF (object) - - -ctypedef struct DBusError: - char *name - char *message - unsigned int dummy1 - unsigned int dummy2 - unsigned int dummy3 - unsigned int dummy4 - unsigned int dummy5 - void *padding1 - -ctypedef struct DBusMessageIter: - void *dummy1 - void *dummy2 - dbus_uint32_t dummy3 - int dummy4 - int dummy5 - int dummy6 - int dummy7 - int dummy8 - int dummy9 - int dummy10 - int dummy11 - int pad1 - int pad2 - void *pad3 - -ctypedef struct DBusObjectPathVTable: - DBusObjectPathUnregisterFunction unregister_function - DBusObjectPathMessageFunction message_function - void (* dbus_internal_pad1) (void *) - void (* dbus_internal_pad2) (void *) - void (* dbus_internal_pad3) (void *) - void (* dbus_internal_pad4) (void *) - - -_user_data_references = [ ] - -class DBusException(Exception): - pass - -class ConnectionError(Exception): - pass - -cdef void cunregister_function_handler (DBusConnection *connection, - void *user_data): - tup = <object>user_data - assert (type(tup) == list) - function = tup[1] - args = [Connection(_conn=<object>connection)] - function(*args) - -cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection, - DBusMessage *msg, - void *user_data): - tup = <object>user_data - assert (type(tup) == list) - function = tup[0] - message = Message(_create=0) - message._set_msg(<object>msg) - args = [Connection(_conn=<object>connection), - message] - retval = function(*args) - if (retval == None): - retval = DBUS_HANDLER_RESULT_HANDLED - return retval - -cdef class Connection: - cdef DBusConnection *conn - - # FIXME: this is a major major hack. We use this because casting values to - # python objects and returning seemed to be corrupting them. This is a "global variable" :-( - cdef char **_parsed_path - - def __init__(self, address=None, _conn=None): - cdef DBusError error - dbus_error_init(&error) - if <DBusConnection*>_conn != NULL: - self.conn = <DBusConnection*>_conn - dbus_connection_ref(self.conn) - else: - self.conn = dbus_connection_open(address, - &error) - if dbus_error_is_set(&error): - raise DBusException, error.message - - dbus_connection_ref(self.conn) - - def _set_conn(self, conn): - self.conn = <DBusConnection*>conn - - def _get_conn(self): - return <object>self.conn - - #FIXME: this is totally busted, don't use a class shared member like parsed_path - def _build_parsed_path(self, path_element_list): - cdef char **cpatharray - size = len(path_element_list) - cpatharray = <char **>malloc(sizeof(char*) * (size + 1)) - - for i in range(size): - path_element = path_element_list[i] - cpatharray[i] = path_element - - cpatharray[size] = NULL - - self._parsed_path = cpatharray - - def get_base_service(self): - return bus_get_base_service(self) - - def setup_with_g_main(self): - dbus_connection_setup_with_g_main(self.conn, NULL) - - def disconnect(self): - dbus_connection_disconnect(self.conn) - - def get_is_connected(self): - return dbus_connection_get_is_connected(self.conn) - - def get_is_authenticated(self): - return dbus_connection_get_is_authenticated(self.conn) - - def flush(self): - dbus_connection_flush(self.conn) - - def borrow_message(self): - m = Message(_create=0) - m._set_msg(<object>dbus_connection_borrow_message(self.conn)) - return m - - def return_message(self, message): - msg = message._get_msg() - dbus_connection_return_message(self.conn, <DBusMessage*>msg) - - def steal_borrowed_message(self, message): - msg = message._get_msg() - dbus_connection_steal_borrowed_message(self.conn, - <DBusMessage*>msg) - - def pop_message(self): - cdef DBusMessage *msg - msg = dbus_connection_pop_message(self.conn) - if msg != NULL: - m = Message(_create=0) - m._set_msg(<object>msg) - else: - m = None - return m - - def get_dispatch_status(self): - return dbus_connection_get_dispatch_status(self.conn) - - def dispatch(self): - return dbus_connection_dispatch(self.conn) - - def send(self, message): - #cdef dbus_uint32_t client_serial - #if type(message) != Message: - # raise TypeError - - msg = message._get_msg() - retval = dbus_connection_send(self.conn, - <DBusMessage*>msg, - NULL) - return retval - - def send_with_reply(self, message, timeout_milliseconds): - cdef dbus_bool_t retval - cdef DBusPendingCall *cpending_call - cdef DBusError error - dbus_error_init(&error) - - cpending_call = NULL - - msg = message._get_msg() - - retval = dbus_connection_send_with_reply(self.conn, - <DBusMessage*>msg, - &cpending_call, - timeout_milliseconds) - - if dbus_error_is_set(&error): - raise DBusException, error.message - - if (cpending_call != NULL): - pending_call = PendingCall(<object>cpending_call) - else: - pending_call = None - - return (retval, pending_call) - - def send_with_reply_and_block(self, message, - timeout_milliseconds=0): - cdef DBusMessage * retval - cdef DBusError error - dbus_error_init(&error) - - msg = message._get_msg() - - retval = dbus_connection_send_with_reply_and_block( - <DBusConnection*>self.conn, - <DBusMessage*>msg, - <int>timeout_milliseconds, - &error) - - if dbus_error_is_set(&error): - raise DBusException, error.message - - if retval == NULL: - raise AssertionError - - m = Message(_create=0) - m._set_msg(<object>retval) - return m - - def set_watch_functions(self, add_function, remove_function, data): - pass - - def set_timeout_functions(self, add_function, remove_function, data): - pass - - def set_wakeup_main_function(self, wakeup_main_function, data): - pass - - # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function - - def add_filter(self, filter_function): - user_data = [ filter_function ] - global _user_data_references - _user_data_references.append(user_data) - - return dbus_connection_add_filter(self.conn, - cmessage_function_handler, - <void*>user_data, - NULL) - - - #FIXME: remove_filter - # this is pretty tricky, we want to only remove the filter - # if we truly have no more calls to our message_function_handler...ugh - - def set_data(self, slot, data): - pass - - def get_data(self, slot): - pass - - def set_max_message_size(self, size): - dbus_connection_set_max_message_size(self.conn, size) - - def get_max_message_size(self): - return dbus_connection_get_max_message_size(self.conn) - - def set_max_received_size(self, size): - dbus_connection_set_max_received_size(self.conn, size) - - def get_max_received_size(self): - return dbus_connection_get_max_received_size(self.conn) - - def get_outgoing_size(self): - return dbus_connection_get_outgoing_size(self.conn) - - # preallocate_send, free_preallocated_send, send_preallocated - - def register_object_path(self, path, unregister_cb, message_cb): - cdef DBusObjectPathVTable cvtable - - cvtable.unregister_function = cunregister_function_handler - cvtable.message_function = cmessage_function_handler - - user_data = [message_cb, unregister_cb] - global _user_data_references - _user_data_references.append(user_data) - - path_element_list = path[1:].split('/') - self._build_parsed_path(path_element_list) - - return dbus_connection_register_object_path(self.conn, self._parsed_path, &cvtable, - <void*>user_data) - - def register_fallback(self, path, unregister_cb, message_cb): - cdef DBusObjectPathVTable cvtable - - cvtable.unregister_function = cunregister_function_handler - cvtable.message_function = cmessage_function_handler - - user_data = [message_cb, unregister_cb] - global _user_data_references - _user_data_references.append(user_data) - - path_element_list = path[1:].split('/') - self._build_parsed_path(path_element_list) - - return dbus_connection_register_fallback(self.conn, self._parsed_path, &cvtable, - <void*>user_data) - - #FIXME: unregister_object_path , see problems with remove_filter - - def list_registered (self, parent_path): - cdef char **cchild_entries - cdef dbus_bool_t retval - - path_element_list = parent_path[1:].split('/') - self._build_parsed_path(path_element_list) - - retval = dbus_connection_list_registered(self.conn, self._parsed_path, &cchild_entries) - - if (not retval): - #FIXME: raise out of memory exception? - return None - - i = 0 - child_entries = [] - - while (cchild_entries[i] != NULL): - child_entries.append(cchild_entries[i]) - i = i + 1 - - dbus_free_string_array(cchild_entries) - - return child_entries - - -cdef class PendingCall: - cdef DBusPendingCall *pending_call - - def __init__(self, _pending_call): - self.pending_call = <DBusPendingCall*>_pending_call - dbus_pending_call_ref(self.pending_call) - - def _get_pending_call(self): - return <object>self.pending_call - - def cancel(self): - dbus_pending_call_cancel(self.pending_call) - - def get_completed(self): - return dbus_pending_call_get_completed(self.pending_call) - - def get_reply(self): - message = Message(_create=0) - message._set_msg(<object>dbus_pending_call_get_reply(self.pending_call)) - return message - - def block(self): - dbus_pending_call_block(self.pending_call) - -cdef class Watch: - cdef DBusWatch* watch - def __init__(self, cwatch): - self.watch = <DBusWatch*>cwatch - - def get_fd(self): - return dbus_watch_get_fd(self.watch) - - # FIXME: not picked up correctly by extract.py - #def get_flags(self): - # return dbus_watch_get_flags(self.watch) - - def handle(self, flags): - return dbus_watch_handle(self.watch, flags) - - def get_enabled(self): - return dbus_watch_get_enabled(self.watch) - -cdef class MessageIter: - cdef DBusMessageIter *iter - cdef DBusMessageIter real_iter - - - def __init__(self, message): - self.iter = &self.real_iter - msg = message._get_msg() - dbus_message_iter_init(<DBusMessage*>msg, self.iter) - - def get_iter(self): - return <object>self.iter - - def has_next(self): - return dbus_message_iter_has_next(self.iter) - - def next(self): - return dbus_message_iter_next(self.iter) - - def get(self): - arg_type = self.get_arg_type() - - if arg_type == TYPE_INVALID: - raise TypeError, 'Invalid arg type in MessageIter' - elif arg_type == TYPE_STRING: - retval = self.get_string() - elif arg_type == TYPE_INT32: - retval = self.get_int32() - elif arg_type == TYPE_UINT32: - retval = self.get_uint32() - elif arg_type == TYPE_DOUBLE: - retval = self.get_double() - elif arg_type == TYPE_BYTE: - retval = self.get_byte() - elif arg_type == TYPE_BOOLEAN: - retval = self.get_boolean() - elif arg_type == TYPE_ARRAY: - array_type = self.get_array_type() - - if array_type == TYPE_STRING: - retval = self.get_string_array() - elif array_type == TYPE_BOOLEAN: - retval = self.get_boolean_array() - else: - raise TypeError, "Unknown array type %d in MessageIter" % (array_type) - else: - raise TypeError, 'Unknown arg type %d in MessageIter' % (argtype) - - return retval - - def get_arg_type(self): - return dbus_message_iter_get_arg_type(self.iter) - - def get_array_type(self): - return dbus_message_iter_get_array_type(self.iter) - - #FIXME: implement get_byte - #def get_byte(self): - # return dbus_message_iter_get_byte(self.iter) - - def get_boolean(self): - return dbus_message_iter_get_boolean(self.iter) - - def get_int32(self): - return dbus_message_iter_get_int32(self.iter) - - def get_uint32(self): - return dbus_message_iter_get_uint32(self.iter) - - def get_double(self): - return dbus_message_iter_get_double(self.iter) - - def get_string(self): - return dbus_message_iter_get_string(self.iter) - - def get_dict_key(self): - return dbus_message_iter_get_dict_key(self.iter) - - # FIXME: implement dbus_message_iter_get_named - # dbus_message_iter_init_array_iterator - - def get_byte_array(self): - cdef int len - cdef unsigned char *retval - dbus_message_iter_get_byte_array(self.iter, &retval, <int*>&len) - list = [] - for i from 0 <= i < len: - list.append(chr(retval[i])) - return list - - # FIXME: implement dbus_message_iter_get_boolean_array - # dbus_message_iter_get_int32_array - # dbus_message_iter_get_uint32_array - # dbus_message_iter_get_double_array - - def get_string_array(self): - cdef int len - cdef char **retval - - dbus_message_iter_get_string_array(self.iter, &retval, <int*>&len) - list = [] - for i from 0 <= i < len: - list.append(retval[i]) - return list - - # dbus_message_append_iter_init included in class Message - - #FIXME: handle all the different types? - def append(self, value): - value_type = type(value) - - if value_type == bool: - retval = self.append_boolean(value) - elif value_type == int: - retval = self.append_int32(value) - elif value_type == float: - retval = self.append_double(value) - elif value_type == str: - retval = self.append_string(value) - elif value_type == list: - if (len(list) == 1): - raise TypeError, "Empty list" - list_type = type(list[0]) - if list_type == str: - self.append_string_array(list) - else: - raise TypeError, "List of unknown type '%s'" % (list_type) - else: - raise TypeError, "Argument of unknown type '%s'" % (value_type) - - return retval - - def append_nil(self): - return dbus_message_iter_append_nil(self.iter) - - def append_boolean(self, value): - return dbus_message_iter_append_boolean(self.iter, value) - - def append_byte(self, value): - return dbus_message_iter_append_byte(self.iter, value) - - def append_int32(self, value): - return dbus_message_iter_append_int32(self.iter, value) - - def append_uint32(self, value): - return dbus_message_iter_append_uint32(self.iter, value) - - def append_double(self, value): - return dbus_message_iter_append_double(self.iter, value) - - def append_string(self, value): - return dbus_message_iter_append_string(self.iter, value) - - # FIXME: dbus_message_iter_append_named - - def append_dict_key(self, value): - return dbus_message_iter_append_dict_key(self.iter, value) - - # FIXME: append_array, append_dict_array, append_boolean_array, append_int32_array, append_uint32_array, append_double_array - - def append_byte_array(self, list): - cdef unsigned char * value - cdef int length - length = len(list) - value = <unsigned char*>malloc(length) - for i from 0 <= i < length: - item = list[i] - if type(item) != str or len(item) != 1: - raise TypeError - value[i] = ord(item) - return dbus_message_iter_append_byte_array(self.iter, value, length) - - def append_string_array(self, list): - cdef char **value - cdef int length - length = len(list) - value = <char**>malloc(length) - for i from 0 <= i < length: - item = list[i] - if type(item) != str: - raise TypeError - value[i] = item - return dbus_message_iter_append_string_array(self.iter, value, length) - - -(MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5) -(TYPE_INVALID, TYPE_NIL, TYPE_BYTE, TYPE_BOOLEAN, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_DOUBLE, TYPE_STRING, TYPE_NAMED, TYPE_ARRAY, TYPE_DICT, TYPE_OBJECT_PATH) = range(14) - -cdef class Message: - cdef DBusMessage *msg - - def __init__(self, message_type=MESSAGE_TYPE_INVALID, - service=None, path=None, interface=None, method=None, - method_call=None, - name=None, - reply_to=None, error_name=None, error_message=None, - _create=1): - cdef char *cservice - if (service == None): - cservice = NULL - else: - cservice = service - - if not _create: - return - - if message_type == MESSAGE_TYPE_METHOD_CALL: - self.msg = dbus_message_new_method_call(cservice, path, interface, method) - elif message_type == MESSAGE_TYPE_METHOD_RETURN: - cmsg = method_call._get_msg() - self.msg = dbus_message_new_method_return(<DBusMessage*>cmsg) - elif message_type == MESSAGE_TYPE_SIGNAL: - self.msg = dbus_message_new_signal(path, interface, name) - elif message_type == MESSAGE_TYPE_ERROR: - cmsg = reply_to._get_msg() - self.msg = dbus_message_new_error(<DBusMessage*>cmsg, error_name, error_message) - - def type_to_name(self, type): - if type == MESSAGE_TYPE_SIGNAL: - return "signal" - elif type == MESSAGE_TYPE_METHOD_CALL: - return "method call" - elif type == MESSAGE_TYPE_METHOD_RETURN: - return "method return" - elif type == MESSAGE_TYPE_ERROR: - return "error" - else: - return "(unknown message type)" - - def __str__(self): - message_type = self.get_type() - sender = self.get_sender() - - if sender == None: - sender = "(no sender)" - - if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL): - retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type), - self.get_interface(), - self.get_member(), - sender) - elif message_type == MESSAGE_TYPE_METHOD_RETURN: - retval = '%s sender=%s' % (self.type_to_name(message_type), - sender) - elif message_type == MESSAGE_TYPE_ERROR: - retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type), - self.get_error_name(), - sender) - else: - retval = "Message of unknown type %d" % (message_type) - - - # FIXME: should really use self.convert_to_tuple() here - - iter = self.get_iter() - value_at_iter = True - - while (value_at_iter): - type = iter.get_arg_type() - - if type == TYPE_INVALID: - break - elif type == TYPE_STRING: - str = iter.get_string() - arg = 'string:%s\n' % (str) - elif type == TYPE_INT32: - num = iter.get_int32() - arg = 'int32:%d\n' % (num) - elif type == TYPE_UINT32: - num = iter.get_uint32() - arg = 'uint32:%u\n' % (num) - elif type == TYPE_DOUBLE: - num = iter.get_double() - arg = 'double:%f\n' % (num) - elif type == TYPE_BYTE: - num = iter.get_byte() - arg = 'byte:%d\n' % (num) - elif type == TYPE_BOOLEAN: - bool = iter.get_boolean() - if (bool): - str = "true" - else: - str = "false" - arg = 'boolean:%s\n' % (str) - else: - arg = '(unknown arg type %d)\n' % type - - retval = retval + arg - value_at_iter = iter.next() - - return retval - - def _set_msg(self, msg): - self.msg = <DBusMessage*>msg - - def _get_msg(self): - return <object>self.msg - - def get_iter(self): - return MessageIter(self) - - def get_args_list(self): - retval = [ ] - - iter = self.get_iter() - try: - retval.append(iter.get()) - except TypeError, e: - return [ ] - - value_at_iter = iter.next() - while (value_at_iter): - retval.append(iter.get()) - value_at_iter = iter.next() - - return retval - - # FIXME: implement dbus_message_copy? - - def get_type(self): - return dbus_message_get_type(self.msg) - - def set_path(self, object_path): - return dbus_message_set_path(self.msg, object_path) - - def get_path(self): - return dbus_message_get_path(self.msg) - - def set_interface(self, interface): - return dbus_message_set_interface(self.msg, interface) - - def get_interface(self): - return dbus_message_get_interface(self.msg) - - def set_member(self, member): - return dbus_message_set_member(self.msg, member) - - def get_member(self): - return dbus_message_get_member(self.msg) - - def set_error_name(self, name): - return dbus_message_set_error_name(self.msg, name) - - def get_error_name(self): - return dbus_message_get_error_name(self.msg) - - def set_destination(self, destination): - return dbus_message_set_destination(self.msg, destination) - - def get_destination(self): - return dbus_message_get_destination(self.msg) - - def set_sender(self, sender): - return dbus_message_set_sender(self.msg, sender) - - def get_sender(self): - cdef char *sender - sender = dbus_message_get_sender(self.msg) - if (sender == NULL): - return None - else: - return sender - - def set_no_reply(self, no_reply): - dbus_message_set_no_reply(self.msg, no_reply) - - def get_no_reply(self): - return dbus_message_get_no_reply(self.msg) - - def is_method_call(self, interface, method): - return dbus_message_is_method_call(self.msg, interface, method) - - def is_signal(self, interface, signal_name): - return dbus_message_is_signal(self.msg, interface, signal_name) - - def is_error(self, error_name): - return dbus_message_is_error(self.msg, error_name) - - def has_destination(self, service): - return dbus_message_has_destination(self.msg, service) - - def has_sender(self, service): - return dbus_message_has_sender(self.msg, service) - - def get_serial(self): - return dbus_message_get_serial(self.msg) - - def set_reply_serial(self, reply_serial): - return dbus_message_set_reply_serial(self.msg, reply_serial) - - def get_reply_serial(self): - return dbus_message_get_reply_serial(self.msg) - - #FIXME: dbus_message_get_path_decomposed - - # FIXME: all the different dbus_message_*args* methods - -class Signal(Message): - def __init__(self, spath, sinterface, sname): - Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, interface=sinterface, name=sname) - -class MethodCall(Message): - def __init__(self, mpath, minterface, mmethod): - Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, interface=minterface, method=mmethod) - -class MethodReturn(Message): - def __init__(self, method_call): - Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call) - -class Error(Message): - def __init__(self, reply_to, error_name, error_message): - Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message) - -cdef class Server: - cdef DBusServer *server - def __init__(self, address): - cdef DBusError error - dbus_error_init(&error) - self.server = dbus_server_listen(address, - &error) - if dbus_error_is_set(&error): - raise DBusException, error.message - - def setup_with_g_main (self): - dbus_server_setup_with_g_main(self.server, NULL) - - def disconnect(self): - dbus_server_disconnect(self.server) - - def get_is_connected(self): - return dbus_server_get_is_connected(self.server) - -# def set_new_connection_function(self, function, data): -# dbus_server_set_new_connection_function(self.conn, function, -# data, NULL) - -# def set_watch_functions(self, add_function, remove_function, data): -# dbus_server_set_watch_functions(self.server, -# add_function, remove_function, -# data, NULL) - -# def set_timeout_functions(self, add_function, remove_function, data): -# dbus_server_set_timeout_functions(self.server, -# add_function, remove_function, -# data, NULL) - -# def handle_watch(self, watch, condition): -# dbus_server_handle_watch(self.conn, watch, condition) - -BUS_SESSION = DBUS_BUS_SESSION -BUS_SYSTEM = DBUS_BUS_SYSTEM -BUS_ACTIVATION = DBUS_BUS_ACTIVATION - -def bus_get (bus_type): - cdef DBusError error - dbus_error_init(&error) - cdef DBusConnection *connection - - connection = dbus_bus_get(bus_type, - &error) - - if dbus_error_is_set(&error): - raise DBusException, error.message - - return Connection(_conn=<object>connection) - -def bus_get_base_service(connection): - conn = connection._get_conn() - return dbus_bus_get_base_service(<DBusConnection*>conn) - -def bus_register(connection): - cdef DBusError error - dbus_error_init(&error) - cdef dbus_bool_t retval - - conn = connection._get_conn() - retval = dbus_bus_register(<DBusConnection*>conn, - &error) - if dbus_error_is_set(&error): - raise DBusException, error.message - - return retval - -SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1 -SERVICE_FLAG_REPLACE_EXISTING = 0x2 - -def bus_acquire_service(connection, service_name, flags=0): - cdef DBusError error - dbus_error_init(&error) - cdef int retval - - conn = connection._get_conn() - retval = dbus_bus_acquire_service(<DBusConnection*>conn, - service_name, - flags, - &error) - if dbus_error_is_set(&error): - raise DBusException, error.message - return retval - -def bus_service_exists(connection, service_name): - cdef DBusError error - dbus_error_init(&error) - cdef dbus_bool_t retval - - conn = connection._get_conn() - retval = dbus_bus_service_exists(<DBusConnection*>conn, - service_name, - &error) - if dbus_error_is_set(&error): - raise DBusException, error.message - return retval - -def bus_add_match(connection, rule): - cdef DBusError error - dbus_error_init(&error) - - conn = connection._get_conn() - dbus_bus_add_match (<DBusConnection*>conn, rule, &error) - - if dbus_error_is_set(&error): - raise DBusException, error.message - -def bus_remove_match(connection, rule): - cdef DBusError error - dbus_error_init(&error) - - conn = connection._get_conn() - dbus_bus_remove_match (<DBusConnection*>conn, rule, &error) - - if dbus_error_is_set(&error): - raise DBusException, error.message diff --git a/python/dbus_h_wrapper.h b/python/dbus_h_wrapper.h deleted file mode 100644 index 2e218c8c..00000000 --- a/python/dbus_h_wrapper.h +++ /dev/null @@ -1,3 +0,0 @@ -#define DBUS_API_SUBJECT_TO_CHANGE 1 -#include <dbus/dbus.h> - diff --git a/python/examples/example-client.py b/python/examples/example-client.py deleted file mode 100644 index 0038b2db..00000000 --- a/python/examples/example-client.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python - -import dbus - -bus = dbus.Bus() -remote_service = bus.get_service("org.designfu.SampleService") -remote_object = remote_service.get_object("/SomeObject", - "org.designfu.SampleInterface") - -hello_reply = remote_object.HelloWorld("Hello from example-client.py!") - -print (hello_reply) diff --git a/python/examples/example-service.py b/python/examples/example-service.py deleted file mode 100644 index 79fb009d..00000000 --- a/python/examples/example-service.py +++ /dev/null @@ -1,18 +0,0 @@ -import dbus - -import pygtk -import gtk - -class SomeObject(dbus.Object): - def __init__(self, service): - dbus.Object.__init__(self, "/SomeObject", [self.HelloWorld], service) - - def HelloWorld(self, hello_message): - print (hello_message) - return "Hello from example-service.py" - - -service = dbus.Service("org.designfu.SampleService") -object = SomeObject(service) - -gtk.main() diff --git a/python/examples/example-signals.py b/python/examples/example-signals.py deleted file mode 100644 index 8e319569..00000000 --- a/python/examples/example-signals.py +++ /dev/null @@ -1,27 +0,0 @@ -import pygtk -import gtk - -import dbus - -class SignalFrom(dbus.Object): - def __init__(self, service): - dbus.Object.__init__(self, "/", [], service) - -def signal_to(interface, signal_name, service, path): - print ("Received signal '%s.%s' from '%s%s'" % (interface, signal_name, service, path)) - -bus = dbus.Bus() -bus.add_signal_receiver(signal_to, - "org.designfu.SignalInterface", - "org.designfu.SignalService", - "/") - - -service = dbus.Service("org.designfu.SignalService", bus) -signal_from = SignalFrom(service) - -signal_from.broadcast_signal("org.designfu.SignalInterface", "HelloWorld") - -gtk.main() - - diff --git a/python/extract.py b/python/extract.py deleted file mode 100644 index 460af5ab..00000000 --- a/python/extract.py +++ /dev/null @@ -1,237 +0,0 @@ -import commands -import glob -import re -import os -import string -import sys - -def clean_func(buf): - buf = strip_comments(buf) - pat = re.compile(r"""\\\n""", re.MULTILINE) - buf = pat.sub('',buf) - pat = re.compile(r"""^[#].*?$""", re.MULTILINE) - buf = pat.sub('',buf) - pat = re.compile(r"""^(typedef|struct|enum)(\s|.|\n)*?;\s*""", re.MULTILINE) - buf = pat.sub('',buf) - pat = re.compile(r"""\s+""", re.MULTILINE) - buf = pat.sub(' ',buf) - pat = re.compile(r""";\s*""", re.MULTILINE) - buf = pat.sub('\n',buf) - buf = buf.lstrip() - #pat=re.compile(r'\s+([*|&]+)\s*(\w+)') - pat = re.compile(r' \s+ ([*|&]+) \s* (\w+)',re.VERBOSE) - buf = pat.sub(r'\1 \2', buf) - pat = re.compile(r'\s+ (\w+) \[ \s* \]',re.VERBOSE) - buf = pat.sub(r'[] \1', buf) -# buf = string.replace(buf, 'G_CONST_RETURN ', 'const-') - buf = string.replace(buf, 'const ', '') - return buf - -def strip_comments(buf): - parts = [] - lastpos = 0 - while 1: - pos = string.find(buf, '/*', lastpos) - if pos >= 0: - parts.append(buf[lastpos:pos]) - pos = string.find(buf, '*/', pos) - if pos >= 0: - lastpos = pos + 2 - else: - break - else: - parts.append(buf[lastpos:]) - break - return string.join(parts, '') - -def find_enums(buf): - enums = [] - buf = strip_comments(buf) - buf = re.sub('\n', ' ', buf) - - enum_pat = re.compile(r'enum\s*{([^}]*)}\s*([A-Z][A-Za-z]*)(\s|;)') - splitter = re.compile(r'\s*,\s', re.MULTILINE) - pos = 0 - while pos < len(buf): - m = enum_pat.search(buf, pos) - if not m: break - - name = m.group(2) - vals = m.group(1) - isflags = string.find(vals, '<<') >= 0 - entries = [] - for val in splitter.split(vals): - if not string.strip(val): continue - entries.append(string.split(val)[0]) - enums.append((name, isflags, entries)) - - pos = m.end() - return enums - -#typedef unsigned int dbus_bool_t; -#typedef struct { -# -# } -#typedef struct FooStruct FooStruct; -# typedef void (* DBusAddWatchFunction) (DBusWatch *watch, -# void *data); - -def find_typedefs(buf): - typedefs = [] - buf = re.sub('\n', ' ', strip_comments(buf)) - typedef_pat = re.compile( - r"""typedef\s*(?P<type>\w*) - \s* - ([(]\s*\*\s*(?P<callback>[\w* ]*)[)]|{([^}]*)}|) - \s* - (?P<args1>[(](?P<args2>[\s\w*,_]*)[)]|[\w ]*)""", - re.MULTILINE | re.VERBOSE) - pat = re.compile(r"""\s+""", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = typedef_pat.search(buf, pos) - if not m: - break - if m.group('type') == 'enum': - pos = m.end() - continue - if m.group('args2') != None: - args = pat.sub(' ', m.group('args2')) - - current = '%s (* %s) (%s)' % (m.group('type'), - m.group('callback'), - args) - else: - current = '%s %s' % (m.group('type'), m.group('args1')) - typedefs.append(current) - pos = m.end() - return typedefs - -proto_pat = re.compile(r""" -(?P<ret>(-|\w|\&|\*)+\s*) # return type -\s+ # skip whitespace -(?P<func>\w+)\s*[(] # match the function name until the opening ( -(?P<args>.*?)[)] # group the function arguments -""", re.IGNORECASE|re.VERBOSE) -arg_split_pat = re.compile("\s*,\s*") - - -def find_functions(buf): - functions = [] - buf = clean_func(buf) - buf = string.split(buf,'\n') - for p in buf: - if len(p) == 0: - continue - - m = proto_pat.match(p) - if m == None: - continue - - func = m.group('func') - ret = m.group('ret') - args = m.group('args') - args = arg_split_pat.split(args) -# for i in range(len(args)): -# spaces = string.count(args[i], ' ') -# if spaces > 1: -# args[i] = string.replace(args[i], ' ', '-', spaces - 1) - - functions.append((func, ret, args)) - return functions - -class Writer: - def __init__(self, filename, enums, typedefs, functions): - if not (enums or typedefs or functions): - return - print 'cdef extern from "%s":' % filename - - self.output_enums(enums) - self.output_typedefs(typedefs) - self.output_functions(functions) - - print ' pass' - print - - def output_enums(self, enums): - for enum in enums: - print ' ctypedef enum %s:' % enum[0] - if enum[1] == 0: - for item in enum[2]: - print ' %s' % item - else: - i = 0 - for item in enum[2]: - print ' %s' % item -# print ' %s = 1 << %d' % (item, i) - i += 1 - print - def output_typedefs(self, typedefs): - for typedef in typedefs: - if typedef.find('va_list') != -1: - continue - - parts = typedef.split() - if parts[0] == 'struct': - if parts[-2] == parts[-1]: - parts = parts[:-1] - print ' ctypedef %s' % ' '.join(parts) - else: - print ' ctypedef %s' % typedef - - def output_functions(self, functions): - for func, ret, args in functions: - if func[0] == '_': - continue - - str = ', '.join(args) - if str.find('...') != -1: - continue - if str.find('va_list') != -1: - continue - if str.strip() == 'void': - continue - print ' %-20s %s (%s)' % (ret, func, str) - -def do_buffer(name, buffer): - functions = find_functions(buffer) - typedefs = find_typedefs(buffer) - enums = find_enums(buffer) - - Writer(name, enums, typedefs, functions) - -def do_header(filename, name=None): - if name == None: - name = filename - - buffer = "" - for line in open(filename).readlines(): - if line[0] == '#': - continue - buffer += line - - print '# -- %s -- ' % filename - do_buffer(name, buffer) - -filename = sys.argv[1] - -if filename.endswith('.h'): - do_header(filename) - raise SystemExit - -cppflags = "" - -for flag in sys.argv[2:]: - cppflags = cppflags + " " + flag - -fd = open(filename) - -for line in fd.readlines(): - if line.startswith('#include'): - filename = line.split(' ')[1][1:-2] - command = "echo '%s'|cpp %s" % (line, cppflags) - sys.stderr.write('running %s' % (command)) - output = commands.getoutput(command) - do_buffer(filename, output) - else: - print line[:-1] diff --git a/test/glib/.cvsignore b/test/glib/.cvsignore deleted file mode 100644 index 2e6b67f0..00000000 --- a/test/glib/.cvsignore +++ /dev/null @@ -1,9 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -test-dbus-glib -test-profile -test-thread-server -test-thread-client - diff --git a/test/glib/Makefile.am b/test/glib/Makefile.am deleted file mode 100644 index 9f900b13..00000000 --- a/test/glib/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) -I$(top_srcdir)/glib - -if DBUS_BUILD_TESTS - -if HAVE_GLIB_THREADS -THREAD_APPS=test-thread-server test-thread-client test-profile - -test_thread_server_SOURCES= \ - test-thread-server.c \ - test-thread.h - -test_thread_server_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la - -test_thread_client_SOURCES= \ - test-thread-client.c \ - test-thread.h - -test_thread_client_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la -endif - -## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we -## build even when not doing "make check" -noinst_PROGRAMS= test-dbus-glib $(THREAD_APPS) - -test_dbus_glib_SOURCES= \ - test-dbus-glib.c - -test_dbus_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la - -else -### not building tests - -if HAVE_GLIB_THREADS -noinst_PROGRAMS=test-profile -endif - -endif - -if HAVE_GLIB_THREADS -test_profile_SOURCES= \ - test-profile.c - -test_profile_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la -endif
\ No newline at end of file diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c index 4d21d105..3b429013 100644 --- a/tools/dbus-launch.c +++ b/tools/dbus-launch.c @@ -460,10 +460,11 @@ babysit (int exit_with_session, char buf[MAX_PID_LEN]; long val; char *end; + int dev_null_fd; /* We chdir ("/") since we are persistent and daemon-like, and fork * again so dbus-launch can reap the parent. However, we don't - * setsid() or close fd 0,1,2 because the idea is to remain attached + * setsid() or close fd 0 because the idea is to remain attached * to the tty and the X server in order to kill the message bus * when the session ends. */ @@ -473,8 +474,24 @@ babysit (int exit_with_session, fprintf (stderr, "Could not change to root directory: %s\n", strerror (errno)); exit (1); - } + } + /* Move stdout/stderr so we don't block an "eval" or otherwise + * lock up. + */ + dev_null_fd = open ("/dev/null", O_RDWR); + if (dev_null_fd >= 0) + { + dup2 (dev_null_fd, 1); + dup2 (dev_null_fd, 2); + } + else + { + fprintf (stderr, "Failed to open /dev/null: %s\n", + strerror (errno)); + /* continue, why not */ + } + ret = fork (); if (ret < 0) @@ -541,7 +558,7 @@ babysit (int exit_with_session, /* Write data to launcher */ write_pid (write_bus_pid_fd, bus_pid_to_kill); close (write_bus_pid_fd); - + if (exit_with_session) { /* Bus is now started and launcher has needed info; |