1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-launch.h dbus-launch utility
4 * Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "dbus-launch.h"
34 #include <X11/Xatom.h>
37 static Atom selection_atom;
38 static Atom address_atom;
42 x_io_error_handler (Display *xdisplay)
44 verbose ("X IO error\n");
45 kill_bus_and_exit (0);
50 get_local_hostname (void)
52 static const int increment = 128;
53 static char *cache = NULL;
60 buffer = realloc (buffer, size);
62 return NULL; /* out of memory */
64 if (gethostname (buffer, size - 1) == -1 &&
65 errno != ENAMETOOLONG)
68 buffer[size - 1] = '\0'; /* to make sure */
76 get_session_file (void)
78 static const char prefix[] = "/.dbus-session-file_";
85 display = xstrdup (getenv ("DISPLAY"));
88 verbose ("X11 integration disabled because X11 is not running\n");
92 /* remove the screen part of the display name */
93 p = strrchr (display, ':');
102 /* replace the : in the display with _ */
103 for (p = display; *p; ++p)
107 hostname = get_local_hostname ();
108 if (hostname == NULL)
115 home = getenv ("HOME");
118 /* try from the user database */
119 struct passwd *user = getpwuid (getuid());
122 verbose ("X11 integration disabled because the home directory"
123 " could not be determined\n");
131 result = malloc (strlen (home) + strlen (prefix) + strlen (hostname) +
132 strlen (display) + 2);
140 strcpy (result, home);
141 strcat (result, prefix);
142 strcat (result, hostname);
143 strcat (result, "_");
144 strcat (result, display);
147 verbose ("session file: %s\n", result);
154 if (xdisplay != NULL)
157 xdisplay = XOpenDisplay (NULL);
158 if (xdisplay != NULL)
160 verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay));
161 XSetIOErrorHandler (x_io_error_handler);
167 init_x_atoms (Display *display)
169 static const char selection_prefix[] = "DBUS_SESSION_SELECTION_";
170 static const char address_prefix[] = "DBUS_SESSION_ADDRESS";
171 static const char pid_prefix[] = "DBUS_SESSION_PID";
172 static int init = FALSE;
181 user = getpwuid (getuid ());
184 verbose ("Could not determine the user informations; aborting X11 integration.\n");
187 user_name = xstrdup(user->pw_name);
189 hostname = get_local_hostname ();
190 if (hostname == NULL)
192 verbose ("Could not create X11 atoms; aborting X11 integration.\n");
197 atom_name = malloc (strlen (hostname) + strlen (user_name) + 2 +
198 MAX (strlen (selection_prefix),
199 MAX (strlen (address_prefix),
200 strlen (pid_prefix))));
201 if (atom_name == NULL)
203 verbose ("Could not create X11 atoms; aborting X11 integration.\n");
208 /* create the selection atom */
209 strcpy (atom_name, selection_prefix);
210 strcat (atom_name, user_name);
211 strcat (atom_name, "_");
212 strcat (atom_name, hostname);
213 selection_atom = XInternAtom (display, atom_name, FALSE);
215 /* create the address property atom */
216 strcpy (atom_name, address_prefix);
217 address_atom = XInternAtom (display, atom_name, FALSE);
219 /* create the PID property atom */
220 strcpy (atom_name, pid_prefix);
221 pid_atom = XInternAtom (display, atom_name, FALSE);
230 * Gets the daemon address from the X11 display.
231 * Returns FALSE if there was an error. Returning
232 * TRUE does not mean the address exists.
235 x11_get_address (char **paddress, pid_t *pid, long *wid)
246 /* locate the selection owner */
247 owner = XGetSelectionOwner (xdisplay, selection_atom);
249 return TRUE; /* no owner */
253 /* get the bus address */
254 XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False,
255 XA_STRING, &type, &format, &items, &after,
256 (unsigned char **) &data);
257 if (type == None || after != 0 || data == NULL || format != 8)
258 return FALSE; /* error */
260 *paddress = xstrdup (data);
267 XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False,
268 XA_CARDINAL, &type, &format, &items, &after,
269 (unsigned char **) &data);
270 if (type != None && after == 0 && data != NULL && format == 32)
271 *pid = (pid_t) *(long*) data;
275 return TRUE; /* success */
279 * Saves the address in the X11 display. Returns 0 on success.
280 * If an error occurs, returns -1. If the selection already exists,
281 * returns 1. (i.e. another daemon is already running)
284 set_address_in_x11(char *address, pid_t pid)
286 char *current_address;
289 /* lock the X11 display to make sure we're doing this atomically */
290 XGrabServer (xdisplay);
292 if (!x11_get_address (¤t_address, NULL, NULL))
295 XUngrabServer (xdisplay);
299 if (current_address != NULL)
301 /* someone saved the address in the meantime */
302 XUngrabServer (xdisplay);
303 free (current_address);
307 /* Create our window */
308 wid = XCreateSimpleWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
309 0, WhitePixel (xdisplay, 0),
310 BlackPixel (xdisplay, 0));
311 verbose ("Created window %d\n", wid);
313 /* Save the property in the window */
314 XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
315 (unsigned char *)address, strlen (address));
316 XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
317 (unsigned char *)&pid, sizeof(pid) / 4);
319 /* Now grab the selection */
320 XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);
322 /* Ungrab the server to let other people use it too */
323 XUngrabServer (xdisplay);
331 * Saves the session address in session file. Returns TRUE on
332 * success, FALSE if an error occurs.
335 set_address_in_file (char *address, pid_t pid, Window wid)
340 session_file = get_session_file();
341 if (session_file == NULL)
344 f = fopen (session_file, "w");
346 return FALSE; /* some kind of error */
347 fprintf (f, "%s\n%ld\n%ld\n", address, (long)pid, (long)wid);
356 x11_save_address (char *address, pid_t pid, long *wid)
358 Window id = set_address_in_x11 (address, pid);
361 if (!set_address_in_file (address, pid, id))
374 return open_x11 () != NULL && init_x_atoms (xdisplay);
378 x11_handle_event (void)
380 if (xdisplay != NULL)
382 while (XPending (xdisplay))
385 XNextEvent (xdisplay, &ignored);
391 void dummy_dbus_launch_x11 (void) { }