X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fdbus-launch-x11.c;h=c7e33309bac742b8656d79b5175ea5f2ab8a02b7;hb=638828526a9e7e4ff790c8949c65f3ee80a2cc79;hp=ac35621991a7cce91e385bb571556b3f5d695674;hpb=f6fa010403cb2badd88ce096ae91f664418508d1;p=platform%2Fupstream%2Fdbus.git diff --git a/tools/dbus-launch-x11.c b/tools/dbus-launch-x11.c index ac35621..c7e3330 100644 --- a/tools/dbus-launch-x11.c +++ b/tools/dbus-launch-x11.c @@ -1,4 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-launch.h dbus-launch utility * * Copyright (C) 2006 Thiago Macieira @@ -17,13 +17,17 @@ * * 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" #ifdef DBUS_BUILD_X11 #include +#include +#include #include #include #include @@ -33,7 +37,7 @@ #include #include -Display *xdisplay; +Display *xdisplay = NULL; static Atom selection_atom; static Atom address_atom; static Atom pid_atom; @@ -46,42 +50,60 @@ x_io_error_handler (Display *xdisplay) 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; + machine = get_machine_uuid (); + if (machine == NULL) + return NULL; + display = xstrdup (getenv ("DISPLAY")); if (display == NULL) { @@ -92,43 +114,44 @@ get_session_file (void) /* 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 _ */ + /* 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, ":"); + + /* 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 = '_'; - - hostname = get_local_hostname (); - if (hostname == NULL) { - /* out of memory */ - free (display); - return NULL; + if (*p == ':') + *p = '_'; } - - home = getenv ("HOME"); - if (home == NULL) - { - /* try from the user database */ - struct passwd *user = getpwuid (getuid()); - if (user == NULL) - { - verbose ("X11 integration disabled because the home directory" - " could not be determined\n"); - free (display); - return NULL; - } - - home = user->pw_dir; - } - - result = malloc (strlen (home) + strlen (prefix) + strlen (hostname) + + + home = get_homedir (); + + result = malloc (strlen (home) + strlen (prefix) + strlen (machine) + strlen (display) + 2); if (result == NULL) { @@ -139,8 +162,8 @@ get_session_file (void) strcpy (result, home); strcat (result, prefix); - strcat (result, hostname); - strcat (result, "_"); + strcat (result, machine); + strcat (result, "-"); strcat (result, display); free (display); @@ -148,6 +171,46 @@ get_session_file (void) 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,35 +229,31 @@ open_x11 (void) 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; if (init) return TRUE; + machine = get_machine_uuid (); + if (machine == NULL) + return FALSE; + user = getpwuid (getuid ()); if (user == NULL) { - verbose ("Could not determine the user informations; aborting X11 integration.\n"); + verbose ("Could not determine user information; aborting X11 integration.\n"); return FALSE; } user_name = xstrdup(user->pw_name); - hostname = get_local_hostname (); - if (hostname == NULL) - { - verbose ("Could not create X11 atoms; aborting X11 integration.\n"); - free (user_name); - return FALSE; - } - - atom_name = malloc (strlen (hostname) + strlen (user_name) + 2 + + atom_name = malloc (strlen (machine) + strlen (user_name) + 2 + MAX (strlen (selection_prefix), MAX (strlen (address_prefix), strlen (pid_prefix)))); @@ -209,7 +268,7 @@ init_x_atoms (Display *display) 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 */ @@ -234,6 +293,7 @@ init_x_atoms (Display *display) int x11_get_address (char **paddress, pid_t *pid, long *wid) { + int result; Atom type; Window owner; int format; @@ -251,10 +311,10 @@ x11_get_address (char **paddress, pid_t *pid, long *wid) *wid = (long) owner; /* get the bus address */ - XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False, - XA_STRING, &type, &format, &items, &after, - (unsigned char **) &data); - if (type == None || after != 0 || data == NULL || format != 8) + result = XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False, + XA_STRING, &type, &format, &items, &after, + (unsigned char **) &data); + if (result != Success || type == None || after != 0 || data == NULL || format != 8) return FALSE; /* error */ *paddress = xstrdup (data); @@ -264,10 +324,10 @@ x11_get_address (char **paddress, pid_t *pid, long *wid) if (pid != NULL) { *pid = 0; - XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False, - XA_CARDINAL, &type, &format, &items, &after, - (unsigned char **) &data); - if (type != None && after == 0 && data != NULL && format == 32) + result = XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False, + XA_CARDINAL, &type, &format, &items, &after, + (unsigned char **) &data); + if (result == Success && type != None && after == 0 && data != NULL && format == 32) *pid = (pid_t) *(long*) data; XFree (data); } @@ -284,44 +344,46 @@ static Window set_address_in_x11(char *address, pid_t pid) { char *current_address; - Window wid; - + Window wid = None; + unsigned long pid32; /* Xlib property functions want _long_ not 32-bit for format "32" */ + /* lock the X11 display to make sure we're doing this atomically */ XGrabServer (xdisplay); if (!x11_get_address (¤t_address, NULL, NULL)) { /* error! */ - XUngrabServer (xdisplay); - return None; + goto out; } if (current_address != NULL) { /* someone saved the address in the meantime */ - XUngrabServer (xdisplay); free (current_address); - return None; + goto out; } /* Create our window */ - wid = XCreateSimpleWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10, - 0, WhitePixel (xdisplay, 0), - BlackPixel (xdisplay, 0)); + wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10, + 0, CopyFromParent, InputOnly, CopyFromParent, + 0, NULL); verbose ("Created window %d\n", wid); /* Save the property in the window */ XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace, (unsigned char *)address, strlen (address)); + pid32 = pid; 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); + out: /* Ungrab the server to let other people use it too */ XUngrabServer (xdisplay); + /* And make sure that the ungrab gets sent to X11 */ XFlush (xdisplay); return wid; @@ -337,17 +399,29 @@ set_address_in_file (char *address, pid_t pid, Window wid) char *session_file; FILE *f; + ensure_session_directory (); session_file = get_session_file(); if (session_file == NULL) return FALSE; f = fopen (session_file, "w"); + free (session_file); 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); return TRUE; } @@ -388,5 +462,7 @@ x11_handle_event (void) } #else +void dummy_dbus_launch_x11 (void); + void dummy_dbus_launch_x11 (void) { } #endif