_dbus_get_autolaunch_address (DBusString *address,
DBusError *error)
{
- static char *argv[5];
- int address_pipe[2];
+ static char *argv[6];
+ int address_pipe[2] = { -1, -1 };
+ int errors_pipe[2] = { -1, -1 };
pid_t pid;
int ret;
int status;
++i;
argv[i] = "--binary-syntax";
++i;
+ argv[i] = "--close-stderr";
+ ++i;
argv[i] = NULL;
++i;
_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));
+ goto out;
+ }
pid = fork ();
if (pid < 0)
/* set-up stdXXX */
close (address_pipe[READ_END]);
+ close (errors_pipe[READ_END]);
close (0); /* close stdin */
close (1); /* close stdout */
close (2); /* close stderr */
_exit (1);
if (dup2 (address_pipe[WRITE_END], 1) == -1)
_exit (1);
- if (dup2 (fd, 2) == -1)
+ if (dup2 (errors_pipe[WRITE_END], 2) == -1)
_exit (1);
close (fd);
close (address_pipe[WRITE_END]);
+ close (errors_pipe[WRITE_END]);
execv (DBUS_BINDIR "/dbus-launch", argv);
/* parent process */
close (address_pipe[WRITE_END]);
+ close (errors_pipe[WRITE_END]);
+ address_pipe[WRITE_END] = -1;
+ errors_pipe[WRITE_END] = -1;
+
ret = 0;
do
{
_dbus_string_get_length (address) == orig_len)
{
/* 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);
+ }
+ while (ret > 0);
+
_dbus_string_set_length (address, orig_len);
- dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
- "Failed to execute dbus-launch to autolaunch D-Bus session");
+ 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));
+ else
+ dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+ "Failed to execute dbus-launch to autolaunch D-Bus session");
goto out;
}
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
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 (errors_pipe[0] != -1)
+ close (errors_pipe[0]);
+ if (errors_pipe[1] != -1)
+ close (errors_pipe[1]);
+
_dbus_string_free (&uuid);
return retval;
}
exit (0);
}
+static void do_close_stderr (void)
+{
+ fflush (stderr);
+
+ /* dbus-launch is a Unix-only program, so we can rely on /dev/null being there.
+ * We're including unistd.h and we're dealing with sh/csh launch sequences...
+ */
+ int fd = open ("/dev/null", O_RDWR);
+ if (fd == -1)
+ {
+ fprintf (stderr, "Internal error: cannot open /dev/null: %s", strerror (errno));
+ exit (1);
+ }
+
+ close (2);
+ if (dup2 (fd, 2) == -1)
+ // error; we can't report an error anymore...
+ exit (1);
+ close (fd);
+}
+
#define READ_END 0
#define WRITE_END 1
int auto_shell_syntax = FALSE;
int autolaunch = FALSE;
int requires_arg = FALSE;
- int i;
+ int close_stderr = FALSE;
+ int i;
int ret;
int bus_pid_to_launcher_pipe[2];
int bus_pid_to_babysitter_pipe[2];
version ();
else if (strcmp (arg, "--exit-with-session") == 0)
exit_with_session = TRUE;
+ else if (strcmp (arg, "--close-stderr") == 0)
+ close_stderr = TRUE;
else if (strstr (arg, "--autolaunch=") == arg)
{
const char *s;
char write_pid_fd_as_string[MAX_FD_LEN];
char write_address_fd_as_string[MAX_FD_LEN];
+ if (close_stderr)
+ do_close_stderr ();
+
verbose ("=== Babysitter's intermediate parent created\n");
/* Fork once more to create babysitter */
close (bus_address_to_launcher_pipe[READ_END]);
close (bus_address_to_launcher_pipe[WRITE_END]);
close (bus_pid_to_babysitter_pipe[WRITE_END]);
-
+
/* babysit() will fork *again*
* and will also reap the pre-forked bus
* daemon