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>
31 DBusConnection
*connection
;
38 #define INTERFACE_CONSOLE_KIT "org.freedesktop.ConsoleKit"
39 #define OBJ_PATH_CONSOLE_KIT "/org/freedesktop/ConsoleKit"
41 #define INTERFACE_CONSOLE_KIT_MANAGER INTERFACE_CONSOLE_KIT ".Manager"
42 #define OBJ_PATH_CONSOLE_KIT_MANAGER OBJ_PATH_CONSOLE_KIT "/Manager"
44 #define INTERFACE_CONSOLE_KIT_SEAT INTERFACE_CONSOLE_KIT ".Seat"
46 static char *console_kit_get_first_seat(struct session_info
*info
);
47 static char *console_kit_check_active_session_change(struct session_info
*info
);
49 struct session_info
*session_info_create(int verbose
)
51 struct session_info
*info
;
55 info
= calloc(1, sizeof(*info
));
59 info
->verbose
= verbose
;
61 dbus_error_init(&error
);
62 info
->connection
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
63 if (info
->connection
== NULL
|| dbus_error_is_set(&error
)) {
64 if (dbus_error_is_set(&error
)) {
65 syslog(LOG_ERR
, "Unable to connect to system bus: %s",
67 dbus_error_free(&error
);
69 syslog(LOG_ERR
, "Unable to connect to system bus");
74 if (!dbus_connection_get_unix_fd(info
->connection
, &info
->fd
)) {
75 syslog(LOG_ERR
, "Unable to get connection fd");
76 session_info_destroy(info
);
80 if (!console_kit_get_first_seat(info
)) {
81 session_info_destroy(info
);
85 /* Register for active session changes */
86 snprintf(match
, sizeof(match
),
87 "type='signal',interface='%s',"
88 "path='%s',member='ActiveSessionChanged'",
89 INTERFACE_CONSOLE_KIT_SEAT
, info
->seat
);
90 dbus_error_init(&error
);
91 dbus_bus_add_match(info
->connection
, match
, &error
);
92 if (dbus_error_is_set(&error
)) {
93 syslog(LOG_ERR
, "Match Error (%s)", error
.message
);
94 session_info_destroy(info
);
101 void session_info_destroy(struct session_info
*info
)
106 dbus_connection_close(info
->connection
);
108 free(info
->active_session
);
112 int session_info_get_fd(struct session_info
*info
)
117 static char *console_kit_get_first_seat(struct session_info
*info
)
120 DBusMessage
*message
= NULL
;
121 DBusMessage
*reply
= NULL
;
122 DBusMessageIter iter
, subiter
;
127 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
128 OBJ_PATH_CONSOLE_KIT_MANAGER
,
129 INTERFACE_CONSOLE_KIT_MANAGER
,
131 if (message
== NULL
) {
132 syslog(LOG_ERR
, "Unable to create dbus message");
136 dbus_error_init(&error
);
137 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
141 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
142 if (dbus_error_is_set(&error
)) {
143 syslog(LOG_ERR
, "GetSeats failed: %s", error
.message
);
144 dbus_error_free(&error
);
146 syslog(LOG_ERR
, "GetSeats failed");
150 dbus_message_iter_init(reply
, &iter
);
151 type
= dbus_message_iter_get_arg_type(&iter
);
152 if (type
!= DBUS_TYPE_ARRAY
) {
154 "expected an array return value, got a '%c' instead", type
);
158 dbus_message_iter_recurse(&iter
, &subiter
);
159 type
= dbus_message_iter_get_arg_type(&subiter
);
160 if (type
!= DBUS_TYPE_OBJECT_PATH
) {
162 "expected an object path element, got a '%c' instead", type
);
166 dbus_message_iter_get_basic(&subiter
, &seat
);
167 info
->seat
= strdup(seat
);
171 dbus_message_unref(reply
);
174 if (message
!= NULL
) {
175 dbus_message_unref(message
);
178 syslog(LOG_INFO
, "(console-kit) seat: %s", info
->seat
);
182 const char *session_info_get_active_session(struct session_info
*info
)
185 DBusMessage
*message
= NULL
;
186 DBusMessage
*reply
= NULL
;
187 char *session
= NULL
;
192 if (info
->active_session
)
193 return console_kit_check_active_session_change(info
);
195 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
197 INTERFACE_CONSOLE_KIT_SEAT
,
199 if (message
== NULL
) {
200 syslog(LOG_ERR
, "Unable to create dbus message");
204 dbus_error_init(&error
);
205 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
209 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
210 if (dbus_error_is_set(&error
)) {
211 syslog(LOG_ERR
, "GetActiveSession failed: %s", error
.message
);
212 dbus_error_free(&error
);
214 syslog(LOG_ERR
, "GetActiveSession failed");
218 dbus_error_init(&error
);
219 if (!dbus_message_get_args(reply
,
221 DBUS_TYPE_OBJECT_PATH
, &session
,
222 DBUS_TYPE_INVALID
)) {
223 if (dbus_error_is_set(&error
)) {
224 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
225 dbus_error_free(&error
);
227 syslog(LOG_ERR
, "error getting ssid from reply");
232 info
->active_session
= strdup(session
);
236 dbus_message_unref(reply
);
239 if (message
!= NULL
) {
240 dbus_message_unref(message
);
243 /* In case the session was changed while we were running */
244 return console_kit_check_active_session_change(info
);
247 char *session_info_session_for_pid(struct session_info
*info
, uint32_t pid
)
250 DBusMessage
*message
= NULL
;
251 DBusMessage
*reply
= NULL
;
252 DBusMessageIter args
;
258 message
= dbus_message_new_method_call(INTERFACE_CONSOLE_KIT
,
259 OBJ_PATH_CONSOLE_KIT_MANAGER
,
260 INTERFACE_CONSOLE_KIT_MANAGER
,
261 "GetSessionForUnixProcess");
262 if (message
== NULL
) {
263 syslog(LOG_ERR
, "Unable to create dbus message");
267 dbus_message_iter_init_append(message
, &args
);
268 if (!dbus_message_iter_append_basic(&args
, DBUS_TYPE_UINT32
, &pid
)) {
269 syslog(LOG_ERR
, "Unable to append dbus message args");
273 dbus_error_init(&error
);
274 reply
= dbus_connection_send_with_reply_and_block(info
->connection
,
278 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
279 if (dbus_error_is_set(&error
)) {
280 syslog(LOG_ERR
, "GetSessionForUnixProcess failed: %s",
282 dbus_error_free(&error
);
284 syslog(LOG_ERR
, "GetSessionForUnixProces failed");
288 dbus_error_init(&error
);
289 if (!dbus_message_get_args(reply
,
291 DBUS_TYPE_OBJECT_PATH
, &ssid
,
292 DBUS_TYPE_INVALID
)) {
293 if (dbus_error_is_set(&error
)) {
294 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
295 dbus_error_free(&error
);
297 syslog(LOG_ERR
, "error getting ssid from reply");
306 dbus_message_unref(reply
);
309 if (message
!= NULL
) {
310 dbus_message_unref(message
);
316 static char *console_kit_check_active_session_change(struct session_info
*info
)
318 DBusMessage
*message
= NULL
;
319 DBusMessageIter iter
;
323 /* non blocking read of the next available message */
324 dbus_connection_read_write(info
->connection
, 0);
325 while ((message
= dbus_connection_pop_message(info
->connection
))) {
326 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
) {
327 const char *member
= dbus_message_get_member (message
);
328 if (!strcmp(member
, "NameAcquired")) {
329 dbus_message_unref(message
);
332 if (strcmp(member
, "ActiveSessionChanged")) {
333 syslog(LOG_ERR
, "unexpected signal member: %s", member
);
334 dbus_message_unref(message
);
338 syslog(LOG_ERR
, "received non signal message!");
339 dbus_message_unref(message
);
343 free(info
->active_session
);
344 info
->active_session
= NULL
;
346 dbus_message_iter_init(message
, &iter
);
347 type
= dbus_message_iter_get_arg_type(&iter
);
348 /* Session should be an object path, but there is a bug in
349 ConsoleKit where it sends a string rather then an object_path
350 accept object_path too in case the bug ever gets fixed */
351 if (type
!= DBUS_TYPE_STRING
&& type
!= DBUS_TYPE_OBJECT_PATH
) {
353 "ActiveSessionChanged message has unexpected type: '%c'",
355 dbus_message_unref(message
);
359 dbus_message_iter_get_basic(&iter
, &session
);
360 if (session
!= NULL
&& session
[0] != '\0') {
361 info
->active_session
= strdup(session
);
363 syslog(LOG_WARNING
, "(console-kit) received invalid session. "
364 "No active-session at the moment");
366 dbus_message_unref(message
);
368 /* non blocking read of the next available message */
369 dbus_connection_read_write(info
->connection
, 0);
373 syslog(LOG_DEBUG
, "(console-kit) active-session: '%s'",
374 (info
->active_session
? info
->active_session
: "None"));
375 return info
->active_session
;