diff options
| -rw-r--r-- | ChangeLog | 34 | ||||
| -rw-r--r-- | bus/activation.c | 63 | ||||
| -rw-r--r-- | bus/activation.h | 7 | ||||
| -rw-r--r-- | bus/driver.c | 41 | ||||
| -rw-r--r-- | dbus/dbus-errors.h | 7 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 44 | ||||
| -rw-r--r-- | dbus/dbus-message.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-protocol.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-server-unix.c | 3 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.c | 61 | ||||
| -rw-r--r-- | dbus/dbus-transport-unix.c | 2 | 
11 files changed, 209 insertions, 59 deletions
@@ -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): diff --git a/bus/activation.c b/bus/activation.c index 7f7dd438..b4acd0f3 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -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; +} diff --git a/bus/activation.h b/bus/activation.h index 901c4eee..15260f01 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -24,6 +24,11 @@  #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 */ diff --git a/bus/driver.c b/bus/driver.c index 9983f573..80478e45 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -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 diff --git a/dbus/dbus-errors.h b/dbus/dbus-errors.h index 5cc77491..1b7b474a 100644 --- a/dbus/dbus-errors.h +++ b/dbus/dbus-errors.h @@ -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  { diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index aca8c2cb..fced9c72 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -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.   * diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 82faf658..2038978b 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -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); diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index f043346a..dd9b3122 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -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 diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 23bbdab3..6da70537 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -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; diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 67677707..83b1f044 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -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 */ diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index ef50863d..84703345 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -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);  | 
