dbus/tools Makefile.am, 1.21, 1.22 dbus-launch-x11.c, NONE, 1.1 dbus-launch.1, 1.6, 1.7 dbus-launch.c, 1.16, 1.17 dbus-launch.h, NONE, 1.1

Thiago J. Macieira thiago at kemper.freedesktop.org
Sat Sep 30 12:38:36 PDT 2006


Update of /cvs/dbus/dbus/tools
In directory kemper:/tmp/cvs-serv22941/tools

Modified Files:
	Makefile.am dbus-launch.1 dbus-launch.c 
Added Files:
	dbus-launch-x11.c dbus-launch.h 
Log Message:
	* configure.in: add DBUS_BINDIR as a #define to C source code.

	* tools/dbus-launch.c
	* tools/dbus-launch.h
	* tools/dbus-launch-x11.c:
	* tools/dbus-launch.1: Add the --autolaunch option to
	dbus-launch, which makes it scan for an existing session
	started with --autolaunch. With that option, it also creates
	an X11 window and saves the bus address and PID to it.

	* dbus/dbus-sysdeps.h:
	* dbus/dbus-sysdeps-unix.c (_dbus_get_autolaunch_address): Add
	a function that runs "dbus-launch --autolaunch" to retrieve
	the running D-Bus session address (or start one if none was running)

	* dbus/dbus-transport.c: Add the handler for the "autolaunch:"
        address protocol, which tries to get the running session from
        dbus-launch.

	* dbus/dbus-bus.c:
	* dbus/dbus-internals.h: Make "autolaunch:" be the default
	D-Bus session bus address.

	* dbus/dbus-connection.c: Fix horrible typo in error message.


Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/tools/Makefile.am,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- Makefile.am	18 Sep 2006 17:17:41 -0000	1.21
+++ Makefile.am	30 Sep 2006 19:38:34 -0000	1.22
@@ -13,7 +13,8 @@
 	dbus-print-message.h
 
 dbus_launch_SOURCES=				\
-	dbus-launch.c
+	dbus-launch.c				\
+	dbus-launch-x11.c
 
 dbus_cleanup_sockets_SOURCES=			\
 	dbus-cleanup-sockets.c

--- NEW FILE: dbus-launch-x11.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-launch.h  dbus-launch utility
 *
 * Copyright (C) 2006 Thiago Macieira <thiago at kde.org>
 *
 * Licensed under the Academic Free License version 2.1
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "dbus-launch.h"

#ifdef DBUS_BUILD_X11
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

Display *xdisplay;
static Atom selection_atom;
static Atom address_atom;
static Atom pid_atom;

static int
x_io_error_handler (Display *xdisplay)
{
  verbose ("X IO error\n");
  kill_bus_and_exit (0);
  return 0;
}

static char *
get_local_hostname (void)
{
  static const int increment = 128;
  static char *cache = NULL;
  char *buffer = NULL;
  int size = 0;

  while (cache == NULL)
    {
      size += increment;
      buffer = realloc (buffer, size);
      if (buffer == NULL)
        return NULL;            /* out of memory */

      if (gethostname (buffer, size - 1) == -1 &&
          errno != ENAMETOOLONG)
        return NULL;

      buffer[size - 1] = '\0';  /* to make sure */
      cache = buffer;
    }

  return cache;
}

static char *
get_session_file (void)
{
  static const char prefix[] = "/.dbus-session-file_";
  char *hostname;
  char *display;
  char *home;
  char *result;
  char *p;

  display = xstrdup (getenv ("DISPLAY"));
  if (display == NULL)
    {
      verbose ("X11 integration disabled because X11 is not running\n");
      return NULL;
    }

  /* remove the screen part of the display name */
  p = strrchr (display, ':');
  if (p != NULL)
    for ( ; *p; ++p)
      if (*p == '.')
        {
          *p = '\0';
          break;
        }

  /* replace the : in the display with _ */
  for (p = display; *p; ++p)
    if (*p == ':')
      *p = '_';

  hostname = get_local_hostname ();
  if (hostname == NULL)
    {
      /* out of memory */
      free (display);
      return NULL;
    }

  home = getenv ("HOME");
  if (home == NULL)
    {
      /* try from the user database */
      struct passwd *user = getpwuid (getuid());
      if (user == NULL)
        {
          verbose ("X11 integration disabled because the home directory"
                   " could not be determined\n");
          free (display);
          return NULL;
        }

      home = user->pw_dir;
    }

  result = malloc (strlen (home) + strlen (prefix) + strlen (hostname) +
                   strlen (display) + 2);
  if (result == NULL)
    {
      /* out of memory */
      free (display);
      return NULL;
    }

  strcpy (result, home);
  strcat (result, prefix);
  strcat (result, hostname);
  strcat (result, "_");
  strcat (result, display);
  free (display);

  verbose ("session file: %s\n", result);
  return result;
}

static Display *
open_x11 (void)
{
  if (xdisplay != NULL)
    return xdisplay;

  xdisplay = XOpenDisplay (NULL);
  if (xdisplay != NULL)
    {
      verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay));
      XSetIOErrorHandler (x_io_error_handler);
    }
  return xdisplay;
}

static int
init_x_atoms (Display *display)
{
  static const char selection_prefix[] = "DBUS_SESSION_SELECTION_";
  static const char address_prefix[] = "DBUS_SESSION_ADDRESS";
  static const char pid_prefix[] = "DBUS_SESSION_PID";
  static int init = FALSE;
  char *atom_name;
  char *hostname;
  char *user_name;
  struct passwd *user;

  if (init)
    return TRUE;

  user = getpwuid (getuid ());
  if (user == NULL)
    {
      verbose ("Could not determine the user informations; aborting X11 integration.\n");
      return FALSE;
    }
  user_name = xstrdup(user->pw_name);

  hostname = get_local_hostname ();
  if (hostname == NULL)
    {
      verbose ("Could not create X11 atoms; aborting X11 integration.\n");
      free (user_name);
      return FALSE;
    }

  atom_name = malloc (strlen (hostname) + strlen (user_name) + 2 +
                      MAX (strlen (selection_prefix),
                           MAX (strlen (address_prefix),
                                strlen (pid_prefix))));
  if (atom_name == NULL)
    {
      verbose ("Could not create X11 atoms; aborting X11 integration.\n");
      free (user_name);
      return FALSE;
    }

  /* create the selection atom */
  strcpy (atom_name, selection_prefix);
  strcat (atom_name, user_name);
  strcat (atom_name, "_");
  strcat (atom_name, hostname);
  selection_atom = XInternAtom (display, atom_name, FALSE);

  /* create the address property atom */
  strcpy (atom_name, address_prefix);
  address_atom = XInternAtom (display, atom_name, FALSE);

  /* create the PID property atom */
  strcpy (atom_name, pid_prefix);
  pid_atom = XInternAtom (display, atom_name, FALSE);

  free (atom_name);
  free (user_name);
  init = TRUE;
  return TRUE;
}

/*
 * Gets the daemon address from the X11 display.
 * Returns FALSE if there was an error. Returning
 * TRUE does not mean the address exists.
 */
int
x11_get_address (char **paddress, pid_t *pid, long *wid)
{
  Atom type;
  Window owner;
  int format;
  unsigned long items;
  unsigned long after;
  char *data;

  *paddress = NULL;

  /* locate the selection owner */
  owner = XGetSelectionOwner (xdisplay, selection_atom);
  if (owner == None)
    return TRUE;                /* no owner */
  if (wid != NULL)
    *wid = (long) owner;

  /* get the bus address */
  XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False,
                      XA_STRING, &type, &format, &items, &after,
                      (unsigned char **) &data);
  if (type == None || after != 0 || data == NULL || format != 8)
    return FALSE;               /* error */

  *paddress = xstrdup (data);
  XFree (data);

  /* get the PID */
  if (pid != NULL)
    {
      *pid = 0;
      XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False,
                          XA_CARDINAL, &type, &format, &items, &after,
                          (unsigned char **) &data);
      if (type != None && after == 0 && data != NULL && format == 32)
        *pid = (pid_t) *(long*) data;
      XFree (data);
    }

  return TRUE;                  /* success */
}

/*
 * Saves the address in the X11 display. Returns 0 on success.
 * If an error occurs, returns -1. If the selection already exists,
 * returns 1. (i.e. another daemon is already running)
 */
static Window
set_address_in_x11(char *address, pid_t pid)
{
  char *current_address;
  Window wid;

  /* lock the X11 display to make sure we're doing this atomically */
  XGrabServer (xdisplay);

  if (!x11_get_address (&current_address, NULL, NULL))
    {
      /* error! */
      XUngrabServer (xdisplay);
      return None;
    }

  if (current_address != NULL)
    {
      /* someone saved the address in the meantime */
      XUngrabServer (xdisplay);
      free (current_address);
      return None;
    }

  /* Create our window */
  wid = XCreateSimpleWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
                             0, WhitePixel (xdisplay, 0),
                             BlackPixel (xdisplay, 0));
  verbose ("Created window %d\n", wid);

  /* Save the property in the window */
  XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
                   (unsigned char *)address, strlen (address));
  XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
                   (unsigned char *)&pid, sizeof(pid) / 4);

  /* Now grab the selection */
  XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);

  /* Ungrab the server to let other people use it too */
  XUngrabServer (xdisplay);

  XFlush (xdisplay);

  return wid;
}

/*
 * Saves the session address in session file. Returns TRUE on
 * success, FALSE if an error occurs.
 */
static int
set_address_in_file (char *address, pid_t pid, Window wid)
{
  char *session_file;
  FILE *f;

  session_file = get_session_file();
  if (session_file == NULL)
    return FALSE;

  f = fopen (session_file, "w");
  if (f == NULL)
    return FALSE;               /* some kind of error */
  fprintf (f, "%s\n%ld\n%ld\n", address, (long)pid, (long)wid);

  fclose (f);
  free (session_file);

  return TRUE;
}

int
x11_save_address (char *address, pid_t pid, long *wid)
{
  Window id = set_address_in_x11 (address, pid);
  if (id != None)
    {
      if (!set_address_in_file (address, pid, id))
        return FALSE;

      if (wid != NULL)
        *wid = (long) id;
      return TRUE;
    }
  return FALSE;
}

int
x11_init (void)
{
  return open_x11 () != NULL && init_x_atoms (xdisplay);
}

void
x11_handle_event (void)
{
  if (xdisplay != NULL)
    {      
      while (XPending (xdisplay))
        {
          XEvent ignored;
          XNextEvent (xdisplay, &ignored);
        }
    }
}  

#else
void dummy_dbus_launch_x11 (void) { }
#endif

Index: dbus-launch.1
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch.1,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- dbus-launch.1	3 Aug 2006 20:34:36 -0000	1.6
+++ dbus-launch.1	30 Sep 2006 19:38:34 -0000	1.7
@@ -7,7 +7,7 @@
 dbus-launch \- Utility to start a message bus from a shell script
 .SH SYNOPSIS
 .PP
-.B dbus-launch [\-\-version] [\-\-sh-syntax] [\-\-csh-syntax] [\-\-auto-syntax] [\-\-exit-with-session] [\-\-config-file=FILENAME] [PROGRAM] [ARGS...]
+.B dbus-launch [\-\-version] [\-\-sh-syntax] [\-\-csh-syntax] [\-\-auto-syntax] [\-\-exit-with-session] [\-\-autolaunch] [\-\-config-file=FILENAME] [PROGRAM] [ARGS...]
 
 .SH DESCRIPTION
 
@@ -90,6 +90,13 @@
 it kills the message bus daemon.
 
 .TP
+.I "--autolaunch"
+This option implies that \fIdbus-launch\fP should scan for a
+previously-started session and reuse the values found there. If no
+session is found, it will start a new session. The
+\-\-exit-with-session option is implied if \-\-autolaunch is given.
+
+.TP
 .I "--sh-syntax"
 Emit Bourne-shell compatible code to set up environment variables.
 

Index: dbus-launch.c
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- dbus-launch.c	1 Sep 2006 20:47:09 -0000	1.16
+++ dbus-launch.c	30 Sep 2006 19:38:34 -0000	1.17
@@ -20,7 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
-#include <config.h>
+#include "dbus-launch.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -32,22 +32,14 @@
 #include <signal.h>
 #include <stdarg.h>
 #include <sys/select.h>
+#include <time.h>
+
 #ifdef DBUS_BUILD_X11
 #include <X11/Xlib.h>
+extern Display *xdisplay;
 #endif
 
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#undef	MAX
-#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
-
-static void
+void
 verbose (const char *format,
          ...)
 {
@@ -95,7 +87,7 @@
   exit (0);
 }
 
-static char *
+char *
 xstrdup (const char *str)
 {
   int len;
@@ -276,8 +268,8 @@
 
 static pid_t bus_pid_to_kill = -1;
 
-static void
-kill_bus_and_exit (void)
+void
+kill_bus_and_exit (int exitcode)
 {
   verbose ("Killing message bus and exiting babysitter\n");
   
@@ -290,18 +282,38 @@
   sleep (3);
   kill (bus_pid_to_kill, SIGKILL);
 
-  exit (0);
+  exit (exitcode);
 }
 
-#ifdef DBUS_BUILD_X11
-static int
-x_io_error_handler (Display *xdisplay)
+static void
+print_variables (const char *bus_address, pid_t bus_pid, long bus_wid,
+		 int c_shell_syntax, int bourne_shell_syntax,
+		 int binary_syntax)
 {
-  verbose ("X IO error\n");
-  kill_bus_and_exit ();
-  return 0;
+  if (binary_syntax)
+    {
+      write (1, bus_address, strlen (bus_address) + 1);
+      write (1, &bus_pid, sizeof bus_pid);
+      write (1, &bus_wid, sizeof bus_wid);
+      return;
+    }
+  else if (c_shell_syntax)
+    {
+      printf ("setenv DBUS_SESSION_BUS_ADDRESS '%s';\n", bus_address);	
+      printf ("set DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
+      if (bus_wid)
+	printf ("set DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid);
+    }
+  else
+    {
+      printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address);
+      if (bourne_shell_syntax)
+	printf ("export DBUS_SESSION_BUS_ADDRESS;\n");
+      printf ("DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
+      if (bus_wid)
+	printf ("DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid);
+    }
 }
-#endif
 
 static int got_sighup = FALSE;
 
@@ -326,9 +338,6 @@
   fd_set err_set;
   struct sigaction act;
   sigset_t empty_mask;
-#ifdef DBUS_BUILD_X11
-  Display *xdisplay;
-#endif
   
   /* install SIGHUP handler */
   got_sighup = FALSE;
@@ -340,17 +349,14 @@
   sigaction (SIGTERM,  &act, NULL);
   
 #ifdef DBUS_BUILD_X11
-  xdisplay = XOpenDisplay (NULL);
+  x11_init();
   if (xdisplay != NULL)
     {
-      verbose ("Successfully opened X display\n");
       x_fd = ConnectionNumber (xdisplay);
-      XSetIOErrorHandler (x_io_error_handler);
     }
   else
     x_fd = -1;
 #else
-  verbose ("Compiled without X11 support\n");
   x_fd = -1;
 #endif
 
@@ -393,7 +399,7 @@
       if (got_sighup)
         {
           verbose ("Got SIGHUP, exiting\n");
-          kill_bus_and_exit ();
+          kill_bus_and_exit (0);
         }
       
 #ifdef DBUS_BUILD_X11
@@ -405,15 +411,7 @@
         verbose ("X fd condition reading = %d error = %d\n",
                  FD_ISSET (x_fd, &read_set),
                  FD_ISSET (x_fd, &err_set));
-      
-      if (xdisplay != NULL)
-        {      
-          while (XPending (xdisplay))
-            {
-              XEvent ignored;
-              XNextEvent (xdisplay, &ignored);
-            }
-        }
+      x11_handle_event ();
 #endif
 
       if (tty_fd >= 0)
@@ -431,7 +429,7 @@
                        bytes_read, errno);
               
               if (bytes_read == 0)
-                kill_bus_and_exit (); /* EOF */
+                kill_bus_and_exit (0); /* EOF */
               else if (bytes_read < 0 && errno != EINTR)
                 {
                   /* This shouldn't happen I don't think; to avoid
@@ -439,14 +437,14 @@
                    */
                   fprintf (stderr, "dbus-launch: error reading from stdin: %s\n",
                            strerror (errno));
-                  kill_bus_and_exit ();
+                  kill_bus_and_exit (0);
                 }
             }
           else if (FD_ISSET (tty_fd, &err_set))
             {
               verbose ("TTY has error condition\n");
               
-              kill_bus_and_exit ();
+              kill_bus_and_exit (0);
             }
         }
     }
@@ -455,19 +453,14 @@
 static void
 babysit (int   exit_with_session,
          pid_t child_pid,
-         int   read_bus_pid_fd,  /* read pid from here */
-         int   write_bus_pid_fd) /* forward pid to here */
+         int   read_bus_pid_fd)  /* read pid from here */
 {
   int ret;
-#define MAX_PID_LEN 64
-  char buf[MAX_PID_LEN];
-  long val;
-  char *end;
   int dev_null_fd;
   const char *s;
 
-  verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d, write_bus_pid_fd = %d\n",
-           exit_with_session, (long) child_pid, read_bus_pid_fd, write_bus_pid_fd);
+  verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n",
+           exit_with_session, (long) child_pid, read_bus_pid_fd);
   
   /* We chdir ("/") since we are persistent and daemon-like, and fork
    * again so dbus-launch can reap the parent.  However, we don't
@@ -536,41 +529,26 @@
   /* Child continues */
   verbose ("=== Babysitter process created\n");
 
-  verbose ("Reading PID from daemon\n");
-  /* Now read data */
-  switch (read_line (read_bus_pid_fd, buf, MAX_PID_LEN))
+  verbose ("Reading PID from bus\n");
+      
+  switch (read_pid (read_bus_pid_fd, &bus_pid_to_kill))
     {
     case READ_STATUS_OK:
       break;
     case READ_STATUS_EOF:
-      fprintf (stderr, "EOF reading PID from bus daemon\n");
+      fprintf (stderr, "EOF in dbus-launch reading PID from bus daemon\n");
       exit (1);
       break;
     case READ_STATUS_ERROR:
-      fprintf (stderr, "Error reading PID from bus daemon: %s\n",
-               strerror (errno));
+      fprintf (stderr, "Error in dbus-launch reading PID from bus daemon: %s\n",
+	       strerror (errno));
       exit (1);
       break;
     }
 
-  end = NULL;
-  val = strtol (buf, &end, 0);
-  if (buf == end || end == NULL)
-    {
-      fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n",
-               buf, strerror (errno));
-      exit (1);
-    }
-
-  bus_pid_to_kill = val;
-
   verbose ("Got PID %ld from daemon\n",
            (long) bus_pid_to_kill);
   
-  /* Write data to launcher */
-  write_pid (write_bus_pid_fd, bus_pid_to_kill);
-  close (write_bus_pid_fd);
-  
   if (exit_with_session)
     {
       /* Bus is now started and launcher has needed info;
@@ -597,9 +575,11 @@
   const char *runprog = NULL;
   int remaining_args = 0;
   int exit_with_session;
+  int binary_syntax = FALSE;
   int c_shell_syntax = FALSE;
   int bourne_shell_syntax = FALSE;
   int auto_shell_syntax = FALSE;
+  int autolaunch = FALSE;
   int i;  
   int ret;
   int bus_pid_to_launcher_pipe[2];
@@ -628,10 +608,14 @@
       else if (strcmp (arg, "-s") == 0 ||
 	       strcmp (arg, "--sh-syntax") == 0)
         bourne_shell_syntax = TRUE;
+      else if (strcmp (arg, "--binary-syntax") == 0)
+	binary_syntax = TRUE;
       else if (strcmp (arg, "--version") == 0)
         version ();
       else if (strcmp (arg, "--exit-with-session") == 0)
         exit_with_session = TRUE;
+      else if (strcmp (arg, "--autolaunch") == 0)
+	autolaunch = TRUE;
       else if (strstr (arg, "--config-file=") == arg)
         {
           const char *file;
@@ -672,9 +656,6 @@
       ++i;
     }
 
-  if (exit_with_session)
-    verbose ("--exit-with-session enabled\n");
-
   if (auto_shell_syntax)
     {
       if ((shname = getenv ("SHELL")) != NULL)
@@ -688,8 +669,52 @@
        bourne_shell_syntax = TRUE;
     }  
 
+  if (exit_with_session)
+    verbose ("--exit-with-session enabled\n");
+
+  if (autolaunch)
+    {
+#ifndef DBUS_BUILD_X11
+      fprintf (stderr, "Autolaunch requested, but X11 support not compiled in.\n"
+	       "Cannot continue.\n");
+      exit (1);
+#else
+      char *address;
+      pid_t pid;
+      long wid;
+
+      verbose ("Autolaunch enabled (using X11).\n");
+      if (!exit_with_session)
+	{
+	  verbose ("--exit-with-session automatically enabled\n");
+	  exit_with_session = TRUE;
+	}
+
+      if (!x11_init ())
+	{
+	  fprintf (stderr, "Autolaunch error: X11 initialization failed.\n");
+	  exit (1);
+	}
+
+      if (!x11_get_address (&address, &pid, &wid))
+	{
+	  fprintf (stderr, "Autolaunch error: X11 communication error.\n");
+	  exit (1);
+	}
+
+      if (address != NULL)
+	{
+	  verbose ("dbus-daemon is already running. Returning existing parameters.\n");
+	  print_variables (address, pid, wid, c_shell_syntax,
+			   bourne_shell_syntax, binary_syntax);
+	  exit (0);
+	}
+#endif
+    }
+
   if (pipe (bus_pid_to_launcher_pipe) < 0 ||
-      pipe (bus_address_to_launcher_pipe) < 0)
+      pipe (bus_address_to_launcher_pipe) < 0 ||
+      pipe (bus_pid_to_babysitter_pipe) < 0)
     {
       fprintf (stderr,
                "Failed to create pipe: %s\n",
@@ -697,9 +722,6 @@
       exit (1);
     }
 
-  bus_pid_to_babysitter_pipe[READ_END] = -1;
-  bus_pid_to_babysitter_pipe[WRITE_END] = -1;
-  
   ret = fork ();
   if (ret < 0)
     {
@@ -716,17 +738,9 @@
       char write_address_fd_as_string[MAX_FD_LEN];
 
       verbose ("=== Babysitter's intermediate parent created\n");
-      
+
       /* Fork once more to create babysitter */
       
-      if (pipe (bus_pid_to_babysitter_pipe) < 0)
-        {
-          fprintf (stderr,
-                   "Failed to create pipe: %s\n",
-                   strerror (errno));
-          exit (1);              
-        }
-      
       ret = fork ();
       if (ret < 0)
         {
@@ -741,6 +755,7 @@
           verbose ("=== Babysitter's intermediate parent continues\n");
           
           close (bus_pid_to_launcher_pipe[READ_END]);
+	  close (bus_pid_to_launcher_pipe[WRITE_END]);
           close (bus_address_to_launcher_pipe[READ_END]);
           close (bus_address_to_launcher_pipe[WRITE_END]);
           close (bus_pid_to_babysitter_pipe[WRITE_END]);
@@ -750,8 +765,7 @@
            * daemon
            */
           babysit (exit_with_session, ret,
-                   bus_pid_to_babysitter_pipe[READ_END],
-                   bus_pid_to_launcher_pipe[WRITE_END]);
+                   bus_pid_to_babysitter_pipe[READ_END]);
           exit (0);
         }
 
@@ -763,10 +777,10 @@
       close (bus_pid_to_launcher_pipe[READ_END]);
       close (bus_address_to_launcher_pipe[READ_END]);
       close (bus_pid_to_babysitter_pipe[READ_END]);
-      close (bus_pid_to_launcher_pipe[WRITE_END]);
+      close (bus_pid_to_babysitter_pipe[WRITE_END]);
 
       sprintf (write_pid_fd_as_string,
-               "%d", bus_pid_to_babysitter_pipe[WRITE_END]);
+               "%d", bus_pid_to_launcher_pipe[WRITE_END]);
 
       sprintf (write_address_fd_as_string,
                "%d", bus_address_to_launcher_pipe[WRITE_END]);
@@ -809,14 +823,20 @@
   else
     {
       /* Parent */
-#define MAX_ADDR_LEN 512
+#define MAX_PID_LEN 64
       pid_t bus_pid;  
       char bus_address[MAX_ADDR_LEN];
+      char buf[MAX_PID_LEN];
+      char *end;
+      long wid = 0;
+      long val;
+      int ret2;
 
       verbose ("=== Parent dbus-launch continues\n");
       
       close (bus_pid_to_launcher_pipe[WRITE_END]);
       close (bus_address_to_launcher_pipe[WRITE_END]);
+      close (bus_pid_to_babysitter_pipe[READ_END]);
 
       verbose ("Waiting for babysitter's intermediate parent\n");
       
@@ -851,25 +871,70 @@
         
       close (bus_address_to_launcher_pipe[READ_END]);
 
-      verbose ("Reading PID from babysitter\n");
-      
-      switch (read_pid (bus_pid_to_launcher_pipe[READ_END], &bus_pid))
-        {
-        case READ_STATUS_OK:
-          break;
-        case READ_STATUS_EOF:
-          fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
-          exit (1);
-          break;
-        case READ_STATUS_ERROR:
-          fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
-                   strerror (errno));
-          exit (1);
-          break;
-        }
+      verbose ("Reading PID from daemon\n");
+      /* Now read data */
+      switch (read_line (bus_pid_to_launcher_pipe[READ_END], buf, MAX_PID_LEN))
+	{
+	case READ_STATUS_OK:
+	  break;
+	case READ_STATUS_EOF:
+	  fprintf (stderr, "EOF reading PID from bus daemon\n");
+	  exit (1);
+	  break;
+	case READ_STATUS_ERROR:
+	  fprintf (stderr, "Error reading PID from bus daemon: %s\n",
+		   strerror (errno));
+	  exit (1);
+	  break;
+	}
+
+      end = NULL;
+      val = strtol (buf, &end, 0);
+      if (buf == end || end == NULL)
+	{
+	  fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n",
+		   buf, strerror (errno));
+	  exit (1);
+	}
+
+      bus_pid = val;
 
       close (bus_pid_to_launcher_pipe[READ_END]);
-      
+
+#ifdef DBUS_BUILD_X11
+      ret2 = x11_save_address (bus_address, bus_pid, &wid);
+      if (ret2 == 0)
+	{
+	  /* another window got added. Return its address */
+	  char *address;
+	  pid_t pid;
+	  long wid;
+
+	  if (x11_get_address (&address, &pid, &wid) && address != NULL)
+	    {
+	      verbose ("dbus-daemon is already running. Returning existing parameters.\n");
+	      print_variables (address, pid, wid, c_shell_syntax,
+			       bourne_shell_syntax, binary_syntax);
+	      free (address);
+
+	      bus_pid_to_kill = bus_pid;
+	      kill_bus_and_exit (0);
+	    }
+
+	  /* if failed, fall through */
+	}
+      if (ret2 <= 0)
+	{
+	  fprintf (stderr, "Error saving bus information.\n");
+	  bus_pid_to_kill = bus_pid;
+	  kill_bus_and_exit (1);
+	}
+#endif
+
+      /* Forward the pid to the babysitter */
+      write_pid (bus_pid_to_babysitter_pipe[WRITE_END], bus_pid);
+      close (bus_pid_to_babysitter_pipe[WRITE_END]);
+
       if (runprog)
 	{
 	  char *envvar;
@@ -904,18 +969,8 @@
 	}
       else
 	{
-	  if (c_shell_syntax)
-	    printf ("setenv DBUS_SESSION_BUS_ADDRESS '%s';\n", bus_address);	
-	  else
-	    {
-	      printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address);
-	      if (bourne_shell_syntax)
-		printf ("export DBUS_SESSION_BUS_ADDRESS;\n");
-	    }
-	  if (c_shell_syntax)
-	    printf ("set DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
-	  else
-	    printf ("DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
+	  print_variables (bus_address, bus_pid, wid, c_shell_syntax,
+			   bourne_shell_syntax, binary_syntax);
 	}
 	  
       verbose ("dbus-launch exiting\n");

--- NEW FILE: dbus-launch.h ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-launch.h  dbus-launch utility
 *
 * Copyright (C) 2006 Thiago Macieira <thiago at kde.org>
 *
 * Licensed under the Academic Free License version 2.1
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef DBUS_LAUNCH_H
#define DBUS_LAUNCH_H

#include <config.h>
#include <sys/types.h>

#ifndef TRUE
#define TRUE (1)
#endif

#ifndef FALSE
#define FALSE (0)
#endif

#undef  MAX
#define MAX(a, b)  (((a) > (b)) ? (a) : (b))

#define MAX_ADDR_LEN 512

/* defined in dbus-launch.c */
void verbose (const char *format, ...);
char *xstrdup (const char *str);
void kill_bus_and_exit (int exitcode);

#ifdef DBUS_BUILD_X11
/* defined in dbus-launch-x11.c */
int x11_init (void);
int x11_get_address (char **paddress, pid_t *pid, long *wid);
int x11_save_address (char *address, pid_t pid, long *wid);
void x11_handle_event (void);
#endif

#endif



More information about the dbus-commit mailing list