2003-02-17 Anders Carlsson <andersca@codefactory.se>

* bus/activation.c: (bus_activation_init), (child_setup),
	(bus_activation_activate_service):
	* bus/activation.h:
	* bus/main.c: (main):
	Set DBUS_ADDRESS environment variable.

	* dbus/dbus-errors.c: (dbus_set_error):
	Don't use va_copy since that's a C99 feature.

	* dbus/dbus-sysdeps.c: (_dbus_setenv), (do_exec),
	(_dbus_spawn_async):
	* dbus/dbus-sysdeps.h:
	Add child_setup_func to _dbus_spawn_async.

	* doc/dbus-specification.sgml:
	Update specification.

	* test/spawn-test.c: (setup_func), (main):
	Fix test.
This commit is contained in:
Anders Carlsson 2003-02-17 09:59:23 +00:00
parent 8faf99b118
commit 3c8db26789
9 changed files with 589 additions and 29 deletions

View file

@ -1,3 +1,25 @@
2003-02-17 Anders Carlsson <andersca@codefactory.se>
* bus/activation.c: (bus_activation_init), (child_setup),
(bus_activation_activate_service):
* bus/activation.h:
* bus/main.c: (main):
Set DBUS_ADDRESS environment variable.
* dbus/dbus-errors.c: (dbus_set_error):
Don't use va_copy since that's a C99 feature.
* dbus/dbus-sysdeps.c: (_dbus_setenv), (do_exec),
(_dbus_spawn_async):
* dbus/dbus-sysdeps.h:
Add child_setup_func to _dbus_spawn_async.
* doc/dbus-specification.sgml:
Update specification.
* test/spawn-test.c: (setup_func), (main):
Fix test.
2003-02-17 Alexander Larsson <alexl@redhat.com>
* dbus/dbus-connection.c (_dbus_connection_handler_destroyed_locked):

View file

@ -34,6 +34,7 @@
#define DBUS_SERVICE_EXEC "Exec"
static DBusHashTable *activation_entries = NULL;
static char *server_address = NULL;
typedef struct
{
@ -174,10 +175,14 @@ load_directory (const char *directory)
void
bus_activation_init (const char **directories)
bus_activation_init (const char *address,
const char **directories)
{
int i;
/* FIXME: We should split up the server addresses. */
BUS_HANDLE_OOM (server_address = _dbus_strdup (address));
BUS_HANDLE_OOM (activation_entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
(DBusFreeFunction)bus_activation_entry_free));
@ -191,6 +196,13 @@ bus_activation_init (const char **directories)
}
}
static void
child_setup (void *data)
{
/* FIXME: Check return value in case of OOM */
_dbus_setenv ("DBUS_ADDRESS", server_address);
}
dbus_bool_t
bus_activation_activate_service (const char *service_name,
DBusError *error)
@ -212,7 +224,9 @@ bus_activation_activate_service (const char *service_name,
argv[0] = entry->exec;
argv[1] = NULL;
if (!_dbus_spawn_async (argv, error))
if (!_dbus_spawn_async (argv,
child_setup, NULL,
error))
return FALSE;
return TRUE;

View file

@ -26,7 +26,8 @@
#include <dbus/dbus.h>
void bus_activation_init (const char **paths);
void bus_activation_init (const char *address,
const char **paths);
dbus_bool_t bus_activation_activate_service (const char *service_name,
DBusError *error);

View file

@ -82,6 +82,15 @@ main (int argc, char **argv)
return 1;
}
server = dbus_server_listen (argv[1], &result);
if (server == NULL)
{
_dbus_warn ("Failed to start server on %s: %s\n",
argv[1], dbus_result_to_string (result));
return 1;
}
if (argc < 3)
{
_dbus_warn ("No service location given, not activating activation\n");
@ -90,15 +99,7 @@ main (int argc, char **argv)
{
char *paths[] = { argv[2], NULL };
bus_activation_init (paths);
}
server = dbus_server_listen (argv[1], &result);
if (server == NULL)
{
_dbus_warn ("Failed to start server on %s: %s\n",
argv[1], dbus_result_to_string (result));
return 1;
bus_activation_init (argv[1], paths);
}
setup_server (server);

View file

@ -238,13 +238,14 @@ dbus_set_error (DBusError *error,
va_start (args, format);
va_copy (args2, args);
/* Measure the message length */
message_length = vsnprintf (&c, 1,format, args) + 1;
message = dbus_malloc (message_length);
va_end (args);
va_start (args, format);
vsprintf (message, format, args2);
if (!message)

View file

@ -66,6 +66,19 @@ _dbus_abort (void)
_exit (1); /* in case someone manages to ignore SIGABRT */
}
/**
* Wrapper for setenv().
*
* @param varname name of environment variable
* @param value value of environment variable
* @returns #TRUE on success.
*/
dbus_bool_t
_dbus_setenv (const char *varname, const char *value)
{
return (setenv (varname, value, TRUE) == 0);
}
/**
* Wrapper for getenv().
*
@ -1564,12 +1577,18 @@ read_ints (int fd,
}
static void
do_exec (int child_err_report_fd,
char **argv)
do_exec (int child_err_report_fd,
char **argv,
DBusSpawnChildSetupFunc child_setup,
void *user_data)
{
#ifdef DBUS_BUILD_TESTS
int i, max_open;
#endif
if (child_setup)
(* child_setup) (user_data);
#ifdef DBUS_BUILD_TESTS
max_open = sysconf (_SC_OPEN_MAX);
@ -1593,8 +1612,10 @@ do_exec (int child_err_report_fd,
}
dbus_bool_t
_dbus_spawn_async (char **argv,
DBusError *error)
_dbus_spawn_async (char **argv,
DBusSpawnChildSetupFunc child_setup,
void *user_data,
DBusError *error)
{
int pid = -1, grandchild_pid;
int child_err_report_pipe[2] = { -1, -1 };
@ -1643,7 +1664,8 @@ _dbus_spawn_async (char **argv,
else if (grandchild_pid == 0)
{
do_exec (child_err_report_pipe[1],
argv);
argv,
child_setup, user_data);
}
else
{

View file

@ -49,7 +49,8 @@ DBUS_BEGIN_DECLS;
void _dbus_abort (void);
const char* _dbus_getenv (const char *varname);
dbus_bool_t _dbus_setenv (const char *varname,
const char *value);
int _dbus_read (int fd,
DBusString *buffer,
@ -148,8 +149,14 @@ dbus_bool_t _dbus_generate_random_bytes (DBusString *str,
int n_bytes);
const char *_dbus_errno_to_string (int errnum);
dbus_bool_t _dbus_spawn_async (char **argv,
DBusError *error);
typedef void (* DBusSpawnChildSetupFunc) (void *user_data);
dbus_bool_t _dbus_spawn_async (char **argv,
DBusSpawnChildSetupFunc child_setup,
void *user_data,
DBusError *error);
void _dbus_disable_sigpipe (void);

View file

@ -698,15 +698,500 @@
responds to a number of messages, allowing applications to
interact with the message bus.
</para>
</sect2>
<sect2 id="bus-messages-hello">
<title><literal>org.freedesktop.DBus.Hello</literal></title>
<para>
[document the messages here]
As a method:
<programlisting>
STRING Hello ()
</programlisting>
Reply arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service assigned to the client</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Before a client is able to send messages to other clients it
must send the <literal>org.freedesktop.DBus.Hello</literal>
message to the message bus service. If a client tries to send
a message to another client, or a message to the message bus
service that isn't the
<literal>org.freedesktop.DBus.Hello</literal> message, it will
be disconnected from the bus.
</para>
<para>
The reply message contains the name of the base service. Any
messages sent to the base service will be rereouted by the
message bus, delivering it to the client.
</para>
</sect2>
<sect2 id="bus-messages-list-services">
<title><literal>org.freedesktop.DBus.ListServices</literal></title>
<para>
As a method:
<programlisting>
STRING_ARRAY ListServices ()
</programlisting>
Reply arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING_ARRAY</entry>
<entry>Array of strings where each string is the name of a service</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Returns a list of all existing services registered with the message bus.
</para>
</sect2>
<sect2 id="bus-messages-service-exists">
<title><literal>org.freedesktop.DBus.ServiceExists</literal></title>
<para>
As a method:
<programlisting>
UINT32 ServiceExists (in STRING service_name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service</entry>
</row>
</tbody>
</tgroup>
</informaltable>
Reply arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>UINT32</entry>
<entry>Return value, 1 if the service exists and 0 otherwise</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Checks if a service with a specified name exists.
</para>
</sect2>
<sect2 id="bus-messages-acquire-service">
<title><literal>org.freedesktop.DBus.AcquireService</literal></title>
<para>
As a method:
<programlisting>
UINT32 AcquireService (in STRING service_name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
Reply arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>UINT32</entry>
<entry>Return value</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Tries to become owner of a specific service. The flags
specified can be the following values logically ORed together:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Identifier</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT</entry>
<entry>0x1</entry>
<entry>
If the client succeeds in being the owner of the specified service,
then ownership of the service can't be transferred until the service
disconnects. If this flag is not set, then any client trying to become
the owner of the service will succeed and the previous owner will be
sent a <literal>org.freedesktop.DBus.ServiceLost</literal> message.
</entry>
</row>
<row>
<entry>DBUS_SERVICE_FLAGS_REPLACE_EXISTING</entry>
<entry>0x2</entry>
<entry>Only become the owner of the service if there is no current owner.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
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_SERVICE_REPLY_PRIMARY_OWNER</entry>
<entry>0x1</entry>
<entry>The client is now the primary owner of the service.</entry>
</row>
<row>
<entry>DBUS_SERVICE_REPLY_IN_QUEUE</entry>
<entry>0x2</entry>
<entry>The service already has an owner which do not want to give up ownership and therefore the client has been put in a queue.</entry>
</row>
<row>
<entry>DBUS_SERVICE_REPLY_SERVICE_EXISTS</entry>
<entry>0x4</entry>
<entry>The service does already have a primary owner, and DBUS_SERVICE_FLAG_REPLACE_EXISTING was not specified when trying to acquire the service.</entry>
</row>
<row>
<entry>DBUS_SERVICE_REPLY_ALREADY_OWNER</entry>
<entry>0x8</entry>
<entry>The client trying to request ownership of the service is already the owner of it.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect2>
<sect2 id="bus-messages-service-acquired">
<title><literal>org.freedesktop.DBus.ServiceAcquired</literal></title>
<para>
As a method:
<programlisting>
ServiceAcquired (in STRING service_name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is sent to a specific client when it becomes the primary owner of a service.
</para>
</sect2>
<sect2 id="bus-messages-service-lost">
<title><literal>org.freedesktop.DBus.ServiceLost</literal></title>
<para>
As a method:
<programlisting>
ServiceLost (in STRING service_name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is sent to a specific client when it loses primary ownership of a service.
</para>
</sect2>
<sect2 id="bus-messages-service-created">
<title><literal>org.freedesktop.DBus.ServiceCreated</literal></title>
<para>
As a method:
<programlisting>
ServiceCreated (in STRING service_name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is broadcast to all clients when a service has been successfully registered on the message bus.
</para>
</sect2>
<sect2 id="bus-messages-service-deleted">
<title><literal>org.freedesktop.DBus.ServiceDeleted</literal></title>
<para>
As a method:
<programlisting>
ServiceDeleted (in STRING service_name)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is broadcast to all clients when a service has been deleted from the message bus.
</para>
</sect2>
<sect2 id="bus-messages-activate-service">
<title><literal>org.freedesktop.DBus.ActivateService</literal></title>
<para>
As a method:
<programlisting>
void ActivateService (in STRING service_name, in UINT32 flags)
</programlisting>
Message arguments:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Argument</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry>STRING</entry>
<entry>Name of the service to activate</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags (currently not used)</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Tries to launch the executable associated with a service. For more information, see the part on <xref linkend="message-bus-activation">
</para>
</sect2>
<sect2 id="services">
<title>Message Bus Services</title>
<para>
A service is a name that identifies a certain client. Each
client connected to the message bus has at least one service
name acquired through the
<literal>org.freedesktop.DBus.Hello</literal> message. In
addition, a client can request additional service names to be
associated with it using the
<literal>org.freedesktop.DBus.AcquireService</literal>
message.
</para>
<para>
Service ownership handling can be specified in the flags part
of the <literal>org.freedesktop.DBus.AcquireService</literal>
message. If a client specifies the
DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT flag, then all clients
trying to acquire the service will be put in a queue. When the
primary owner disconnects from the bus or removes ownership
from the service, the next client in the queue will be the
primary owner. If the DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT
flag is not specified, then the primary owner will lose
ownership whenever another client requests ownership of the
service.
</para>
</sect2>
<sect2 id="message-bus-activation">
<title>Message Bus Service Activation</title>
<para>
[document file format, filesystem locations, etc. for activation]
Activation is a way to launch executables that handle certain
services. The bus daemon looks in certain directories
(possibly different depending on if it's a system bus or a
message bus) for service description files.
</para>
<para>
Service description files have the ".service" file
extension. The message bus will only load service description
files ending with .service; all other files will be ignored.
The file format is similar to that of <ulink
url="http://www.freedesktop.org/standards/desktop-entry-spec/desktop-entry-spec.html">desktop
entries</ulink>. All service description files must be in
UTF-8 encoding.
<figure>
<title>Example service description file</title>
<programlisting>
# Sample service description file
[D-BUS Service]
Name=org.gnome.ConfigurationDatabase
Exec=gconfd-2
</programlisting>
</figure>
</para>
<para>
When a client requests a service to be activated, the bus
daemon tries to find it in the list of activation entries. It
then tries to spawn the executable associated with it. If this
fails, it will report an error.
</para>
<para>
The executable launched will have the environment variable
<literal>DBUS_ADDRESS</literal> set to the address of the
server so it can connect and register the appropriate services.
</para>
</sect2>
<sect2 id="message-bus-location">
@ -730,16 +1215,17 @@
</para>
</sect2>
</sect1>
<!--
<appendix id="implementation-notes">
<title>Implementation notes</title>
<sect1 id="implementation-notes-subsection">
<title></title>
<para>
</para>
</sect1>
</appendix>
-->
<glossary><title>Glossary</title>
<para>
This glossary defines some of the terms used in this specification.

View file

@ -5,6 +5,12 @@
#undef DBUS_COMPILATION
#include <stdio.h>
static void
setup_func (void *data)
{
printf ("entering setup func.\n");
}
int
main (int argc, char **argv)
{
@ -24,7 +30,7 @@ main (int argc, char **argv)
argv_copy [i] = argv[i + 1];
argv_copy[argc - 1] = NULL;
if (!_dbus_spawn_async (argv_copy, &error))
if (!_dbus_spawn_async (argv_copy, setup_func, NULL, &error))
{
fprintf (stderr, "Could not launch application: \"%s\"\n",
error.message);