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 member
= dbus_message_get_member (message
);
113 if (g_strcmp0(member
, SEAT_SIGNAL_ACTIVE_SESSION_CHANGED
) == 0) {
114 DBusMessageIter iter
;
118 free(info
->active_session
);
119 info
->active_session
= NULL
;
121 dbus_message_iter_init(message
, &iter
);
122 type
= dbus_message_iter_get_arg_type(&iter
);
123 /* Session should be an object path, but there is a bug in
124 ConsoleKit where it sends a string rather then an object_path
125 accept object_path too in case the bug ever gets fixed */
126 if (type
== DBUS_TYPE_STRING
|| type
== DBUS_TYPE_OBJECT_PATH
) {
127 dbus_message_iter_get_basic(&iter
, &session
);
128 if (session
!= NULL
&& session
[0] != '\0') {
129 info
->active_session
= g_strdup(session
);
131 syslog(LOG_WARNING
, "(console-kit) received invalid session. "
132 "No active-session at the moment");
136 "ActiveSessionChanged message has unexpected type: '%c'",
140 if (dbus_message_get_type(message
) != DBUS_MESSAGE_TYPE_SIGNAL
) {
141 syslog(LOG_WARNING
, "(console-kit) received non signal message");
142 } else if (info
->verbose
) {
143 syslog(LOG_DEBUG
, "(console-kit) Signal not handled: %s", member
);
147 dbus_message_unref(message
);
148 dbus_connection_read_write(info
->connection
, 0);
149 message
= dbus_connection_pop_message(info
->connection
);
153 struct session_info
*session_info_create(int verbose
)
155 struct session_info
*info
;
158 info
= calloc(1, sizeof(*info
));
162 info
->verbose
= verbose
;
164 dbus_error_init(&error
);
165 info
->connection
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
166 if (info
->connection
== NULL
|| dbus_error_is_set(&error
)) {
167 if (dbus_error_is_set(&error
)) {
168 syslog(LOG_ERR
, "Unable to connect to system bus: %s",
170 dbus_error_free(&error
);
172 syslog(LOG_ERR
, "Unable to connect to system bus");
177 if (!dbus_connection_get_unix_fd(info
->connection
, &info
->fd
)) {
178 syslog(LOG_ERR
, "Unable to get connection fd");
179 session_info_destroy(info
);
183 if (!console_kit_get_first_seat(info
)) {
184 session_info_destroy(info
);
188 si_dbus_match_rule_update(info
);
192 void session_info_destroy(struct session_info
*info
)
197 si_dbus_match_remove(info
);
198 dbus_connection_close(info
->connection
);
200 free(info
->active_session
);
204 int session_info_get_fd(struct session_info
*info
)
209 static char *console_kit_get_first_seat(struct session_info
*info
)
212 DBusMessage
*message
= NULL
;
213 DBusMessage
*reply
= NULL
;
214 DBusMessageIter iter
, subiter
;
219 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
220 OBJ_PATH_CONSOLE_KIT_MANAGER
,
221 INTERFACE_CONSOLE_KIT_MANAGER
,
223 if (message
== NULL
) {
224 syslog(LOG_ERR
, "Unable to create dbus message");
228 dbus_error_init(&error
);
229 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
233 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
234 if (dbus_error_is_set(&error
)) {
235 syslog(LOG_ERR
, "GetSeats failed: %s", error
.message
);
236 dbus_error_free(&error
);
238 syslog(LOG_ERR
, "GetSeats failed");
242 dbus_message_iter_init(reply
, &iter
);
243 type
= dbus_message_iter_get_arg_type(&iter
);
244 if (type
!= DBUS_TYPE_ARRAY
) {
246 "expected an array return value, got a '%c' instead", type
);
250 dbus_message_iter_recurse(&iter
, &subiter
);
251 type
= dbus_message_iter_get_arg_type(&subiter
);
252 if (type
!= DBUS_TYPE_OBJECT_PATH
) {
254 "expected an object path element, got a '%c' instead", type
);
258 dbus_message_iter_get_basic(&subiter
, &seat
);
259 info
->seat
= strdup(seat
);
263 dbus_message_unref(reply
);
266 if (message
!= NULL
) {
267 dbus_message_unref(message
);
270 syslog(LOG_INFO
, "(console-kit) seat: %s", info
->seat
);
274 const char *session_info_get_active_session(struct session_info
*info
)
277 DBusMessage
*message
= NULL
;
278 DBusMessage
*reply
= NULL
;
279 char *session
= NULL
;
284 if (info
->active_session
)
285 return console_kit_check_active_session_change(info
);
287 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
289 INTERFACE_CONSOLE_KIT_SEAT
,
291 if (message
== NULL
) {
292 syslog(LOG_ERR
, "Unable to create dbus message");
296 dbus_error_init(&error
);
297 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
301 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
302 if (dbus_error_is_set(&error
)) {
303 syslog(LOG_ERR
, "GetActiveSession failed: %s", error
.message
);
304 dbus_error_free(&error
);
306 syslog(LOG_ERR
, "GetActiveSession failed");
310 dbus_error_init(&error
);
311 if (!dbus_message_get_args(reply
,
313 DBUS_TYPE_OBJECT_PATH
, &session
,
314 DBUS_TYPE_INVALID
)) {
315 if (dbus_error_is_set(&error
)) {
316 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
317 dbus_error_free(&error
);
319 syslog(LOG_ERR
, "error getting ssid from reply");
324 info
->active_session
= strdup(session
);
328 dbus_message_unref(reply
);
331 if (message
!= NULL
) {
332 dbus_message_unref(message
);
335 /* In case the session was changed while we were running */
336 return console_kit_check_active_session_change(info
);
339 char *session_info_session_for_pid(struct session_info
*info
, uint32_t pid
)
342 DBusMessage
*message
= NULL
;
343 DBusMessage
*reply
= NULL
;
344 DBusMessageIter args
;
350 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
351 OBJ_PATH_CONSOLE_KIT_MANAGER
,
352 INTERFACE_CONSOLE_KIT_MANAGER
,
353 "GetSessionForUnixProcess");
354 if (message
== NULL
) {
355 syslog(LOG_ERR
, "Unable to create dbus message");
359 dbus_message_iter_init_append(message
, &args
);
360 if (!dbus_message_iter_append_basic(&args
, DBUS_TYPE_UINT32
, &pid
)) {
361 syslog(LOG_ERR
, "Unable to append dbus message args");
365 dbus_error_init(&error
);
366 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
370 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
371 if (dbus_error_is_set(&error
)) {
372 syslog(LOG_ERR
, "GetSessionForUnixProcess failed: %s",
374 dbus_error_free(&error
);
376 syslog(LOG_ERR
, "GetSessionForUnixProces failed");
380 dbus_error_init(&error
);
381 if (!dbus_message_get_args(reply
,
383 DBUS_TYPE_OBJECT_PATH
, &ssid
,
384 DBUS_TYPE_INVALID
)) {
385 if (dbus_error_is_set(&error
)) {
386 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
387 dbus_error_free(&error
);
389 syslog(LOG_ERR
, "error getting ssid from reply");
398 dbus_message_unref(reply
);
401 if (message
!= NULL
) {
402 dbus_message_unref(message
);
408 static char *console_kit_check_active_session_change(struct session_info
*info
)
410 si_dbus_read_signals(info
);
412 syslog(LOG_DEBUG
, "(console-kit) active-session: '%s'",
413 (info
->active_session
? info
->active_session
: "None"));
415 return info
->active_session
;