2003-02-17 Anders Carlsson <andersca@codefactory.se>
authorAnders Carlsson <andersca@codefactory.se>
Mon, 17 Feb 2003 09:59:23 +0000 (09:59 +0000)
committerAnders Carlsson <andersca@codefactory.se>
Mon, 17 Feb 2003 09:59:23 +0000 (09:59 +0000)
* 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.

ChangeLog
bus/activation.c
bus/activation.h
bus/main.c
dbus/dbus-errors.c
dbus/dbus-sysdeps.c
dbus/dbus-sysdeps.h
doc/dbus-specification.sgml
test/spawn-test.c

index 09a584a..f339ef3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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):
index b4acd0f..b5cec44 100644 (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;
index 15260f0..5f29871 100644 (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);
 
index 68e3a7b..fdb6462 100644 (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);
index dfc52fb..92cca03 100644 (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)
index 83b1f04..1308a6b 100644 (file)
@@ -67,6 +67,19 @@ _dbus_abort (void)
 }
 
 /**
+ * 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().
  *
  * @param varname name of environment variable
@@ -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
        {
index 42697a0..50da679 100644 (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);
 
index b54be17..6412bf5 100644 (file)
         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">
       </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.
index fda0309..18462eb 100644 (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);