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); |