Systemd/src/login/logind-seat-dbus.c

476 lines
14 KiB
C
Raw Normal View History

2011-05-26 02:21:16 +02:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
2011-05-26 02:21:16 +02:00
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
2011-05-26 02:21:16 +02:00
You should have received a copy of the GNU Lesser General Public License
2011-05-26 02:21:16 +02:00
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
2011-06-17 15:59:18 +02:00
#include <string.h>
2011-05-26 02:21:16 +02:00
#include "bus-common-errors.h"
#include "bus-label.h"
#include "bus-util.h"
2011-05-26 02:21:16 +02:00
#include "logind-seat.h"
#include "logind.h"
#include "strv.h"
#include "user-util.h"
#include "util.h"
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
static int property_get_active_session(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
_cleanup_free_ char *p = NULL;
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
assert(bus);
assert(reply);
2011-05-26 02:21:16 +02:00
assert(s);
2013-11-05 01:10:21 +01:00
p = s->active ? session_bus_path(s->active) : strdup("/");
if (!p)
2011-05-26 02:21:16 +02:00
return -ENOMEM;
2013-11-05 01:10:21 +01:00
return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
}
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
static int property_get_can_multi_session(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
assert(bus);
assert(reply);
assert(s);
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
2011-05-26 02:21:16 +02:00
}
2013-11-05 01:10:21 +01:00
static int property_get_can_tty(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
assert(bus);
assert(reply);
assert(s);
return sd_bus_message_append(reply, "b", seat_can_tty(s));
}
static int property_get_can_graphical(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
assert(bus);
assert(reply);
assert(s);
return sd_bus_message_append(reply, "b", seat_can_graphical(s));
2013-11-05 01:10:21 +01:00
}
static int property_get_sessions(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
2011-05-26 02:21:16 +02:00
Session *session;
2013-11-05 01:10:21 +01:00
int r;
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
assert(bus);
assert(reply);
2011-05-26 02:21:16 +02:00
assert(s);
2013-11-05 01:10:21 +01:00
r = sd_bus_message_open_container(reply, 'a', "(so)");
if (r < 0)
return r;
2011-05-26 02:21:16 +02:00
LIST_FOREACH(sessions_by_seat, session, s->sessions) {
_cleanup_free_ char *p = NULL;
2011-05-26 02:21:16 +02:00
p = session_bus_path(session);
if (!p)
return -ENOMEM;
2013-11-05 01:10:21 +01:00
r = sd_bus_message_append(reply, "(so)", session->id, p);
if (r < 0)
return r;
2011-05-26 02:21:16 +02:00
}
2013-11-05 01:10:21 +01:00
r = sd_bus_message_close_container(reply);
if (r < 0)
return r;
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
return 1;
2011-05-26 02:21:16 +02:00
}
2013-11-05 01:10:21 +01:00
static int property_get_idle_hint(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
2013-11-05 01:10:21 +01:00
assert(bus);
assert(reply);
assert(s);
2013-11-05 01:10:21 +01:00
return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
}
2013-11-05 01:10:21 +01:00
static int property_get_idle_since_hint(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
dual_timestamp t;
uint64_t u;
int r;
2013-11-05 01:10:21 +01:00
assert(bus);
assert(reply);
assert(s);
2013-11-05 01:10:21 +01:00
r = seat_get_idle_hint(s, &t);
if (r < 0)
return r;
2013-11-05 01:10:21 +01:00
u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
2013-11-05 01:10:21 +01:00
return sd_bus_message_append(reply, "t", u);
}
int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
int r;
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
assert(message);
2011-06-17 15:59:18 +02:00
assert(s);
r = bus_verify_polkit_async(
message,
CAP_KILL,
"org.freedesktop.login1.manage",
NULL,
false,
UID_INVALID,
&s->manager->polkit_registry,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* Will call us back */
r = seat_stop_sessions(s, true);
2013-11-05 01:10:21 +01:00
if (r < 0)
return r;
2011-06-17 15:59:18 +02:00
return sd_bus_reply_method_return(message, NULL);
2011-06-17 15:59:18 +02:00
}
static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Seat *s = userdata;
const char *name;
Session *session;
int r;
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
assert(message);
2011-06-17 15:59:18 +02:00
assert(s);
2013-11-05 01:10:21 +01:00
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
session = hashmap_get(s->manager->sessions, name);
if (!session)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
if (session->seat != s)
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
r = session_activate(session);
if (r < 0)
return r;
2011-05-26 02:21:16 +02:00
return sd_bus_reply_method_return(message, NULL);
2011-05-26 02:21:16 +02:00
}
static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_error *error) {
logind: introduce session "positions" logind has no concept of session ordering. Sessions have a unique name, some attributes about the capabilities and that's already it. There is currently no stable+total order on sessions. If we use the logind API to switch between sessions, we are faced with an unordered list of sessions we have no clue of. This used to be no problem on seats with VTs or on seats with only a single active session. However, with the introduction of multi-session capability for seats without VTs, we need to find a way to order sessions in a stable way. This patch introduces session "positions". A position is a simple integer assigned to a session which is never changed implicitly (currently, we also don't change it explicitly, but that may be changed someday). For seats with VTs, we force the position to be the same as the VTnr. Without VTs, we simply find the lowest unassigned number and use it as position. If position-assignment fails or if, for any reason, we decide to not assign a position to a session, the position is set to 0 (which is treated as invalid position). During session_load() or if two sessions have the same VTnr, we may end up with two sessions with the same position (this shouldn't happen, but lets be fail-safe in case some other part of the stack fails). This case is dealt with gracefully by ignoring any session but the first session assigned to the position. Thus, session->pos is a hint, seat->positions[i] is the definite position-assignment. Always verify both match in case you need to modify them! Additionally, we introduce SwitchTo(unsigned int) on the seat-dbus-API. You can call it with any integer value != 0 and logind will try to switch to the request position. If you implement a compositor or any other session-controller, you simply watch for ctrl+alt+F1 to F12 and call SwitchTo(Fx). logind will figure a way out deal with this number. For convenience, we also introduce SwitchToNext/Previous(). It should be called on ctrl+alt+Left/Right (like the kernel-console used to support). Note that the public API (SwitchTo*()) is *not* bound to the underlying logic that is implemented now. We don't export "session-positions" on the dbus/C API! They are an implementation detail. Instead, the SwitchTo*() API is supposed to be a hint to let logind choose the session-switching logic. Any foreground session-controller is free to enumerate/order existing sessions according to their needs and call Session.Activate() manually. But the SwitchTo*() API provides a uniform behavior across session-controllers. Background: Session-switching keys depend on the active keymap. The XKB specification provides the XKB_KEY_XF86Switch_VT_1-12 key-symbols which have to be mapped by all keymaps to allow session-switching. It is usually bound to ctrl+alt+Fx but may be set differently. A compositor passes any keyboard input to XKB before passing it to clients. In case a key-press invokes the XKB_KEY_XF86Switch_VT_x action, the keypress is *not* forwarded to clients, but instead a session-switch is scheduled. This actually prevents us from handling these keys outside of the session. If an active compositor has a keymap with a different mapping of these keys, and logind itself tries to catch these combinations, we end up with the key-press sent to the compositor's clients *and* handled by logind. This is *bad* and we must avoid this. The only situation where a background process is allowed to handle key-presses is debugging and emergency-keys. In these cases, we don't care for keymap mismatches and accept the double-event. Another exception is unmapped keys like PowerOff/Suspend (even though this one is controversial).
2013-11-30 11:39:48 +01:00
Seat *s = userdata;
unsigned int to;
int r;
assert(message);
assert(s);
r = sd_bus_message_read(message, "u", &to);
if (r < 0)
return r;
if (to <= 0)
return -EINVAL;
r = seat_switch_to(s, to);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus_error *error) {
logind: introduce session "positions" logind has no concept of session ordering. Sessions have a unique name, some attributes about the capabilities and that's already it. There is currently no stable+total order on sessions. If we use the logind API to switch between sessions, we are faced with an unordered list of sessions we have no clue of. This used to be no problem on seats with VTs or on seats with only a single active session. However, with the introduction of multi-session capability for seats without VTs, we need to find a way to order sessions in a stable way. This patch introduces session "positions". A position is a simple integer assigned to a session which is never changed implicitly (currently, we also don't change it explicitly, but that may be changed someday). For seats with VTs, we force the position to be the same as the VTnr. Without VTs, we simply find the lowest unassigned number and use it as position. If position-assignment fails or if, for any reason, we decide to not assign a position to a session, the position is set to 0 (which is treated as invalid position). During session_load() or if two sessions have the same VTnr, we may end up with two sessions with the same position (this shouldn't happen, but lets be fail-safe in case some other part of the stack fails). This case is dealt with gracefully by ignoring any session but the first session assigned to the position. Thus, session->pos is a hint, seat->positions[i] is the definite position-assignment. Always verify both match in case you need to modify them! Additionally, we introduce SwitchTo(unsigned int) on the seat-dbus-API. You can call it with any integer value != 0 and logind will try to switch to the request position. If you implement a compositor or any other session-controller, you simply watch for ctrl+alt+F1 to F12 and call SwitchTo(Fx). logind will figure a way out deal with this number. For convenience, we also introduce SwitchToNext/Previous(). It should be called on ctrl+alt+Left/Right (like the kernel-console used to support). Note that the public API (SwitchTo*()) is *not* bound to the underlying logic that is implemented now. We don't export "session-positions" on the dbus/C API! They are an implementation detail. Instead, the SwitchTo*() API is supposed to be a hint to let logind choose the session-switching logic. Any foreground session-controller is free to enumerate/order existing sessions according to their needs and call Session.Activate() manually. But the SwitchTo*() API provides a uniform behavior across session-controllers. Background: Session-switching keys depend on the active keymap. The XKB specification provides the XKB_KEY_XF86Switch_VT_1-12 key-symbols which have to be mapped by all keymaps to allow session-switching. It is usually bound to ctrl+alt+Fx but may be set differently. A compositor passes any keyboard input to XKB before passing it to clients. In case a key-press invokes the XKB_KEY_XF86Switch_VT_x action, the keypress is *not* forwarded to clients, but instead a session-switch is scheduled. This actually prevents us from handling these keys outside of the session. If an active compositor has a keymap with a different mapping of these keys, and logind itself tries to catch these combinations, we end up with the key-press sent to the compositor's clients *and* handled by logind. This is *bad* and we must avoid this. The only situation where a background process is allowed to handle key-presses is debugging and emergency-keys. In these cases, we don't care for keymap mismatches and accept the double-event. Another exception is unmapped keys like PowerOff/Suspend (even though this one is controversial).
2013-11-30 11:39:48 +01:00
Seat *s = userdata;
int r;
assert(message);
assert(s);
r = seat_switch_to_next(s);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd_bus_error *error) {
logind: introduce session "positions" logind has no concept of session ordering. Sessions have a unique name, some attributes about the capabilities and that's already it. There is currently no stable+total order on sessions. If we use the logind API to switch between sessions, we are faced with an unordered list of sessions we have no clue of. This used to be no problem on seats with VTs or on seats with only a single active session. However, with the introduction of multi-session capability for seats without VTs, we need to find a way to order sessions in a stable way. This patch introduces session "positions". A position is a simple integer assigned to a session which is never changed implicitly (currently, we also don't change it explicitly, but that may be changed someday). For seats with VTs, we force the position to be the same as the VTnr. Without VTs, we simply find the lowest unassigned number and use it as position. If position-assignment fails or if, for any reason, we decide to not assign a position to a session, the position is set to 0 (which is treated as invalid position). During session_load() or if two sessions have the same VTnr, we may end up with two sessions with the same position (this shouldn't happen, but lets be fail-safe in case some other part of the stack fails). This case is dealt with gracefully by ignoring any session but the first session assigned to the position. Thus, session->pos is a hint, seat->positions[i] is the definite position-assignment. Always verify both match in case you need to modify them! Additionally, we introduce SwitchTo(unsigned int) on the seat-dbus-API. You can call it with any integer value != 0 and logind will try to switch to the request position. If you implement a compositor or any other session-controller, you simply watch for ctrl+alt+F1 to F12 and call SwitchTo(Fx). logind will figure a way out deal with this number. For convenience, we also introduce SwitchToNext/Previous(). It should be called on ctrl+alt+Left/Right (like the kernel-console used to support). Note that the public API (SwitchTo*()) is *not* bound to the underlying logic that is implemented now. We don't export "session-positions" on the dbus/C API! They are an implementation detail. Instead, the SwitchTo*() API is supposed to be a hint to let logind choose the session-switching logic. Any foreground session-controller is free to enumerate/order existing sessions according to their needs and call Session.Activate() manually. But the SwitchTo*() API provides a uniform behavior across session-controllers. Background: Session-switching keys depend on the active keymap. The XKB specification provides the XKB_KEY_XF86Switch_VT_1-12 key-symbols which have to be mapped by all keymaps to allow session-switching. It is usually bound to ctrl+alt+Fx but may be set differently. A compositor passes any keyboard input to XKB before passing it to clients. In case a key-press invokes the XKB_KEY_XF86Switch_VT_x action, the keypress is *not* forwarded to clients, but instead a session-switch is scheduled. This actually prevents us from handling these keys outside of the session. If an active compositor has a keymap with a different mapping of these keys, and logind itself tries to catch these combinations, we end up with the key-press sent to the compositor's clients *and* handled by logind. This is *bad* and we must avoid this. The only situation where a background process is allowed to handle key-presses is debugging and emergency-keys. In these cases, we don't care for keymap mismatches and accept the double-event. Another exception is unmapped keys like PowerOff/Suspend (even though this one is controversial).
2013-11-30 11:39:48 +01:00
Seat *s = userdata;
int r;
assert(message);
assert(s);
r = seat_switch_to_previous(s);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
2013-11-05 01:10:21 +01:00
const sd_bus_vtable seat_vtable[] = {
SD_BUS_VTABLE_START(0),
2011-06-17 15:59:18 +02:00
SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST),
2013-11-05 01:10:21 +01:00
SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2013-11-05 01:10:21 +01:00
SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2011-05-26 02:21:16 +02:00
SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
2013-12-10 17:41:39 +01:00
SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
logind: introduce session "positions" logind has no concept of session ordering. Sessions have a unique name, some attributes about the capabilities and that's already it. There is currently no stable+total order on sessions. If we use the logind API to switch between sessions, we are faced with an unordered list of sessions we have no clue of. This used to be no problem on seats with VTs or on seats with only a single active session. However, with the introduction of multi-session capability for seats without VTs, we need to find a way to order sessions in a stable way. This patch introduces session "positions". A position is a simple integer assigned to a session which is never changed implicitly (currently, we also don't change it explicitly, but that may be changed someday). For seats with VTs, we force the position to be the same as the VTnr. Without VTs, we simply find the lowest unassigned number and use it as position. If position-assignment fails or if, for any reason, we decide to not assign a position to a session, the position is set to 0 (which is treated as invalid position). During session_load() or if two sessions have the same VTnr, we may end up with two sessions with the same position (this shouldn't happen, but lets be fail-safe in case some other part of the stack fails). This case is dealt with gracefully by ignoring any session but the first session assigned to the position. Thus, session->pos is a hint, seat->positions[i] is the definite position-assignment. Always verify both match in case you need to modify them! Additionally, we introduce SwitchTo(unsigned int) on the seat-dbus-API. You can call it with any integer value != 0 and logind will try to switch to the request position. If you implement a compositor or any other session-controller, you simply watch for ctrl+alt+F1 to F12 and call SwitchTo(Fx). logind will figure a way out deal with this number. For convenience, we also introduce SwitchToNext/Previous(). It should be called on ctrl+alt+Left/Right (like the kernel-console used to support). Note that the public API (SwitchTo*()) is *not* bound to the underlying logic that is implemented now. We don't export "session-positions" on the dbus/C API! They are an implementation detail. Instead, the SwitchTo*() API is supposed to be a hint to let logind choose the session-switching logic. Any foreground session-controller is free to enumerate/order existing sessions according to their needs and call Session.Activate() manually. But the SwitchTo*() API provides a uniform behavior across session-controllers. Background: Session-switching keys depend on the active keymap. The XKB specification provides the XKB_KEY_XF86Switch_VT_1-12 key-symbols which have to be mapped by all keymaps to allow session-switching. It is usually bound to ctrl+alt+Fx but may be set differently. A compositor passes any keyboard input to XKB before passing it to clients. In case a key-press invokes the XKB_KEY_XF86Switch_VT_x action, the keypress is *not* forwarded to clients, but instead a session-switch is scheduled. This actually prevents us from handling these keys outside of the session. If an active compositor has a keymap with a different mapping of these keys, and logind itself tries to catch these combinations, we end up with the key-press sent to the compositor's clients *and* handled by logind. This is *bad* and we must avoid this. The only situation where a background process is allowed to handle key-presses is debugging and emergency-keys. In these cases, we don't care for keymap mismatches and accept the double-event. Another exception is unmapped keys like PowerOff/Suspend (even though this one is controversial).
2013-11-30 11:39:48 +01:00
SD_BUS_METHOD("SwitchTo", "u", NULL, method_switch_to, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED),
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
SD_BUS_VTABLE_END
};
2011-06-17 15:59:18 +02:00
int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
Manager *m = userdata;
Seat *seat;
int r;
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
assert(bus);
assert(path);
assert(interface);
assert(found);
assert(m);
2011-06-17 15:59:18 +02:00
if (streq(path, "/org/freedesktop/login1/seat/self")) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
sd_bus_message *message;
Session *session;
const char *name;
2011-06-17 15:59:18 +02:00
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_session(creds, &name);
if (r < 0)
return r;
session = hashmap_get(m->sessions, name);
if (!session)
return 0;
2011-06-17 15:59:18 +02:00
seat = session->seat;
} else {
_cleanup_free_ char *e = NULL;
const char *p;
p = startswith(path, "/org/freedesktop/login1/seat/");
if (!p)
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
seat = hashmap_get(m->seats, e);
}
2011-06-17 15:59:18 +02:00
if (!seat)
return 0;
2013-11-05 01:10:21 +01:00
*found = seat;
return 1;
}
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
char *seat_bus_path(Seat *s) {
_cleanup_free_ char *t = NULL;
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
assert(s);
2011-06-17 15:59:18 +02:00
t = bus_label_escape(s->id);
2013-11-05 01:10:21 +01:00
if (!t)
return NULL;
2011-06-17 15:59:18 +02:00
2013-11-05 01:10:21 +01:00
return strappend("/org/freedesktop/login1/seat/", t);
2011-05-26 02:21:16 +02:00
}
int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
2013-11-05 01:10:21 +01:00
_cleanup_strv_free_ char **l = NULL;
sd_bus_message *message;
2011-05-26 02:21:16 +02:00
Manager *m = userdata;
2013-11-05 01:10:21 +01:00
Seat *seat;
Iterator i;
2011-05-26 02:21:16 +02:00
int r;
2013-11-05 01:10:21 +01:00
assert(bus);
assert(path);
assert(nodes);
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
HASHMAP_FOREACH(seat, m->seats, i) {
char *p;
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
p = seat_bus_path(seat);
if (!p)
return -ENOMEM;
2011-05-26 02:21:16 +02:00
r = strv_consume(&l, p);
if (r < 0)
2013-11-05 01:10:21 +01:00
return r;
2011-05-26 02:21:16 +02:00
}
message = sd_bus_get_current_message(bus);
if (message) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *name;
Session *session;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
if (r >= 0) {
r = sd_bus_creds_get_session(creds, &name);
if (r >= 0) {
session = hashmap_get(m->sessions, name);
if (session && session->seat) {
r = strv_extend(&l, "/org/freedesktop/login1/seat/self");
if (r < 0)
return r;
}
}
}
}
2013-11-05 01:10:21 +01:00
*nodes = l;
l = NULL;
2011-05-26 02:21:16 +02:00
2013-11-05 01:10:21 +01:00
return 1;
2011-05-26 02:21:16 +02:00
}
int seat_send_signal(Seat *s, bool new_seat) {
_cleanup_free_ char *p = NULL;
assert(s);
p = seat_bus_path(s);
if (!p)
return -ENOMEM;
2013-11-05 01:10:21 +01:00
return sd_bus_emit_signal(
s->manager->bus,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
new_seat ? "SeatNew" : "SeatRemoved",
"so", s->id, p);
}
2013-11-05 01:10:21 +01:00
int seat_send_changed(Seat *s, const char *properties, ...) {
_cleanup_free_ char *p = NULL;
2013-11-05 01:10:21 +01:00
char **l;
assert(s);
2011-06-24 19:42:45 +02:00
if (!s->started)
return 0;
p = seat_bus_path(s);
if (!p)
return -ENOMEM;
2013-11-05 01:10:21 +01:00
l = strv_from_stdarg_alloca(properties);
2013-11-05 01:10:21 +01:00
return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
}