1 /* console-kit.c vdagentd ConsoleKit integration code
3 Copyright 2010-2012 Red Hat, Inc.
6 Hans de Goede <hdegoede@redhat.com>
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 3 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, see <http://www.gnu.org/licenses/>.
22 #include "session-info.h"
23 #include <dbus/dbus.h>
32 DBusConnection
*connection
;
37 gchar
*match_seat_signals
;
40 #define INTERFACE_CONSOLE_KIT "org.freedesktop.ConsoleKit"
41 #define OBJ_PATH_CONSOLE_KIT "/org/freedesktop/ConsoleKit"
43 #define INTERFACE_CONSOLE_KIT_MANAGER INTERFACE_CONSOLE_KIT ".Manager"
44 #define OBJ_PATH_CONSOLE_KIT_MANAGER OBJ_PATH_CONSOLE_KIT "/Manager"
46 #define INTERFACE_CONSOLE_KIT_SEAT INTERFACE_CONSOLE_KIT ".Seat"
48 #define SEAT_SIGNAL_ACTIVE_SESSION_CHANGED "ActiveSessionChanged"
50 static char *console_kit_get_first_seat(struct session_info
*info
);
51 static char *console_kit_check_active_session_change(struct session_info
*info
);
53 static void si_dbus_match_remove(struct session_info
*info
)
56 if (info
->match_seat_signals
!= NULL
) {
57 dbus_error_init(&error
);
58 dbus_bus_remove_match(info
->connection
,
59 info
->match_seat_signals
,
62 syslog(LOG_DEBUG
, "(console-kit) seat match removed: %s",
63 info
->match_seat_signals
);
64 g_free(info
->match_seat_signals
);
65 info
->match_seat_signals
= NULL
;
69 static void si_dbus_match_rule_update(struct session_info
*info
)
73 if (info
->connection
== NULL
)
76 si_dbus_match_remove(info
);
79 if (info
->seat
!= NULL
) {
80 info
->match_seat_signals
=
81 g_strdup_printf ("type='signal',interface='%s',path='%s',"
82 "member='ActiveSessionChanged'",
83 INTERFACE_CONSOLE_KIT_SEAT
,
86 syslog(LOG_DEBUG
, "(console-kit) seat match: %s",
87 info
->match_seat_signals
);
89 dbus_error_init(&error
);
90 dbus_bus_add_match(info
->connection
,
91 info
->match_seat_signals
,
93 if (dbus_error_is_set(&error
)) {
94 syslog(LOG_WARNING
, "Unable to add dbus rule match: %s",
96 dbus_error_free(&error
);
97 g_free(info
->match_seat_signals
);
103 si_dbus_read_signals(struct session_info
*info
)
105 DBusMessage
*message
= NULL
;
107 dbus_connection_read_write(info
->connection
, 0);
108 message
= dbus_connection_pop_message(info
->connection
);
109 while (message
!= NULL
) {
112 if (dbus_message_get_type(message
) != DBUS_MESSAGE_TYPE_SIGNAL
) {
113 syslog(LOG_WARNING
, "(console-kit) received non signal message");
114 dbus_message_unref(message
);
118 member
= dbus_message_get_member (message
);
119 if (g_strcmp0(member
, SEAT_SIGNAL_ACTIVE_SESSION_CHANGED
) == 0) {
120 DBusMessageIter iter
;
124 free(info
->active_session
);
125 info
->active_session
= NULL
;
127 dbus_message_iter_init(message
, &iter
);
128 type
= dbus_message_iter_get_arg_type(&iter
);
129 /* Session should be an object path, but there is a bug in
130 ConsoleKit where it sends a string rather then an object_path
131 accept object_path too in case the bug ever gets fixed */
132 if (type
== DBUS_TYPE_STRING
|| type
== DBUS_TYPE_OBJECT_PATH
) {
133 dbus_message_iter_get_basic(&iter
, &session
);
134 if (session
!= NULL
&& session
[0] != '\0') {
135 info
->active_session
= g_strdup(session
);
137 syslog(LOG_WARNING
, "(console-kit) received invalid session. "
138 "No active-session at the moment");
142 "ActiveSessionChanged message has unexpected type: '%c'",
145 } else if (info
->verbose
) {
146 syslog(LOG_DEBUG
, "(console-kit) Signal not handled: %s", member
);
149 dbus_message_unref(message
);
150 dbus_connection_read_write(info
->connection
, 0);
151 message
= dbus_connection_pop_message(info
->connection
);
155 struct session_info
*session_info_create(int verbose
)
157 struct session_info
*info
;
160 info
= calloc(1, sizeof(*info
));
164 info
->verbose
= verbose
;
166 dbus_error_init(&error
);
167 info
->connection
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
168 if (info
->connection
== NULL
|| dbus_error_is_set(&error
)) {
169 if (dbus_error_is_set(&error
)) {
170 syslog(LOG_ERR
, "Unable to connect to system bus: %s",
172 dbus_error_free(&error
);
174 syslog(LOG_ERR
, "Unable to connect to system bus");
179 if (!dbus_connection_get_unix_fd(info
->connection
, &info
->fd
)) {
180 syslog(LOG_ERR
, "Unable to get connection fd");
181 session_info_destroy(info
);
185 if (!console_kit_get_first_seat(info
)) {
186 session_info_destroy(info
);
190 si_dbus_match_rule_update(info
);
194 void session_info_destroy(struct session_info
*info
)
199 si_dbus_match_remove(info
);
200 dbus_connection_close(info
->connection
);
202 free(info
->active_session
);
206 int session_info_get_fd(struct session_info
*info
)
211 static char *console_kit_get_first_seat(struct session_info
*info
)
214 DBusMessage
*message
= NULL
;
215 DBusMessage
*reply
= NULL
;
216 DBusMessageIter iter
, subiter
;
221 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
222 OBJ_PATH_CONSOLE_KIT_MANAGER
,
223 INTERFACE_CONSOLE_KIT_MANAGER
,
225 if (message
== NULL
) {
226 syslog(LOG_ERR
, "Unable to create dbus message");
230 dbus_error_init(&error
);
231 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
235 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
236 if (dbus_error_is_set(&error
)) {
237 syslog(LOG_ERR
, "GetSeats failed: %s", error
.message
);
238 dbus_error_free(&error
);
240 syslog(LOG_ERR
, "GetSeats failed");
244 dbus_message_iter_init(reply
, &iter
);
245 type
= dbus_message_iter_get_arg_type(&iter
);
246 if (type
!= DBUS_TYPE_ARRAY
) {
248 "expected an array return value, got a '%c' instead", type
);
252 dbus_message_iter_recurse(&iter
, &subiter
);
253 type
= dbus_message_iter_get_arg_type(&subiter
);
254 if (type
!= DBUS_TYPE_OBJECT_PATH
) {
256 "expected an object path element, got a '%c' instead", type
);
260 dbus_message_iter_get_basic(&subiter
, &seat
);
261 info
->seat
= strdup(seat
);
265 dbus_message_unref(reply
);
268 if (message
!= NULL
) {
269 dbus_message_unref(message
);
272 syslog(LOG_INFO
, "(console-kit) seat: %s", info
->seat
);
276 const char *session_info_get_active_session(struct session_info
*info
)
279 DBusMessage
*message
= NULL
;
280 DBusMessage
*reply
= NULL
;
281 char *session
= NULL
;
286 if (info
->active_session
)
287 return console_kit_check_active_session_change(info
);
289 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
291 INTERFACE_CONSOLE_KIT_SEAT
,
293 if (message
== NULL
) {
294 syslog(LOG_ERR
, "Unable to create dbus message");
298 dbus_error_init(&error
);
299 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
303 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
304 if (dbus_error_is_set(&error
)) {
305 syslog(LOG_ERR
, "GetActiveSession failed: %s", error
.message
);
306 dbus_error_free(&error
);
308 syslog(LOG_ERR
, "GetActiveSession failed");
312 dbus_error_init(&error
);
313 if (!dbus_message_get_args(reply
,
315 DBUS_TYPE_OBJECT_PATH
, &session
,
316 DBUS_TYPE_INVALID
)) {
317 if (dbus_error_is_set(&error
)) {
318 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
319 dbus_error_free(&error
);
321 syslog(LOG_ERR
, "error getting ssid from reply");
326 info
->active_session
= strdup(session
);
330 dbus_message_unref(reply
);
333 if (message
!= NULL
) {
334 dbus_message_unref(message
);
337 /* In case the session was changed while we were running */
338 return console_kit_check_active_session_change(info
);
341 char *session_info_session_for_pid(struct session_info
*info
, uint32_t pid
)
344 DBusMessage
*message
= NULL
;
345 DBusMessage
*reply
= NULL
;
346 DBusMessageIter args
;
352 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
353 OBJ_PATH_CONSOLE_KIT_MANAGER
,
354 INTERFACE_CONSOLE_KIT_MANAGER
,
355 "GetSessionForUnixProcess");
356 if (message
== NULL
) {
357 syslog(LOG_ERR
, "Unable to create dbus message");
361 dbus_message_iter_init_append(message
, &args
);
362 if (!dbus_message_iter_append_basic(&args
, DBUS_TYPE_UINT32
, &pid
)) {
363 syslog(LOG_ERR
, "Unable to append dbus message args");
367 dbus_error_init(&error
);
368 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
372 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
373 if (dbus_error_is_set(&error
)) {
374 syslog(LOG_ERR
, "GetSessionForUnixProcess failed: %s",
376 dbus_error_free(&error
);
378 syslog(LOG_ERR
, "GetSessionForUnixProces failed");
382 dbus_error_init(&error
);
383 if (!dbus_message_get_args(reply
,
385 DBUS_TYPE_OBJECT_PATH
, &ssid
,
386 DBUS_TYPE_INVALID
)) {
387 if (dbus_error_is_set(&error
)) {
388 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
389 dbus_error_free(&error
);
391 syslog(LOG_ERR
, "error getting ssid from reply");
400 dbus_message_unref(reply
);
403 if (message
!= NULL
) {
404 dbus_message_unref(message
);
410 static char *console_kit_check_active_session_change(struct session_info
*info
)
412 si_dbus_read_signals(info
);
414 syslog(LOG_DEBUG
, "(console-kit) active-session: '%s'",
415 (info
->active_session
? info
->active_session
: "None"));
417 return info
->active_session
;