]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/x-server.c
Prevent PID error when launching guest session in LXDE
[sojka/lightdm.git] / src / x-server.c
1 /*
2  * Copyright (C) 2010-2011 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  *
5  * This program is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation, either version 3 of the License, or (at your option) any later
8  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9  * license.
10  */
11
12 #include <config.h>
13 #include <string.h>
14 #include <xcb/xcb.h>
15
16 #include "x-server.h"
17 #include "configuration.h"
18
19 struct XServerPrivate
20 {
21     /* Host running the server */
22     gchar *hostname;
23
24     /* Display number */
25     guint number;
26
27     /* Cached server address */
28     gchar *address;
29
30     /* Authority */
31     XAuthority *authority;
32
33     /* Connection to this X server */
34     xcb_connection_t *connection;
35 };
36
37 G_DEFINE_TYPE (XServer, x_server, DISPLAY_SERVER_TYPE);
38
39 void
40 x_server_set_hostname (XServer *server, const gchar *hostname)
41 {
42     g_return_if_fail (server != NULL);
43     g_free (server->priv->hostname);
44     server->priv->hostname = g_strdup (hostname);
45     g_free (server->priv->address);
46     server->priv->address = NULL;
47 }
48
49 gchar *
50 x_server_get_hostname (XServer *server)
51 {
52     g_return_val_if_fail (server != NULL, NULL);
53     return server->priv->hostname;
54 }
55
56 void
57 x_server_set_display_number (XServer *server, guint number)
58 {
59     g_return_if_fail (server != NULL);
60     server->priv->number = number;
61     g_free (server->priv->address);
62     server->priv->address = NULL;
63 }
64
65 guint
66 x_server_get_display_number (XServer *server)
67 {
68     g_return_val_if_fail (server != NULL, 0);
69     return server->priv->number;
70 }
71
72 const gchar *
73 x_server_get_address (XServer *server)
74 {
75     g_return_val_if_fail (server != NULL, NULL);
76
77     if (!server->priv->address)
78     {
79         if (server->priv->hostname)
80             server->priv->address = g_strdup_printf("%s:%d", server->priv->hostname, server->priv->number);
81         else
82             server->priv->address = g_strdup_printf(":%d", server->priv->number);
83     }
84
85     return server->priv->address;
86 }
87
88 void
89 x_server_set_authority (XServer *server, XAuthority *authority)
90 {
91     g_return_if_fail (server != NULL);
92
93     g_clear_object (&server->priv->authority);
94     if (authority)
95         server->priv->authority = g_object_ref (authority);
96 }
97
98 XAuthority *
99 x_server_get_authority (XServer *server)
100 {
101     g_return_val_if_fail (server != NULL, NULL);
102     return server->priv->authority;
103 }
104
105 static const gchar *
106 x_server_get_session_type (DisplayServer *server)
107 {
108     return "x";
109 }
110
111 static gboolean
112 x_server_get_can_share (DisplayServer *server)
113 {
114     return TRUE;
115 }
116
117 static gboolean
118 x_server_start (DisplayServer *display_server)
119 {
120     XServer *server = X_SERVER (display_server);
121     xcb_auth_info_t *auth = NULL, a;
122
123     if (server->priv->authority)
124     {
125         a.namelen = strlen (x_authority_get_authorization_name (server->priv->authority));
126         a.name = (char *) x_authority_get_authorization_name (server->priv->authority);
127         a.datalen = x_authority_get_authorization_data_length (server->priv->authority);
128         a.data = (char *) x_authority_get_authorization_data (server->priv->authority);
129         auth = &a;
130     }
131
132     /* Open connection */
133     l_debug (server, "Connecting to XServer %s", x_server_get_address (server));
134     server->priv->connection = xcb_connect_to_display_with_auth_info (x_server_get_address (server), auth, NULL);
135     if (xcb_connection_has_error (server->priv->connection))
136     {
137         l_debug (server, "Error connecting to XServer %s", x_server_get_address (server));
138         return FALSE;
139     }
140
141     return DISPLAY_SERVER_CLASS (x_server_parent_class)->start (display_server);
142 }
143
144 static void
145 x_server_connect_session (DisplayServer *display_server, Session *session)
146 {
147     gint vt;
148
149     session_set_env (session, "XDG_SESSION_TYPE", "x11");
150
151     display_server = session_get_display_server (session);
152
153     vt = display_server_get_vt (display_server);
154     if (vt > 0)
155     {
156         gchar *t;
157
158         t = g_strdup_printf ("/dev/tty%d", vt);
159         session_set_tty (session, t);
160         g_free (t);
161
162         t = g_strdup_printf ("%d", vt);
163         session_set_env (session, "XDG_VTNR", t);
164         g_free (t);
165     }
166     else
167         l_debug (session, "Not setting XDG_VTNR");
168
169     session_set_env (session, "DISPLAY", x_server_get_address (X_SERVER (display_server)));
170     session_set_xdisplay (session, x_server_get_address (X_SERVER (display_server)));
171     session_set_remote_host_name (session, x_server_get_hostname (X_SERVER (display_server)));
172     session_set_x_authority (session,
173                              x_server_get_authority (X_SERVER (display_server)),
174                              config_get_boolean (config_get_instance (), "LightDM", "user-authority-in-system-dir"));
175 }
176
177 static void
178 x_server_disconnect_session (DisplayServer *display_server, Session *session)
179 {
180     gint vt;
181
182     session_unset_env (session, "XDG_SESSION_TYPE");
183     vt = display_server_get_vt (display_server);
184     if (vt > 0)
185     {
186         session_set_tty (session, NULL);
187         session_unset_env (session, "XDG_VTNR");
188     }
189     session_unset_env (session, "DISPLAY");
190     session_set_xdisplay (session, NULL);
191     session_set_remote_host_name (session, NULL);
192     session_set_x_authority (session, NULL, FALSE);
193 }
194
195 void
196 x_server_init (XServer *server)
197 {
198     server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, X_SERVER_TYPE, XServerPrivate);
199 }
200
201 static void
202 x_server_finalize (GObject *object)
203 {
204     XServer *self = X_SERVER (object);
205
206     g_free (self->priv->hostname);
207     g_free (self->priv->address);
208     g_clear_object (&self->priv->authority);
209     if (self->priv->connection)
210         xcb_disconnect (self->priv->connection);
211
212     G_OBJECT_CLASS (x_server_parent_class)->finalize (object);
213 }
214
215 static void
216 x_server_class_init (XServerClass *klass)
217 {
218     GObjectClass *object_class = G_OBJECT_CLASS (klass);
219     DisplayServerClass *display_server_class = DISPLAY_SERVER_CLASS (klass);
220
221     display_server_class->get_session_type = x_server_get_session_type;
222     display_server_class->get_can_share = x_server_get_can_share;
223     display_server_class->start = x_server_start;
224     display_server_class->connect_session = x_server_connect_session;
225     display_server_class->disconnect_session = x_server_disconnect_session;
226     object_class->finalize = x_server_finalize;
227
228     g_type_class_add_private (klass, sizeof (XServerPrivate));
229 }