X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fdbus-launch.c;h=bbaac2c3a8907db15db3fb093cb29182879bbc9a;hb=d6ad37c3044ed6c72bf652c6e505c6ad9aa9e889;hp=e07141a1d2fa7d96ba53ad5b535fcc65bac09aaf;hpb=d6e1b2adb3d8e51ce1bb47295cef12d9fe1a15a8;p=platform%2Fupstream%2Fdbus.git diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c index e07141a..bbaac2c 100644 --- a/tools/dbus-launch.c +++ b/tools/dbus-launch.c @@ -1,9 +1,10 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-launch.c dbus-launch utility * - * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2003, 2006 Red Hat, Inc. + * Copyright (C) 2006 Thiago Macieira * - * Licensed under the Academic Free License version 1.2 + * 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 @@ -17,11 +18,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ + #include +#include "dbus-launch.h" #include +#include #include #include #include @@ -31,22 +35,79 @@ #include #include #include +#include +#include + #ifdef DBUS_BUILD_X11 #include +extern Display *xdisplay; #endif -#ifndef TRUE -#define TRUE (1) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif +static char* machine_uuid = NULL; -#undef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +const char* +get_machine_uuid (void) +{ + return machine_uuid; +} static void +save_machine_uuid (const char *uuid_arg) +{ + if (strlen (uuid_arg) != 32) + { + fprintf (stderr, "machine ID '%s' looks like it's the wrong length, should be 32 hex digits", + uuid_arg); + exit (1); + } + + machine_uuid = xstrdup (uuid_arg); +} + +#define UUID_MAXLEN 40 +/* Read the machine uuid from file if needed. Returns TRUE if machine_uuid is + * set after this function */ +static int +read_machine_uuid_if_needed (void) +{ + FILE *f; + char uuid[UUID_MAXLEN]; + size_t len; + int ret = FALSE; + + if (machine_uuid != NULL) + return TRUE; + + f = fopen (DBUS_MACHINE_UUID_FILE, "r"); + if (f == NULL) + return FALSE; + + if (fgets (uuid, UUID_MAXLEN, f) == NULL) + goto out; + + len = strlen (uuid); + if (len < 32) + goto out; + + /* rstrip the read uuid */ + while (len > 31 && isspace(uuid[len - 1])) + len--; + + if (len != 32) + goto out; + + uuid[len] = '\0'; + machine_uuid = xstrdup (uuid); + verbose ("UID: %s\n", machine_uuid); + ret = TRUE; + +out: + fclose(f); + return ret; +} + + +void verbose (const char *format, ...) { @@ -86,7 +147,7 @@ usage (int ecode) static void version (void) { - printf ("D-BUS Message Bus Launcher %s\n" + printf ("D-Bus Message Bus Launcher %s\n" "Copyright (C) 2003 Red Hat, Inc.\n" "This is free software; see the source for copying conditions.\n" "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", @@ -94,7 +155,7 @@ version (void) exit (0); } -static char * +char * xstrdup (const char *str) { int len; @@ -136,7 +197,7 @@ read_line (int fd, while (TRUE) { - size_t chunk; + ssize_t chunk; size_t to_read; again: @@ -189,7 +250,7 @@ read_pid (int fd, while (TRUE) { - size_t chunk; + ssize_t chunk; size_t to_read; again: @@ -276,31 +337,65 @@ do_waitpid (pid_t pid) static pid_t bus_pid_to_kill = -1; static void -kill_bus_and_exit (void) +kill_bus(void) { verbose ("Killing message bus and exiting babysitter\n"); - + kill (bus_pid_to_kill, SIGTERM); + sleep (3); + kill (bus_pid_to_kill, SIGKILL); +} + +void +kill_bus_and_exit (int exitcode) +{ /* in case these point to any NFS mounts, get rid of them immediately */ close (0); close (1); close (2); - kill (bus_pid_to_kill, SIGTERM); - sleep (3); - kill (bus_pid_to_kill, SIGKILL); + kill_bus(); - 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) + { + do_write (1, bus_address, strlen (bus_address) + 1); + do_write (1, &bus_pid, sizeof bus_pid); + do_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); + fflush (stdout); + } + else if (bourne_shell_syntax) + { + printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address); + 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); + fflush (stdout); + } + else + { + printf ("DBUS_SESSION_BUS_ADDRESS=%s\n", bus_address); + printf ("DBUS_SESSION_BUS_PID=%ld\n", (long) bus_pid); + if (bus_wid) + printf ("DBUS_SESSION_BUS_WINDOWID=%ld\n", (long) bus_wid); + fflush (stdout); + } } -#endif static int got_sighup = FALSE; @@ -309,7 +404,11 @@ signal_handler (int sig) { switch (sig) { +#ifdef SIGHUP case SIGHUP: +#endif + case SIGINT: + case SIGTERM: got_sighup = TRUE; break; } @@ -322,12 +421,8 @@ kill_bus_when_session_ends (void) int x_fd; fd_set read_set; fd_set err_set; - int ret; struct sigaction act; sigset_t empty_mask; -#ifdef DBUS_BUILD_X11 - Display *xdisplay; -#endif /* install SIGHUP handler */ got_sighup = FALSE; @@ -335,20 +430,19 @@ kill_bus_when_session_ends (void) act.sa_handler = signal_handler; act.sa_mask = empty_mask; act.sa_flags = 0; - sigaction (SIGHUP, &act, 0); + sigaction (SIGHUP, &act, NULL); + sigaction (SIGTERM, &act, NULL); + sigaction (SIGINT, &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 @@ -370,6 +464,17 @@ kill_bus_when_session_ends (void) while (TRUE) { +#ifdef DBUS_BUILD_X11 + /* Dump events on the floor, and let + * IO error handler run if we lose + * the X connection. It's important to + * run this before going into select() since + * we might have queued outgoing messages or + * events. + */ + x11_handle_event (); +#endif + FD_ZERO (&read_set); FD_ZERO (&err_set); @@ -384,34 +489,23 @@ kill_bus_when_session_ends (void) FD_SET (x_fd, &read_set); FD_SET (x_fd, &err_set); } - - ret = select (MAX (tty_fd, x_fd) + 1, - &read_set, NULL, &err_set, NULL); + + select (MAX (tty_fd, x_fd) + 1, + &read_set, NULL, &err_set, NULL); if (got_sighup) { verbose ("Got SIGHUP, exiting\n"); - kill_bus_and_exit (); + kill_bus_and_exit (0); } #ifdef DBUS_BUILD_X11 - /* Dump events on the floor, and let - * IO error handler run if we lose - * the X connection + /* Events will be processed before we select again */ if (x_fd >= 0) 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); - } - } #endif if (tty_fd >= 0) @@ -429,7 +523,7 @@ kill_bus_when_session_ends (void) 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 @@ -437,14 +531,14 @@ kill_bus_when_session_ends (void) */ 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); } } } @@ -453,19 +547,14 @@ kill_bus_when_session_ends (void) 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 @@ -534,41 +623,26 @@ babysit (int exit_with_session, /* 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; @@ -584,6 +658,96 @@ babysit (int exit_with_session, exit (0); } +static void +do_close_stderr (void) +{ + int fd; + + 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... + */ + 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); +} + +static void +pass_info (const char *runprog, const char *bus_address, pid_t bus_pid, + long bus_wid, int c_shell_syntax, int bourne_shell_syntax, + int binary_syntax, + int argc, char **argv, int remaining_args) +{ + char *envvar = NULL; + char **args = NULL; + + if (runprog) + { + int i; + + envvar = malloc (strlen ("DBUS_SESSION_BUS_ADDRESS=") + + strlen (bus_address) + 1); + args = malloc (sizeof (char *) * ((argc-remaining_args)+2)); + + if (envvar == NULL || args == NULL) + goto oom; + + args[0] = xstrdup (runprog); + if (!args[0]) + goto oom; + for (i = 1; i <= (argc-remaining_args); i++) + { + size_t len = strlen (argv[remaining_args+i-1])+1; + args[i] = malloc (len); + if (!args[i]) + goto oom; + strncpy (args[i], argv[remaining_args+i-1], len); + } + args[i] = NULL; + + strcpy (envvar, "DBUS_SESSION_BUS_ADDRESS="); + strcat (envvar, bus_address); + putenv (envvar); + + execvp (runprog, args); + fprintf (stderr, "Couldn't exec %s: %s\n", runprog, strerror (errno)); + exit (1); + } + else + { + print_variables (bus_address, bus_pid, bus_wid, c_shell_syntax, + bourne_shell_syntax, binary_syntax); + } + verbose ("dbus-launch exiting\n"); + + fflush (stdout); + fflush (stderr); + close (1); + close (2); + exit (0); +oom: + if (envvar) + free (envvar); + + if (args) + free (args); + + fprintf (stderr, "Out of memory!"); + exit (1); +} + #define READ_END 0 #define WRITE_END 1 @@ -595,10 +759,14 @@ main (int argc, char **argv) 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 i; + int autolaunch = FALSE; + int requires_arg = FALSE; + int close_stderr = FALSE; + int i; int ret; int bus_pid_to_launcher_pipe[2]; int bus_pid_to_babysitter_pipe[2]; @@ -613,7 +781,7 @@ main (int argc, char **argv) while (i < argc) { const char *arg = argv[i]; - + if (strcmp (arg, "--help") == 0 || strcmp (arg, "-h") == 0 || strcmp (arg, "-?") == 0) @@ -621,15 +789,52 @@ main (int argc, char **argv) else if (strcmp (arg, "--auto-syntax") == 0) auto_shell_syntax = TRUE; else if (strcmp (arg, "-c") == 0 || - strcmp (arg, "--csh-syntax") == 0) + strcmp (arg, "--csh-syntax") == 0) c_shell_syntax = TRUE; else if (strcmp (arg, "-s") == 0 || - strcmp (arg, "--sh-syntax") == 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, "--close-stderr") == 0) + close_stderr = TRUE; + else if (strstr (arg, "--autolaunch=") == arg) + { + const char *s; + + if (autolaunch) + { + fprintf (stderr, "--autolaunch given twice\n"); + exit (1); + } + + autolaunch = TRUE; + + s = strchr (arg, '='); + ++s; + + save_machine_uuid (s); + } + else if (prev_arg && + strcmp (prev_arg, "--autolaunch") == 0) + { + if (autolaunch) + { + fprintf (stderr, "--autolaunch given twice\n"); + exit (1); + } + + autolaunch = TRUE; + + save_machine_uuid (arg); + requires_arg = FALSE; + } + else if (strcmp (arg, "--autolaunch") == 0) + requires_arg = TRUE; else if (strstr (arg, "--config-file=") == arg) { const char *file; @@ -655,9 +860,24 @@ main (int argc, char **argv) } config_file = xstrdup (arg); + requires_arg = FALSE; } else if (strcmp (arg, "--config-file") == 0) - ; /* wait for next arg */ + requires_arg = TRUE; + else if (arg[0] == '-') + { + if (strcmp (arg, "--") != 0) + { + fprintf (stderr, "Option `%s' is unknown.\n", arg); + exit (1); + } + else + { + runprog = argv[i+1]; + remaining_args = i+2; + break; + } + } else { runprog = arg; @@ -669,9 +889,11 @@ main (int argc, char **argv) ++i; } - - if (exit_with_session) - verbose ("--exit-with-session enabled\n"); + if (requires_arg) + { + fprintf (stderr, "Option `%s' requires an argument.\n", prev_arg); + exit (1); + } if (auto_shell_syntax) { @@ -686,8 +908,68 @@ main (int argc, char **argv) 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 /* DBUS_BUILD_X11 */ +#ifndef DBUS_ENABLE_X11_AUTOLAUNCH + fprintf (stderr, "X11 autolaunch support disabled at compile time.\n"); + exit (1); +#else /* DBUS_ENABLE_X11_AUTOLAUNCH */ + char *address; + pid_t pid; + long wid; + + if (get_machine_uuid () == NULL) + { + fprintf (stderr, "Machine UUID not provided as arg to --autolaunch\n"); + exit (1); + } + + 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"); + pass_info (runprog, address, pid, wid, c_shell_syntax, + bourne_shell_syntax, binary_syntax, argc, argv, remaining_args); + exit (0); + } +#endif /* DBUS_ENABLE_X11_AUTOLAUNCH */ + } + else if (read_machine_uuid_if_needed()) + { + x11_init(); +#endif /* DBUS_BUILD_X11 */ + } + + 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", @@ -695,9 +977,6 @@ main (int argc, char **argv) exit (1); } - bus_pid_to_babysitter_pipe[READ_END] = -1; - bus_pid_to_babysitter_pipe[WRITE_END] = -1; - ret = fork (); if (ret < 0) { @@ -713,18 +992,17 @@ main (int argc, char **argv) char write_pid_fd_as_string[MAX_FD_LEN]; char write_address_fd_as_string[MAX_FD_LEN]; +#ifdef DBUS_BUILD_X11 + xdisplay = NULL; +#endif + + if (close_stderr) + do_close_stderr (); + 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) { @@ -739,40 +1017,78 @@ main (int argc, char **argv) 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]); - + /* babysit() will fork *again* * and will also reap the pre-forked bus * 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); } verbose ("=== Bus exec process created\n"); /* Now we are the bus process (well, almost; - * dbus-daemon-1 itself forks again) + * dbus-daemon itself forks again) */ 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]); verbose ("Calling exec()\n"); + +#ifdef DBUS_BUILD_TESTS + /* exec from testdir */ + if (getenv("DBUS_USE_TEST_BINARY") != NULL) + { + execl (TEST_BUS_BINARY, + TEST_BUS_BINARY, + "--fork", + "--print-pid", write_pid_fd_as_string, + "--print-address", write_address_fd_as_string, + config_file ? "--config-file" : "--session", + config_file, /* has to be last in this varargs list */ + NULL); + + fprintf (stderr, + "Failed to execute test message bus daemon %s: %s. Will try again with the system path.\n", + TEST_BUS_BINARY, strerror (errno)); + } + #endif /* DBUS_BUILD_TESTS */ + + execl (DBUS_DAEMONDIR"/dbus-daemon", + DBUS_DAEMONDIR"/dbus-daemon", + "--fork", + "--print-pid", write_pid_fd_as_string, + "--print-address", write_address_fd_as_string, + config_file ? "--config-file" : "--session", + config_file, /* has to be last in this varargs list */ + NULL); + + fprintf (stderr, + "Failed to execute message bus daemon %s: %s. Will try again without full path.\n", + DBUS_DAEMONDIR"/dbus-daemon", strerror (errno)); - execlp ("dbus-daemon-1", - "dbus-daemon-1", + /* + * If it failed, try running without full PATH. Note this is needed + * because the build process builds the run-with-tmp-session-bus.conf + * file and the dbus-daemon will not be in the install location during + * build time. + */ + execlp ("dbus-daemon", + "dbus-daemon", "--fork", "--print-pid", write_pid_fd_as_string, "--print-address", write_address_fd_as_string, @@ -788,14 +1104,20 @@ main (int argc, char **argv) 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"); @@ -830,85 +1152,77 @@ main (int argc, char **argv) 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; - } - - close (bus_pid_to_launcher_pipe[READ_END]); - - if (runprog) + verbose ("Reading PID from daemon\n"); + /* Now read data */ + switch (read_line (bus_pid_to_launcher_pipe[READ_END], buf, MAX_PID_LEN)) { - char *envvar; - char **args; - - envvar = malloc (strlen ("DBUS_SESSION_BUS_ADDRESS=") + strlen (bus_address) + 1); - args = malloc (sizeof (char *) * ((argc-remaining_args)+2)); - - if (envvar == NULL || args == NULL) - goto oom; - - args[0] = xstrdup (runprog); - if (!args[0]) - goto oom; - for (i = 1; i <= (argc-remaining_args); i++) - { - size_t len = strlen (argv[remaining_args+i-1])+1; - args[i] = malloc (len); - if (!args[i]) - goto oom; - strncpy (args[i], argv[remaining_args+i-1], len); - } - args[i] = NULL; - - strcpy (envvar, "DBUS_SESSION_BUS_ADDRESS="); - strcat (envvar, bus_address); - putenv (envvar); - - execvp (runprog, args); - fprintf (stderr, "Couldn't exec %s: %s\n", runprog, strerror (errno)); + 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; } - else + + end = NULL; + val = strtol (buf, &end, 0); + if (buf == end || end == NULL) { - 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); + fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n", + buf, strerror (errno)); + exit (1); } - - verbose ("dbus-launch exiting\n"); - fflush (stdout); - fflush (stderr); - close (1); - close (2); - - exit (0); - } - + bus_pid = val; + + close (bus_pid_to_launcher_pipe[READ_END]); + +#ifdef DBUS_ENABLE_X11_AUTOLAUNCH + if (xdisplay != NULL) + { + verbose("Saving x11 address\n"); + ret2 = x11_save_address (bus_address, bus_pid, &wid); + /* Only get an existing dbus session when autolaunching */ + if (autolaunch) + { + if (ret2 == 0) + { + char *address = NULL; + /* another window got added. Return its address */ + bus_pid_to_kill = bus_pid; + if (x11_get_address (&address, &bus_pid, &wid) + && address != NULL) + { + verbose ("dbus-daemon is already running. Returning existing parameters.\n"); + /* Kill the old bus */ + kill_bus(); + pass_info (runprog, address, bus_pid, wid, + c_shell_syntax, bourne_shell_syntax, binary_syntax, + argc, argv, remaining_args); + } + } + 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]); + + pass_info (runprog, bus_address, bus_pid, wid, c_shell_syntax, + bourne_shell_syntax, binary_syntax, argc, argv, remaining_args); + } + return 0; - oom: - fprintf (stderr, "Out of memory!"); - exit (1); }