From 96e785bb0614dc9ebbf6aebe12797d93a1b76b14 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 13 Jul 2009 13:02:21 -0400 Subject: Bug 14259 - Refactor _dbus_get_autolaunch_address Split out the process-launching code, which can be reused for other applications; in particular, a forthcoming patch to parse output from launchd for MacOS X. (cherry picked from commit 6b163e95e7a2318a98c16c0d0944337e38e62efa) --- dbus/dbus-sysdeps-unix.c | 184 +++++++++++++++++++++++++++++------------------ 1 file changed, 114 insertions(+), 70 deletions(-) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 6396378c..a26f02d6 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -2863,23 +2863,30 @@ _dbus_get_tmpdir(void) } /** - * Determines the address of the session bus by querying a - * platform-specific method. + * Execute a subprocess, returning up to 1024 bytes of output + * into @p result. * - * If successful, returns #TRUE and appends the address to @p - * address. If a failure happens, returns #FALSE and + * If successful, returns #TRUE and appends the output to @p + * result. If a failure happens, returns #FALSE and * sets an error in @p error. * - * @param address a DBusString where the address can be stored + * @note It's not an error if the subprocess terminates normally + * without writing any data to stdout. Verify the @p result length + * before and after this function call to cover this case. + * + * @param progname initial path to exec + * @param argv NULL-terminated list of arguments + * @param result a DBusString where the output can be append * @param error a DBusError to store the error in case of failure * @returns #TRUE on success, #FALSE if an error happened */ -dbus_bool_t -_dbus_get_autolaunch_address (DBusString *address, - DBusError *error) +static dbus_bool_t +_read_subprocess_line_argv (const char *progpath, + char * const *argv, + DBusString *result, + DBusError *error) { - static char *argv[6]; - int address_pipe[2] = { -1, -1 }; + int result_pipe[2] = { -1, -1 }; int errors_pipe[2] = { -1, -1 }; pid_t pid; int ret; @@ -2907,48 +2914,26 @@ _dbus_get_autolaunch_address (DBusString *address, sigaddset (&new_set, SIGCHLD); sigprocmask (SIG_BLOCK, &new_set, &old_set); - if (!_dbus_get_local_machine_uuid_encoded (&uuid)) - { - _DBUS_SET_OOM (error); - goto out; - } - - i = 0; - argv[i] = "dbus-launch"; - ++i; - argv[i] = "--autolaunch"; - ++i; - argv[i] = _dbus_string_get_data (&uuid); - ++i; - argv[i] = "--binary-syntax"; - ++i; - argv[i] = "--close-stderr"; - ++i; - argv[i] = NULL; - ++i; - - _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); - - orig_len = _dbus_string_get_length (address); + orig_len = _dbus_string_get_length (result); #define READ_END 0 #define WRITE_END 1 - if (pipe (address_pipe) < 0) + if (pipe (result_pipe) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to create a pipe: %s", - _dbus_strerror (errno)); - _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n", - _dbus_strerror (errno)); + "Failed to create a pipe to call %s: %s", + progpath, _dbus_strerror (errno)); + _dbus_verbose ("Failed to create a pipe to call %s: %s\n", + progpath, _dbus_strerror (errno)); goto out; } if (pipe (errors_pipe) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to create a pipe: %s", - _dbus_strerror (errno)); - _dbus_verbose ("Failed to create a pipe to call dbus-launch: %s\n", - _dbus_strerror (errno)); + "Failed to create a pipe to call %s: %s", + progpath, _dbus_strerror (errno)); + _dbus_verbose ("Failed to create a pipe to call %s: %s\n", + progpath, _dbus_strerror (errno)); goto out; } @@ -2956,10 +2941,10 @@ _dbus_get_autolaunch_address (DBusString *address, if (pid < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to fork(): %s", - _dbus_strerror (errno)); - _dbus_verbose ("Failed to fork() to call dbus-launch: %s\n", - _dbus_strerror (errno)); + "Failed to fork() to call %s: %s", + progpath, _dbus_strerror (errno)); + _dbus_verbose ("Failed to fork() to call %s: %s\n", + progpath, _dbus_strerror (errno)); goto out; } @@ -2977,7 +2962,7 @@ _dbus_get_autolaunch_address (DBusString *address, _dbus_verbose ("/dev/null fd %d opened\n", fd); /* set-up stdXXX */ - close (address_pipe[READ_END]); + close (result_pipe[READ_END]); close (errors_pipe[READ_END]); close (0); /* close stdin */ close (1); /* close stdout */ @@ -2985,7 +2970,7 @@ _dbus_get_autolaunch_address (DBusString *address, if (dup2 (fd, 0) == -1) _exit (1); - if (dup2 (address_pipe[WRITE_END], 1) == -1) + if (dup2 (result_pipe[WRITE_END], 1) == -1) _exit (1); if (dup2 (errors_pipe[WRITE_END], 2) == -1) _exit (1); @@ -3002,25 +2987,26 @@ _dbus_get_autolaunch_address (DBusString *address, sigprocmask(SIG_SETMASK, &old_set, NULL); - execv (DBUS_BINDIR "/dbus-launch", argv); - - /* failed, try searching PATH */ - execvp ("dbus-launch", argv); + /* If it looks fully-qualified, try execv first */ + if (progpath[0] == '/') + execv (progpath, argv); + else + execvp (progpath, argv); /* still nothing, we failed */ _exit (1); } /* parent process */ - close (address_pipe[WRITE_END]); + close (result_pipe[WRITE_END]); close (errors_pipe[WRITE_END]); - address_pipe[WRITE_END] = -1; + result_pipe[WRITE_END] = -1; errors_pipe[WRITE_END] = -1; ret = 0; do { - ret = _dbus_read (address_pipe[READ_END], address, 1024); + ret = _dbus_read (result_pipe[READ_END], result, 1024); } while (ret > 0); @@ -3033,27 +3019,27 @@ _dbus_get_autolaunch_address (DBusString *address, /* We succeeded if the process exited with status 0 and anything was read */ - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 || - _dbus_string_get_length (address) == orig_len) + if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) { /* The process ended with error */ DBusString error_message; _dbus_string_init (&error_message); ret = 0; do - { - ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); - } + { + ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); + } while (ret > 0); - _dbus_string_set_length (address, orig_len); + _dbus_string_set_length (result, orig_len); if (_dbus_string_get_length (&error_message) > 0) - dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, - "dbus-launch failed to autolaunch D-Bus session: %s", - _dbus_string_get_data (&error_message)); + dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, + "%s terminated abnormally with the following error: %s", + progpath, _dbus_string_get_data (&error_message)); else - dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, - "Failed to execute dbus-launch to autolaunch D-Bus session"); + dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, + "%s terminated abnormally without any error message", + progpath); goto out; } @@ -3067,15 +3053,73 @@ _dbus_get_autolaunch_address (DBusString *address, else _DBUS_ASSERT_ERROR_IS_SET (error); - if (address_pipe[0] != -1) - close (address_pipe[0]); - if (address_pipe[1] != -1) - close (address_pipe[1]); + if (result_pipe[0] != -1) + close (result_pipe[0]); + if (result_pipe[1] != -1) + close (result_pipe[1]); if (errors_pipe[0] != -1) close (errors_pipe[0]); if (errors_pipe[1] != -1) close (errors_pipe[1]); + return retval; +} + +/** + * Returns the address of a new session bus. + * + * If successful, returns #TRUE and appends the address to @p + * address. If a failure happens, returns #FALSE and + * sets an error in @p error. + * + * @param address a DBusString where the address can be stored + * @param error a DBusError to store the error in case of failure + * @returns #TRUE on success, #FALSE if an error happened + */ +dbus_bool_t +_dbus_get_autolaunch_address (DBusString *address, + DBusError *error) +{ + static char *argv[6]; + int i; + DBusString uuid; + dbus_bool_t retval; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + retval = FALSE; + + if (!_dbus_string_init (&uuid)) + { + _DBUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_get_local_machine_uuid_encoded (&uuid)) + { + _DBUS_SET_OOM (error); + goto out; + } + + i = 0; + argv[i] = "dbus-launch"; + ++i; + argv[i] = "--autolaunch"; + ++i; + argv[i] = _dbus_string_get_data (&uuid); + ++i; + argv[i] = "--binary-syntax"; + ++i; + argv[i] = "--close-stderr"; + ++i; + argv[i] = NULL; + ++i; + + _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); + + retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", + argv, address, error); + + out: _dbus_string_free (&uuid); return retval; } -- cgit