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
;
41 #define LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session"
42 #define LOGIND_SESSION_OBJ_TEMPLATE "'/org/freedesktop/login1/session/_3%s'"
44 #define SESSION_SIGNAL_LOCK "Lock"
45 #define SESSION_SIGNAL_UNLOCK "Unlock"
48 static DBusConnection
*si_dbus_get_system_bus(void)
50 DBusConnection
*connection
;
53 dbus_error_init(&error
);
54 connection
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
);
55 if (connection
== NULL
|| dbus_error_is_set(&error
)) {
56 if (dbus_error_is_set(&error
)) {
57 syslog(LOG_WARNING
, "Unable to connect to system bus: %s",
59 dbus_error_free(&error
);
61 syslog(LOG_WARNING
, "Unable to connect to system bus");
68 static void si_dbus_match_remove(struct session_info
*si
)
71 if (si
->dbus
.match_session_signals
== NULL
)
74 dbus_error_init(&error
);
75 dbus_bus_remove_match(si
->dbus
.system_connection
,
76 si
->dbus
.match_session_signals
,
79 g_free(si
->dbus
.match_session_signals
);
80 si
->dbus
.match_session_signals
= NULL
;
83 static void si_dbus_match_rule_update(struct session_info
*si
)
87 if (si
->dbus
.system_connection
== NULL
||
91 si_dbus_match_remove(si
);
93 si
->dbus
.match_session_signals
=
94 g_strdup_printf ("type='signal',interface='%s',path="
95 LOGIND_SESSION_OBJ_TEMPLATE
,
96 LOGIND_SESSION_INTERFACE
,
99 syslog(LOG_DEBUG
, "logind match: %s", si
->dbus
.match_session_signals
);
101 dbus_error_init(&error
);
102 dbus_bus_add_match(si
->dbus
.system_connection
,
103 si
->dbus
.match_session_signals
,
105 if (dbus_error_is_set(&error
)) {
106 syslog(LOG_WARNING
, "Unable to add dbus rule match: %s",
108 dbus_error_free(&error
);
109 g_free(si
->dbus
.match_session_signals
);
110 si
->dbus
.match_session_signals
= NULL
;
115 si_dbus_read_signals(struct session_info
*si
)
117 DBusMessage
*message
= NULL
;
119 dbus_connection_read_write(si
->dbus
.system_connection
, 0);
120 message
= dbus_connection_pop_message(si
->dbus
.system_connection
);
121 while (message
!= NULL
) {
124 member
= dbus_message_get_member (message
);
125 if (g_strcmp0(member
, SESSION_SIGNAL_LOCK
) == 0) {
126 si
->session_is_locked
= TRUE
;
127 } else if (g_strcmp0(member
, SESSION_SIGNAL_UNLOCK
) == 0) {
128 si
->session_is_locked
= FALSE
;
130 if (dbus_message_get_type(message
) != DBUS_MESSAGE_TYPE_SIGNAL
) {
131 syslog(LOG_WARNING
, "(systemd-login) received non signal message");
132 } else if (si
->verbose
) {
133 syslog(LOG_DEBUG
, "(systemd-login) Signal not handled: %s", member
);
137 dbus_message_unref(message
);
138 dbus_connection_read_write(si
->dbus
.system_connection
, 0);
139 message
= dbus_connection_pop_message(si
->dbus
.system_connection
);
143 struct session_info
*session_info_create(int verbose
)
145 struct session_info
*si
;
148 si
= calloc(1, sizeof(*si
));
152 si
->verbose
= verbose
;
153 si
->session_is_locked
= FALSE
;
155 r
= sd_login_monitor_new("session", &si
->mon
);
157 syslog(LOG_ERR
, "Error creating login monitor: %s", strerror(-r
));
162 si
->dbus
.system_connection
= si_dbus_get_system_bus();
166 void session_info_destroy(struct session_info
*si
)
171 si_dbus_match_remove(si
);
172 dbus_connection_close(si
->dbus
.system_connection
);
173 sd_login_monitor_unref(si
->mon
);
178 int session_info_get_fd(struct session_info
*si
)
180 return sd_login_monitor_get_fd(si
->mon
);
183 const char *session_info_get_active_session(struct session_info
*si
)
186 char *old_session
= si
->session
;
189 r
= sd_seat_get_active("seat0", &si
->session
, NULL
);
190 /* ENOENT happens when a seat is switching from one session to another */
191 if (r
< 0 && r
!= -ENOENT
)
192 syslog(LOG_ERR
, "Error getting active session: %s",
195 if (si
->verbose
&& si
->session
&&
196 (!old_session
|| strcmp(old_session
, si
->session
)))
197 syslog(LOG_INFO
, "Active session: %s", si
->session
);
199 sd_login_monitor_flush(si
->mon
);
202 si_dbus_match_rule_update(si
);
206 char *session_info_session_for_pid(struct session_info
*si
, uint32_t pid
)
209 char *session
= NULL
;
211 r
= sd_pid_get_session(pid
, &session
);
213 syslog(LOG_ERR
, "Error getting session for pid %u: %s",
215 else if (si
->verbose
)
216 syslog(LOG_INFO
, "Session for pid %u: %s", pid
, session
);
221 gboolean
session_info_session_is_locked(struct session_info
*si
)
223 g_return_val_if_fail (si
!= NULL
, FALSE
);
225 /* We could also rely on IdleHint property from Session which seems to work
226 * well in rhel7 but it wasn't working well in my own system (F23). I'm
227 * convinced for now that Lock/Unlock signals should be enough but that
228 * means Lock/Unlock being done by logind. That might take a while.
229 * Check: https://bugzilla.gnome.org/show_bug.cgi?id=764773 */
231 si_dbus_read_signals(si
);
232 return si
->session_is_locked
;