*
*/
#include "activation.h"
+#include "activation-exit-codes.h"
#include "desktop-file.h"
#include "services.h"
#include "test.h"
#include <errno.h>
#endif
-#define DBUS_SERVICE_SECTION "D-BUS Service"
-#define DBUS_SERVICE_NAME "Name"
-#define DBUS_SERVICE_EXEC "Exec"
-
struct BusActivation
{
int refcount;
int refcount;
char *name;
char *exec;
+ char *user;
unsigned long mtime;
BusServiceDirectory *s_dir;
char *filename;
dbus_free (entry->name);
dbus_free (entry->exec);
+ dbus_free (entry->user);
dbus_free (entry->filename);
dbus_free (entry);
BusDesktopFile *desktop_file,
DBusError *error)
{
- char *name, *exec;
+ char *name, *exec, *user;
BusActivationEntry *entry;
DBusStat stat_buf;
DBusString file_path;
+ DBusError tmp_error;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
name = NULL;
exec = NULL;
+ user = NULL;
entry = NULL;
+ dbus_error_init (&tmp_error);
+
if (!_dbus_string_init (&file_path))
{
BUS_SET_OOM (error);
error))
goto failed;
+ /* user is not _required_ unless we are using system activation */
+ if (!bus_desktop_file_get_string (desktop_file,
+ DBUS_SERVICE_SECTION,
+ DBUS_SERVICE_USER,
+ &user, &tmp_error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+ /* if we got OOM, then exit */
+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_move_error (&tmp_error, error);
+ goto failed;
+ }
+ else
+ {
+ /* if we have error because we didn't find anything then continue */
+ dbus_error_free (&tmp_error);
+ dbus_free (user);
+ user = NULL;
+ }
+ }
+ _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
entry = _dbus_hash_table_lookup_string (s_dir->entries,
_dbus_string_get_const_data (filename));
if (entry == NULL) /* New file */
entry->name = name;
entry->exec = exec;
+ entry->user = user;
entry->refcount = 1;
entry->s_dir = s_dir;
dbus_free (entry->name);
dbus_free (entry->exec);
+ dbus_free (entry->user);
entry->name = name;
entry->exec = exec;
+ entry->user = user;
if (!_dbus_hash_table_insert_string (activation->entries,
entry->name, bus_activation_entry_ref(entry)))
{
failed:
dbus_free (name);
dbus_free (exec);
+ dbus_free (user);
_dbus_string_free (&file_path);
if (entry)
pending_activation->service_name);
}
+/**
+ * Depending on the exit code of the helper, set the error accordingly
+ */
+static void
+handle_activation_exit_error (int exit_code,
+ DBusError *error)
+{
+ switch (exit_code)
+ {
+ case BUS_SPAWN_EXIT_CODE_NO_MEMORY:
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+ "Launcher could not run (out of memory)");
+ break;
+ case BUS_SPAWN_EXIT_CODE_SETUP_FAILED:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+ "Failed to setup environment correctly");
+ break;
+ case BUS_SPAWN_EXIT_CODE_NAME_INVALID:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
+ "Bus name is not valid or missing");
+ break;
+ case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
+ "Bus name not found in system service directory");
+ break;
+ case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+ "The permission of the setuid helper is not correct");
+ break;
+ case BUS_SPAWN_EXIT_CODE_FILE_INVALID:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+ "The service file is incorrect or does not have all required attributes");
+ break;
+ case BUS_SPAWN_EXIT_CODE_EXEC_FAILED:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+ "Cannot launch daemon, file not found or permissions invalid");
+ break;
+ case BUS_SPAWN_EXIT_CODE_INVALID_ARGS:
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Invalid arguments to command line");
+ break;
+ case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
+ "Launched child was signaled, it probably crashed");
+ break;
+ default:
+ dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
+ "Launch helper exited with unknown return code %i", exit_code);
+ break;
+ }
+}
+
static dbus_bool_t
babysitter_watch_callback (DBusWatch *watch,
unsigned int condition,
dbus_error_init (&error);
_dbus_babysitter_set_child_exit_error (babysitter, &error);
+ /* refine the error code if we got an exit code */
+ if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED))
+ {
+ int exit_code = 0;
+ if (_dbus_babysitter_get_child_exit_status (babysitter, &exit_code))
+ {
+ dbus_error_free (&error);
+ handle_activation_exit_error (exit_code, &error);
+ }
+ }
+
/* Destroy all pending activations with the same exec */
_dbus_hash_iter_init (pending_activation->activation->pending_activations,
&iter);
BusPendingActivationEntry *pending_activation_entry;
DBusMessage *message;
DBusString service_str;
+ const char *servicehelper;
char **argv;
char **envp = NULL;
int argc;
dbus_bool_t retval;
DBusHashIter iter;
dbus_bool_t activated;
+ DBusString command;
activated = TRUE;
if (activated)
return TRUE;
- /* Now try to spawn the process */
- if (!_dbus_shell_parse_argv (entry->exec, &argc, &argv, error))
+ /* use command as system and session different */
+ if (!_dbus_string_init (&command))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ /* does the bus use a helper? */
+ servicehelper = bus_context_get_servicehelper (activation->context);
+ if (servicehelper != NULL)
+ {
+ if (entry->user == NULL)
+ {
+ _dbus_string_free (&command);
+ dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
+ "Cannot do system-bus activation with no user\n");
+ return FALSE;
+ }
+
+ /* join the helper path and the service name */
+ if (!_dbus_string_append (&command, servicehelper))
+ {
+ _dbus_string_free (&command);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ if (!_dbus_string_append (&command, " "))
+ {
+ _dbus_string_free (&command);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ if (!_dbus_string_append (&command, service_name))
+ {
+ _dbus_string_free (&command);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* the bus does not use a helper, so we can append arguments with the exec line */
+ if (!_dbus_string_append (&command, entry->exec))
+ {
+ _dbus_string_free (&command);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+
+ /* convert command into arguments */
+ if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error))
{
_dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
_DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_hash_table_remove_string (activation->pending_activations,
pending_activation->service_name);
+ _dbus_string_free (&command);
return FALSE;
}
+ _dbus_string_free (&command);
_dbus_verbose ("Spawning %s ...\n", argv[0]);
if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,