2003-02-16 Anders Carlsson <andersca@codefactory.se>
authorAnders Carlsson <andersca@codefactory.se>
Sun, 16 Feb 2003 10:00:37 +0000 (10:00 +0000)
committerAnders Carlsson <andersca@codefactory.se>
Sun, 16 Feb 2003 10:00:37 +0000 (10:00 +0000)
* bus/activation.c: (load_directory), (bus_activation_init),
(bus_activation_activate_service):
* bus/activation.h:
* bus/driver.c:
(bus_driver_handle_activate_service), (bus_driver_handle_message):
More work on the activation handling.

* dbus/dbus-errors.h:
Add some error messages

* dbus/dbus-message.c: (dbus_message_new_error_reply):
* dbus/dbus-message.h:
New function that creates an error message.

* dbus/dbus-protocol.h:
Add ACTIVATE_SERVER message.

* dbus/dbus-server-unix.c: (unix_handle_watch),
(_dbus_server_new_for_domain_socket):
Call _dbus_fd_set_close_on_exec.

* dbus/dbus-sysdeps.c: (make_pipe), (do_exec),
(_dbus_spawn_async), (_dbus_disable_sigpipe),
(_dbus_fd_set_close_on_exec):
* dbus/dbus-sysdeps.h:
Add _dbus_fd_set_close_on exec function. Also add function that checks
that all open fds are set to close-on-exec and warns otherwise.

* dbus/dbus-transport-unix.c:
(_dbus_transport_new_for_domain_socket):
Call _dbus_fd_set_close_on_exec.

ChangeLog
bus/activation.c
bus/activation.h
bus/driver.c
dbus/dbus-errors.h
dbus/dbus-message.c
dbus/dbus-message.h
dbus/dbus-protocol.h
dbus/dbus-server-unix.c
dbus/dbus-sysdeps.c
dbus/dbus-transport-unix.c

index 9476896..afb58cf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2003-02-16  Anders Carlsson  <andersca@codefactory.se>
+
+       * bus/activation.c: (load_directory), (bus_activation_init),
+       (bus_activation_activate_service):
+       * bus/activation.h:
+       * bus/driver.c: 
+       (bus_driver_handle_activate_service), (bus_driver_handle_message):
+       More work on the activation handling.
+       
+       * dbus/dbus-errors.h:
+       Add some error messages
+       
+       * dbus/dbus-message.c: (dbus_message_new_error_reply):
+       * dbus/dbus-message.h:
+       New function that creates an error message.
+       
+       * dbus/dbus-protocol.h:
+       Add ACTIVATE_SERVER message.
+       
+       * dbus/dbus-server-unix.c: (unix_handle_watch),
+       (_dbus_server_new_for_domain_socket):
+       Call _dbus_fd_set_close_on_exec.
+       
+       * dbus/dbus-sysdeps.c: (make_pipe), (do_exec),
+       (_dbus_spawn_async), (_dbus_disable_sigpipe),
+       (_dbus_fd_set_close_on_exec):
+       * dbus/dbus-sysdeps.h:
+       Add _dbus_fd_set_close_on exec function. Also add function that checks
+       that all open fds are set to close-on-exec and warns otherwise.
+       
+       * dbus/dbus-transport-unix.c:
+       (_dbus_transport_new_for_domain_socket):
+       Call _dbus_fd_set_close_on_exec.
+
 2003-02-16  Havoc Pennington  <hp@pobox.com>
 
        * dbus/dbus-connection.c (dbus_connection_set_change_sigpipe):
index 7f7dd43..b4acd0f 100644 (file)
@@ -41,6 +41,12 @@ typedef struct
   char *exec;
 } BusActivationEntry;
 
+static DBusHashTable *pending_activations = NULL;
+typedef struct
+{
+  char *service;
+} BusPendingActivation;
+
 static void
 bus_activation_entry_free (BusActivationEntry *entry)
 {
@@ -164,36 +170,6 @@ load_directory (const char *directory)
       bus_desktop_file_free (desktop_file);
       _dbus_string_free (&full_path);
     }
-
-#if 0
-  while ((directory_entry = readdir (directory_handle)))
-    {
-      DBusString path, filename;
-      BusDesktopFile *desktop_file;
-      DBusError error;
-      const char *filename_c;
-
-      
-      _dbus_string_init_const (&filename, directory_entry->d_name);
-
-
-      _dbus_string_get_const_data (&path, &filename_c);      
-
-      if (!desktop_file)
-       {
-         _dbus_verbose ("Could not load %s: %s\n", filename_c,
-                        error.message);
-         dbus_error_free (&error);
-         _dbus_string_free (&path);
-         continue;
-       }
-
-      if (!add_desktop_file_entry (desktop_file))
-       {
-         _dbus_verbose ("Could not add %s to activation entry list.\n", filename_c);
-       }
-    }
-#endif
 }
 
 
@@ -214,3 +190,30 @@ bus_activation_init (const char **directories)
       i++;
     }
 }
+
+dbus_bool_t
+bus_activation_activate_service (const char  *service_name,
+                                DBusError   *error)
+{
+  BusActivationEntry *entry;
+  char *argv[2];
+  
+  entry = _dbus_hash_table_lookup_string (activation_entries, service_name);
+
+  if (!entry)
+    {
+      dbus_set_error (error, DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND,
+                     "The service %s was not found in the activation entry list",
+                     service_name);
+      return FALSE;
+    }
+
+  /* Now try to spawn the process */
+  argv[0] = entry->exec;
+  argv[1] = NULL;
+
+  if (!_dbus_spawn_async (argv, error))
+    return FALSE;
+
+  return TRUE;
+}
index 901c4ee..15260f0 100644 (file)
 #ifndef BUS_ACTIVATION_H
 #define BUS_ACTIVATION_H
 
-void bus_activation_init (const char **paths);
+#include <dbus/dbus.h>
+
+void        bus_activation_init             (const char **paths);
+dbus_bool_t bus_activation_activate_service (const char  *service_name,
+                                            DBusError   *error);
+
 
 #endif /* BUS_ACTIVATION_H */
index 9983f57..80478e4 100644 (file)
@@ -21,6 +21,7 @@
  *
  */
 
+#include "activation.h"
 #include "connection.h"
 #include "driver.h"
 #include "dispatch.h"
@@ -169,7 +170,7 @@ bus_driver_handle_hello (DBusConnection *connection,
 {
   DBusString unique_name;
   BusService *service;
-  
+
   BUS_HANDLE_OOM (_dbus_string_init (&unique_name, _DBUS_INT_MAX));
   BUS_HANDLE_OOM (create_unique_client_name (&unique_name));
 
@@ -208,7 +209,7 @@ bus_driver_send_welcome_message (DBusConnection *connection,
                                            NULL));
   
   BUS_HANDLE_OOM (dbus_connection_send_message (connection, welcome, NULL, NULL));
-
+  
   dbus_message_unref (welcome);
 }
 
@@ -363,6 +364,39 @@ bus_driver_handle_service_exists (DBusConnection *connection,
   dbus_free (name);
 }
 
+static void
+bus_driver_handle_activate_service (DBusConnection *connection,
+                                   DBusMessage    *message)
+{
+  DBusResultCode result;
+  dbus_uint32_t flags;
+  char *name;
+  DBusError error;
+  
+  BUS_HANDLE_OOM ((result = dbus_message_get_args (message,
+                                                  DBUS_TYPE_STRING, &name,
+                                                  DBUS_TYPE_UINT32, &flags,
+                                                  0)) != DBUS_RESULT_NO_MEMORY);
+  if (result != DBUS_RESULT_SUCCESS)
+    {
+      dbus_free (name);
+      dbus_connection_disconnect (connection);
+      return;
+    }
+
+  if (!bus_activation_activate_service (name, &error))
+    {
+      DBusMessage *error_reply;
+      
+      BUS_HANDLE_OOM (error_reply = dbus_message_new_error_reply (message,
+                                                                 error.name, error.message));
+      dbus_error_free (&error);
+
+      BUS_HANDLE_OOM (dbus_connection_send_message (connection, error_reply, NULL, NULL));
+      dbus_message_unref (error_reply);
+    }
+}
+
 void
 bus_driver_handle_message (DBusConnection *connection,
                           DBusMessage    *message)
@@ -391,7 +425,8 @@ bus_driver_handle_message (DBusConnection *connection,
     bus_driver_handle_acquire_service (connection, message);
   else if (strcmp (name, DBUS_MESSAGE_SERVICE_EXISTS) == 0)
     bus_driver_handle_service_exists (connection, message);
-  
+  else if (strcmp (name, DBUS_MESSAGE_ACTIVATE_SERVICE) == 0)
+    bus_driver_handle_activate_service (connection, message);
 }
 
 void
index 5cc7749..1b7b474 100644 (file)
@@ -49,9 +49,10 @@ struct DBusError
   void *padding1; /**< placeholder */
 };
 
-#define DBUS_ERROR_SPAWN_FORK_FAILED "org.freedesktop.DBus.Error.Spawn.ForkFailed"
-#define DBUS_ERROR_SPAWN_FAILED      "org.freedesktop.DBus.Error.Spawn.Failed"
-#define DBUS_ERROR_NO_MEMORY         "org.freedesktop.DBus.Error.NoMemory"
+#define DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND "org.freedesktop.DBus.Activate.ServiceNotFound"
+#define DBUS_ERROR_SPAWN_FORK_FAILED          "org.freedesktop.DBus.Error.Spawn.ForkFailed"
+#define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
+#define DBUS_ERROR_NO_MEMORY                  "org.freedesktop.DBus.Error.NoMemory"
 
 typedef enum
 {
index aca8c2c..fced9c7 100644 (file)
@@ -817,6 +817,50 @@ dbus_message_new_reply (DBusMessage *original_message)
 }
 
 /**
+ * Creates a new message that is an error reply to a certain message.
+ *
+ * @param original_message the original message
+ * @param error_name the error name
+ * @param error_message the error message string
+ * @returns a new error message
+ */
+DBusMessage*
+dbus_message_new_error_reply (DBusMessage *original_message,
+                             const char  *error_name,
+                             const char  *error_message)
+{
+  DBusMessage *message;
+  const char *sender;
+
+  sender = get_string_field (original_message,
+                             FIELD_SENDER, NULL);
+  
+  _dbus_assert (sender != NULL);
+  
+  message = dbus_message_new (sender, error_name);
+  
+  if (message == NULL)
+    return NULL;
+
+  if (!_dbus_message_set_reply_serial (message,
+                                       _dbus_message_get_client_serial (original_message)))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  if (!dbus_message_append_string (message, error_message))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  dbus_message_set_is_error (message, TRUE);
+  
+  return message;
+}
+
+/**
  * Creates a new message that is an exact replica of the message
  * specified, except that its refcount is set to 1.
  *
index 82faf65..2038978 100644 (file)
@@ -39,6 +39,9 @@ typedef struct DBusMessageIter DBusMessageIter;
 DBusMessage* dbus_message_new              (const char        *service,
                                            const char        *name);
 DBusMessage* dbus_message_new_reply        (DBusMessage       *original_message);
+DBusMessage* dbus_message_new_error_reply  (DBusMessage       *original_message,
+                                           const char        *error_name,
+                                           const char        *error_message);
 DBusMessage *dbus_message_new_from_message (const DBusMessage *message);
 
 void         dbus_message_ref   (DBusMessage *message);
index f043346..dd9b312 100644 (file)
@@ -76,6 +76,7 @@ extern "C" {
 #define DBUS_SERVICE_REPLY_ALREADY_OWNER  0x8
   
 /* Messages */
+#define DBUS_MESSAGE_ACTIVATE_SERVICE      "org.freedesktop.DBus.ActivateService"  
 #define DBUS_MESSAGE_SERVICE_EXISTS        "org.freedesktop.DBus.ServiceExists"
 #define DBUS_MESSAGE_HELLO                 "org.freedesktop.DBus.Hello"
 #define DBUS_MESSAGE_LIST_SERVICES         "org.freedesktop.DBus.ListServices"
@@ -84,7 +85,7 @@ extern "C" {
 #define DBUS_MESSAGE_SERVICE_CREATED       "org.freedesktop.DBus.ServiceCreated"
 #define DBUS_MESSAGE_SERVICE_DELETED       "org.freedesktop.DBus.ServiceDeleted"
 #define DBUS_MESSAGE_SERVICE_LOST          "org.freedesktop.DBus.ServiceLost"
-
+  
 #define DBUS_MESSAGE_LOCAL_DISCONNECT      "org.freedesktop.Local.Disconnect"
   
 #ifdef __cplusplus
index 23bbdab..6da7053 100644 (file)
@@ -145,6 +145,7 @@ unix_handle_watch (DBusServer  *server,
         }
       else
         {
+         _dbus_fd_set_close_on_exec (client_fd);         
           handle_new_client_fd (server, client_fd);
         }
     }
@@ -247,6 +248,8 @@ _dbus_server_new_for_domain_socket (const char     *path,
   int listen_fd;
 
   listen_fd = _dbus_listen_unix_socket (path, result);
+  _dbus_fd_set_close_on_exec (listen_fd);
+  
   if (listen_fd < 0)
     return NULL;
   
index 6767770..83b1f04 100644 (file)
@@ -281,7 +281,7 @@ _dbus_connect_unix_socket (const char     *path,
   struct sockaddr_un addr;  
   
   fd = socket (AF_LOCAL, SOCK_STREAM, 0);
-
+  
   if (fd < 0)
     {
       dbus_set_result (result,
@@ -340,7 +340,7 @@ _dbus_listen_unix_socket (const char     *path,
   struct sockaddr_un addr;
 
   listen_fd = socket (AF_LOCAL, SOCK_STREAM, 0);
-
+  
   if (listen_fd < 0)
     {
       dbus_set_result (result, _dbus_result_from_errno (errno));
@@ -1490,7 +1490,11 @@ make_pipe (int        p[2],
       return FALSE;
     }
   else
-    return TRUE;
+    {
+      _dbus_fd_set_close_on_exec (p[0]);
+      _dbus_fd_set_close_on_exec (p[1]);      
+      return TRUE;
+    }
 }
 
 enum
@@ -1563,6 +1567,23 @@ static void
 do_exec (int    child_err_report_fd,
         char **argv)
 {
+#ifdef DBUS_BUILD_TESTS
+  int i, max_open;
+  
+  max_open = sysconf (_SC_OPEN_MAX);
+
+  
+  for (i = 3; i < max_open; i++)
+    {
+      int retval;
+
+      retval = fcntl (i, F_GETFD);
+
+      if (retval != -1 && !(retval & FD_CLOEXEC))
+       _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
+    }
+#endif
+  
   execvp (argv[0], argv);
 
   /* Exec failed */
@@ -1577,19 +1598,13 @@ _dbus_spawn_async (char      **argv,
 {
   int pid = -1, grandchild_pid;
   int child_err_report_pipe[2] = { -1, -1 };
-  int child_pid_report_pipe[2] = { -1, -1 };
   int status;
   
-  printf ("spawning application: %s\n", argv[0]);
-
   if (!make_pipe (child_err_report_pipe, error))
     return FALSE;
 
-  if (!make_pipe (child_pid_report_pipe, error))
-    goto cleanup_and_fail;
-  
   pid = fork ();
-
+  
   if (pid < 0)
     {
       dbus_set_error (error,
@@ -1612,7 +1627,6 @@ _dbus_spawn_async (char      **argv,
        * though
        */
       close_and_invalidate (&child_err_report_pipe[0]);
-      close_and_invalidate (&child_pid_report_pipe[0]);
 
       /* We need to fork an intermediate child that launches the
        * final child. The purpose of the intermediate child
@@ -1623,10 +1637,6 @@ _dbus_spawn_async (char      **argv,
       
       if (grandchild_pid < 0)
        {
-         /* report -1 as child PID */
-         write (child_pid_report_pipe[1], &grandchild_pid,
-                sizeof(grandchild_pid));
-         
          write_err_and_exit (child_err_report_pipe[1],
                              CHILD_FORK_FAILED);              
        }
@@ -1637,9 +1647,6 @@ _dbus_spawn_async (char      **argv,
        }
       else
        {
-         write (child_pid_report_pipe[1], &grandchild_pid, sizeof(grandchild_pid));
-         close_and_invalidate (&child_pid_report_pipe[1]);
-              
          _exit (0);
        }
     }
@@ -1652,7 +1659,6 @@ _dbus_spawn_async (char      **argv,
       
       /* Close the uncared-about ends of the pipes */
       close_and_invalidate (&child_err_report_pipe[1]);
-      close_and_invalidate (&child_pid_report_pipe[1]);
 
     wait_again:
       if (waitpid (pid, &status, 0) < 0)
@@ -1716,8 +1722,6 @@ _dbus_spawn_async (char      **argv,
   
   close_and_invalidate (&child_err_report_pipe[0]);
   close_and_invalidate (&child_err_report_pipe[1]);
-  close_and_invalidate (&child_pid_report_pipe[0]);
-  close_and_invalidate (&child_pid_report_pipe[1]);
 
   return FALSE;
 }
@@ -1731,4 +1735,19 @@ _dbus_disable_sigpipe (void)
   signal (SIGPIPE, SIG_IGN);
 }
 
+void
+_dbus_fd_set_close_on_exec (int fd)
+{
+  int val;
+  
+  val = fcntl (fd, F_GETFD, 0);
+  
+  if (val < 0)
+    return;
+
+  val |= FD_CLOEXEC;
+  
+  fcntl (fd, F_SETFD, val);
+}
+
 /** @} end of sysdeps */
index ef50863..8470334 100644 (file)
@@ -1102,6 +1102,8 @@ _dbus_transport_new_for_domain_socket (const char     *path,
   if (fd < 0)
     return NULL;
 
+  _dbus_fd_set_close_on_exec (fd);
+  
   _dbus_verbose ("Successfully connected to unix socket %s\n",
                  path);