summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am18
-rw-r--r--tools/dbus-launch-win.c11
-rw-r--r--tools/dbus-launch.c187
-rw-r--r--tools/dbus-monitor.c51
-rw-r--r--tools/dbus-print-message.c10
-rw-r--r--tools/dbus-run-session.c464
-rw-r--r--tools/dbus-send.c73
-rwxr-xr-xtools/run-with-tmp-session-bus.sh52
-rw-r--r--tools/strtoll.c1
-rw-r--r--tools/strtoull.c1
10 files changed, 747 insertions, 121 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 08b90234..73d95fcf 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -2,6 +2,7 @@ configdir=$(sysconfdir)/dbus-1
AM_CPPFLAGS = \
-I$(top_srcdir) \
+ $(DBUS_STATIC_BUILD_CPPFLAGS) \
$(DBUS_X_CFLAGS) \
-DDBUS_COMPILATION \
-DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
@@ -19,6 +20,7 @@ bin_PROGRAMS = \
if DBUS_UNIX
bin_PROGRAMS += \
dbus-cleanup-sockets \
+ dbus-run-session \
dbus-uuidgen \
$(NULL)
endif
@@ -42,6 +44,13 @@ dbus_launch_SOURCES= \
dbus-launch.c \
dbus-launch-x11.c \
dbus-launch.h
+
+dbus_run_session_SOURCES = \
+ dbus-run-session.c
+
+dbus_run_session_LDADD = \
+ $(top_builddir)/dbus/libdbus-1.la \
+ $(NULL)
endif
dbus_cleanup_sockets_SOURCES= \
@@ -71,6 +80,9 @@ EXTRA_DIST = run-with-tmp-session-bus.sh strtoll.c strtoull.c
CLEANFILES = \
run-with-tmp-session-bus.conf
-#create the /var/lib/data directory for dbus-uuidgen
-localstatelibdir = $(localstatedir)/lib/dbus
-localstatelib_DATA =
+# create the /var/lib/dbus directory for dbus-uuidgen
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/dbus
+
+installcheck-local:
+ test -d $(DESTDIR)$(localstatedir)/lib/dbus
diff --git a/tools/dbus-launch-win.c b/tools/dbus-launch-win.c
index ea4bf0dd..d899010a 100644
--- a/tools/dbus-launch-win.c
+++ b/tools/dbus-launch-win.c
@@ -130,9 +130,10 @@ main (int argc, char **argv)
fprintf (stderr, "%ls %ls\n", dbusDaemonPath, command);
#else
command[0] = L'\0';
- /* Windows CE has a different interpretation of cmdline: Start with argv[1]. */
- wcscpy_s (command, sizeof (command), dbusDaemonPath);
- wcscat_s (command, sizeof (command), L" --session");
+ /* Windows cmdline starts with path, which can contain spaces. */
+ wcscpy_s (command, sizeof (command), L"\"");
+ wcscat_s (command, sizeof (command), dbusDaemonPath);
+ wcscat_s (command, sizeof (command), L"\" --session");
if (verbose)
fprintf (stderr, "%ls\n", command);
#endif
@@ -158,8 +159,8 @@ main (int argc, char **argv)
if (result == 0)
{
if (verbose)
- fprintf (stderr, "Could not start " DBUS_DAEMON_NAME ". error=%d\n",
- GetLastError ());
+ fprintf (stderr, "Could not start " DBUS_DAEMON_NAME ". error=%u\n",
+ (unsigned)GetLastError ());
return 4;
}
diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c
index bbaac2c3..7ecee63e 100644
--- a/tools/dbus-launch.c
+++ b/tools/dbus-launch.c
@@ -43,6 +43,47 @@
extern Display *xdisplay;
#endif
+/* PROCESSES
+ *
+ * If you are in a shell and run "dbus-launch myapp", here is what happens:
+ *
+ * shell [*]
+ * \- main() --exec--> myapp[*]
+ * \- "intermediate parent"
+ * \- bus-runner --exec--> dbus-daemon --fork
+ * \- babysitter[*] \- final dbus-daemon[*]
+ *
+ * Processes marked [*] survive the initial flurry of activity.
+ *
+ * If you run "dbus-launch --sh-syntax" then the diagram is the same, except
+ * that main() prints variables and exits 0 instead of exec'ing myapp.
+ *
+ * PIPES
+ *
+ * dbus-daemon --print-pid -> bus_pid_to_launcher_pipe -> main
+ * dbus-daemon --print-address -> bus_address_to_launcher_pipe -> main
+ * main -> bus_pid_to_babysitter_pipe -> babysitter
+ *
+ * The intermediate parent looks pretty useless at first glance. Its purpose
+ * is to avoid the bus-runner becoming a zombie: when the intermediate parent
+ * terminates, the bus-runner and babysitter are reparented to init, which
+ * reaps them if they have finished. We can't rely on main() to reap arbitrary
+ * children because it might exec myapp, after which it can't be relied on to
+ * reap its children. We *can* rely on main() to reap the intermediate parent,
+ * because that happens before it execs myapp.
+ *
+ * It's unclear why dbus-daemon needs to fork, but we explicitly tell it to
+ * for some reason, then wait for it. If we left it undefined, a forking
+ * dbus-daemon would get the parent process reparented to init and reaped
+ * when the intermediate parent terminated, and a non-forking dbus-daemon
+ * would get reparented to init and carry on there.
+ *
+ * myapp is exec'd by the process that initially ran main() so that it's
+ * the shell's child, so the shell knows how to do job control and stuff.
+ * This is desirable for the "dbus-launch an application" use-case, less so
+ * for the "dbus-launch a test suite in an isolated session" use-case.
+ */
+
static char* machine_uuid = NULL;
const char*
@@ -64,6 +105,7 @@ save_machine_uuid (const char *uuid_arg)
machine_uuid = xstrdup (uuid_arg);
}
+#ifdef DBUS_BUILD_X11
#define UUID_MAXLEN 40
/* Read the machine uuid from file if needed. Returns TRUE if machine_uuid is
* set after this function */
@@ -90,7 +132,7 @@ read_machine_uuid_if_needed (void)
goto out;
/* rstrip the read uuid */
- while (len > 31 && isspace(uuid[len - 1]))
+ while (len > 31 && isspace((int) uuid[len - 1]))
len--;
if (len != 32)
@@ -105,12 +147,13 @@ out:
fclose(f);
return ret;
}
-
+#endif /* DBUS_BUILD_X11 */
void
verbose (const char *format,
...)
{
+#ifdef DBUS_ENABLE_VERBOSE_MODE
va_list args;
static int verbose = TRUE;
static int verbose_initted = FALSE;
@@ -135,12 +178,16 @@ verbose (const char *format,
va_start (args, format);
vfprintf (stderr, format, args);
va_end (args);
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
}
static void
usage (int ecode)
{
- fprintf (stderr, "dbus-launch [--version] [--help] [--sh-syntax] [--csh-syntax] [--auto-syntax] [--exit-with-session]\n");
+ fprintf (stderr, "dbus-launch [--version] [--help] [--sh-syntax]"
+ " [--csh-syntax] [--auto-syntax] [--binary-syntax] [--close-stderr]"
+ " [--exit-with-session] [--autolaunch=MACHINEID]"
+ " [--config-file=FILENAME] [PROGRAM] [ARGS...]\n");
exit (ecode);
}
@@ -175,6 +222,26 @@ xstrdup (const char *str)
return copy;
}
+static char *
+concat2 (const char *a,
+ const char *b)
+{
+ size_t la, lb;
+ char *ret;
+
+ la = strlen (a);
+ lb = strlen (b);
+
+ ret = malloc (la + lb + 1);
+
+ if (ret == NULL)
+ return NULL;
+
+ memcpy (ret, a, la);
+ memcpy (ret + la, b, lb + 1);
+ return ret;
+}
+
typedef enum
{
READ_STATUS_OK, /**< Read succeeded */
@@ -404,9 +471,7 @@ signal_handler (int sig)
{
switch (sig)
{
-#ifdef SIGHUP
case SIGHUP:
-#endif
case SIGINT:
case SIGTERM:
got_sighup = TRUE;
@@ -451,11 +516,20 @@ kill_bus_when_session_ends (void)
else
tty_fd = -1;
- if (tty_fd >= 0)
- verbose ("stdin isatty(), monitoring it\n");
+ if (x_fd >= 0)
+ {
+ verbose ("session lifetime is defined by X, not monitoring stdin\n");
+ tty_fd = -1;
+ }
+ else if (tty_fd >= 0)
+ {
+ verbose ("stdin isatty(), monitoring it\n");
+ }
else
- verbose ("stdin was not a TTY, not monitoring it\n");
-
+ {
+ verbose ("stdin was not a TTY, not monitoring it\n");
+ }
+
if (tty_fd < 0 && x_fd < 0)
{
fprintf (stderr, "No terminal on standard input and no X display; cannot attach message bus to session lifetime\n");
@@ -583,6 +657,7 @@ babysit (int exit_with_session,
s = getenv ("DBUS_DEBUG_OUTPUT");
if (s == NULL || *s == '\0')
dup2 (dev_null_fd, 2);
+ close (dev_null_fd);
}
else
{
@@ -704,31 +779,35 @@ pass_info (const char *runprog, const char *bus_address, pid_t bus_pid,
if (envvar == NULL || args == NULL)
goto oom;
- args[0] = xstrdup (runprog);
+ 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;
+ 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])
+ {
+ while (i > 1)
+ free (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);
+ 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);
+ 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);
+ bourne_shell_syntax, binary_syntax);
}
verbose ("dbus-launch exiting\n");
@@ -1049,24 +1128,41 @@ main (int argc, char **argv)
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 */
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
+ {
+ const char *test_daemon;
+ /* exec from testdir */
+ if (getenv ("DBUS_USE_TEST_BINARY") != NULL &&
+ (test_daemon = getenv ("DBUS_TEST_DAEMON")) != NULL)
+ {
+ if (config_file == NULL && getenv ("DBUS_TEST_DATA") != NULL)
+ {
+ config_file = concat2 (getenv ("DBUS_TEST_DATA"),
+ "/valid-config-files/session.conf");
+
+ if (config_file == NULL)
+ {
+ fprintf (stderr, "Out of memory\n");
+ exit (1);
+ }
+ }
+
+ execl (test_daemon,
+ test_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 test message bus daemon %s: %s.\n",
+ test_daemon, strerror (errno));
+ exit (1);
+ }
+ }
+ #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
execl (DBUS_DAEMONDIR"/dbus-daemon",
DBUS_DAEMONDIR"/dbus-daemon",
@@ -1111,7 +1207,6 @@ main (int argc, char **argv)
char *end;
long wid = 0;
long val;
- int ret2;
verbose ("=== Parent dbus-launch continues\n");
@@ -1185,6 +1280,8 @@ main (int argc, char **argv)
#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
if (xdisplay != NULL)
{
+ int ret2;
+
verbose("Saving x11 address\n");
ret2 = x11_save_address (bus_address, bus_pid, &wid);
/* Only get an existing dbus session when autolaunching */
diff --git a/tools/dbus-monitor.c b/tools/dbus-monitor.c
index a4b54782..ff8390d7 100644
--- a/tools/dbus-monitor.c
+++ b/tools/dbus-monitor.c
@@ -106,6 +106,9 @@ monitor_filter_func (DBusConnection *connection,
#ifdef __APPLE__
#define PROFILE_TIMED_FORMAT "%s\t%lu\t%d"
+#elif defined(__NetBSD__)
+#include <inttypes.h>
+#define PROFILE_TIMED_FORMAT "%s\t%" PRId64 "\t%d"
#else
#define PROFILE_TIMED_FORMAT "%s\t%lu\t%lu"
#endif
@@ -310,7 +313,7 @@ main (int argc, char *argv[])
filters = (char **) realloc (filters, numFilters * sizeof (char *));
if (filters == NULL)
oom ("adding a new filter slot");
- filters[j] = (char *) malloc (filter_len * sizeof (char *));
+ filters[j] = (char *) malloc (filter_len);
if (filters[j] == NULL)
oom ("adding a new filter");
snprintf (filters[j], filter_len, "%s,%s", EAVESDROPPING_RULE, arg);
@@ -364,41 +367,45 @@ main (int argc, char *argv[])
if (numFilters)
{
+ size_t offset = 0;
for (i = 0; i < j; i++)
{
- dbus_bus_add_match (connection, filters[i], &error);
- if (dbus_error_is_set (&error))
+ dbus_bus_add_match (connection, filters[i] + offset, &error);
+ if (dbus_error_is_set (&error) && i == 0 && offset == 0)
+ {
+ /* We might be talking to a pre-1.5.6 dbus-daemon
+ * which wouldn't understand eavesdrop=true.
+ * If this works, carry on with offset > 0
+ * on the remaining iterations. */
+ offset = strlen (EAVESDROPPING_RULE) + 1;
+ dbus_error_free (&error);
+ dbus_bus_add_match (connection, filters[i] + offset, &error);
+ }
+
+ if (dbus_error_is_set (&error))
{
fprintf (stderr, "Failed to setup match \"%s\": %s\n",
filters[i], error.message);
dbus_error_free (&error);
exit (1);
}
- free(filters[i]);
+ free(filters[i]);
}
}
else
{
dbus_bus_add_match (connection,
- EAVESDROPPING_RULE ",type='signal'",
- &error);
- if (dbus_error_is_set (&error))
- goto lose;
- dbus_bus_add_match (connection,
- EAVESDROPPING_RULE ",type='method_call'",
- &error);
+ EAVESDROPPING_RULE,
+ &error);
if (dbus_error_is_set (&error))
- goto lose;
- dbus_bus_add_match (connection,
- EAVESDROPPING_RULE ",type='method_return'",
- &error);
- if (dbus_error_is_set (&error))
- goto lose;
- dbus_bus_add_match (connection,
- EAVESDROPPING_RULE ",type='error'",
- &error);
- if (dbus_error_is_set (&error))
- goto lose;
+ {
+ dbus_error_free (&error);
+ dbus_bus_add_match (connection,
+ "",
+ &error);
+ if (dbus_error_is_set (&error))
+ goto lose;
+ }
}
if (!dbus_connection_add_filter (connection, filter_func, NULL, NULL)) {
diff --git a/tools/dbus-print-message.c b/tools/dbus-print-message.c
index 75d00aca..e0dd2da6 100644
--- a/tools/dbus-print-message.c
+++ b/tools/dbus-print-message.c
@@ -346,7 +346,15 @@ print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
printf("}\n");
break;
}
-
+
+ case DBUS_TYPE_UNIX_FD:
+ {
+ int fd;
+ dbus_message_iter_get_basic (iter, &fd);
+ printf ("unix fd %d\n", fd);
+ break;
+ }
+
default:
printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type);
break;
diff --git a/tools/dbus-run-session.c b/tools/dbus-run-session.c
new file mode 100644
index 00000000..105ab3b4
--- /dev/null
+++ b/tools/dbus-run-session.c
@@ -0,0 +1,464 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-run-session.c - run a child process in its own session
+ *
+ * Copyright © 2003-2006 Red Hat, Inc.
+ * Copyright © 2006 Thiago Macieira <thiago@kde.org>
+ * Copyright © 2011-2012 Nokia Corporation
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include "dbus/dbus.h"
+
+#define MAX_ADDR_LEN 512
+#define PIPE_READ_END 0
+#define PIPE_WRITE_END 1
+
+/* PROCESSES
+ *
+ * If you are in a shell and run "dbus-run-session myapp", here is what
+ * happens (compare and contrast with dbus-launch):
+ *
+ * shell
+ * \- dbus-run-session myapp
+ * \- dbus-daemon --nofork --print-address --session
+ * \- myapp
+ *
+ * All processes are long-running.
+ *
+ * When myapp exits, dbus-run-session kills dbus-daemon and terminates.
+ *
+ * If dbus-daemon exits, dbus-run-session warns and continues to run.
+ *
+ * PIPES
+ *
+ * dbus-daemon --print-address -> bus_address_pipe -> d-r-s
+ */
+
+static const char me[] = "dbus-run-session";
+
+static void
+usage (int ecode)
+{
+ fprintf (stderr,
+ "%s [OPTIONS] [--] PROGRAM [ARGUMENTS]\n"
+ "%s --version\n"
+ "%s --help\n"
+ "\n"
+ "Options:\n"
+ "--dbus-daemon=BINARY run BINARY instead of dbus-daemon\n"
+ "--config-file=FILENAME pass to dbus-daemon instead of --session\n"
+ "\n",
+ me, me, me);
+ exit (ecode);
+}
+
+static void
+version (void)
+{
+ printf ("%s %s\n"
+ "Copyright (C) 2003-2006 Red Hat, Inc.\n"
+ "Copyright (C) 2006 Thiago Macieira\n"
+ "Copyright © 2011-2012 Nokia Corporation\n"
+ "\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",
+ me, VERSION);
+ exit (0);
+}
+
+static void
+oom (void)
+{
+ fprintf (stderr, "%s: out of memory\n", me);
+ exit (1);
+}
+
+typedef enum
+{
+ READ_STATUS_OK, /**< Read succeeded */
+ READ_STATUS_ERROR, /**< Some kind of error */
+ READ_STATUS_EOF /**< EOF returned */
+} ReadStatus;
+
+static ReadStatus
+read_line (int fd,
+ char *buf,
+ size_t maxlen)
+{
+ size_t bytes = 0;
+ ReadStatus retval;
+
+ memset (buf, '\0', maxlen);
+ maxlen -= 1; /* ensure nul term */
+
+ retval = READ_STATUS_OK;
+
+ while (1)
+ {
+ ssize_t chunk;
+ size_t to_read;
+
+ again:
+ to_read = maxlen - bytes;
+
+ if (to_read == 0)
+ break;
+
+ chunk = read (fd,
+ buf + bytes,
+ to_read);
+ if (chunk < 0 && errno == EINTR)
+ goto again;
+
+ if (chunk < 0)
+ {
+ retval = READ_STATUS_ERROR;
+ break;
+ }
+ else if (chunk == 0)
+ {
+ retval = READ_STATUS_EOF;
+ break; /* EOF */
+ }
+ else /* chunk > 0 */
+ bytes += chunk;
+ }
+
+ if (retval == READ_STATUS_EOF &&
+ bytes > 0)
+ retval = READ_STATUS_OK;
+
+ /* whack newline */
+ if (retval != READ_STATUS_ERROR &&
+ bytes > 0 &&
+ buf[bytes-1] == '\n')
+ buf[bytes-1] = '\0';
+
+ return retval;
+}
+
+static void
+exec_dbus_daemon (const char *dbus_daemon,
+ int bus_address_pipe[2],
+ const char *config_file)
+{
+ /* Child process, which execs dbus-daemon or dies trying */
+#define MAX_FD_LEN 64
+ char write_address_fd_as_string[MAX_FD_LEN];
+
+ close (bus_address_pipe[PIPE_READ_END]);
+
+ sprintf (write_address_fd_as_string, "%d", bus_address_pipe[PIPE_WRITE_END]);
+
+ execlp (dbus_daemon,
+ dbus_daemon,
+ "--nofork",
+ "--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, "%s: failed to execute message bus daemon '%s': %s\n",
+ me, dbus_daemon, strerror (errno));
+}
+
+static void
+exec_app (int prog_arg, char **argv)
+{
+ execvp (argv[prog_arg], argv + prog_arg);
+
+ fprintf (stderr, "%s: failed to exec '%s': %s\n", me, argv[prog_arg],
+ strerror (errno));
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ int prog_arg = 0;
+ int bus_address_pipe[2] = { 0, 0 };
+ const char *config_file = NULL;
+ const char *dbus_daemon = NULL;
+ char bus_address[MAX_ADDR_LEN] = { 0 };
+ const char *prev_arg = NULL;
+ int i = 1;
+ int requires_arg = 0;
+ pid_t bus_pid;
+ pid_t app_pid;
+
+ while (i < argc)
+ {
+ const char *arg = argv[i];
+
+ if (requires_arg)
+ {
+ const char **arg_dest;
+
+ assert (prev_arg != NULL);
+
+ if (strcmp (prev_arg, "--config-file") == 0)
+ {
+ arg_dest = &config_file;
+ }
+ else if (strcmp (prev_arg, "--dbus-daemon") == 0)
+ {
+ arg_dest = &dbus_daemon;
+ }
+ else
+ {
+ /* shouldn't happen */
+ fprintf (stderr, "%s: internal error: %s not fully implemented\n",
+ me, prev_arg);
+ return 127;
+ }
+
+ if (*arg_dest != NULL)
+ {
+ fprintf (stderr, "%s: %s given twice\n", me, prev_arg);
+ return 127;
+ }
+
+ *arg_dest = arg;
+ requires_arg = 0;
+ prev_arg = arg;
+ ++i;
+ continue;
+ }
+
+ if (strcmp (arg, "--help") == 0 ||
+ strcmp (arg, "-h") == 0 ||
+ strcmp (arg, "-?") == 0)
+ {
+ usage (0);
+ }
+ else if (strcmp (arg, "--version") == 0)
+ {
+ version ();
+ }
+ else if (strstr (arg, "--config-file=") == arg)
+ {
+ const char *file;
+
+ if (config_file != NULL)
+ {
+ fprintf (stderr, "%s: --config-file given twice\n", me);
+ return 127;
+ }
+
+ file = strchr (arg, '=');
+ ++file;
+
+ config_file = file;
+ }
+ else if (strstr (arg, "--dbus-daemon=") == arg)
+ {
+ const char *file;
+
+ if (dbus_daemon != NULL)
+ {
+ fprintf (stderr, "%s: --dbus-daemon given twice\n", me);
+ return 127;
+ }
+
+ file = strchr (arg, '=');
+ ++file;
+
+ dbus_daemon = file;
+ }
+ else if (strcmp (arg, "--config-file") == 0 ||
+ strcmp (arg, "--dbus-daemon") == 0)
+ {
+ requires_arg = 1;
+ }
+ else if (arg[0] == '-')
+ {
+ if (strcmp (arg, "--") != 0)
+ {
+ fprintf (stderr, "%s: option '%s' is unknown\n", me, arg);
+ return 127;
+ }
+ else
+ {
+ prog_arg = i + 1;
+ break;
+ }
+ }
+ else
+ {
+ prog_arg = i;
+ break;
+ }
+
+ prev_arg = arg;
+ ++i;
+ }
+
+ /* "dbus-run-session" and "dbus-run-session ... --" are not allowed:
+ * there must be something to run */
+ if (prog_arg < 1 || prog_arg >= argc)
+ {
+ fprintf (stderr, "%s: a non-option argument is required\n", me);
+ return 127;
+ }
+
+ if (requires_arg)
+ {
+ fprintf (stderr, "%s: option '%s' requires an argument\n", me, prev_arg);
+ return 127;
+ }
+
+ if (dbus_daemon == NULL)
+ dbus_daemon = "dbus-daemon";
+
+ if (pipe (bus_address_pipe) < 0)
+ {
+ fprintf (stderr, "%s: failed to create pipe: %s\n", me, strerror (errno));
+ return 127;
+ }
+
+ bus_pid = fork ();
+
+ if (bus_pid < 0)
+ {
+ fprintf (stderr, "%s: failed to fork: %s\n", me, strerror (errno));
+ return 127;
+ }
+
+ if (bus_pid == 0)
+ {
+ /* child */
+ exec_dbus_daemon (dbus_daemon, bus_address_pipe, config_file);
+ /* not reached */
+ return 127;
+ }
+
+ close (bus_address_pipe[PIPE_WRITE_END]);
+
+ switch (read_line (bus_address_pipe[PIPE_READ_END], bus_address, MAX_ADDR_LEN))
+ {
+ case READ_STATUS_OK:
+ break;
+
+ case READ_STATUS_EOF:
+ fprintf (stderr, "%s: EOF reading address from bus daemon\n", me);
+ return 127;
+ break;
+
+ case READ_STATUS_ERROR:
+ fprintf (stderr, "%s: error reading address from bus daemon: %s\n",
+ me, strerror (errno));
+ return 127;
+ break;
+ }
+
+ close (bus_address_pipe[PIPE_READ_END]);
+
+ if (!dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", bus_address) ||
+ !dbus_setenv ("DBUS_SESSION_BUS_PID", NULL) ||
+ !dbus_setenv ("DBUS_SESSION_BUS_WINDOWID", NULL) ||
+ !dbus_setenv ("DBUS_STARTER_ADDRESS", NULL) ||
+ !dbus_setenv ("DBUS_STARTER_BUS_TYPE", NULL))
+ oom ();
+
+ app_pid = fork ();
+
+ if (app_pid < 0)
+ {
+ fprintf (stderr, "%s: failed to fork: %s\n", me, strerror (errno));
+ return 127;
+ }
+
+ if (app_pid == 0)
+ {
+ /* child */
+ exec_app (prog_arg, argv);
+ /* not reached */
+ return 127;
+ }
+
+ while (1)
+ {
+ int child_status;
+ pid_t child_pid = waitpid (-1, &child_status, 0);
+
+ if (child_pid == (pid_t) -1)
+ {
+ int errsv = errno;
+
+ if (errsv == EINTR)
+ continue;
+
+ /* shouldn't happen: the only other documented errors are ECHILD,
+ * which shouldn't happen because we terminate when all our children
+ * have died, and EINVAL, which would indicate programming error */
+ fprintf (stderr, "%s: waitpid() failed: %s\n", me, strerror (errsv));
+ return 127;
+ }
+ else if (child_pid == bus_pid)
+ {
+ /* no need to kill it, now */
+ bus_pid = 0;
+
+ if (WIFEXITED (child_status))
+ fprintf (stderr, "%s: dbus-daemon exited with code %d\n",
+ me, WEXITSTATUS (child_status));
+ else if (WIFSIGNALED (child_status))
+ fprintf (stderr, "%s: dbus-daemon terminated by signal %d\n",
+ me, WTERMSIG (child_status));
+ else
+ fprintf (stderr, "%s: dbus-daemon died or something\n", me);
+ }
+ else if (child_pid == app_pid)
+ {
+ if (bus_pid != 0)
+ kill (bus_pid, SIGTERM);
+
+ if (WIFEXITED (child_status))
+ return WEXITSTATUS (child_status);
+
+ /* if it died from a signal, behave like sh(1) */
+ if (WIFSIGNALED (child_status))
+ return 128 + WTERMSIG (child_status);
+
+ /* I give up (this should never be reached) */
+ fprintf (stderr, "%s: child process died or something\n", me);
+ return 127;
+ }
+ else
+ {
+ fprintf (stderr, "%s: ignoring unknown child process %ld\n", me,
+ (long) child_pid);
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/dbus-send.c b/tools/dbus-send.c
index e403a587..d3ff2589 100644
--- a/tools/dbus-send.c
+++ b/tools/dbus-send.c
@@ -51,7 +51,7 @@ static const char *appname;
static void
usage (int ecode)
{
- fprintf (stderr, "Usage: %s [--help] [--system | --session | --address=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname);
+ fprintf (stderr, "Usage: %s [--help] [--system | --session | --bus=ADDRESS | --peer=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname);
exit (ecode);
}
@@ -241,6 +241,7 @@ main (int argc, char *argv[])
int message_type = DBUS_MESSAGE_TYPE_SIGNAL;
const char *type_str = NULL;
const char *address = NULL;
+ int is_bus = FALSE;
int session_or_system = FALSE;
appname = argv[0];
@@ -266,34 +267,66 @@ main (int argc, char *argv[])
type = DBUS_BUS_SESSION;
session_or_system = TRUE;
}
- else if (strstr (arg, "--address") == arg)
+ else if ((strstr (arg, "--bus=") == arg) || (strstr (arg, "--peer=") == arg) || (strstr (arg, "--address=") == arg))
{
- address = strchr (arg, '=');
-
- if (address == NULL)
+ if (arg[2] == 'b') /* bus */
{
- fprintf (stderr, "\"--address=\" requires an ADDRESS\n");
- usage (1);
+ is_bus = TRUE;
+ }
+ else if (arg[2] == 'p') /* peer */
+ {
+ is_bus = FALSE;
}
- else
+ else /* address; keeping backwards compatibility */
+ {
+ is_bus = FALSE;
+ }
+
+ address = strchr (arg, '=') + 1;
+
+ if (address[0] == '\0')
{
- address = address + 1;
+ fprintf (stderr, "\"--peer=\" and \"--bus=\" require an ADDRESS\n");
+ usage (1);
}
}
else if (strncmp (arg, "--print-reply", 13) == 0)
{
print_reply = TRUE;
message_type = DBUS_MESSAGE_TYPE_METHOD_CALL;
- if (*(arg + 13) != '\0')
+ if (strcmp (arg + 13, "=literal") == 0)
print_reply_literal = TRUE;
+ else if (*(arg + 13) != '\0')
+ {
+ fprintf (stderr, "invalid value (%s) of \"--print-reply\"\n", arg + 13);
+ usage (1);
+ }
}
else if (strstr (arg, "--reply-timeout=") == arg)
{
+ if (*(strchr (arg, '=') + 1) == '\0')
+ {
+ fprintf (stderr, "\"--reply-timeout=\" requires an MSEC\n");
+ usage (1);
+ }
reply_timeout = strtol (strchr (arg, '=') + 1,
NULL, 10);
+ if (reply_timeout <= 0)
+ {
+ fprintf (stderr, "invalid value (%s) of \"--reply-timeout\"\n",
+ strchr (arg, '=') + 1);
+ usage (1);
+ }
}
else if (strstr (arg, "--dest=") == arg)
- dest = strchr (arg, '=') + 1;
+ {
+ if (*(strchr (arg, '=') + 1) == '\0')
+ {
+ fprintf (stderr, "\"--dest=\" requires an NAME\n");
+ usage (1);
+ }
+ dest = strchr (arg, '=') + 1;
+ }
else if (strstr (arg, "--type=") == arg)
type_str = strchr (arg, '=') + 1;
else if (!strcmp(arg, "--help"))
@@ -312,7 +345,7 @@ main (int argc, char *argv[])
if (session_or_system &&
(address != NULL))
{
- fprintf (stderr, "\"--address\" may not be used with \"--system\" or \"--session\"\n");
+ fprintf (stderr, "\"--peer\" and \"--bus\" may not be used with \"--system\" or \"--session\"\n");
usage (1);
}
@@ -330,6 +363,12 @@ main (int argc, char *argv[])
dbus_error_init (&error);
+ if (dest && !dbus_validate_bus_name (dest, &error))
+ {
+ fprintf (stderr, "invalid value (%s) of \"--dest\"\n", dest);
+ usage (1);
+ }
+
if (address != NULL)
{
connection = dbus_connection_open (address, &error);
@@ -348,6 +387,16 @@ main (int argc, char *argv[])
dbus_error_free (&error);
exit (1);
}
+ else if ((address != NULL) && is_bus)
+ {
+ if (!dbus_bus_register (connection, &error))
+ {
+ fprintf (stderr, "Failed to register on connection to \"%s\" message bus: %s\n",
+ address, error.message);
+ dbus_error_free (&error);
+ exit (1);
+ }
+ }
if (message_type == DBUS_MESSAGE_TYPE_METHOD_CALL)
{
diff --git a/tools/run-with-tmp-session-bus.sh b/tools/run-with-tmp-session-bus.sh
index c39999fb..94ae8fc8 100755
--- a/tools/run-with-tmp-session-bus.sh
+++ b/tools/run-with-tmp-session-bus.sh
@@ -1,16 +1,15 @@
#! /bin/sh
-SCRIPTNAME=$0
-WRAPPED_SCRIPT=$1
+SCRIPTNAME="$0"
+WRAPPED_SCRIPT="$1"
shift
-die()
+CONFIG_FILE=./tmp-session-bus.$$.conf
+
+die ()
{
- if ! test -z "$DBUS_SESSION_BUS_PID" ; then
- echo "killing message bus "$DBUS_SESSION_BUS_PID >&2
- kill -9 $DBUS_SESSION_BUS_PID
- fi
- echo $SCRIPTNAME: $* >&2
+ echo "$SCRIPTNAME: $*" >&2
+ rm -f "$CONFIG_FILE"
exit 1
}
@@ -18,10 +17,6 @@ if test -z "$DBUS_TOP_BUILDDIR" ; then
die "Must set DBUS_TOP_BUILDDIR"
fi
-## convenient to be able to ctrl+C without leaking the message bus process
-trap 'die "Received SIGINT"' INT
-
-CONFIG_FILE=./run-with-tmp-session-bus.conf
SERVICE_DIR="$DBUS_TOP_BUILDDIR/test/data/valid-service-files"
ESCAPED_SERVICE_DIR=`echo $SERVICE_DIR | sed -e 's/\//\\\\\\//g'`
echo "escaped service dir is: $ESCAPED_SERVICE_DIR" >&2
@@ -50,27 +45,18 @@ export LD_LIBRARY_PATH
unset DBUS_SESSION_BUS_ADDRESS
unset DBUS_SESSION_BUS_PID
-echo "Running $DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE" >&2
-
-DBUS_USE_TEST_BINARY=1
+# this does not actually affect dbus-run-session any more, but could be
+# significant for dbus-launch as used by the autolaunch test
+DBUS_USE_TEST_BINARY=1
export DBUS_USE_TEST_BINARY
-eval `$DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE`
-
-if test -z "$DBUS_SESSION_BUS_PID" ; then
- die "Failed to launch message bus for test script to run"
-fi
-
-echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2
-
-# Execute wrapped script
-echo "Running $WRAPPED_SCRIPT $@" >&2
-$WRAPPED_SCRIPT "$@" || die "script \"$WRAPPED_SCRIPT\" failed"
-
-kill -TERM $DBUS_SESSION_BUS_PID || die "Message bus vanished! should not have happened" && echo "Killed daemon $DBUS_SESSION_BUS_PID" >&2
-
-sleep 2
-## be sure it really died
-kill -9 $DBUS_SESSION_BUS_PID > /dev/null 2>&1 || true
+$DBUS_TOP_BUILDDIR/tools/dbus-run-session \
+ --config-file="$CONFIG_FILE" \
+ --dbus-daemon="$DBUS_TOP_BUILDDIR/bus/dbus-daemon" \
+ -- \
+ "$WRAPPED_SCRIPT" "$@"
+error=$?
-exit 0
+# clean up
+rm -f "$CONFIG_FILE"
+exit $error
diff --git a/tools/strtoll.c b/tools/strtoll.c
index e4f57701..7360c630 100644
--- a/tools/strtoll.c
+++ b/tools/strtoll.c
@@ -27,6 +27,7 @@
* SUCH DAMAGE.
*/
+#include "config.h"
#include <limits.h>
#ifdef HAVE_ERRNO_H
diff --git a/tools/strtoull.c b/tools/strtoull.c
index 459c5091..35595542 100644
--- a/tools/strtoull.c
+++ b/tools/strtoull.c
@@ -27,6 +27,7 @@
* SUCH DAMAGE.
*/
+#include "config.h"
#include <limits.h>
#ifdef HAVE_ERRNO_H