1 /* systemd-login.c vdagentd libsystemd-login integration code
3 Copyright 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"
27 #include <systemd/sd-login.h>
28 #include <dbus/dbus.h>
32 sd_login_monitor
*mon
;
35 DBusConnection
*system_connection
;
36 char *match_session_signals
;
38 gboolean session_is_locked
;
39 gboolean session_locked_hint
;
42 #define LOGIND_INTERFACE "org.freedesktop.login1"
44 #define LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session"
45 #define LOGIND_SESSION_OBJ_TEMPLATE "/org/freedesktop/login1/session/_3%s"
47 #define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
49 #define SESSION_SIGNAL_LOCK "Lock"
50 #define SESSION_SIGNAL_UNLOCK "Unlock"
52 #define SESSION_PROP_LOCKED_HINT "LockedHint"
55 static DBusConnection
*si_dbus_get_system_bus(void)
57 DBusConnection
*connection
;
60 dbus_error_init(&error
);
61 connection
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
62 if (connection
== NULL
|| dbus_error_is_set(&error
)) {
63 if (dbus_error_is_set(&error
)) {
64 syslog(LOG_WARNING
, "Unable to connect to system bus: %s",
66 dbus_error_free(&error
);
68 syslog(LOG_WARNING
, "Unable to connect to system bus");
75 static void si_dbus_match_remove(struct session_info
*si
)
78 if (si
->dbus
.match_session_signals
== NULL
)
81 dbus_error_init(&error
);
82 dbus_bus_remove_match(si
->dbus
.system_connection
,
83 si
->dbus
.match_session_signals
,
86 g_free(si
->dbus
.match_session_signals
);
87 si
->dbus
.match_session_signals
= NULL
;
90 static void si_dbus_match_rule_update(struct session_info
*si
)
94 if (si
->dbus
.system_connection
== NULL
||
98 si_dbus_match_remove(si
);
100 si
->dbus
.match_session_signals
=
101 g_strdup_printf ("type='signal',interface='%s',path='"
102 LOGIND_SESSION_OBJ_TEMPLATE
"'",
103 LOGIND_SESSION_INTERFACE
,
106 syslog(LOG_DEBUG
, "logind match: %s", si
->dbus
.match_session_signals
);
108 dbus_error_init(&error
);
109 dbus_bus_add_match(si
->dbus
.system_connection
,
110 si
->dbus
.match_session_signals
,
112 if (dbus_error_is_set(&error
)) {
113 syslog(LOG_WARNING
, "Unable to add dbus rule match: %s",
115 dbus_error_free(&error
);
116 g_free(si
->dbus
.match_session_signals
);
117 si
->dbus
.match_session_signals
= NULL
;
122 si_dbus_read_properties(struct session_info
*si
)
124 dbus_bool_t locked_hint
, ret
;
125 DBusMessageIter iter
, iter_variant
;
128 DBusMessage
*message
= NULL
;
129 DBusMessage
*reply
= NULL
;
130 gchar
*session_object
;
131 const gchar
*interface
, *property
;
133 if (si
->session
== NULL
)
136 session_object
= g_strdup_printf(LOGIND_SESSION_OBJ_TEMPLATE
, si
->session
);
137 message
= dbus_message_new_method_call(LOGIND_INTERFACE
,
139 DBUS_PROPERTIES_INTERFACE
,
141 g_free (session_object
);
142 if (message
== NULL
) {
143 syslog(LOG_ERR
, "Unable to create dbus message");
147 interface
= LOGIND_SESSION_INTERFACE
;
148 property
= SESSION_PROP_LOCKED_HINT
;
149 ret
= dbus_message_append_args(message
,
150 DBUS_TYPE_STRING
, &interface
,
151 DBUS_TYPE_STRING
, &property
,
154 syslog(LOG_ERR
, "Unable to request locked-hint");
158 dbus_error_init(&error
);
159 reply
= dbus_connection_send_with_reply_and_block(si
->dbus
.system_connection
,
164 if (dbus_error_is_set(&error
)) {
165 syslog(LOG_ERR
, "Properties.Get failed (locked-hint) due %s", error
.message
);
166 dbus_error_free(&error
);
168 syslog(LOG_ERR
, "Properties.Get failed (locked-hint)");
173 dbus_message_iter_init(reply
, &iter
);
174 type
= dbus_message_iter_get_arg_type(&iter
);
175 if (type
!= DBUS_TYPE_VARIANT
) {
176 syslog(LOG_ERR
, "expected a variant, got a '%c' instead", type
);
180 dbus_message_iter_recurse(&iter
, &iter_variant
);
181 type
= dbus_message_iter_get_arg_type(&iter_variant
);
182 if (type
!= DBUS_TYPE_BOOLEAN
) {
183 syslog(LOG_ERR
, "expected a boolean, got a '%c' instead", type
);
186 dbus_message_iter_get_basic(&iter_variant
, &locked_hint
);
188 si
->session_locked_hint
= (locked_hint
) ? TRUE
: FALSE
;
191 dbus_message_unref(reply
);
194 if (message
!= NULL
) {
195 dbus_message_unref(message
);
200 si_dbus_read_signals(struct session_info
*si
)
202 DBusMessage
*message
= NULL
;
204 dbus_connection_read_write(si
->dbus
.system_connection
, 0);
205 message
= dbus_connection_pop_message(si
->dbus
.system_connection
);
206 while (message
!= NULL
) {
209 member
= dbus_message_get_member (message
);
210 if (g_strcmp0(member
, SESSION_SIGNAL_LOCK
) == 0) {
211 si
->session_is_locked
= TRUE
;
212 } else if (g_strcmp0(member
, SESSION_SIGNAL_UNLOCK
) == 0) {
213 si
->session_is_locked
= FALSE
;
215 if (dbus_message_get_type(message
) != DBUS_MESSAGE_TYPE_SIGNAL
) {
216 syslog(LOG_WARNING
, "(systemd-login) received non signal message");
217 } else if (si
->verbose
) {
218 syslog(LOG_DEBUG
, "(systemd-login) Signal not handled: %s", member
);
222 dbus_message_unref(message
);
223 dbus_connection_read_write(si
->dbus
.system_connection
, 0);
224 message
= dbus_connection_pop_message(si
->dbus
.system_connection
);
228 struct session_info
*session_info_create(int verbose
)
230 struct session_info
*si
;
233 si
= calloc(1, sizeof(*si
));
237 si
->verbose
= verbose
;
238 si
->session_is_locked
= FALSE
;
240 r
= sd_login_monitor_new("session", &si
->mon
);
242 syslog(LOG_ERR
, "Error creating login monitor: %s", strerror(-r
));
247 si
->dbus
.system_connection
= si_dbus_get_system_bus();
251 void session_info_destroy(struct session_info
*si
)
256 si_dbus_match_remove(si
);
257 dbus_connection_close(si
->dbus
.system_connection
);
258 sd_login_monitor_unref(si
->mon
);
263 int session_info_get_fd(struct session_info
*si
)
265 return sd_login_monitor_get_fd(si
->mon
);
268 const char *session_info_get_active_session(struct session_info
*si
)
271 char *old_session
= si
->session
;
274 r
= sd_seat_get_active("seat0", &si
->session
, NULL
);
275 /* ENOENT happens when a seat is switching from one session to another */
276 if (r
< 0 && r
!= -ENOENT
)
277 syslog(LOG_ERR
, "Error getting active session: %s",
280 if (si
->verbose
&& si
->session
&&
281 (!old_session
|| strcmp(old_session
, si
->session
)))
282 syslog(LOG_INFO
, "Active session: %s", si
->session
);
284 sd_login_monitor_flush(si
->mon
);
287 si_dbus_match_rule_update(si
);
291 char *session_info_session_for_pid(struct session_info
*si
, uint32_t pid
)
294 char *session
= NULL
;
296 r
= sd_pid_get_session(pid
, &session
);
298 syslog(LOG_ERR
, "Error getting session for pid %u: %s",
300 else if (si
->verbose
)
301 syslog(LOG_INFO
, "Session for pid %u: %s", pid
, session
);
306 gboolean
session_info_session_is_locked(struct session_info
*si
)
310 g_return_val_if_fail (si
!= NULL
, FALSE
);
312 si_dbus_read_signals(si
);
313 si_dbus_read_properties(si
);
315 locked
= (si
->session_is_locked
|| si
->session_locked_hint
);
317 syslog(LOG_DEBUG
, "(systemd-login) session is locked: %s",
318 locked
? "yes" : "no");
323 /* This function should only be called after session_info_get_active_session
324 * in order to verify if active session belongs to user (non greeter) */
325 gboolean
session_info_is_user(struct session_info
*si
)
330 g_return_val_if_fail (si
!= NULL
, TRUE
);
331 g_return_val_if_fail (si
->session
!= NULL
, TRUE
);
333 if (sd_session_get_class(si
->session
, &class) != 0) {
334 syslog(LOG_WARNING
, "Unable to get class from session: %s",
340 syslog(LOG_DEBUG
, "(systemd-login) class for %s is %s",
343 ret
= (g_strcmp0(class, "user") == 0);