1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
6 #include "bus-common-errors.h"
7 #include "bus-get-properties.h"
9 #include "bus-polkit.h"
11 #include "devnum-util.h"
13 #include "logind-brightness.h"
14 #include "logind-dbus.h"
15 #include "logind-polkit.h"
16 #include "logind-seat-dbus.h"
17 #include "logind-session-dbus.h"
18 #include "logind-session-device.h"
19 #include "logind-session.h"
20 #include "logind-user-dbus.h"
22 #include "missing_capability.h"
23 #include "path-util.h"
24 #include "signal-util.h"
26 #include "terminal-util.h"
27 #include "user-util.h"
29 static int property_get_user(
32 const char *interface
,
34 sd_bus_message
*reply
,
36 sd_bus_error
*error
) {
38 _cleanup_free_
char *p
= NULL
;
39 Session
*s
= ASSERT_PTR(userdata
);
44 p
= user_bus_path(s
->user
);
48 return sd_bus_message_append(reply
, "(uo)", (uint32_t) s
->user
->user_record
->uid
, p
);
51 static int property_get_name(
54 const char *interface
,
56 sd_bus_message
*reply
,
58 sd_bus_error
*error
) {
60 Session
*s
= ASSERT_PTR(userdata
);
65 return sd_bus_message_append(reply
, "s", s
->user
->user_record
->user_name
);
68 static int property_get_seat(
71 const char *interface
,
73 sd_bus_message
*reply
,
75 sd_bus_error
*error
) {
77 _cleanup_free_
char *p
= NULL
;
78 Session
*s
= ASSERT_PTR(userdata
);
83 p
= s
->seat
? seat_bus_path(s
->seat
) : strdup("/");
87 return sd_bus_message_append(reply
, "(so)", s
->seat
? s
->seat
->id
: "", p
);
90 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, session_type
, SessionType
);
91 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class
, session_class
, SessionClass
);
92 static BUS_DEFINE_PROPERTY_GET(property_get_active
, "b", Session
, session_is_active
);
93 static BUS_DEFINE_PROPERTY_GET2(property_get_state
, "s", Session
, session_get_state
, session_state_to_string
);
95 static int property_get_idle_hint(
98 const char *interface
,
100 sd_bus_message
*reply
,
102 sd_bus_error
*error
) {
104 Session
*s
= ASSERT_PTR(userdata
);
109 return sd_bus_message_append(reply
, "b", session_get_idle_hint(s
, NULL
) > 0);
112 static int property_get_idle_since_hint(
115 const char *interface
,
116 const char *property
,
117 sd_bus_message
*reply
,
119 sd_bus_error
*error
) {
121 Session
*s
= ASSERT_PTR(userdata
);
122 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
129 r
= session_get_idle_hint(s
, &t
);
133 u
= streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
;
135 return sd_bus_message_append(reply
, "t", u
);
138 static int property_get_locked_hint(
141 const char *interface
,
142 const char *property
,
143 sd_bus_message
*reply
,
145 sd_bus_error
*error
) {
147 Session
*s
= ASSERT_PTR(userdata
);
152 return sd_bus_message_append(reply
, "b", session_get_locked_hint(s
) > 0);
155 int bus_session_method_terminate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
156 Session
*s
= ASSERT_PTR(userdata
);
161 r
= bus_verify_polkit_async_full(
163 "org.freedesktop.login1.manage",
165 s
->user
->user_record
->uid
,
167 &s
->manager
->polkit_registry
,
172 return 1; /* Will call us back */
174 r
= session_stop(s
, /* force = */ true);
178 return sd_bus_reply_method_return(message
, NULL
);
181 int bus_session_method_activate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
182 Session
*s
= ASSERT_PTR(userdata
);
187 r
= check_polkit_chvt(message
, s
->manager
, error
);
191 return 1; /* Will call us back */
193 r
= session_activate(s
);
197 return sd_bus_reply_method_return(message
, NULL
);
200 int bus_session_method_lock(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
201 Session
*s
= ASSERT_PTR(userdata
);
206 r
= bus_verify_polkit_async_full(
208 "org.freedesktop.login1.lock-sessions",
210 s
->user
->user_record
->uid
,
212 &s
->manager
->polkit_registry
,
217 return 1; /* Will call us back */
219 r
= session_send_lock(s
, /* lock= */ strstr(sd_bus_message_get_member(message
), "Lock"));
221 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session does not support lock screen.");
225 return sd_bus_reply_method_return(message
, NULL
);
228 static int method_set_idle_hint(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
229 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
230 Session
*s
= ASSERT_PTR(userdata
);
236 r
= sd_bus_message_read(message
, "b", &b
);
240 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
244 r
= sd_bus_creds_get_euid(creds
, &uid
);
248 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
249 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may set idle hint");
251 r
= session_set_idle_hint(s
, b
);
253 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Idle hint control is not supported on non-graphical and non-user sessions.");
257 return sd_bus_reply_method_return(message
, NULL
);
260 static int method_set_locked_hint(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
261 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
262 Session
*s
= ASSERT_PTR(userdata
);
268 r
= sd_bus_message_read(message
, "b", &b
);
272 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
276 r
= sd_bus_creds_get_euid(creds
, &uid
);
280 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
281 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may set locked hint");
283 r
= session_set_locked_hint(s
, b
);
285 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session does not support lock screen.");
289 return sd_bus_reply_method_return(message
, NULL
);
292 int bus_session_method_kill(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
293 Session
*s
= ASSERT_PTR(userdata
);
301 r
= sd_bus_message_read(message
, "si", &swho
, &signo
);
308 who
= kill_who_from_string(swho
);
310 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid kill parameter '%s'", swho
);
313 if (!SIGNAL_VALID(signo
))
314 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid signal %i", signo
);
316 r
= bus_verify_polkit_async_full(
318 "org.freedesktop.login1.manage",
320 s
->user
->user_record
->uid
,
322 &s
->manager
->polkit_registry
,
327 return 1; /* Will call us back */
329 r
= session_kill(s
, who
, signo
);
333 return sd_bus_reply_method_return(message
, NULL
);
336 static int method_take_control(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
337 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
338 Session
*s
= ASSERT_PTR(userdata
);
344 r
= sd_bus_message_read(message
, "b", &force
);
348 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
352 r
= sd_bus_creds_get_euid(creds
, &uid
);
356 if (uid
!= 0 && (force
|| uid
!= s
->user
->user_record
->uid
))
357 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may take control");
359 r
= session_set_controller(s
, sd_bus_message_get_sender(message
), force
, true);
363 return sd_bus_reply_method_return(message
, NULL
);
366 static int method_release_control(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
367 Session
*s
= ASSERT_PTR(userdata
);
371 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
372 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
374 session_drop_controller(s
);
376 return sd_bus_reply_method_return(message
, NULL
);
379 static int method_set_type(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
380 Session
*s
= ASSERT_PTR(userdata
);
387 r
= sd_bus_message_read(message
, "s", &t
);
391 type
= session_type_from_string(t
);
393 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
394 "Invalid session type '%s'", t
);
396 if (!SESSION_CLASS_CAN_CHANGE_TYPE(s
->class))
397 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session class doesn't support changing type.");
399 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
400 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You must be in control of this session to set type");
402 session_set_type(s
, type
);
404 return sd_bus_reply_method_return(message
, NULL
);
407 static int method_set_class(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
408 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
409 Session
*s
= ASSERT_PTR(userdata
);
417 r
= sd_bus_message_read(message
, "s", &c
);
421 class = session_class_from_string(c
);
423 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
424 "Invalid session class '%s'", c
);
426 /* For now, we'll allow only upgrades user-incomplete → user */
427 if (class != SESSION_USER
)
428 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
429 "Class may only be set to 'user'");
431 if (s
->class == SESSION_USER
) /* No change, shortcut */
432 return sd_bus_reply_method_return(message
, NULL
);
433 if (s
->class != SESSION_USER_INCOMPLETE
)
434 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
435 "Only sessions with class 'user-incomplete' may change class");
437 if (s
->upgrade_message
)
438 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
439 "Set session class operation already in progress");
441 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
445 r
= sd_bus_creds_get_euid(creds
, &uid
);
449 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
450 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may change its class");
452 session_set_class(s
, class);
454 s
->upgrade_message
= sd_bus_message_ref(message
);
456 r
= session_send_upgrade_reply(s
, /* error= */ NULL
);
463 static int method_set_display(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
464 Session
*s
= ASSERT_PTR(userdata
);
470 r
= sd_bus_message_read(message
, "s", &display
);
474 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
475 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You must be in control of this session to set display");
477 if (!SESSION_TYPE_IS_GRAPHICAL(s
->type
))
478 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Setting display is only supported for graphical sessions");
480 r
= session_set_display(s
, display
);
484 return sd_bus_reply_method_return(message
, NULL
);
487 static int method_set_tty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
488 Session
*s
= ASSERT_PTR(userdata
);
490 _cleanup_free_
char *q
= NULL
;
494 r
= sd_bus_message_read(message
, "h", &fd
);
498 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
499 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You must be in control of this session to set tty");
503 flags
= fcntl(fd
, F_GETFL
, 0);
506 if ((flags
& O_ACCMODE
) != O_RDWR
)
508 if (FLAGS_SET(flags
, O_PATH
))
511 r
= getttyname_malloc(fd
, &q
);
515 r
= session_set_tty(s
, q
);
519 return sd_bus_reply_method_return(message
, NULL
);
522 static int method_take_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
523 Session
*s
= ASSERT_PTR(userdata
);
524 uint32_t major
, minor
;
525 _cleanup_(session_device_freep
) SessionDevice
*sd
= NULL
;
531 r
= sd_bus_message_read(message
, "uu", &major
, &minor
);
535 if (!DEVICE_MAJOR_VALID(major
) || !DEVICE_MINOR_VALID(minor
))
536 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Device major/minor is not valid.");
538 if (!SESSION_CLASS_CAN_TAKE_DEVICE(s
->class))
539 return sd_bus_error_set(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Session class doesn't support taking device control.");
541 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
542 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
544 dev
= makedev(major
, minor
);
545 sd
= hashmap_get(s
->devices
, &dev
);
547 /* We don't allow retrieving a device multiple times.
548 * The related ReleaseDevice call is not ref-counted.
549 * The caller should use dup() if it requires more
550 * than one fd (it would be functionally
552 return sd_bus_error_set(error
, BUS_ERROR_DEVICE_IS_TAKEN
, "Device already taken");
554 r
= session_device_new(s
, dev
, true, &sd
);
558 r
= session_device_save(sd
);
562 r
= sd_bus_reply_method_return(message
, "hb", sd
->fd
, !sd
->active
);
572 static int method_release_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
573 Session
*s
= ASSERT_PTR(userdata
);
574 uint32_t major
, minor
;
581 r
= sd_bus_message_read(message
, "uu", &major
, &minor
);
585 if (!DEVICE_MAJOR_VALID(major
) || !DEVICE_MINOR_VALID(minor
))
586 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Device major/minor is not valid.");
588 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
589 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
591 dev
= makedev(major
, minor
);
592 sd
= hashmap_get(s
->devices
, &dev
);
594 return sd_bus_error_set(error
, BUS_ERROR_DEVICE_NOT_TAKEN
, "Device not taken");
596 session_device_free(sd
);
599 return sd_bus_reply_method_return(message
, NULL
);
602 static int method_pause_device_complete(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
603 Session
*s
= ASSERT_PTR(userdata
);
604 uint32_t major
, minor
;
611 r
= sd_bus_message_read(message
, "uu", &major
, &minor
);
615 if (!DEVICE_MAJOR_VALID(major
) || !DEVICE_MINOR_VALID(minor
))
616 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Device major/minor is not valid.");
618 if (!session_is_controller(s
, sd_bus_message_get_sender(message
)))
619 return sd_bus_error_set(error
, BUS_ERROR_NOT_IN_CONTROL
, "You are not in control of this session");
621 dev
= makedev(major
, minor
);
622 sd
= hashmap_get(s
->devices
, &dev
);
624 return sd_bus_error_set(error
, BUS_ERROR_DEVICE_NOT_TAKEN
, "Device not taken");
626 session_device_complete_pause(sd
);
628 return sd_bus_reply_method_return(message
, NULL
);
631 static int method_set_brightness(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
632 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
633 _cleanup_(sd_device_unrefp
) sd_device
*d
= NULL
;
634 const char *subsystem
, *name
, *seat
;
635 Session
*s
= ASSERT_PTR(userdata
);
642 r
= sd_bus_message_read(message
, "ssu", &subsystem
, &name
, &brightness
);
646 if (!STR_IN_SET(subsystem
, "backlight", "leds"))
647 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Subsystem type %s not supported, must be one of 'backlight' or 'leds'.", subsystem
);
648 if (!filename_is_valid(name
))
649 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not a valid device name %s, refusing.", name
);
652 return sd_bus_error_set(error
, BUS_ERROR_NOT_YOUR_DEVICE
, "Your session has no seat, refusing.");
653 if (s
->seat
->active
!= s
)
654 return sd_bus_error_set(error
, BUS_ERROR_NOT_YOUR_DEVICE
, "Session is not in foreground, refusing.");
656 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
660 r
= sd_bus_creds_get_euid(creds
, &uid
);
664 if (uid
!= 0 && uid
!= s
->user
->user_record
->uid
)
665 return sd_bus_error_set(error
, SD_BUS_ERROR_ACCESS_DENIED
, "Only owner of session may change brightness.");
667 r
= sd_device_new_from_subsystem_sysname(&d
, subsystem
, name
);
669 return sd_bus_error_set_errnof(error
, r
, "Failed to open device %s:%s: %m", subsystem
, name
);
671 if (sd_device_get_property_value(d
, "ID_SEAT", &seat
) >= 0 && !streq_ptr(seat
, s
->seat
->id
))
672 return sd_bus_error_setf(error
, BUS_ERROR_NOT_YOUR_DEVICE
, "Device %s:%s does not belong to your seat %s, refusing.", subsystem
, name
, s
->seat
->id
);
674 r
= manager_write_brightness(s
->manager
, d
, brightness
, message
);
681 static int session_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
682 _cleanup_free_
char *e
= NULL
;
683 sd_bus_message
*message
;
684 Manager
*m
= ASSERT_PTR(userdata
);
694 p
= startswith(path
, "/org/freedesktop/login1/session/");
698 e
= bus_label_unescape(p
);
702 message
= sd_bus_get_current_message(bus
);
704 r
= manager_get_session_from_creds(m
, message
, e
, error
, &session
);
706 sd_bus_error_free(error
);
716 char *session_bus_path(Session
*s
) {
717 _cleanup_free_
char *t
= NULL
;
721 t
= bus_label_escape(s
->id
);
725 return strjoin("/org/freedesktop/login1/session/", t
);
728 static int session_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
729 _cleanup_strv_free_
char **l
= NULL
;
730 sd_bus_message
*message
;
731 Manager
*m
= userdata
;
739 HASHMAP_FOREACH(session
, m
->sessions
) {
742 p
= session_bus_path(session
);
746 r
= strv_consume(&l
, p
);
751 message
= sd_bus_get_current_message(bus
);
753 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
755 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
757 bool may_auto
= false;
760 r
= sd_bus_creds_get_session(creds
, &name
);
762 session
= hashmap_get(m
->sessions
, name
);
764 r
= strv_extend(&l
, "/org/freedesktop/login1/session/self");
775 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
779 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
780 may_auto
= user
&& user
->display
;
785 r
= strv_extend(&l
, "/org/freedesktop/login1/session/auto");
792 *nodes
= TAKE_PTR(l
);
796 int session_send_signal(Session
*s
, bool new_session
) {
797 _cleanup_free_
char *p
= NULL
;
801 p
= session_bus_path(s
);
805 return sd_bus_emit_signal(
807 "/org/freedesktop/login1",
808 "org.freedesktop.login1.Manager",
809 new_session
? "SessionNew" : "SessionRemoved",
813 int session_send_changed(Session
*s
, const char *properties
, ...) {
814 _cleanup_free_
char *p
= NULL
;
822 p
= session_bus_path(s
);
826 l
= strv_from_stdarg_alloca(properties
);
828 return sd_bus_emit_properties_changed_strv(s
->manager
->bus
, p
, "org.freedesktop.login1.Session", l
);
831 int session_send_lock(Session
*s
, bool lock
) {
832 _cleanup_free_
char *p
= NULL
;
836 if (!SESSION_CLASS_CAN_LOCK(s
->class))
839 p
= session_bus_path(s
);
843 return sd_bus_emit_signal(
846 "org.freedesktop.login1.Session",
847 lock
? "Lock" : "Unlock",
851 int session_send_lock_all(Manager
*m
, bool lock
) {
857 HASHMAP_FOREACH(session
, m
->sessions
) {
860 if (!SESSION_CLASS_CAN_LOCK(session
->class))
863 k
= session_send_lock(session
, lock
);
871 static bool session_job_pending(Session
*s
) {
875 /* Check if we have some jobs enqueued and not finished yet. Each time we get JobRemoved signal about
876 * relevant units, session_send_create_reply and hence us is called (see match_job_removed).
877 * Note that we don't care about job result here. */
879 return s
->scope_job
||
880 s
->user
->runtime_dir_job
||
881 (SESSION_CLASS_WANTS_SERVICE_MANAGER(s
->class) && s
->user
->service_manager_job
);
884 int session_send_create_reply(Session
*s
, sd_bus_error
*error
) {
885 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*c
= NULL
;
886 _cleanup_close_
int fifo_fd
= -EBADF
;
887 _cleanup_free_
char *p
= NULL
;
891 /* This is called after the session scope and the user service were successfully created, and finishes where
892 * bus_manager_create_session() left off. */
894 if (!s
->create_message
)
897 /* If error occurred, return it immediately. Otherwise let's wait for all jobs to finish before
899 if (!sd_bus_error_is_set(error
) && session_job_pending(s
))
902 c
= TAKE_PTR(s
->create_message
);
904 return sd_bus_reply_method_error(c
, error
);
906 fifo_fd
= session_create_fifo(s
);
910 /* Update the session state file before we notify the client about the result. */
913 p
= session_bus_path(s
);
917 log_debug("Sending reply about created session: "
918 "id=%s object_path=%s uid=%u runtime_path=%s "
919 "session_fd=%d seat=%s vtnr=%u",
922 (uint32_t) s
->user
->user_record
->uid
,
923 s
->user
->runtime_path
,
925 s
->seat
? s
->seat
->id
: "",
928 return sd_bus_reply_method_return(
932 s
->user
->runtime_path
,
934 (uint32_t) s
->user
->user_record
->uid
,
935 s
->seat
? s
->seat
->id
: "",
940 int session_send_upgrade_reply(Session
*s
, sd_bus_error
*error
) {
941 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*c
= NULL
;
944 if (!s
->upgrade_message
)
947 /* See comments in session_send_create_reply */
948 if (!sd_bus_error_is_set(error
) && session_job_pending(s
))
951 c
= TAKE_PTR(s
->upgrade_message
);
953 return sd_bus_reply_method_error(c
, error
);
957 return sd_bus_reply_method_return(c
, NULL
);
960 static const sd_bus_vtable session_vtable
[] = {
961 SD_BUS_VTABLE_START(0),
963 SD_BUS_PROPERTY("Id", "s", NULL
, offsetof(Session
, id
), SD_BUS_VTABLE_PROPERTY_CONST
),
964 SD_BUS_PROPERTY("User", "(uo)", property_get_user
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
965 SD_BUS_PROPERTY("Name", "s", property_get_name
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
966 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session
, timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
967 SD_BUS_PROPERTY("VTNr", "u", NULL
, offsetof(Session
, vtnr
), SD_BUS_VTABLE_PROPERTY_CONST
),
968 SD_BUS_PROPERTY("Seat", "(so)", property_get_seat
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
969 SD_BUS_PROPERTY("TTY", "s", NULL
, offsetof(Session
, tty
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
970 SD_BUS_PROPERTY("Display", "s", NULL
, offsetof(Session
, display
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
971 SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool
, offsetof(Session
, remote
), SD_BUS_VTABLE_PROPERTY_CONST
),
972 SD_BUS_PROPERTY("RemoteHost", "s", NULL
, offsetof(Session
, remote_host
), SD_BUS_VTABLE_PROPERTY_CONST
),
973 SD_BUS_PROPERTY("RemoteUser", "s", NULL
, offsetof(Session
, remote_user
), SD_BUS_VTABLE_PROPERTY_CONST
),
974 SD_BUS_PROPERTY("Service", "s", NULL
, offsetof(Session
, service
), SD_BUS_VTABLE_PROPERTY_CONST
),
975 SD_BUS_PROPERTY("Desktop", "s", NULL
, offsetof(Session
, desktop
), SD_BUS_VTABLE_PROPERTY_CONST
),
976 SD_BUS_PROPERTY("Scope", "s", NULL
, offsetof(Session
, scope
), SD_BUS_VTABLE_PROPERTY_CONST
),
977 SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid
, offsetof(Session
, leader
.pid
), SD_BUS_VTABLE_PROPERTY_CONST
),
978 SD_BUS_PROPERTY("Audit", "u", NULL
, offsetof(Session
, audit_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
979 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Session
, type
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
980 SD_BUS_PROPERTY("Class", "s", property_get_class
, offsetof(Session
, class), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
981 SD_BUS_PROPERTY("Active", "b", property_get_active
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
982 SD_BUS_PROPERTY("State", "s", property_get_state
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
983 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
984 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
985 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
986 SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
988 SD_BUS_METHOD("Terminate",
991 bus_session_method_terminate
,
992 SD_BUS_VTABLE_UNPRIVILEGED
),
993 SD_BUS_METHOD("Activate",
996 bus_session_method_activate
,
997 SD_BUS_VTABLE_UNPRIVILEGED
),
998 SD_BUS_METHOD("Lock",
1001 bus_session_method_lock
,
1002 SD_BUS_VTABLE_UNPRIVILEGED
),
1003 SD_BUS_METHOD("Unlock",
1006 bus_session_method_lock
,
1007 SD_BUS_VTABLE_UNPRIVILEGED
),
1008 SD_BUS_METHOD_WITH_ARGS("SetIdleHint",
1009 SD_BUS_ARGS("b", idle
),
1011 method_set_idle_hint
,
1012 SD_BUS_VTABLE_UNPRIVILEGED
),
1013 SD_BUS_METHOD_WITH_ARGS("SetLockedHint",
1014 SD_BUS_ARGS("b", locked
),
1016 method_set_locked_hint
,
1017 SD_BUS_VTABLE_UNPRIVILEGED
),
1018 SD_BUS_METHOD_WITH_ARGS("Kill",
1019 SD_BUS_ARGS("s", who
, "i", signal_number
),
1021 bus_session_method_kill
,
1022 SD_BUS_VTABLE_UNPRIVILEGED
),
1023 SD_BUS_METHOD_WITH_ARGS("TakeControl",
1024 SD_BUS_ARGS("b", force
),
1026 method_take_control
,
1027 SD_BUS_VTABLE_UNPRIVILEGED
),
1028 SD_BUS_METHOD("ReleaseControl",
1031 method_release_control
,
1032 SD_BUS_VTABLE_UNPRIVILEGED
),
1033 SD_BUS_METHOD_WITH_ARGS("SetType",
1034 SD_BUS_ARGS("s", type
),
1037 SD_BUS_VTABLE_UNPRIVILEGED
),
1038 SD_BUS_METHOD_WITH_ARGS("SetClass",
1039 SD_BUS_ARGS("s", class),
1042 SD_BUS_VTABLE_UNPRIVILEGED
),
1043 SD_BUS_METHOD_WITH_ARGS("SetDisplay",
1044 SD_BUS_ARGS("s", display
),
1047 SD_BUS_VTABLE_UNPRIVILEGED
),
1048 SD_BUS_METHOD_WITH_ARGS("SetTTY",
1049 SD_BUS_ARGS("h", tty_fd
),
1052 SD_BUS_VTABLE_UNPRIVILEGED
),
1053 SD_BUS_METHOD_WITH_ARGS("TakeDevice",
1054 SD_BUS_ARGS("u", major
, "u", minor
),
1055 SD_BUS_RESULT("h", fd
, "b", inactive
),
1057 SD_BUS_VTABLE_UNPRIVILEGED
),
1058 SD_BUS_METHOD_WITH_ARGS("ReleaseDevice",
1059 SD_BUS_ARGS("u", major
, "u", minor
),
1061 method_release_device
,
1062 SD_BUS_VTABLE_UNPRIVILEGED
),
1063 SD_BUS_METHOD_WITH_ARGS("PauseDeviceComplete",
1064 SD_BUS_ARGS("u", major
, "u", minor
),
1066 method_pause_device_complete
,
1067 SD_BUS_VTABLE_UNPRIVILEGED
),
1068 SD_BUS_METHOD_WITH_ARGS("SetBrightness",
1069 SD_BUS_ARGS("s", subsystem
, "s", name
, "u", brightness
),
1071 method_set_brightness
,
1072 SD_BUS_VTABLE_UNPRIVILEGED
),
1074 SD_BUS_SIGNAL_WITH_ARGS("PauseDevice",
1075 SD_BUS_ARGS("u", major
, "u", minor
, "s", type
),
1077 SD_BUS_SIGNAL_WITH_ARGS("ResumeDevice",
1078 SD_BUS_ARGS("u", major
, "u", minor
, "h", fd
),
1080 SD_BUS_SIGNAL("Lock", NULL
, 0),
1081 SD_BUS_SIGNAL("Unlock", NULL
, 0),
1086 const BusObjectImplementation session_object
= {
1087 "/org/freedesktop/login1/session",
1088 "org.freedesktop.login1.Session",
1089 .fallback_vtables
= BUS_FALLBACK_VTABLES({session_vtable
, session_object_find
}),
1090 .node_enumerator
= session_node_enumerator
,