Only install modules-load.d and tmpfiles.d files when using the systemd service
[vd_agent/hramrach.git] / src / console-kit.c
blob759a81e1013ff815a4e5ba9f64692a631cd878a8
1 /* console-kit.c vdagentd ConsoleKit integration code
3 Copyright 2010-2012 Red Hat, Inc.
5 Red Hat Authors:
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>
24 #include <stdbool.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <syslog.h>
30 struct session_info {
31 DBusConnection *connection;
32 int fd;
33 char *seat;
34 char *active_session;
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;
43 DBusError error;
44 char match[1024];
46 ck = calloc(1, sizeof(*ck));
47 if (!ck)
48 return NULL;
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",
55 error.message);
56 dbus_error_free(&error);
57 } else
58 syslog(LOG_ERR, "Unable to connect to system bus");
59 free(ck);
60 return NULL;
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);
66 return NULL;
69 if (!console_kit_get_first_seat(ck)) {
70 session_info_destroy(ck);
71 return NULL;
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);
83 return NULL;
86 return ck;
89 void session_info_destroy(struct session_info *ck)
91 if (!ck)
92 return;
94 dbus_connection_close(ck->connection);
95 free(ck->seat);
96 free(ck->active_session);
97 free(ck);
100 int session_info_get_fd(struct session_info *ck)
102 return ck->fd;
105 static char *console_kit_get_first_seat(struct session_info *ck)
107 DBusError error;
108 DBusMessage *message = NULL;
109 DBusMessage *reply = NULL;
110 DBusMessageIter iter, subiter;
111 int type;
112 char *seat = NULL;
114 message = dbus_message_new_method_call("org.freedesktop.ConsoleKit",
115 "/org/freedesktop/ConsoleKit/Manager",
116 "org.freedesktop.ConsoleKit.Manager",
117 "GetSeats");
118 if (message == NULL) {
119 syslog(LOG_ERR, "Unable to create dbus message");
120 goto exit;
123 dbus_error_init(&error);
124 reply = dbus_connection_send_with_reply_and_block(ck->connection,
125 message,
127 &error);
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);
132 } else
133 syslog(LOG_ERR, "GetSeats failed");
134 goto exit;
137 dbus_message_iter_init(reply, &iter);
138 type = dbus_message_iter_get_arg_type(&iter);
139 if (type != DBUS_TYPE_ARRAY) {
140 syslog(LOG_ERR,
141 "expected an array return value, got a '%c' instead", type);
142 goto exit;
145 dbus_message_iter_recurse(&iter, &subiter);
146 type = dbus_message_iter_get_arg_type(&subiter);
147 if (type != DBUS_TYPE_OBJECT_PATH) {
148 syslog(LOG_ERR,
149 "expected an object path element, got a '%c' instead", type);
150 goto exit;
153 dbus_message_iter_get_basic(&subiter, &seat);
154 ck->seat = strdup(seat);
156 exit:
157 if (reply != NULL) {
158 dbus_message_unref(reply);
161 if (message != NULL) {
162 dbus_message_unref(message);
165 return ck->seat;
168 const char *session_info_get_active_session(struct session_info *ck)
170 DBusError error;
171 DBusMessage *message = NULL;
172 DBusMessage *reply = NULL;
173 char *session = NULL;
175 if (!ck)
176 return 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",
182 ck->seat,
183 "org.freedesktop.ConsoleKit.Seat",
184 "GetActiveSession");
185 if (message == NULL) {
186 syslog(LOG_ERR, "Unable to create dbus message");
187 goto exit;
190 dbus_error_init(&error);
191 reply = dbus_connection_send_with_reply_and_block(ck->connection,
192 message,
194 &error);
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);
199 } else
200 syslog(LOG_ERR, "GetActiveSession failed");
201 goto exit;
204 dbus_error_init(&error);
205 if (!dbus_message_get_args(reply,
206 &error,
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);
212 } else
213 syslog(LOG_ERR, "error getting ssid from reply");
214 session = NULL;
215 goto exit;
218 ck->active_session = strdup(session);
220 exit:
221 if (reply != NULL) {
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)
235 DBusError error;
236 DBusMessage *message = NULL;
237 DBusMessage *reply = NULL;
238 DBusMessageIter args;
239 char *ssid = NULL;
241 if (!ck)
242 return NULL;
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");
250 goto exit;
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");
256 goto exit;
259 dbus_error_init(&error);
260 reply = dbus_connection_send_with_reply_and_block(ck->connection,
261 message,
263 &error);
264 if (reply == NULL || dbus_error_is_set(&error)) {
265 if (dbus_error_is_set(&error)) {
266 syslog(LOG_ERR, "GetSessionForUnixProcess failed: %s",
267 error.message);
268 dbus_error_free(&error);
269 } else
270 syslog(LOG_ERR, "GetSessionForUnixProces failed");
271 goto exit;
274 dbus_error_init(&error);
275 if (!dbus_message_get_args(reply,
276 &error,
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);
282 } else
283 syslog(LOG_ERR, "error getting ssid from reply");
284 ssid = NULL;
285 goto exit;
288 ssid = strdup(ssid);
290 exit:
291 if (reply != NULL) {
292 dbus_message_unref(reply);
295 if (message != NULL) {
296 dbus_message_unref(message);
299 return ssid;
302 static char *console_kit_check_active_session_change(struct session_info *ck)
304 DBusMessage *message = NULL;
305 DBusMessageIter iter;
306 char *session;
307 int type;
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);
316 continue;
318 if (strcmp(member, "ActiveSessionChanged")) {
319 syslog(LOG_ERR, "unexpected signal member: %s", member);
320 dbus_message_unref(message);
321 continue;
323 } else {
324 syslog(LOG_ERR, "received non signal message!");
325 dbus_message_unref(message);
326 continue;
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) {
338 syslog(LOG_ERR,
339 "ActiveSessionChanged message has unexpected type: '%c'",
340 type);
341 dbus_message_unref(message);
342 continue;
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;