1d012387afef0ba02185ebe27bc6bb15551912e92Havoc Pennington/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira/* dbus-launch.h  dbus-launch utility
3f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira *
4f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
5f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira *
6f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * Licensed under the Academic Free License version 2.1
7f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira *
8f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * This program is free software; you can redistribute it and/or modify
9f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * it under the terms of the GNU General Public License as published by
10f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * the Free Software Foundation; either version 2 of the License, or
11f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * (at your option) any later version.
12f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira *
13f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * This program is distributed in the hope that it will be useful,
14f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * but WITHOUT ANY WARRANTY; without even the implied warranty of
15f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * GNU General Public License for more details.
17f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira *
18f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * You should have received a copy of the GNU General Public License
19f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * along with this program; if not, write to the Free Software
205baf2f856a9c6625993234855b07680da1c8916fTobias Mueller * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira *
22f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira */
23dbecdeabb20e0ce11121819c63373f0afba57c58Marcus Brinkmann
24dbecdeabb20e0ce11121819c63373f0afba57c58Marcus Brinkmann#include <config.h>
25f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include "dbus-launch.h"
26f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
27f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#ifdef DBUS_BUILD_X11
28f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <stdlib.h>
2910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington#include <sys/types.h>
3010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington#include <sys/stat.h>
31f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <unistd.h>
32f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <fcntl.h>
33f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <errno.h>
34f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <stdio.h>
35f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <string.h>
36f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <pwd.h>
37f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <X11/Xlib.h>
38f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#include <X11/Xatom.h>
39f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
40d8155bf51bf6484a94e734601526bf211053a5e1Havoc PenningtonDisplay *xdisplay = NULL;
41f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic Atom selection_atom;
42f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic Atom address_atom;
43f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic Atom pid_atom;
44f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
45f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic int
46f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirax_io_error_handler (Display *xdisplay)
47f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
48f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  verbose ("X IO error\n");
49f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  kill_bus_and_exit (0);
50f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return 0;
51f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
52f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
5310fe37f58213d3895229208453c3e691e554ed72Havoc Penningtonstatic void
5410fe37f58213d3895229208453c3e691e554ed72Havoc Penningtonremove_prefix (char *s,
5510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington               char *prefix)
56f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
5710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  int plen;
5810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
5910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  plen = strlen (prefix);
60f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
6110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  if (strncmp (s, prefix, plen) == 0)
62f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
6310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      memmove (s, s + plen, strlen (s) - plen + 1);
6410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    }
6510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington}
66f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
6710fe37f58213d3895229208453c3e691e554ed72Havoc Penningtonstatic const char*
6810fe37f58213d3895229208453c3e691e554ed72Havoc Penningtonget_homedir (void)
6910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington{
7010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  const char *home;
7110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
7210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  home = getenv ("HOME");
7310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  if (home == NULL)
7410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    {
7510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      /* try from the user database */
7610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      struct passwd *user = getpwuid (getuid());
7710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      if (user != NULL)
7810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington        home = user->pw_dir;
7910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    }
80f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
8110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  if (home == NULL)
8210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    {
8310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      fprintf (stderr, "Can't get user home directory\n");
8410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      exit (1);
85f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
86f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
8710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  return home;
88f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
89f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
9010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington#define DBUS_DIR ".dbus"
9110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington#define DBUS_SESSION_BUS_DIR "session-bus"
9210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
93f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic char *
94f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraget_session_file (void)
95f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
9610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  static const char prefix[] = "/" DBUS_DIR "/" DBUS_SESSION_BUS_DIR "/";
9710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  const char *machine;
9810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  const char *home;
99f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *display;
100f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *result;
101f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *p;
102f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
10301b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira  machine = get_machine_uuid ();
10401b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira  if (machine == NULL)
10501b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira    return NULL;
10601b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira
107f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  display = xstrdup (getenv ("DISPLAY"));
108f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (display == NULL)
109f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
110f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      verbose ("X11 integration disabled because X11 is not running\n");
111f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      return NULL;
112f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
113f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
114f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* remove the screen part of the display name */
115f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  p = strrchr (display, ':');
116f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (p != NULL)
11710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    {
11810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      for ( ; *p; ++p)
119f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        {
12010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington          if (*p == '.')
12110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington            {
12210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington              *p = '\0';
12310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington              break;
12410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington            }
125f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        }
126f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
127f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
12810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  /* Note that we leave the hostname in the display most of the
12910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * time. The idea is that we want to be per-(machine,display,user)
13010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * triplet to be extra-sure we get a bus we can connect to. Ideally
13110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * we'd recognize when the hostname matches the machine we're on in
13210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * all cases; we do try to drop localhost and localhost.localdomain
13310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * as a special common case so that alternate spellings of DISPLAY
13410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * don't result in extra bus instances.
13510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   *
13610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * We also kill the ":" if there's nothing in front of it. This
13710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * avoids an ugly double underscore in the filename.
13810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   */
13910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  remove_prefix (display, "localhost.localdomain:");
14010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  remove_prefix (display, "localhost:");
14110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  remove_prefix (display, ":");
14210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
14310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  /* replace the : in the display with _ if the : is still there.
14410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   * use _ instead of - since it can't be in hostnames.
14510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington   */
14610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  for (p = display; *p; ++p)
147f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
14810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      if (*p == ':')
14910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington        *p = '_';
150f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
15110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
15210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  home = get_homedir ();
15310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
15410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  result = malloc (strlen (home) + strlen (prefix) + strlen (machine) +
155f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                   strlen (display) + 2);
156f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (result == NULL)
157f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
158f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      /* out of memory */
159f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      free (display);
160f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      return NULL;
161f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
162f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
163f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcpy (result, home);
164f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcat (result, prefix);
16510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (result, machine);
16610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (result, "-");
167f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcat (result, display);
168f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  free (display);
169f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
170f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  verbose ("session file: %s\n", result);
171f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return result;
172f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
173f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
17410fe37f58213d3895229208453c3e691e554ed72Havoc Penningtonstatic void
17510fe37f58213d3895229208453c3e691e554ed72Havoc Penningtonensure_session_directory (void)
17610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington{
17710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  const char *home;
17810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  char *dir;
17910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
18010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  home = get_homedir ();
18110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
18210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  /* be sure we have space for / and nul */
18310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  dir = malloc (strlen (home) + strlen (DBUS_DIR) + strlen (DBUS_SESSION_BUS_DIR) + 3);
18410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  if (dir == NULL)
18510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    {
18610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      fprintf (stderr, "no memory\n");
18710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      exit (1);
18810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    }
18910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
19010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcpy (dir, home);
19110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (dir, "/");
19210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (dir, DBUS_DIR);
19310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
19410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  if (mkdir (dir, 0700) < 0)
19510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    {
19610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      /* only print a warning here, writing the session file itself will fail later */
19710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      if (errno != EEXIST)
19810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington        fprintf (stderr, "Unable to create %s\n", dir);
19910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    }
20010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
20110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (dir, "/");
20210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (dir, DBUS_SESSION_BUS_DIR);
20310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
20410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  if (mkdir (dir, 0700) < 0)
20510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    {
20610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      /* only print a warning here, writing the session file itself will fail later */
20710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington      if (errno != EEXIST)
20810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington        fprintf (stderr, "Unable to create %s\n", dir);
20910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington    }
21010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
21110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  free (dir);
21210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington}
21310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
214f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic Display *
215f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraopen_x11 (void)
216f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
217f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (xdisplay != NULL)
218f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    return xdisplay;
219f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
220f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  xdisplay = XOpenDisplay (NULL);
221f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (xdisplay != NULL)
222f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
223f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay));
224f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      XSetIOErrorHandler (x_io_error_handler);
225f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
226f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return xdisplay;
227f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
228f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
229f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic int
230f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirainit_x_atoms (Display *display)
231f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
23210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  static const char selection_prefix[] = "_DBUS_SESSION_BUS_SELECTION_";
23310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  static const char address_prefix[] = "_DBUS_SESSION_BUS_ADDRESS";
23410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  static const char pid_prefix[] = "_DBUS_SESSION_BUS_PID";
235f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  static int init = FALSE;
236f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *atom_name;
23710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  const char *machine;
238f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *user_name;
239f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  struct passwd *user;
240f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
241f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (init)
242f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    return TRUE;
243f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
24401b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira  machine = get_machine_uuid ();
24501b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira  if (machine == NULL)
24601b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira    return FALSE;
24701b91ba121034f94c1e4d4511b9e61f622dde48cThiago Macieira
248f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  user = getpwuid (getuid ());
249f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (user == NULL)
250f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
251f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      verbose ("Could not determine the user informations; aborting X11 integration.\n");
252f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      return FALSE;
253f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
254f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  user_name = xstrdup(user->pw_name);
255f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
25610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  atom_name = malloc (strlen (machine) + strlen (user_name) + 2 +
257f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                      MAX (strlen (selection_prefix),
258f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                           MAX (strlen (address_prefix),
259f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                                strlen (pid_prefix))));
260f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (atom_name == NULL)
261f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
262f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      verbose ("Could not create X11 atoms; aborting X11 integration.\n");
263f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      free (user_name);
264f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      return FALSE;
265f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
266f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
267f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* create the selection atom */
268f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcpy (atom_name, selection_prefix);
269f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcat (atom_name, user_name);
270f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcat (atom_name, "_");
27110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  strcat (atom_name, machine);
272f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  selection_atom = XInternAtom (display, atom_name, FALSE);
273f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
274f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* create the address property atom */
275f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcpy (atom_name, address_prefix);
276f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  address_atom = XInternAtom (display, atom_name, FALSE);
277f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
278f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* create the PID property atom */
279f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  strcpy (atom_name, pid_prefix);
280f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  pid_atom = XInternAtom (display, atom_name, FALSE);
281f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
282f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  free (atom_name);
283f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  free (user_name);
284f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  init = TRUE;
285f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return TRUE;
286f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
287f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
288f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira/*
289f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * Gets the daemon address from the X11 display.
290f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * Returns FALSE if there was an error. Returning
291f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * TRUE does not mean the address exists.
292f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira */
293f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraint
294f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirax11_get_address (char **paddress, pid_t *pid, long *wid)
295f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
296f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  Atom type;
297f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  Window owner;
298f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  int format;
299f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  unsigned long items;
300f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  unsigned long after;
301f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *data;
302f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
303f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  *paddress = NULL;
304f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
305f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* locate the selection owner */
306f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  owner = XGetSelectionOwner (xdisplay, selection_atom);
307f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (owner == None)
308f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    return TRUE;                /* no owner */
309f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (wid != NULL)
310f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    *wid = (long) owner;
311f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
312f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* get the bus address */
313f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False,
314f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                      XA_STRING, &type, &format, &items, &after,
315f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                      (unsigned char **) &data);
316f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (type == None || after != 0 || data == NULL || format != 8)
317f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    return FALSE;               /* error */
318f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
319f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  *paddress = xstrdup (data);
320f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XFree (data);
321f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
322f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* get the PID */
323f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (pid != NULL)
324f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
325f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      *pid = 0;
326f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False,
327f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                          XA_CARDINAL, &type, &format, &items, &after,
328f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                          (unsigned char **) &data);
329f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      if (type != None && after == 0 && data != NULL && format == 32)
330f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        *pid = (pid_t) *(long*) data;
331f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      XFree (data);
332f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
333f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
334f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return TRUE;                  /* success */
335f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
336f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
337f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira/*
338f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * Saves the address in the X11 display. Returns 0 on success.
339f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * If an error occurs, returns -1. If the selection already exists,
340f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * returns 1. (i.e. another daemon is already running)
341f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira */
342f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic Window
343f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraset_address_in_x11(char *address, pid_t pid)
344f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
345f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *current_address;
346193ebb7083fb1e9dccff04fc0a9d805a0aa03ea2Colin Walters  Window wid = None;
347163555c7ab56132ee27e3e7d9a26eb985682c1b5Havoc Pennington  unsigned long pid32; /* Xlib property functions want _long_ not 32-bit for format "32" */
34810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington
349f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* lock the X11 display to make sure we're doing this atomically */
350f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XGrabServer (xdisplay);
351f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
352f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (!x11_get_address (&current_address, NULL, NULL))
353f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
354f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      /* error! */
355193ebb7083fb1e9dccff04fc0a9d805a0aa03ea2Colin Walters      goto out;
356f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
357f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
358f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (current_address != NULL)
359f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
360f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      /* someone saved the address in the meantime */
361f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      free (current_address);
362193ebb7083fb1e9dccff04fc0a9d805a0aa03ea2Colin Walters      goto out;
363f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
364f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
365f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* Create our window */
3668f5c3e3c25901b089bc3fb87d53c7a98df48121fEamon Walsh  wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
3678f5c3e3c25901b089bc3fb87d53c7a98df48121fEamon Walsh                       0, CopyFromParent, InputOnly, CopyFromParent,
3688f5c3e3c25901b089bc3fb87d53c7a98df48121fEamon Walsh                       0, NULL);
369f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  verbose ("Created window %d\n", wid);
370f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
371f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* Save the property in the window */
372f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
373f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira                   (unsigned char *)address, strlen (address));
37410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  pid32 = pid;
375f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
37610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington                   (unsigned char *)&pid32, 1);
377f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
378f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* Now grab the selection */
379f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);
380f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
381193ebb7083fb1e9dccff04fc0a9d805a0aa03ea2Colin Walters out:
382f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  /* Ungrab the server to let other people use it too */
383f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XUngrabServer (xdisplay);
384f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
385193ebb7083fb1e9dccff04fc0a9d805a0aa03ea2Colin Walters  /* And make sure that the ungrab gets sent to X11 */
386f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  XFlush (xdisplay);
387f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
388f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return wid;
389f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
390f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
391f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira/*
392f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * Saves the session address in session file. Returns TRUE on
393f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira * success, FALSE if an error occurs.
394f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira */
395f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirastatic int
396f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraset_address_in_file (char *address, pid_t pid, Window wid)
397f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
398f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  char *session_file;
399f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  FILE *f;
400f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
40110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  ensure_session_directory ();
402f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  session_file = get_session_file();
403f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (session_file == NULL)
404f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    return FALSE;
405f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
406f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  f = fopen (session_file, "w");
407f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (f == NULL)
408f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    return FALSE;               /* some kind of error */
40910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington  fprintf (f,
41010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "# This file allows processes on the machine with id %s using \n"
41110fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "# display %s to find the D-Bus session bus with the below address.\n"
41210fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "# If the DBUS_SESSION_BUS_ADDRESS environment variable is set, it will\n"
41310fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "# be used rather than this file.\n"
41410fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "# See \"man dbus-launch\" for more details.\n"
41510fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "DBUS_SESSION_BUS_ADDRESS=%s\n"
41610fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "DBUS_SESSION_BUS_PID=%ld\n"
41710fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           "DBUS_SESSION_BUS_WINDOWID=%ld\n",
41810fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           get_machine_uuid (),
41910fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           getenv ("DISPLAY"),
42010fe37f58213d3895229208453c3e691e554ed72Havoc Pennington           address, (long)pid, (long)wid);
421f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
422f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  fclose (f);
423f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  free (session_file);
424f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
425f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return TRUE;
426f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
427f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
428f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraint
429f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirax11_save_address (char *address, pid_t pid, long *wid)
430f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
431f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  Window id = set_address_in_x11 (address, pid);
432f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (id != None)
433f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
434f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      if (!set_address_in_file (address, pid, id))
435f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        return FALSE;
436f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
437f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      if (wid != NULL)
438f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        *wid = (long) id;
439f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      return TRUE;
440f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
441f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return FALSE;
442f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
443f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
444f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiraint
445f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirax11_init (void)
446f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
447f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  return open_x11 () != NULL && init_x_atoms (xdisplay);
448f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
449f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
450f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiravoid
451f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieirax11_handle_event (void)
452f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira{
453f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira  if (xdisplay != NULL)
454f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    {
455f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira      while (XPending (xdisplay))
456f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        {
457f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira          XEvent ignored;
458f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira          XNextEvent (xdisplay, &ignored);
459f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira        }
460f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira    }
461f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira}
462f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira
463f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#else
46446df8b52d970d7c4ec3a61b5c696a05d0cb55f5dRalf Habackervoid dummy_dbus_launch_x11 (void);
46546df8b52d970d7c4ec3a61b5c696a05d0cb55f5dRalf Habacker
466f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieiravoid dummy_dbus_launch_x11 (void) { }
467f6fa010403cb2badd88ce096ae91f664418508d1Thiago Macieira#endif
468