Home | History | Annotate | Download | only in tools
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-launch.c  dbus-launch utility
      3  *
      4  * Copyright (C) 2003, 2006 Red Hat, Inc.
      5  * Copyright (C) 2006 Thiago Macieira <thiago (at) kde.org>
      6  *
      7  * Licensed under the Academic Free License version 2.1
      8  *
      9  * This program is free software; you can redistribute it and/or modify
     10  * it under the terms of the GNU General Public License as published by
     11  * the Free Software Foundation; either version 2 of the License, or
     12  * (at your option) any later version.
     13  *
     14  * This program is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  * GNU General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU General Public License
     20  * along with this program; if not, write to the Free Software
     21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #include <config.h>
     26 #include "dbus-launch.h"
     27 #include <stdlib.h>
     28 #include <ctype.h>
     29 #include <unistd.h>
     30 #include <fcntl.h>
     31 #include <signal.h>
     32 #include <sys/wait.h>
     33 #include <errno.h>
     34 #include <stdio.h>
     35 #include <string.h>
     36 #include <signal.h>
     37 #include <stdarg.h>
     38 #include <sys/select.h>
     39 #include <time.h>
     40 
     41 #ifdef DBUS_BUILD_X11
     42 #include <X11/Xlib.h>
     43 extern Display *xdisplay;
     44 #endif
     45 
     46 static char* machine_uuid = NULL;
     47 
     48 const char*
     49 get_machine_uuid (void)
     50 {
     51   return machine_uuid;
     52 }
     53 
     54 static void
     55 save_machine_uuid (const char *uuid_arg)
     56 {
     57   if (strlen (uuid_arg) != 32)
     58     {
     59       fprintf (stderr, "machine ID '%s' looks like it's the wrong length, should be 32 hex digits",
     60                uuid_arg);
     61       exit (1);
     62     }
     63 
     64   machine_uuid = xstrdup (uuid_arg);
     65 }
     66 
     67 #define UUID_MAXLEN 40
     68 /* Read the machine uuid from file if needed. Returns TRUE if machine_uuid is
     69  * set after this function */
     70 static int
     71 read_machine_uuid_if_needed (void)
     72 {
     73   FILE *f;
     74   char uuid[UUID_MAXLEN];
     75   size_t len;
     76   int ret = FALSE;
     77 
     78   if (machine_uuid != NULL)
     79     return TRUE;
     80 
     81   f = fopen (DBUS_MACHINE_UUID_FILE, "r");
     82   if (f == NULL)
     83     return FALSE;
     84 
     85   if (fgets (uuid, UUID_MAXLEN, f) == NULL)
     86     goto out;
     87 
     88   len = strlen (uuid);
     89   if (len < 32)
     90     goto out;
     91 
     92   /* rstrip the read uuid */
     93   while (len > 31 && isspace(uuid[len - 1]))
     94     len--;
     95 
     96   if (len != 32)
     97     goto out;
     98 
     99   uuid[len] = '\0';
    100   machine_uuid = xstrdup (uuid);
    101   verbose ("UID: %s\n", machine_uuid);
    102   ret = TRUE;
    103 
    104 out:
    105   fclose(f);
    106   return ret;
    107 }
    108 
    109 
    110 void
    111 verbose (const char *format,
    112          ...)
    113 {
    114   va_list args;
    115   static int verbose = TRUE;
    116   static int verbose_initted = FALSE;
    117 
    118   /* things are written a bit oddly here so that
    119    * in the non-verbose case we just have the one
    120    * conditional and return immediately.
    121    */
    122   if (!verbose)
    123     return;
    124 
    125   if (!verbose_initted)
    126     {
    127       verbose = getenv ("DBUS_VERBOSE") != NULL;
    128       verbose_initted = TRUE;
    129       if (!verbose)
    130         return;
    131     }
    132 
    133   fprintf (stderr, "%lu: ", (unsigned long) getpid ());
    134 
    135   va_start (args, format);
    136   vfprintf (stderr, format, args);
    137   va_end (args);
    138 }
    139 
    140 static void
    141 usage (int ecode)
    142 {
    143   fprintf (stderr, "dbus-launch [--version] [--help] [--sh-syntax] [--csh-syntax] [--auto-syntax] [--exit-with-session]\n");
    144   exit (ecode);
    145 }
    146 
    147 static void
    148 version (void)
    149 {
    150   printf ("D-Bus Message Bus Launcher %s\n"
    151           "Copyright (C) 2003 Red Hat, Inc.\n"
    152           "This is free software; see the source for copying conditions.\n"
    153           "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
    154           VERSION);
    155   exit (0);
    156 }
    157 
    158 char *
    159 xstrdup (const char *str)
    160 {
    161   int len;
    162   char *copy;
    163 
    164   if (str == NULL)
    165     return NULL;
    166 
    167   len = strlen (str);
    168 
    169   copy = malloc (len + 1);
    170   if (copy == NULL)
    171     return NULL;
    172 
    173   memcpy (copy, str, len + 1);
    174 
    175   return copy;
    176 }
    177 
    178 typedef enum
    179 {
    180   READ_STATUS_OK,    /**< Read succeeded */
    181   READ_STATUS_ERROR, /**< Some kind of error */
    182   READ_STATUS_EOF    /**< EOF returned */
    183 } ReadStatus;
    184 
    185 static ReadStatus
    186 read_line (int        fd,
    187            char      *buf,
    188            size_t     maxlen)
    189 {
    190   size_t bytes = 0;
    191   ReadStatus retval;
    192 
    193   memset (buf, '\0', maxlen);
    194   maxlen -= 1; /* ensure nul term */
    195 
    196   retval = READ_STATUS_OK;
    197 
    198   while (TRUE)
    199     {
    200       ssize_t chunk;
    201       size_t to_read;
    202 
    203     again:
    204       to_read = maxlen - bytes;
    205 
    206       if (to_read == 0)
    207         break;
    208 
    209       chunk = read (fd,
    210                     buf + bytes,
    211                     to_read);
    212       if (chunk < 0 && errno == EINTR)
    213         goto again;
    214 
    215       if (chunk < 0)
    216         {
    217           retval = READ_STATUS_ERROR;
    218           break;
    219         }
    220       else if (chunk == 0)
    221         {
    222           retval = READ_STATUS_EOF;
    223           break; /* EOF */
    224         }
    225       else /* chunk > 0 */
    226 	bytes += chunk;
    227     }
    228 
    229   if (retval == READ_STATUS_EOF &&
    230       bytes > 0)
    231     retval = READ_STATUS_OK;
    232 
    233   /* whack newline */
    234   if (retval != READ_STATUS_ERROR &&
    235       bytes > 0 &&
    236       buf[bytes-1] == '\n')
    237     buf[bytes-1] = '\0';
    238 
    239   return retval;
    240 }
    241 
    242 static ReadStatus
    243 read_pid (int        fd,
    244           pid_t     *buf)
    245 {
    246   size_t bytes = 0;
    247   ReadStatus retval;
    248 
    249   retval = READ_STATUS_OK;
    250 
    251   while (TRUE)
    252     {
    253       ssize_t chunk;
    254       size_t to_read;
    255 
    256     again:
    257       to_read = sizeof (pid_t) - bytes;
    258 
    259       if (to_read == 0)
    260         break;
    261 
    262       chunk = read (fd,
    263                     ((char*)buf) + bytes,
    264                     to_read);
    265       if (chunk < 0 && errno == EINTR)
    266         goto again;
    267 
    268       if (chunk < 0)
    269         {
    270           retval = READ_STATUS_ERROR;
    271           break;
    272         }
    273       else if (chunk == 0)
    274         {
    275           retval = READ_STATUS_EOF;
    276           break; /* EOF */
    277         }
    278       else /* chunk > 0 */
    279 	bytes += chunk;
    280     }
    281 
    282   return retval;
    283 }
    284 
    285 static void
    286 do_write (int fd, const void *buf, size_t count)
    287 {
    288   size_t bytes_written;
    289   int ret;
    290 
    291   bytes_written = 0;
    292 
    293  again:
    294 
    295   ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
    296 
    297   if (ret < 0)
    298     {
    299       if (errno == EINTR)
    300         goto again;
    301       else
    302         {
    303           fprintf (stderr, "Failed to write data to pipe! %s\n",
    304                    strerror (errno));
    305           exit (1); /* give up, we suck */
    306         }
    307     }
    308   else
    309     bytes_written += ret;
    310 
    311   if (bytes_written < count)
    312     goto again;
    313 }
    314 
    315 static void
    316 write_pid (int   fd,
    317            pid_t pid)
    318 {
    319   do_write (fd, &pid, sizeof (pid));
    320 }
    321 
    322 static int
    323 do_waitpid (pid_t pid)
    324 {
    325   int ret;
    326 
    327  again:
    328   ret = waitpid (pid, NULL, 0);
    329 
    330   if (ret < 0 &&
    331       errno == EINTR)
    332     goto again;
    333 
    334   return ret;
    335 }
    336 
    337 static pid_t bus_pid_to_kill = -1;
    338 
    339 static void
    340 kill_bus(void)
    341 {
    342   verbose ("Killing message bus and exiting babysitter\n");
    343   kill (bus_pid_to_kill, SIGTERM);
    344   sleep (3);
    345   kill (bus_pid_to_kill, SIGKILL);
    346 }
    347 
    348 void
    349 kill_bus_and_exit (int exitcode)
    350 {
    351   /* in case these point to any NFS mounts, get rid of them immediately */
    352   close (0);
    353   close (1);
    354   close (2);
    355 
    356   kill_bus();
    357 
    358   exit (exitcode);
    359 }
    360 
    361 static void
    362 print_variables (const char *bus_address, pid_t bus_pid, long bus_wid,
    363 		 int c_shell_syntax, int bourne_shell_syntax,
    364 		 int binary_syntax)
    365 {
    366   if (binary_syntax)
    367     {
    368       do_write (1, bus_address, strlen (bus_address) + 1);
    369       do_write (1, &bus_pid, sizeof bus_pid);
    370       do_write (1, &bus_wid, sizeof bus_wid);
    371       return;
    372     }
    373   else if (c_shell_syntax)
    374     {
    375       printf ("setenv DBUS_SESSION_BUS_ADDRESS '%s';\n", bus_address);
    376       printf ("set DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
    377       if (bus_wid)
    378         printf ("set DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid);
    379       fflush (stdout);
    380     }
    381   else if (bourne_shell_syntax)
    382     {
    383       printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address);
    384       printf ("export DBUS_SESSION_BUS_ADDRESS;\n");
    385       printf ("DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
    386       if (bus_wid)
    387         printf ("DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid);
    388       fflush (stdout);
    389     }
    390   else
    391     {
    392       printf ("DBUS_SESSION_BUS_ADDRESS=%s\n", bus_address);
    393       printf ("DBUS_SESSION_BUS_PID=%ld\n", (long) bus_pid);
    394       if (bus_wid)
    395 	printf ("DBUS_SESSION_BUS_WINDOWID=%ld\n", (long) bus_wid);
    396       fflush (stdout);
    397     }
    398 }
    399 
    400 static int got_sighup = FALSE;
    401 
    402 static void
    403 signal_handler (int sig)
    404 {
    405   switch (sig)
    406     {
    407 #ifdef SIGHUP
    408     case SIGHUP:
    409 #endif
    410     case SIGINT:
    411     case SIGTERM:
    412       got_sighup = TRUE;
    413       break;
    414     }
    415 }
    416 
    417 static void
    418 kill_bus_when_session_ends (void)
    419 {
    420   int tty_fd;
    421   int x_fd;
    422   fd_set read_set;
    423   fd_set err_set;
    424   struct sigaction act;
    425   sigset_t empty_mask;
    426 
    427   /* install SIGHUP handler */
    428   got_sighup = FALSE;
    429   sigemptyset (&empty_mask);
    430   act.sa_handler = signal_handler;
    431   act.sa_mask    = empty_mask;
    432   act.sa_flags   = 0;
    433   sigaction (SIGHUP,  &act, NULL);
    434   sigaction (SIGTERM,  &act, NULL);
    435   sigaction (SIGINT,  &act, NULL);
    436 
    437 #ifdef DBUS_BUILD_X11
    438   x11_init();
    439   if (xdisplay != NULL)
    440     {
    441       x_fd = ConnectionNumber (xdisplay);
    442     }
    443   else
    444     x_fd = -1;
    445 #else
    446   x_fd = -1;
    447 #endif
    448 
    449   if (isatty (0))
    450     tty_fd = 0;
    451   else
    452     tty_fd = -1;
    453 
    454   if (tty_fd >= 0)
    455     verbose ("stdin isatty(), monitoring it\n");
    456   else
    457     verbose ("stdin was not a TTY, not monitoring it\n");
    458 
    459   if (tty_fd < 0 && x_fd < 0)
    460     {
    461       fprintf (stderr, "No terminal on standard input and no X display; cannot attach message bus to session lifetime\n");
    462       exit (1);
    463     }
    464 
    465   while (TRUE)
    466     {
    467 #ifdef DBUS_BUILD_X11
    468       /* Dump events on the floor, and let
    469        * IO error handler run if we lose
    470        * the X connection. It's important to
    471        * run this before going into select() since
    472        * we might have queued outgoing messages or
    473        * events.
    474        */
    475       x11_handle_event ();
    476 #endif
    477 
    478       FD_ZERO (&read_set);
    479       FD_ZERO (&err_set);
    480 
    481       if (tty_fd >= 0)
    482         {
    483           FD_SET (tty_fd, &read_set);
    484           FD_SET (tty_fd, &err_set);
    485         }
    486 
    487       if (x_fd >= 0)
    488         {
    489           FD_SET (x_fd, &read_set);
    490           FD_SET (x_fd, &err_set);
    491         }
    492 
    493       select (MAX (tty_fd, x_fd) + 1,
    494               &read_set, NULL, &err_set, NULL);
    495 
    496       if (got_sighup)
    497         {
    498           verbose ("Got SIGHUP, exiting\n");
    499           kill_bus_and_exit (0);
    500         }
    501 
    502 #ifdef DBUS_BUILD_X11
    503       /* Events will be processed before we select again
    504        */
    505       if (x_fd >= 0)
    506         verbose ("X fd condition reading = %d error = %d\n",
    507                  FD_ISSET (x_fd, &read_set),
    508                  FD_ISSET (x_fd, &err_set));
    509 #endif
    510 
    511       if (tty_fd >= 0)
    512         {
    513           if (FD_ISSET (tty_fd, &read_set))
    514             {
    515               int bytes_read;
    516               char discard[512];
    517 
    518               verbose ("TTY ready for reading\n");
    519 
    520               bytes_read = read (tty_fd, discard, sizeof (discard));
    521 
    522               verbose ("Read %d bytes from TTY errno = %d\n",
    523                        bytes_read, errno);
    524 
    525               if (bytes_read == 0)
    526                 kill_bus_and_exit (0); /* EOF */
    527               else if (bytes_read < 0 && errno != EINTR)
    528                 {
    529                   /* This shouldn't happen I don't think; to avoid
    530                    * spinning on the fd forever we exit.
    531                    */
    532                   fprintf (stderr, "dbus-launch: error reading from stdin: %s\n",
    533                            strerror (errno));
    534                   kill_bus_and_exit (0);
    535                 }
    536             }
    537           else if (FD_ISSET (tty_fd, &err_set))
    538             {
    539               verbose ("TTY has error condition\n");
    540 
    541               kill_bus_and_exit (0);
    542             }
    543         }
    544     }
    545 }
    546 
    547 static void
    548 babysit (int   exit_with_session,
    549          pid_t child_pid,
    550          int   read_bus_pid_fd)  /* read pid from here */
    551 {
    552   int ret;
    553   int dev_null_fd;
    554   const char *s;
    555 
    556   verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n",
    557            exit_with_session, (long) child_pid, read_bus_pid_fd);
    558 
    559   /* We chdir ("/") since we are persistent and daemon-like, and fork
    560    * again so dbus-launch can reap the parent.  However, we don't
    561    * setsid() or close fd 0 because the idea is to remain attached
    562    * to the tty and the X server in order to kill the message bus
    563    * when the session ends.
    564    */
    565 
    566   if (chdir ("/") < 0)
    567     {
    568       fprintf (stderr, "Could not change to root directory: %s\n",
    569                strerror (errno));
    570       exit (1);
    571     }
    572 
    573   /* Close stdout/stderr so we don't block an "eval" or otherwise
    574    * lock up. stdout is still chaining through to dbus-launch
    575    * and in turn to the parent shell.
    576    */
    577   dev_null_fd = open ("/dev/null", O_RDWR);
    578   if (dev_null_fd >= 0)
    579     {
    580       if (!exit_with_session)
    581         dup2 (dev_null_fd, 0);
    582       dup2 (dev_null_fd, 1);
    583       s = getenv ("DBUS_DEBUG_OUTPUT");
    584       if (s == NULL || *s == '\0')
    585         dup2 (dev_null_fd, 2);
    586     }
    587   else
    588     {
    589       fprintf (stderr, "Failed to open /dev/null: %s\n",
    590                strerror (errno));
    591       /* continue, why not */
    592     }
    593 
    594   ret = fork ();
    595 
    596   if (ret < 0)
    597     {
    598       fprintf (stderr, "fork() failed in babysitter: %s\n",
    599                strerror (errno));
    600       exit (1);
    601     }
    602 
    603   if (ret > 0)
    604     {
    605       /* Parent reaps pre-fork part of bus daemon, then exits and is
    606        * reaped so the babysitter isn't a zombie
    607        */
    608 
    609       verbose ("=== Babysitter's intermediate parent continues again\n");
    610 
    611       if (do_waitpid (child_pid) < 0)
    612         {
    613           /* shouldn't happen */
    614           fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n");
    615           exit (1);
    616         }
    617 
    618       verbose ("Babysitter's intermediate parent exiting\n");
    619 
    620       exit (0);
    621     }
    622 
    623   /* Child continues */
    624   verbose ("=== Babysitter process created\n");
    625 
    626   verbose ("Reading PID from bus\n");
    627 
    628   switch (read_pid (read_bus_pid_fd, &bus_pid_to_kill))
    629     {
    630     case READ_STATUS_OK:
    631       break;
    632     case READ_STATUS_EOF:
    633       fprintf (stderr, "EOF in dbus-launch reading PID from bus daemon\n");
    634       exit (1);
    635       break;
    636     case READ_STATUS_ERROR:
    637       fprintf (stderr, "Error in dbus-launch reading PID from bus daemon: %s\n",
    638 	       strerror (errno));
    639       exit (1);
    640       break;
    641     }
    642 
    643   verbose ("Got PID %ld from daemon\n",
    644            (long) bus_pid_to_kill);
    645 
    646   if (exit_with_session)
    647     {
    648       /* Bus is now started and launcher has needed info;
    649        * we connect to X display and tty and wait to
    650        * kill bus if requested.
    651        */
    652 
    653       kill_bus_when_session_ends ();
    654     }
    655 
    656   verbose ("Babysitter exiting\n");
    657 
    658   exit (0);
    659 }
    660 
    661 static void
    662 do_close_stderr (void)
    663 {
    664   int fd;
    665 
    666   fflush (stderr);
    667 
    668   /* dbus-launch is a Unix-only program, so we can rely on /dev/null being there.
    669    * We're including unistd.h and we're dealing with sh/csh launch sequences...
    670    */
    671   fd = open ("/dev/null", O_RDWR);
    672   if (fd == -1)
    673     {
    674       fprintf (stderr, "Internal error: cannot open /dev/null: %s", strerror (errno));
    675       exit (1);
    676     }
    677 
    678   close (2);
    679   if (dup2 (fd, 2) == -1)
    680     {
    681       /* error; we can't report an error anymore... */
    682       exit (1);
    683     }
    684   close (fd);
    685 }
    686 
    687 static void
    688 pass_info (const char *runprog, const char *bus_address, pid_t bus_pid,
    689            long bus_wid, int c_shell_syntax, int bourne_shell_syntax,
    690            int binary_syntax,
    691            int argc, char **argv, int remaining_args)
    692 {
    693   if (runprog)
    694     {
    695       char *envvar;
    696       char **args;
    697       int i;
    698 
    699       envvar = malloc (strlen ("DBUS_SESSION_BUS_ADDRESS=") +
    700           strlen (bus_address) + 1);
    701       args = malloc (sizeof (char *) * ((argc-remaining_args)+2));
    702 
    703       if (envvar == NULL || args == NULL)
    704         goto oom;
    705 
    706      args[0] = xstrdup (runprog);
    707       if (!args[0])
    708         goto oom;
    709      for (i = 1; i <= (argc-remaining_args); i++)
    710       {
    711         size_t len = strlen (argv[remaining_args+i-1])+1;
    712         args[i] = malloc (len);
    713         if (!args[i])
    714           goto oom;
    715         strncpy (args[i], argv[remaining_args+i-1], len);
    716        }
    717      args[i] = NULL;
    718 
    719      strcpy (envvar, "DBUS_SESSION_BUS_ADDRESS=");
    720      strcat (envvar, bus_address);
    721      putenv (envvar);
    722 
    723      execvp (runprog, args);
    724      fprintf (stderr, "Couldn't exec %s: %s\n", runprog, strerror (errno));
    725      exit (1);
    726     }
    727    else
    728     {
    729       print_variables (bus_address, bus_pid, bus_wid, c_shell_syntax,
    730          bourne_shell_syntax, binary_syntax);
    731     }
    732   verbose ("dbus-launch exiting\n");
    733 
    734   fflush (stdout);
    735   fflush (stderr);
    736   close (1);
    737   close (2);
    738   exit (0);
    739 oom:
    740   fprintf (stderr, "Out of memory!");
    741   exit (1);
    742 }
    743 
    744 #define READ_END  0
    745 #define WRITE_END 1
    746 
    747 int
    748 main (int argc, char **argv)
    749 {
    750   const char *prev_arg;
    751   const char *shname;
    752   const char *runprog = NULL;
    753   int remaining_args = 0;
    754   int exit_with_session;
    755   int binary_syntax = FALSE;
    756   int c_shell_syntax = FALSE;
    757   int bourne_shell_syntax = FALSE;
    758   int auto_shell_syntax = FALSE;
    759   int autolaunch = FALSE;
    760   int requires_arg = FALSE;
    761   int close_stderr = FALSE;
    762   int i;
    763   int ret;
    764   int bus_pid_to_launcher_pipe[2];
    765   int bus_pid_to_babysitter_pipe[2];
    766   int bus_address_to_launcher_pipe[2];
    767   char *config_file;
    768 
    769   exit_with_session = FALSE;
    770   config_file = NULL;
    771 
    772   prev_arg = NULL;
    773   i = 1;
    774   while (i < argc)
    775     {
    776       const char *arg = argv[i];
    777 
    778       if (strcmp (arg, "--help") == 0 ||
    779           strcmp (arg, "-h") == 0 ||
    780           strcmp (arg, "-?") == 0)
    781         usage (0);
    782       else if (strcmp (arg, "--auto-syntax") == 0)
    783         auto_shell_syntax = TRUE;
    784       else if (strcmp (arg, "-c") == 0 ||
    785                strcmp (arg, "--csh-syntax") == 0)
    786         c_shell_syntax = TRUE;
    787       else if (strcmp (arg, "-s") == 0 ||
    788                strcmp (arg, "--sh-syntax") == 0)
    789         bourne_shell_syntax = TRUE;
    790       else if (strcmp (arg, "--binary-syntax") == 0)
    791         binary_syntax = TRUE;
    792       else if (strcmp (arg, "--version") == 0)
    793         version ();
    794       else if (strcmp (arg, "--exit-with-session") == 0)
    795         exit_with_session = TRUE;
    796       else if (strcmp (arg, "--close-stderr") == 0)
    797         close_stderr = TRUE;
    798       else if (strstr (arg, "--autolaunch=") == arg)
    799         {
    800           const char *s;
    801 
    802           if (autolaunch)
    803             {
    804               fprintf (stderr, "--autolaunch given twice\n");
    805               exit (1);
    806             }
    807 
    808           autolaunch = TRUE;
    809 
    810           s = strchr (arg, '=');
    811           ++s;
    812 
    813           save_machine_uuid (s);
    814         }
    815       else if (prev_arg &&
    816                strcmp (prev_arg, "--autolaunch") == 0)
    817         {
    818           if (autolaunch)
    819             {
    820               fprintf (stderr, "--autolaunch given twice\n");
    821               exit (1);
    822             }
    823 
    824           autolaunch = TRUE;
    825 
    826           save_machine_uuid (arg);
    827 	  requires_arg = FALSE;
    828         }
    829       else if (strcmp (arg, "--autolaunch") == 0)
    830 	requires_arg = TRUE;
    831       else if (strstr (arg, "--config-file=") == arg)
    832         {
    833           const char *file;
    834 
    835           if (config_file != NULL)
    836             {
    837               fprintf (stderr, "--config-file given twice\n");
    838               exit (1);
    839             }
    840 
    841           file = strchr (arg, '=');
    842           ++file;
    843 
    844           config_file = xstrdup (file);
    845         }
    846       else if (prev_arg &&
    847                strcmp (prev_arg, "--config-file") == 0)
    848         {
    849           if (config_file != NULL)
    850             {
    851               fprintf (stderr, "--config-file given twice\n");
    852               exit (1);
    853             }
    854 
    855           config_file = xstrdup (arg);
    856 	  requires_arg = FALSE;
    857         }
    858       else if (strcmp (arg, "--config-file") == 0)
    859 	requires_arg = TRUE;
    860       else if (arg[0] == '-')
    861         {
    862           if (strcmp (arg, "--") != 0)
    863             {
    864               fprintf (stderr, "Option `%s' is unknown.\n", arg);
    865               exit (1);
    866             }
    867           else
    868             {
    869               runprog = argv[i+1];
    870               remaining_args = i+2;
    871               break;
    872             }
    873         }
    874       else
    875 	{
    876 	  runprog = arg;
    877 	  remaining_args = i+1;
    878 	  break;
    879 	}
    880 
    881       prev_arg = arg;
    882 
    883       ++i;
    884     }
    885   if (requires_arg)
    886     {
    887       fprintf (stderr, "Option `%s' requires an argument.\n", prev_arg);
    888       exit (1);
    889     }
    890 
    891   if (auto_shell_syntax)
    892     {
    893       if ((shname = getenv ("SHELL")) != NULL)
    894        {
    895          if (!strncmp (shname + strlen (shname) - 3, "csh", 3))
    896            c_shell_syntax = TRUE;
    897          else
    898            bourne_shell_syntax = TRUE;
    899        }
    900       else
    901        bourne_shell_syntax = TRUE;
    902     }
    903 
    904   if (exit_with_session)
    905     verbose ("--exit-with-session enabled\n");
    906 
    907   if (autolaunch)
    908     {
    909 #ifndef DBUS_BUILD_X11
    910       fprintf (stderr, "Autolaunch requested, but X11 support not compiled in.\n"
    911 	       "Cannot continue.\n");
    912       exit (1);
    913 #else
    914       char *address;
    915       pid_t pid;
    916       long wid;
    917 
    918       if (get_machine_uuid () == NULL)
    919         {
    920           fprintf (stderr, "Machine UUID not provided as arg to --autolaunch\n");
    921           exit (1);
    922         }
    923 
    924       verbose ("Autolaunch enabled (using X11).\n");
    925       if (!exit_with_session)
    926 	{
    927 	  verbose ("--exit-with-session automatically enabled\n");
    928 	  exit_with_session = TRUE;
    929 	}
    930 
    931       if (!x11_init ())
    932 	{
    933 	  fprintf (stderr, "Autolaunch error: X11 initialization failed.\n");
    934 	  exit (1);
    935 	}
    936 
    937       if (!x11_get_address (&address, &pid, &wid))
    938 	{
    939 	  fprintf (stderr, "Autolaunch error: X11 communication error.\n");
    940 	  exit (1);
    941 	}
    942 
    943       if (address != NULL)
    944 	{
    945 	  verbose ("dbus-daemon is already running. Returning existing parameters.\n");
    946 	  pass_info (runprog, address, pid, wid, c_shell_syntax,
    947 			   bourne_shell_syntax, binary_syntax, argc, argv, remaining_args);
    948 	  exit (0);
    949 	}
    950     }
    951    else if (read_machine_uuid_if_needed())
    952     {
    953       x11_init();
    954 #endif
    955     }
    956 
    957 
    958   if (pipe (bus_pid_to_launcher_pipe) < 0 ||
    959       pipe (bus_address_to_launcher_pipe) < 0 ||
    960       pipe (bus_pid_to_babysitter_pipe) < 0)
    961     {
    962       fprintf (stderr,
    963                "Failed to create pipe: %s\n",
    964                strerror (errno));
    965       exit (1);
    966     }
    967 
    968   ret = fork ();
    969   if (ret < 0)
    970     {
    971       fprintf (stderr, "Failed to fork: %s\n",
    972                strerror (errno));
    973       exit (1);
    974     }
    975 
    976   if (ret == 0)
    977     {
    978       /* Child */
    979 #define MAX_FD_LEN 64
    980       char write_pid_fd_as_string[MAX_FD_LEN];
    981       char write_address_fd_as_string[MAX_FD_LEN];
    982 
    983 #ifdef DBUS_BUILD_X11
    984       xdisplay = NULL;
    985 #endif
    986 
    987       if (close_stderr)
    988 	do_close_stderr ();
    989 
    990       verbose ("=== Babysitter's intermediate parent created\n");
    991 
    992       /* Fork once more to create babysitter */
    993 
    994       ret = fork ();
    995       if (ret < 0)
    996         {
    997           fprintf (stderr, "Failed to fork: %s\n",
    998                    strerror (errno));
    999           exit (1);
   1000         }
   1001 
   1002       if (ret > 0)
   1003         {
   1004           /* In babysitter */
   1005           verbose ("=== Babysitter's intermediate parent continues\n");
   1006 
   1007           close (bus_pid_to_launcher_pipe[READ_END]);
   1008 	  close (bus_pid_to_launcher_pipe[WRITE_END]);
   1009           close (bus_address_to_launcher_pipe[READ_END]);
   1010           close (bus_address_to_launcher_pipe[WRITE_END]);
   1011           close (bus_pid_to_babysitter_pipe[WRITE_END]);
   1012 
   1013           /* babysit() will fork *again*
   1014            * and will also reap the pre-forked bus
   1015            * daemon
   1016            */
   1017           babysit (exit_with_session, ret,
   1018                    bus_pid_to_babysitter_pipe[READ_END]);
   1019           exit (0);
   1020         }
   1021 
   1022       verbose ("=== Bus exec process created\n");
   1023 
   1024       /* Now we are the bus process (well, almost;
   1025        * dbus-daemon itself forks again)
   1026        */
   1027       close (bus_pid_to_launcher_pipe[READ_END]);
   1028       close (bus_address_to_launcher_pipe[READ_END]);
   1029       close (bus_pid_to_babysitter_pipe[READ_END]);
   1030       close (bus_pid_to_babysitter_pipe[WRITE_END]);
   1031 
   1032       sprintf (write_pid_fd_as_string,
   1033                "%d", bus_pid_to_launcher_pipe[WRITE_END]);
   1034 
   1035       sprintf (write_address_fd_as_string,
   1036                "%d", bus_address_to_launcher_pipe[WRITE_END]);
   1037 
   1038       verbose ("Calling exec()\n");
   1039 
   1040 #ifdef DBUS_BUILD_TESTS
   1041       /* exec from testdir */
   1042       if (getenv("DBUS_USE_TEST_BINARY") != NULL)
   1043         {
   1044           execl (TEST_BUS_BINARY,
   1045                  TEST_BUS_BINARY,
   1046                  "--fork",
   1047                  "--print-pid", write_pid_fd_as_string,
   1048                  "--print-address", write_address_fd_as_string,
   1049                  config_file ? "--config-file" : "--session",
   1050                  config_file, /* has to be last in this varargs list */
   1051                  NULL);
   1052 
   1053           fprintf (stderr,
   1054                    "Failed to execute test message bus daemon %s: %s. Will try again with the system path.\n",
   1055                    TEST_BUS_BINARY, strerror (errno));
   1056         }
   1057  #endif /* DBUS_BUILD_TESTS */
   1058 
   1059       execl (DBUS_DAEMONDIR"/dbus-daemon",
   1060              DBUS_DAEMONDIR"/dbus-daemon",
   1061              "--fork",
   1062              "--print-pid", write_pid_fd_as_string,
   1063              "--print-address", write_address_fd_as_string,
   1064              config_file ? "--config-file" : "--session",
   1065              config_file, /* has to be last in this varargs list */
   1066              NULL);
   1067 
   1068       fprintf (stderr,
   1069                "Failed to execute message bus daemon %s: %s.  Will try again without full path.\n",
   1070                DBUS_DAEMONDIR"/dbus-daemon", strerror (errno));
   1071 
   1072       /*
   1073        * If it failed, try running without full PATH.  Note this is needed
   1074        * because the build process builds the run-with-tmp-session-bus.conf
   1075        * file and the dbus-daemon will not be in the install location during
   1076        * build time.
   1077        */
   1078       execlp ("dbus-daemon",
   1079               "dbus-daemon",
   1080               "--fork",
   1081               "--print-pid", write_pid_fd_as_string,
   1082               "--print-address", write_address_fd_as_string,
   1083               config_file ? "--config-file" : "--session",
   1084               config_file, /* has to be last in this varargs list */
   1085               NULL);
   1086 
   1087       fprintf (stderr,
   1088                "Failed to execute message bus daemon: %s\n",
   1089                strerror (errno));
   1090       exit (1);
   1091     }
   1092   else
   1093     {
   1094       /* Parent */
   1095 #define MAX_PID_LEN 64
   1096       pid_t bus_pid;
   1097       char bus_address[MAX_ADDR_LEN];
   1098       char buf[MAX_PID_LEN];
   1099       char *end;
   1100       long wid = 0;
   1101       long val;
   1102       int ret2;
   1103 
   1104       verbose ("=== Parent dbus-launch continues\n");
   1105 
   1106       close (bus_pid_to_launcher_pipe[WRITE_END]);
   1107       close (bus_address_to_launcher_pipe[WRITE_END]);
   1108       close (bus_pid_to_babysitter_pipe[READ_END]);
   1109 
   1110       verbose ("Waiting for babysitter's intermediate parent\n");
   1111 
   1112       /* Immediately reap parent of babysitter
   1113        * (which was created just for us to reap)
   1114        */
   1115       if (do_waitpid (ret) < 0)
   1116         {
   1117           fprintf (stderr, "Failed to waitpid() for babysitter intermediate process: %s\n",
   1118                    strerror (errno));
   1119           exit (1);
   1120         }
   1121 
   1122       verbose ("Reading address from bus\n");
   1123 
   1124       /* Read the pipe data, print, and exit */
   1125       switch (read_line (bus_address_to_launcher_pipe[READ_END],
   1126                          bus_address, MAX_ADDR_LEN))
   1127         {
   1128         case READ_STATUS_OK:
   1129           break;
   1130         case READ_STATUS_EOF:
   1131           fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
   1132           exit (1);
   1133           break;
   1134         case READ_STATUS_ERROR:
   1135           fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
   1136                    strerror (errno));
   1137           exit (1);
   1138           break;
   1139         }
   1140 
   1141       close (bus_address_to_launcher_pipe[READ_END]);
   1142 
   1143       verbose ("Reading PID from daemon\n");
   1144       /* Now read data */
   1145       switch (read_line (bus_pid_to_launcher_pipe[READ_END], buf, MAX_PID_LEN))
   1146 	{
   1147 	case READ_STATUS_OK:
   1148 	  break;
   1149 	case READ_STATUS_EOF:
   1150 	  fprintf (stderr, "EOF reading PID from bus daemon\n");
   1151 	  exit (1);
   1152 	  break;
   1153 	case READ_STATUS_ERROR:
   1154 	  fprintf (stderr, "Error reading PID from bus daemon: %s\n",
   1155 		   strerror (errno));
   1156 	  exit (1);
   1157 	  break;
   1158 	}
   1159 
   1160       end = NULL;
   1161       val = strtol (buf, &end, 0);
   1162       if (buf == end || end == NULL)
   1163 	{
   1164 	  fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n",
   1165 		   buf, strerror (errno));
   1166 	  exit (1);
   1167 	}
   1168 
   1169       bus_pid = val;
   1170 
   1171       close (bus_pid_to_launcher_pipe[READ_END]);
   1172 
   1173 #ifdef DBUS_BUILD_X11
   1174       if (xdisplay != NULL)
   1175         {
   1176           verbose("Saving x11 address\n");
   1177           ret2 = x11_save_address (bus_address, bus_pid, &wid);
   1178           /* Only get an existing dbus session when autolaunching */
   1179           if (autolaunch)
   1180             {
   1181               if (ret2 == 0)
   1182                 {
   1183                   char *address = NULL;
   1184                   /* another window got added. Return its address */
   1185                   bus_pid_to_kill = bus_pid;
   1186                   if (x11_get_address (&address, &bus_pid, &wid)
   1187                        && address != NULL)
   1188                     {
   1189                       verbose ("dbus-daemon is already running. Returning existing parameters.\n");
   1190                       /* Kill the old bus */
   1191                       kill_bus();
   1192                       pass_info (runprog, address, bus_pid, wid,
   1193                          c_shell_syntax, bourne_shell_syntax, binary_syntax,
   1194                          argc, argv, remaining_args);
   1195                     }
   1196                   }
   1197               if (ret2 < 0)
   1198                 {
   1199                   fprintf (stderr, "Error saving bus information.\n");
   1200                   bus_pid_to_kill = bus_pid;
   1201                   kill_bus_and_exit (1);
   1202                 }
   1203             }
   1204         }
   1205 #endif
   1206 
   1207       /* Forward the pid to the babysitter */
   1208       write_pid (bus_pid_to_babysitter_pipe[WRITE_END], bus_pid);
   1209       close (bus_pid_to_babysitter_pipe[WRITE_END]);
   1210 
   1211        pass_info (runprog, bus_address, bus_pid, wid, c_shell_syntax,
   1212               bourne_shell_syntax, binary_syntax, argc, argv, remaining_args);
   1213     }
   1214 
   1215   return 0;
   1216 }
   1217