dbus/tools Makefile.am, 1.24, 1.25 dbus-launch-x11.c, 1.2,
1.3 dbus-launch.1, 1.7, 1.8 dbus-launch.c, 1.18,
1.19 dbus-launch.h, 1.1, 1.2
Havoc Pennington
hp at kemper.freedesktop.org
Sun Oct 1 13:05:41 PDT 2006
Update of /cvs/dbus/dbus/tools
In directory kemper:/tmp/cvs-serv6139/tools
Modified Files:
Makefile.am dbus-launch-x11.c dbus-launch.1 dbus-launch.c
dbus-launch.h
Log Message:
2006-10-01 Havoc Pennington <hp at redhat.com>
* tools/dbus-launch.c (print_variables): if no syntax is given,
don't print something that's sort-of-half-sh-syntax, just print
a plain key-value pairs thing.
* tools/dbus-launch-x11.c: use machine ID rather than hostname for
the local machine representation (but still have the hostname in
the display). Remove the hostname from the display if it is
localhost. Change session files to be named
~/.dbus/session-bus/machine-display. Change X atoms to be
underscore-prefixed so nobody whines about ICCCM compliance.
Otherwise name them the same as the env variables.
Change session file format to include key-value pairs and an
explanatory comment. Keys are the same as the env variables.
(set_address_in_x11): X property format can't depend on
sizeof(pid_t) on a particular machine, fix to always be 32 bits
* tools/dbus-launch.c: make --autolaunch take a machine id
argument. If --autolaunch is used with a program to run, complain
for now (but add a FIXME). Also, don't look for existing bus if
there's a program to run (but add a FIXME).
* dbus/dbus-sysdeps-unix.c (_dbus_get_autolaunch_address): pass
machine uuid to dbus-launch (avoids linking dbus-launch to libdbus
just to get this, and avoids duplicating uuid-reading code).
* tools/dbus-launch.1: clarify various things
Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/tools/Makefile.am,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- Makefile.am 1 Oct 2006 15:36:19 -0000 1.24
+++ Makefile.am 1 Oct 2006 20:05:39 -0000 1.25
@@ -1,4 +1,6 @@
-INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\"
+configdir=$(sysconfdir)/dbus-1
+
+INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\" -DDBUS_MACHINE_UUID_FILE=\""$(configdir)/machine-id"\"
bin_PROGRAMS=dbus-send dbus-monitor dbus-launch dbus-cleanup-sockets dbus-uuidgen
Index: dbus-launch-x11.c
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch-x11.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- dbus-launch-x11.c 1 Oct 2006 03:18:47 -0000 1.2
+++ dbus-launch-x11.c 1 Oct 2006 20:05:39 -0000 1.3
@@ -24,6 +24,8 @@
#ifdef DBUS_BUILD_X11
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
@@ -46,39 +48,53 @@
return 0;
}
-static char *
-get_local_hostname (void)
+static void
+remove_prefix (char *s,
+ char *prefix)
{
- static const int increment = 128;
- static char *cache = NULL;
- char *buffer = NULL;
- int size = 0;
+ int plen;
- while (cache == NULL)
+ plen = strlen (prefix);
+
+ if (strncmp (s, prefix, plen) == 0)
{
- size += increment;
- buffer = realloc (buffer, size);
- if (buffer == NULL)
- return NULL; /* out of memory */
+ memmove (s, s + plen, strlen (s) - plen + 1);
+ }
+}
- if (gethostname (buffer, size - 1) == -1 &&
- errno != ENAMETOOLONG)
- return NULL;
+static const char*
+get_homedir (void)
+{
+ const char *home;
+
+ home = getenv ("HOME");
+ if (home == NULL)
+ {
+ /* try from the user database */
+ struct passwd *user = getpwuid (getuid());
+ if (user != NULL)
+ home = user->pw_dir;
+ }
- buffer[size - 1] = '\0'; /* to make sure */
- cache = buffer;
+ if (home == NULL)
+ {
+ fprintf (stderr, "Can't get user home directory\n");
+ exit (1);
}
- return cache;
+ return home;
}
+#define DBUS_DIR ".dbus"
+#define DBUS_SESSION_BUS_DIR "session-bus"
+
static char *
get_session_file (void)
{
- static const char prefix[] = "/.dbus-session-file_";
- char *hostname;
+ static const char prefix[] = "/" DBUS_DIR "/" DBUS_SESSION_BUS_DIR "/";
+ const char *machine;
+ const char *home;
char *display;
- char *home;
char *result;
char *p;
@@ -92,43 +108,46 @@
/* remove the screen part of the display name */
p = strrchr (display, ':');
if (p != NULL)
- for ( ; *p; ++p)
- if (*p == '.')
+ {
+ for ( ; *p; ++p)
{
- *p = '\0';
- break;
+ if (*p == '.')
+ {
+ *p = '\0';
+ break;
+ }
}
-
- /* replace the : in the display with _ */
- for (p = display; *p; ++p)
- if (*p == ':')
- *p = '_';
-
- hostname = get_local_hostname ();
- if (hostname == NULL)
- {
- /* out of memory */
- free (display);
- return NULL;
}
- home = getenv ("HOME");
- if (home == NULL)
- {
- /* try from the user database */
- struct passwd *user = getpwuid (getuid());
- if (user == NULL)
- {
- verbose ("X11 integration disabled because the home directory"
- " could not be determined\n");
- free (display);
- return NULL;
- }
+ /* Note that we leave the hostname in the display most of the
+ * time. The idea is that we want to be per-(machine,display,user)
+ * triplet to be extra-sure we get a bus we can connect to. Ideally
+ * we'd recognize when the hostname matches the machine we're on in
+ * all cases; we do try to drop localhost and localhost.localdomain
+ * as a special common case so that alternate spellings of DISPLAY
+ * don't result in extra bus instances.
+ *
+ * We also kill the ":" if there's nothing in front of it. This
+ * avoids an ugly double underscore in the filename.
+ */
+ remove_prefix (display, "localhost.localdomain:");
+ remove_prefix (display, "localhost:");
+ remove_prefix (display, ":");
- home = user->pw_dir;
+ /* replace the : in the display with _ if the : is still there.
+ * use _ instead of - since it can't be in hostnames.
+ */
+ for (p = display; *p; ++p)
+ {
+ if (*p == ':')
+ *p = '_';
}
+
+ machine = get_machine_uuid ();
- result = malloc (strlen (home) + strlen (prefix) + strlen (hostname) +
+ home = get_homedir ();
+
+ result = malloc (strlen (home) + strlen (prefix) + strlen (machine) +
strlen (display) + 2);
if (result == NULL)
{
@@ -139,8 +158,8 @@
strcpy (result, home);
strcat (result, prefix);
- strcat (result, hostname);
- strcat (result, "_");
+ strcat (result, machine);
+ strcat (result, "-");
strcat (result, display);
free (display);
@@ -148,6 +167,46 @@
return result;
}
+static void
+ensure_session_directory (void)
+{
+ const char *home;
+ char *dir;
+
+ home = get_homedir ();
+
+ /* be sure we have space for / and nul */
+ dir = malloc (strlen (home) + strlen (DBUS_DIR) + strlen (DBUS_SESSION_BUS_DIR) + 3);
+ if (dir == NULL)
+ {
+ fprintf (stderr, "no memory\n");
+ exit (1);
+ }
+
+ strcpy (dir, home);
+ strcat (dir, "/");
+ strcat (dir, DBUS_DIR);
+
+ if (mkdir (dir, 0700) < 0)
+ {
+ /* only print a warning here, writing the session file itself will fail later */
+ if (errno != EEXIST)
+ fprintf (stderr, "Unable to create %s\n", dir);
+ }
+
+ strcat (dir, "/");
+ strcat (dir, DBUS_SESSION_BUS_DIR);
+
+ if (mkdir (dir, 0700) < 0)
+ {
+ /* only print a warning here, writing the session file itself will fail later */
+ if (errno != EEXIST)
+ fprintf (stderr, "Unable to create %s\n", dir);
+ }
+
+ free (dir);
+}
+
static Display *
open_x11 (void)
{
@@ -166,12 +225,12 @@
static int
init_x_atoms (Display *display)
{
- static const char selection_prefix[] = "DBUS_SESSION_SELECTION_";
- static const char address_prefix[] = "DBUS_SESSION_ADDRESS";
- static const char pid_prefix[] = "DBUS_SESSION_PID";
+ static const char selection_prefix[] = "_DBUS_SESSION_BUS_SELECTION_";
+ static const char address_prefix[] = "_DBUS_SESSION_BUS_ADDRESS";
+ static const char pid_prefix[] = "_DBUS_SESSION_BUS_PID";
static int init = FALSE;
char *atom_name;
- char *hostname;
+ const char *machine;
char *user_name;
struct passwd *user;
@@ -186,15 +245,9 @@
}
user_name = xstrdup(user->pw_name);
- hostname = get_local_hostname ();
- if (hostname == NULL)
- {
- verbose ("Could not create X11 atoms; aborting X11 integration.\n");
- free (user_name);
- return FALSE;
- }
+ machine = get_machine_uuid ();
- atom_name = malloc (strlen (hostname) + strlen (user_name) + 2 +
+ atom_name = malloc (strlen (machine) + strlen (user_name) + 2 +
MAX (strlen (selection_prefix),
MAX (strlen (address_prefix),
strlen (pid_prefix))));
@@ -209,7 +262,7 @@
strcpy (atom_name, selection_prefix);
strcat (atom_name, user_name);
strcat (atom_name, "_");
- strcat (atom_name, hostname);
+ strcat (atom_name, machine);
selection_atom = XInternAtom (display, atom_name, FALSE);
/* create the address property atom */
@@ -285,7 +338,8 @@
{
char *current_address;
Window wid;
-
+ int pid32;
+
/* lock the X11 display to make sure we're doing this atomically */
XGrabServer (xdisplay);
@@ -313,8 +367,14 @@
/* Save the property in the window */
XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
(unsigned char *)address, strlen (address));
+ pid32 = pid;
+ if (sizeof(pid32) != 4)
+ {
+ fprintf (stderr, "int is not 32 bits!\n");
+ exit (1);
+ }
XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *)&pid, sizeof(pid) / 4);
+ (unsigned char *)&pid32, 1);
/* Now grab the selection */
XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);
@@ -337,6 +397,7 @@
char *session_file;
FILE *f;
+ ensure_session_directory ();
session_file = get_session_file();
if (session_file == NULL)
return FALSE;
@@ -344,7 +405,18 @@
f = fopen (session_file, "w");
if (f == NULL)
return FALSE; /* some kind of error */
- fprintf (f, "%s\n%ld\n%ld\n", address, (long)pid, (long)wid);
+ fprintf (f,
+ "# This file allows processes on the machine with id %s using \n"
+ "# display %s to find the D-Bus session bus with the below address.\n"
+ "# If the DBUS_SESSION_BUS_ADDRESS environment variable is set, it will\n"
+ "# be used rather than this file.\n"
+ "# See \"man dbus-launch\" for more details.\n"
+ "DBUS_SESSION_BUS_ADDRESS=%s\n"
+ "DBUS_SESSION_BUS_PID=%ld\n"
+ "DBUS_SESSION_BUS_WINDOWID=%ld\n",
+ get_machine_uuid (),
+ getenv ("DISPLAY"),
+ address, (long)pid, (long)wid);
fclose (f);
free (session_file);
Index: dbus-launch.1
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch.1,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- dbus-launch.1 30 Sep 2006 19:38:34 -0000 1.7
+++ dbus-launch.1 1 Oct 2006 20:05:39 -0000 1.8
@@ -7,27 +7,36 @@
dbus-launch \- Utility to start a message bus from a shell script
.SH SYNOPSIS
.PP
-.B dbus-launch [\-\-version] [\-\-sh-syntax] [\-\-csh-syntax] [\-\-auto-syntax] [\-\-exit-with-session] [\-\-autolaunch] [\-\-config-file=FILENAME] [PROGRAM] [ARGS...]
+.B dbus-launch [\-\-version] [\-\-sh-syntax] [\-\-csh-syntax] [\-\-auto-syntax] [\-\-exit-with-session] [\-\-autolaunch=MACHINEID] [\-\-config-file=FILENAME] [PROGRAM] [ARGS...]
.SH DESCRIPTION
-The \fIdbus-launch\fP command is used to start \fIdbus-daemon\fP
-from a shell script. It would normally be called from a user's login
+The \fIdbus-launch\fP command is used to start a session bus
+instance of \fIdbus-daemon\fP from a shell script.
+It would normally be called from a user's login
scripts. Unlike the daemon itself, \fIdbus-launch\fP exits, so
backticks or the $() construct can be used to read information from
\fIdbus-launch\fP.
-With no arguments, \fIdbus-launch\fP will simply print the values of
-DBUS_SESSION_BUS_ADDRESS and DBUS_SESSION_BUS_PID.
+With no arguments, \fIdbus-launch\fP will launch a session bus
+instance and print the address and pid of that instance to standard
+output.
You may specify a program to be run; in this case, \fIdbus-launch\fP
-will then set the appropriate environment variables and execute the
+will launch a session bus instance, set the appropriate environment
+variables so the specified program can find the bus, and then execute the
specified program, with the specified arguments. See below for
examples.
-Finally, you may use the \-\-sh-syntax, \-\-csh-syntax, or
-\-\-auto-syntax commands to cause \fIdbus-launch\fP to emit shell code
-to set up the environment. This is useful in shell scripts.
+If you launch a program, \fIdbus-launch\fP will not print the
+information about the new bus to standard output.
+
+When \fIdbus-launch\fP prints bus information to standard output, by
+default it is in a simple key-value pairs format. However, you may
+request several alternate syntaxes using the \-\-sh-syntax, \-\-csh-syntax,
+\-\-binary-syntax, or
+\-\-auto-syntax options. Several of these cause \fIdbus-launch\fP to emit shell code
+to set up the environment.
With the \-\-auto-syntax option, \fIdbus-launch\fP looks at the value
of the SHELL environment variable to determine which shell syntax
@@ -67,12 +76,60 @@
.fi
The above would likely be appropriate for ~/.xsession or ~/.Xclients.
+.SH AUTOMATIC LAUNCHING
+
+.PP
+If DBUS_SESSION_BUS_ADDRESS is not set for a process that tries to use
+D-Bus, by default the process will attempt to invoke dbus-launch with
+the --autolaunch option to start up a new session bus or find the
+existing bus address on the X display or in a file in
+~/.dbus/session-bus/
+
+.PP
+Whenever an autolaunch occurs, the application that had to
+start a new bus will be in its own little world; it can effectively
+end up starting a whole new session if it tries to use a lot of
+bus services. This can be suboptimal or even totally broken, depending
+on the app and what it tries to do.
+
+.PP
+There are two common reasons for autolaunch. One is ssh to a remote
+machine. The ideal fix for that would be forwarding of
+DBUS_SESSION_BUS_ADDRESS in the same way that DISPLAY is forwarded.
+In the meantime, you can edit the session.conf config file to
+have your session bus listen on TCP, and manually set
+DBUS_SESSION_BUS_ADDRESS, if you like.
+
+.PP
+The second common reason for autolaunch is an su to another user, and
+display of X applications running as the second user on the display
+belonging to the first user. Perhaps the ideal fix in this case
+would be to allow the second user to connect to the session bus of the
+first user, just as they can connect to the first user's display.
+However, a mechanism for that has not been coded.
+
+.PP
+You can always avoid autolaunch by manually setting
+DBUS_SESSION_BUS_ADDRESS. Autolaunch happens because the default
+address if none is set is "autolaunch:", so if any other address is
+set there will be no autolaunch. You can however include autolaunch in
+an explicit session bus address as a fallback, for example
+DBUS_SESSION_BUS_ADDRESS="something:,autolaunch:" - in that case if
+the first address doesn't work, processes will autolaunch. (The bus
+address variable contains a comma-separated list of addresses to try.)
+
.SH OPTIONS
The following options are supported:
.TP
.I "--auto-syntax"
Choose \-\-csh-syntax or \-\-sh-syntax based on the SHELL environment variable.
+.I "--binary-syntax"
+Write to stdout a nul-terminated bus address, then the bus PID as a
+binary integer of size sizeof(pid_t), then the bus X window ID as a
+binary integer of size sizeof(long). Integers are in the machine's
+byte order, not network byte order or any other canonical byte order.
+
.TP
.I "--config-file=FILENAME"
Pass \-\-config-file=FILENAME to the bus daemon, instead of passing it
@@ -90,11 +147,12 @@
it kills the message bus daemon.
.TP
-.I "--autolaunch"
+.I "--autolaunch=MACHINEID"
This option implies that \fIdbus-launch\fP should scan for a
previously-started session and reuse the values found there. If no
session is found, it will start a new session. The
\-\-exit-with-session option is implied if \-\-autolaunch is given.
+This option is used by libdbus, you probably do not want to use it manually.
.TP
.I "--sh-syntax"
Index: dbus-launch.c
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- dbus-launch.c 1 Oct 2006 03:18:47 -0000 1.18
+++ dbus-launch.c 1 Oct 2006 20:05:39 -0000 1.19
@@ -1,7 +1,8 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-launch.c dbus-launch utility
*
- * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2003, 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Thiago Macieira <thiago at kde.org>
*
* Licensed under the Academic Free License version 2.1
*
@@ -39,6 +40,27 @@
extern Display *xdisplay;
#endif
+static char* machine_uuid = NULL;
+
+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);
+}
+
void
verbose (const char *format,
...)
@@ -303,8 +325,9 @@
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
+ else if (bourne_shell_syntax)
{
printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address);
if (bourne_shell_syntax)
@@ -312,6 +335,15 @@
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);
}
}
@@ -614,8 +646,38 @@
version ();
else if (strcmp (arg, "--exit-with-session") == 0)
exit_with_session = 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);
+ }
else if (strcmp (arg, "--autolaunch") == 0)
- autolaunch = TRUE;
+ ; /* wait for next arg */
else if (strstr (arg, "--config-file=") == arg)
{
const char *file;
@@ -673,7 +735,7 @@
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");
@@ -682,7 +744,23 @@
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);
+ }
+ /* FIXME right now autolaunch always does print_variables(), but it should really
+ * exec the child program instead if a child program was specified. For now
+ * we just exit if this conflict arises.
+ */
+ if (runprog)
+ {
+ fprintf (stderr, "Currently --autolaunch does not support running a program\n");
+ exit (1);
+ }
+
verbose ("Autolaunch enabled (using X11).\n");
if (!exit_with_session)
{
@@ -703,7 +781,7 @@
}
if (address != NULL)
- {
+ {
verbose ("dbus-daemon is already running. Returning existing parameters.\n");
print_variables (address, pid, wid, c_shell_syntax,
bourne_shell_syntax, binary_syntax);
@@ -902,7 +980,10 @@
close (bus_pid_to_launcher_pipe[READ_END]);
#ifdef DBUS_BUILD_X11
- if (xdisplay != NULL)
+ /* FIXME the runprog == NULL is broken - we need to launch the runprog with the existing bus,
+ * instead of just doing print_variables() if there's an existing bus.
+ */
+ if (xdisplay != NULL && runprog == NULL)
{
ret2 = x11_save_address (bus_address, bus_pid, &wid);
if (ret2 == 0)
Index: dbus-launch.h
===================================================================
RCS file: /cvs/dbus/dbus/tools/dbus-launch.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- dbus-launch.h 30 Sep 2006 19:38:34 -0000 1.1
+++ dbus-launch.h 1 Oct 2006 20:05:39 -0000 1.2
@@ -45,6 +45,8 @@
char *xstrdup (const char *str);
void kill_bus_and_exit (int exitcode);
+const char* get_machine_uuid (void);
+
#ifdef DBUS_BUILD_X11
/* defined in dbus-launch-x11.c */
int x11_init (void);
More information about the dbus-commit
mailing list