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
;
37 static char *console_kit_get_first_seat(struct session_info
*ck
);
38 static char *console_kit_check_active_session_change(struct session_info
*ck
);
40 struct session_info
*session_info_create(int verbose
)
42 struct session_info
*ck
;
46 ck
= calloc(1, sizeof(*ck
));
50 dbus_error_init(&error
);
51 ck
->connection
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
52 if (ck
->connection
== NULL
|| dbus_error_is_set(&error
)) {
53 if (dbus_error_is_set(&error
)) {
54 syslog(LOG_ERR
, "Unable to connect to system bus: %s",
56 dbus_error_free(&error
);
58 syslog(LOG_ERR
, "Unable to connect to system bus");
63 if (!dbus_connection_get_unix_fd(ck
->connection
, &ck
->fd
)) {
64 syslog(LOG_ERR
, "Unable to get connection fd");
65 session_info_destroy(ck
);
69 if (!console_kit_get_first_seat(ck
)) {
70 session_info_destroy(ck
);
74 /* Register for active session changes */
75 snprintf(match
, sizeof(match
),
76 "type='signal',interface='org.freedesktop.ConsoleKit.Seat',"
77 "path='%s',member='ActiveSessionChanged'", ck
->seat
);
78 dbus_error_init(&error
);
79 dbus_bus_add_match(ck
->connection
, match
, &error
);
80 if (dbus_error_is_set(&error
)) {
81 syslog(LOG_ERR
, "Match Error (%s)", error
.message
);
82 session_info_destroy(ck
);
89 void session_info_destroy(struct session_info
*ck
)
94 dbus_connection_close(ck
->connection
);
96 free(ck
->active_session
);
100 int session_info_get_fd(struct session_info
*ck
)
105 static char *console_kit_get_first_seat(struct session_info
*ck
)
108 DBusMessage
*message
= NULL
;
109 DBusMessage
*reply
= NULL
;
110 DBusMessageIter iter
, subiter
;
114 message
= dbus_message_new_method_call("org.freedesktop.ConsoleKit",
115 "/org/freedesktop/ConsoleKit/Manager",
116 "org.freedesktop.ConsoleKit.Manager",
118 if (message
== NULL
) {
119 syslog(LOG_ERR
, "Unable to create dbus message");
123 dbus_error_init(&error
);
124 reply
= dbus_connection_send_with_reply_and_block(ck
->connection
,
128 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
129 if (dbus_error_is_set(&error
)) {
130 syslog(LOG_ERR
, "GetSeats failed: %s", error
.message
);
131 dbus_error_free(&error
);
133 syslog(LOG_ERR
, "GetSeats failed");
137 dbus_message_iter_init(reply
, &iter
);
138 type
= dbus_message_iter_get_arg_type(&iter
);
139 if (type
!= DBUS_TYPE_ARRAY
) {
141 "expected an array return value, got a '%c' instead", type
);
145 dbus_message_iter_recurse(&iter
, &subiter
);
146 type
= dbus_message_iter_get_arg_type(&subiter
);
147 if (type
!= DBUS_TYPE_OBJECT_PATH
) {
149 "expected an object path element, got a '%c' instead", type
);
153 dbus_message_iter_get_basic(&subiter
, &seat
);
154 ck
->seat
= strdup(seat
);
158 dbus_message_unref(reply
);
161 if (message
!= NULL
) {
162 dbus_message_unref(message
);
168 const char *session_info_get_active_session(struct session_info
*ck
)
171 DBusMessage
*message
= NULL
;
172 DBusMessage
*reply
= NULL
;
173 char *session
= NULL
;
178 if (ck
->active_session
)
179 return console_kit_check_active_session_change(ck
);
181 message
= dbus_message_new_method_call("org.freedesktop.ConsoleKit",
183 "org.freedesktop.ConsoleKit.Seat",
185 if (message
== NULL
) {
186 syslog(LOG_ERR
, "Unable to create dbus message");
190 dbus_error_init(&error
);
191 reply
= dbus_connection_send_with_reply_and_block(ck
->connection
,
195 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
196 if (dbus_error_is_set(&error
)) {
197 syslog(LOG_ERR
, "GetActiveSession failed: %s", error
.message
);
198 dbus_error_free(&error
);
200 syslog(LOG_ERR
, "GetActiveSession failed");
204 dbus_error_init(&error
);
205 if (!dbus_message_get_args(reply
,
207 DBUS_TYPE_OBJECT_PATH
, &session
,
208 DBUS_TYPE_INVALID
)) {
209 if (dbus_error_is_set(&error
)) {
210 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
211 dbus_error_free(&error
);
213 syslog(LOG_ERR
, "error getting ssid from reply");
218 ck
->active_session
= strdup(session
);
222 dbus_message_unref(reply
);
225 if (message
!= NULL
) {
226 dbus_message_unref(message
);
229 /* In case the session was changed while we were running */
230 return console_kit_check_active_session_change(ck
);
233 char *session_info_session_for_pid(struct session_info
*ck
, uint32_t pid
)
236 DBusMessage
*message
= NULL
;
237 DBusMessage
*reply
= NULL
;
238 DBusMessageIter args
;
244 message
= dbus_message_new_method_call("org.freedesktop.ConsoleKit",
245 "/org/freedesktop/ConsoleKit/Manager",
246 "org.freedesktop.ConsoleKit.Manager",
247 "GetSessionForUnixProcess");
248 if (message
== NULL
) {
249 syslog(LOG_ERR
, "Unable to create dbus message");
253 dbus_message_iter_init_append(message
, &args
);
254 if (!dbus_message_iter_append_basic(&args
, DBUS_TYPE_UINT32
, &pid
)) {
255 syslog(LOG_ERR
, "Unable to append dbus message args");
259 dbus_error_init(&error
);
260 reply
= dbus_connection_send_with_reply_and_block(ck
->connection
,
264 if (reply
== NULL
|| dbus_error_is_set(&error
)) {
265 if (dbus_error_is_set(&error
)) {
266 syslog(LOG_ERR
, "GetSessionForUnixProcess failed: %s",
268 dbus_error_free(&error
);
270 syslog(LOG_ERR
, "GetSessionForUnixProces failed");
274 dbus_error_init(&error
);
275 if (!dbus_message_get_args(reply
,
277 DBUS_TYPE_OBJECT_PATH
, &ssid
,
278 DBUS_TYPE_INVALID
)) {
279 if (dbus_error_is_set(&error
)) {
280 syslog(LOG_ERR
, "error get ssid from reply: %s", error
.message
);
281 dbus_error_free(&error
);
283 syslog(LOG_ERR
, "error getting ssid from reply");
292 dbus_message_unref(reply
);
295 if (message
!= NULL
) {
296 dbus_message_unref(message
);
302 static char *console_kit_check_active_session_change(struct session_info
*ck
)
304 DBusMessage
*message
= NULL
;
305 DBusMessageIter iter
;
309 /* non blocking read of the next available message */
310 dbus_connection_read_write(ck
->connection
, 0);
311 while ((message
= dbus_connection_pop_message(ck
->connection
))) {
312 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
) {
313 const char *member
= dbus_message_get_member (message
);
314 if (!strcmp(member
, "NameAcquired")) {
315 dbus_message_unref(message
);
318 if (strcmp(member
, "ActiveSessionChanged")) {
319 syslog(LOG_ERR
, "unexpected signal member: %s", member
);
320 dbus_message_unref(message
);
324 syslog(LOG_ERR
, "received non signal message!");
325 dbus_message_unref(message
);
329 free(ck
->active_session
);
330 ck
->active_session
= NULL
;
332 dbus_message_iter_init(message
, &iter
);
333 type
= dbus_message_iter_get_arg_type(&iter
);
334 /* Session should be an object path, but there is a bug in
335 ConsoleKit where it sends a string rather then an object_path
336 accept object_path too in case the bug ever gets fixed */
337 if (type
!= DBUS_TYPE_STRING
&& type
!= DBUS_TYPE_OBJECT_PATH
) {
339 "ActiveSessionChanged message has unexpected type: '%c'",
341 dbus_message_unref(message
);
345 dbus_message_iter_get_basic(&iter
, &session
);
346 ck
->active_session
= strdup(session
);
347 dbus_message_unref(message
);
349 /* non blocking read of the next available message */
350 dbus_connection_read_write(ck
->connection
, 0);
353 return ck
->active_session
;