* dbus/dbus-sysdeps-unix.c: capture the dbus-launch stderr
authorThiago Macieira <thiago@kde.org>
Sat, 3 Mar 2007 10:36:46 +0000 (10:36 +0000)
committerThiago Macieira <thiago@kde.org>
Sat, 3 Mar 2007 10:36:46 +0000 (10:36 +0000)
        output and add it to the DBusError message we return.

* tools/dbus-launch.1:
* tools/dbus-launch.c: Add option --close-stderr to, well,
close stderr before starting dbus-daemon.

ChangeLog
dbus/dbus-sysdeps-unix.c
tools/dbus-launch.1
tools/dbus-launch.c

index 640ccc3..68c875c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-03-03  Thiago Macieira  <thiago@kde.org>
+
+       * dbus/dbus-sysdeps-unix.c: capture the dbus-launch stderr
+        output and add it to the DBusError message we return.
+
+       * tools/dbus-launch.1:
+       * tools/dbus-launch.c: Add option --close-stderr to, well,
+       close stderr before starting dbus-daemon.
+
 2007-01-31  Havoc Pennington  <hp@redhat.com>
 
        * bus/dbus-daemon.1.in: write a section in the man page on running
index 26fa5f9..ebb269c 100644 (file)
@@ -2434,8 +2434,9 @@ dbus_bool_t
 _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;
@@ -2464,6 +2465,8 @@ _dbus_get_autolaunch_address (DBusString *address,
   ++i;
   argv[i] = "--binary-syntax";
   ++i;
+  argv[i] = "--close-stderr";
+  ++i;
   argv[i] = NULL;
   ++i;
 
@@ -2482,6 +2485,15 @@ _dbus_get_autolaunch_address (DBusString *address,
                      _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)
@@ -2504,6 +2516,7 @@ _dbus_get_autolaunch_address (DBusString *address,
 
       /* 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 */
@@ -2512,11 +2525,12 @@ _dbus_get_autolaunch_address (DBusString *address,
         _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);
 
@@ -2529,6 +2543,10 @@ _dbus_get_autolaunch_address (DBusString *address,
 
   /* 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 
     {
@@ -2549,9 +2567,23 @@ _dbus_get_autolaunch_address (DBusString *address,
       _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;
     }
 
@@ -2562,7 +2594,16 @@ _dbus_get_autolaunch_address (DBusString *address,
     _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;
 }
index 68adb2c..0ea1949 100644 (file)
@@ -136,6 +136,13 @@ binary integer of size sizeof(long). Integers are in the machine's
 byte order, not network byte order or any other canonical byte order.
 
 .TP
+.I "--close-stderr"
+Close the standard error output stream before starting the D-Bus
+daemon. This is useful if you want to capture dbus-launch error
+messages but you don't want dbus-daemon to keep the stream open to
+your application.
+
+.TP
 .I "--config-file=FILENAME"
 Pass \-\-config-file=FILENAME to the bus daemon, instead of passing it 
 the \-\-session argument. See the man page for dbus-daemon
index 7e53e7e..d307278 100644 (file)
@@ -596,6 +596,27 @@ babysit (int   exit_with_session,
   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
 
@@ -613,7 +634,8 @@ main (int argc, char **argv)
   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];
@@ -647,6 +669,8 @@ main (int argc, char **argv)
         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;
@@ -837,6 +861,9 @@ main (int argc, char **argv)
       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 */
@@ -859,7 +886,7 @@ main (int argc, char **argv)
           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