1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "dbus-common.h"
30 #define BUS_MANAGER_INTERFACE \
31 " <interface name=\"org.freedesktop.login1.Manager\">\n" \
32 " <method name=\"GetSession\">\n" \
33 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
34 " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
36 " <method name=\"GetUser\">\n" \
37 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
38 " <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
40 " <method name=\"GetSeat\">\n" \
41 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
42 " <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
44 " <method name=\"ListSessions\">\n" \
45 " <arg name=\"sessions\" type=\"a(susso)\" direction=\"out\"/>\n" \
47 " <method name=\"ListUsers\">\n" \
48 " <arg name=\"users\" type=\"a(uso)\" direction=\"out\"/>\n" \
50 " <method name=\"ListSeats\">\n" \
51 " <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
53 " <method name=\"CreateSession\">\n" \
54 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
55 " <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \
56 " <arg name=\"sevice\" type=\"s\" direction=\"in\"/>\n" \
57 " <arg name=\"type\" type=\"s\" direction=\"in\"/>\n" \
58 " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
59 " <arg name=\"tty\" type=\"s\" direction=\"in\"/>\n" \
60 " <arg name=\"display\" type=\"s\" direction=\"in\"/>\n" \
61 " <arg name=\"remote\" type=\"b\" direction=\"in\"/>\n" \
62 " <arg name=\"remote_user\" type=\"s\" direction=\"in\"/>\n" \
63 " <arg name=\"remote_host\" type=\"s\" direction=\"in\"/>\n" \
64 " <arg name=\"controllers\" type=\"as\" direction=\"in\"/>\n" \
65 " <arg name=\"reset_controllers\" type=\"as\" direction=\"in\"/>\n" \
66 " <arg name=\"kill_processes\" type=\"b\" direction=\"in\"/>\n" \
67 " <arg name=\"id\" type=\"s\" direction=\"out\"/>\n" \
68 " <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
69 " <arg name=\"runtime_path\" type=\"o\" direction=\"out\"/>\n" \
70 " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
72 " <method name=\"ActivateSession\">\n" \
73 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
75 " <method name=\"TerminateSession\">\n" \
76 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
78 " <method name=\"TerminateUser\">\n" \
79 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
81 " <method name=\"TerminateSeat\">\n" \
82 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
84 " <signal name=\"SessionNew\">\n" \
85 " <arg name=\"id\" type=\"s\"/>\n" \
86 " <arg name=\"path\" type=\"o\"/>\n" \
88 " <signal name=\"SessionRemoved\">\n" \
89 " <arg name=\"id\" type=\"s\"/>\n" \
90 " <arg name=\"path\" type=\"o\"/>\n" \
92 " <signal name=\"UserNew\">\n" \
93 " <arg name=\"uid\" type=\"u\"/>\n" \
94 " <arg name=\"path\" type=\"o\"/>\n" \
96 " <signal name=\"UserRemoved\">\n" \
97 " <arg name=\"uid\" type=\"u\"/>\n" \
98 " <arg name=\"path\" type=\"o\"/>\n" \
100 " <signal name=\"SeatNew\">\n" \
101 " <arg name=\"id\" type=\"s\"/>\n" \
102 " <arg name=\"path\" type=\"o\"/>\n" \
104 " <signal name=\"SeatRemoved\">\n" \
105 " <arg name=\"id\" type=\"s\"/>\n" \
106 " <arg name=\"path\" type=\"o\"/>\n" \
108 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
109 " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
110 " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
111 " <property name=\"NAutoVTs\" type=\"u\" access=\"read\"/>\n" \
112 " <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
113 " <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
114 " <property name=\"KillUserProcesses\" type=\"b\" access=\"read\"/>\n" \
115 " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
116 " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
117 " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
120 #define INTROSPECTION_BEGIN \
121 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
123 BUS_MANAGER_INTERFACE \
124 BUS_PROPERTIES_INTERFACE \
126 BUS_INTROSPECTABLE_INTERFACE
128 #define INTROSPECTION_END \
131 #define INTERFACES_LIST \
132 BUS_GENERIC_INTERFACES_LIST \
133 "org.freedesktop.login1.Manager\0"
135 static int bus_manager_append_idle_hint(DBusMessageIter
*i
, const char *property
, void *data
) {
143 b
= manager_get_idle_hint(m
, NULL
) > 0;
144 if (!dbus_message_iter_append_basic(i
, DBUS_TYPE_BOOLEAN
, &b
))
150 static int bus_manager_append_idle_hint_since(DBusMessageIter
*i
, const char *property
, void *data
) {
159 manager_get_idle_hint(m
, &t
);
160 u
= streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
;
162 if (!dbus_message_iter_append_basic(i
, DBUS_TYPE_UINT64
, &u
))
168 static int bus_manager_create_session(Manager
*m
, DBusMessage
*message
, DBusMessage
**_reply
) {
169 Session
*session
= NULL
;
171 const char *type
, *seat
, *tty
, *display
, *remote_user
, *remote_host
, *service
;
172 uint32_t uid
, leader
, audit_id
= 0;
173 dbus_bool_t remote
, kill_processes
;
174 char **controllers
= NULL
, **reset_controllers
= NULL
;
177 DBusMessageIter iter
;
181 int pipe_fds
[2] = { -1, -1 };
182 DBusMessage
*reply
= NULL
;
189 if (!dbus_message_iter_init(message
, &iter
) ||
190 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_UINT32
)
193 dbus_message_iter_get_basic(&iter
, &uid
);
195 if (!dbus_message_iter_next(&iter
) ||
196 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_UINT32
)
199 dbus_message_iter_get_basic(&iter
, &leader
);
202 !dbus_message_iter_next(&iter
) ||
203 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
206 dbus_message_iter_get_basic(&iter
, &service
);
208 if (!dbus_message_iter_next(&iter
) ||
209 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
212 dbus_message_iter_get_basic(&iter
, &type
);
213 t
= session_type_from_string(type
);
216 !dbus_message_iter_next(&iter
) ||
217 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
220 dbus_message_iter_get_basic(&iter
, &seat
);
225 s
= hashmap_get(m
->seats
, seat
);
230 if (!dbus_message_iter_next(&iter
) ||
231 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
234 dbus_message_iter_get_basic(&iter
, &tty
);
236 if (tty_is_vc(tty
)) {
240 else if (s
!= m
->vtconsole
)
243 vtnr
= vtnr_from_tty(tty
);
246 return vtnr
< 0 ? vtnr
: -EINVAL
;
248 } else if (s
== m
->vtconsole
)
251 if (!dbus_message_iter_next(&iter
) ||
252 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
255 dbus_message_iter_get_basic(&iter
, &display
);
257 if (!dbus_message_iter_next(&iter
) ||
258 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_BOOLEAN
)
261 dbus_message_iter_get_basic(&iter
, &remote
);
263 if (!dbus_message_iter_next(&iter
) ||
264 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
267 dbus_message_iter_get_basic(&iter
, &remote_user
);
269 if (!dbus_message_iter_next(&iter
) ||
270 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_STRING
)
273 dbus_message_iter_get_basic(&iter
, &remote_host
);
275 if (!dbus_message_iter_next(&iter
) ||
276 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
277 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRING
)
280 r
= bus_parse_strv_iter(&iter
, &controllers
);
284 if (!dbus_message_iter_next(&iter
) ||
285 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_ARRAY
||
286 dbus_message_iter_get_element_type(&iter
) != DBUS_TYPE_STRING
) {
291 r
= bus_parse_strv_iter(&iter
, &reset_controllers
);
295 if (!dbus_message_iter_next(&iter
) ||
296 dbus_message_iter_get_arg_type(&iter
) != DBUS_TYPE_BOOLEAN
) {
301 dbus_message_iter_get_basic(&iter
, &kill_processes
);
303 r
= manager_add_user_by_uid(m
, uid
, &user
);
307 audit_session_from_pid(leader
, &audit_id
);
310 asprintf(&id
, "%lu", (unsigned long) audit_id
);
312 asprintf(&id
, "c%lu", ++m
->session_counter
);
319 if (hashmap_get(m
->sessions
, id
)) {
324 r
= manager_add_session(m
, user
, id
, &session
);
329 session
->leader
= leader
;
330 session
->audit_id
= audit_id
;
332 session
->remote
= remote
;
333 session
->controllers
= controllers
;
334 session
->reset_controllers
= reset_controllers
;
335 session
->kill_processes
= kill_processes
;
336 session
->vtnr
= vtnr
;
338 controllers
= reset_controllers
= NULL
;
341 session
->tty
= strdup(tty
);
348 if (!isempty(display
)) {
349 session
->display
= strdup(display
);
350 if (!session
->display
) {
356 if (!isempty(remote_user
)) {
357 session
->remote_user
= strdup(remote_user
);
358 if (!session
->remote_user
) {
364 if (!isempty(remote_host
)) {
365 session
->remote_host
= strdup(remote_host
);
366 if (!session
->remote_host
) {
372 if (!isempty(service
)) {
373 session
->service
= strdup(service
);
374 if (!session
->service
) {
380 if (pipe(pipe_fds
) < 0) {
385 session
->pipe_fd
= pipe_fds
[0];
389 r
= seat_attach_session(s
, session
);
394 r
= session_start(session
);
398 reply
= dbus_message_new_method_return(message
);
404 p
= session_bus_path(session
);
410 b
= dbus_message_append_args(
412 DBUS_TYPE_STRING
, &session
->id
,
413 DBUS_TYPE_OBJECT_PATH
, &p
,
414 DBUS_TYPE_STRING
, &session
->user
->runtime_path
,
415 DBUS_TYPE_UNIX_FD
, &pipe_fds
[1],
424 close_nointr_nofail(pipe_fds
[1]);
430 strv_free(controllers
);
431 strv_free(reset_controllers
);
434 session_add_to_gc_queue(session
);
437 user_add_to_gc_queue(user
);
439 close_pipe(pipe_fds
);
442 dbus_message_unref(reply
);
447 static DBusHandlerResult
manager_message_handler(
448 DBusConnection
*connection
,
449 DBusMessage
*message
,
452 Manager
*m
= userdata
;
454 const BusProperty properties
[] = {
455 { "org.freedesktop.login1.Manager", "ControlGroupHierarchy", bus_property_append_string
, "s", m
->cgroup_path
},
456 { "org.freedesktop.login1.Manager", "Controllers", bus_property_append_strv
, "as", m
->controllers
},
457 { "org.freedesktop.login1.Manager", "NAutoVTs", bus_property_append_unsigned
, "u", &m
->n_autovts
},
458 { "org.freedesktop.login1.Manager", "KillOnlyUsers", bus_property_append_strv
, "as", m
->kill_only_users
},
459 { "org.freedesktop.login1.Manager", "KillExcludeUsers", bus_property_append_strv
, "as", m
->kill_exclude_users
},
460 { "org.freedesktop.login1.Manager", "KillUserProcesses", bus_property_append_bool
, "b", &m
->kill_user_processes
},
461 { "org.freedesktop.login1.Manager", "IdleHint", bus_manager_append_idle_hint
, "b", m
},
462 { "org.freedesktop.login1.Manager", "IdleSinceHint", bus_manager_append_idle_hint_since
, "t", m
},
463 { "org.freedesktop.login1.Manager", "IdleSinceHintMonotonic", bus_manager_append_idle_hint_since
, "t", m
},
464 { NULL
, NULL
, NULL
, NULL
, NULL
}
468 DBusMessage
*reply
= NULL
;
475 dbus_error_init(&error
);
477 if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "GetSession")) {
483 if (!dbus_message_get_args(
486 DBUS_TYPE_STRING
, &name
,
488 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
490 session
= hashmap_get(m
->sessions
, name
);
492 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
494 reply
= dbus_message_new_method_return(message
);
498 p
= session_bus_path(session
);
502 b
= dbus_message_append_args(
504 DBUS_TYPE_OBJECT_PATH
, &p
,
511 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "GetUser")) {
517 if (!dbus_message_get_args(
520 DBUS_TYPE_UINT32
, &uid
,
522 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
524 user
= hashmap_get(m
->users
, ULONG_TO_PTR((unsigned long) uid
));
526 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
528 reply
= dbus_message_new_method_return(message
);
532 p
= user_bus_path(user
);
536 b
= dbus_message_append_args(
538 DBUS_TYPE_OBJECT_PATH
, &p
,
545 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "GetSeat")) {
551 if (!dbus_message_get_args(
554 DBUS_TYPE_STRING
, &name
,
556 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
558 seat
= hashmap_get(m
->seats
, name
);
560 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
562 reply
= dbus_message_new_method_return(message
);
566 p
= seat_bus_path(seat
);
570 b
= dbus_message_append_args(
572 DBUS_TYPE_OBJECT_PATH
, &p
,
579 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "ListSessions")) {
583 DBusMessageIter iter
, sub
;
584 const char *empty
= "";
586 reply
= dbus_message_new_method_return(message
);
590 dbus_message_iter_init_append(reply
, &iter
);
592 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "(susso)", &sub
))
595 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
596 DBusMessageIter sub2
;
599 if (!dbus_message_iter_open_container(&sub
, DBUS_TYPE_STRUCT
, NULL
, &sub2
))
602 uid
= session
->user
->uid
;
604 p
= session_bus_path(session
);
608 if (!dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_STRING
, &session
->id
) ||
609 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_UINT32
, &uid
) ||
610 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_STRING
, &session
->user
->name
) ||
611 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_STRING
, session
->seat
? (const char**) &session
->seat
->id
: &empty
) ||
612 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_OBJECT_PATH
, &p
)) {
619 if (!dbus_message_iter_close_container(&sub
, &sub2
))
623 if (!dbus_message_iter_close_container(&iter
, &sub
))
626 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "ListUsers")) {
630 DBusMessageIter iter
, sub
;
632 reply
= dbus_message_new_method_return(message
);
636 dbus_message_iter_init_append(reply
, &iter
);
638 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "(uso)", &sub
))
641 HASHMAP_FOREACH(user
, m
->users
, i
) {
642 DBusMessageIter sub2
;
645 if (!dbus_message_iter_open_container(&sub
, DBUS_TYPE_STRUCT
, NULL
, &sub2
))
650 p
= user_bus_path(user
);
654 if (!dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_UINT32
, &uid
) ||
655 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_STRING
, &user
->name
) ||
656 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_OBJECT_PATH
, &p
)) {
663 if (!dbus_message_iter_close_container(&sub
, &sub2
))
667 if (!dbus_message_iter_close_container(&iter
, &sub
))
670 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "ListSeats")) {
674 DBusMessageIter iter
, sub
;
676 reply
= dbus_message_new_method_return(message
);
680 dbus_message_iter_init_append(reply
, &iter
);
682 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "(so)", &sub
))
685 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
686 DBusMessageIter sub2
;
688 if (!dbus_message_iter_open_container(&sub
, DBUS_TYPE_STRUCT
, NULL
, &sub2
))
691 p
= seat_bus_path(seat
);
695 if (!dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_STRING
, &seat
->id
) ||
696 !dbus_message_iter_append_basic(&sub2
, DBUS_TYPE_OBJECT_PATH
, &p
)) {
703 if (!dbus_message_iter_close_container(&sub
, &sub2
))
707 if (!dbus_message_iter_close_container(&iter
, &sub
))
710 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "CreateSession")) {
712 r
= bus_manager_create_session(m
, message
, &reply
);
717 return bus_send_error_reply(connection
, message
, &error
, r
);
719 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "ActivateSession")) {
723 if (!dbus_message_get_args(
726 DBUS_TYPE_STRING
, &name
,
728 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
730 session
= hashmap_get(m
->sessions
, name
);
732 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
734 r
= session_activate(session
);
736 return bus_send_error_reply(connection
, message
, NULL
, r
);
738 reply
= dbus_message_new_method_return(message
);
742 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "TerminateSession")) {
746 if (!dbus_message_get_args(
749 DBUS_TYPE_STRING
, &name
,
751 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
753 session
= hashmap_get(m
->sessions
, name
);
755 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
757 r
= session_stop(session
);
759 return bus_send_error_reply(connection
, message
, NULL
, r
);
761 reply
= dbus_message_new_method_return(message
);
765 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "TerminateUser")) {
769 if (!dbus_message_get_args(
772 DBUS_TYPE_UINT32
, &uid
,
774 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
776 user
= hashmap_get(m
->users
, ULONG_TO_PTR((unsigned long) uid
));
778 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
782 return bus_send_error_reply(connection
, message
, NULL
, r
);
784 reply
= dbus_message_new_method_return(message
);
788 } else if (dbus_message_is_method_call(message
, "org.freedesktop.login1.Manager", "TerminateSeat")) {
792 if (!dbus_message_get_args(
795 DBUS_TYPE_STRING
, &name
,
797 return bus_send_error_reply(connection
, message
, &error
, -EINVAL
);
799 seat
= hashmap_get(m
->seats
, name
);
801 return bus_send_error_reply(connection
, message
, &error
, -ENOENT
);
803 r
= seat_stop_sessions(seat
);
805 return bus_send_error_reply(connection
, message
, NULL
, r
);
807 reply
= dbus_message_new_method_return(message
);
811 } else if (dbus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", "Introspect")) {
812 char *introspection
= NULL
;
821 if (!(reply
= dbus_message_new_method_return(message
)))
824 /* We roll our own introspection code here, instead of
825 * relying on bus_default_message_handler() because we
826 * need to generate our introspection string
829 if (!(f
= open_memstream(&introspection
, &size
)))
832 fputs(INTROSPECTION_BEGIN
, f
);
834 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
835 p
= bus_path_escape(seat
->id
);
838 fprintf(f
, "<node name=\"seat/%s\"/>", p
);
843 HASHMAP_FOREACH(user
, m
->users
, i
)
844 fprintf(f
, "<node name=\"user/%llu\"/>", (unsigned long long) user
->uid
);
846 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
847 p
= bus_path_escape(session
->id
);
850 fprintf(f
, "<node name=\"session/%s\"/>", p
);
855 fputs(INTROSPECTION_END
, f
);
868 if (!dbus_message_append_args(reply
, DBUS_TYPE_STRING
, &introspection
, DBUS_TYPE_INVALID
)) {
875 return bus_default_message_handler(connection
, message
, NULL
, INTERFACES_LIST
, properties
);
878 if (!dbus_connection_send(connection
, reply
, NULL
))
881 dbus_message_unref(reply
);
884 return DBUS_HANDLER_RESULT_HANDLED
;
888 dbus_message_unref(reply
);
890 dbus_error_free(&error
);
892 return DBUS_HANDLER_RESULT_NEED_MEMORY
;
895 const DBusObjectPathVTable bus_manager_vtable
= {
896 .message_function
= manager_message_handler
899 DBusHandlerResult
bus_message_filter(
900 DBusConnection
*connection
,
901 DBusMessage
*message
,
904 Manager
*m
= userdata
;
911 dbus_error_init(&error
);
913 if (dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
916 if (!dbus_message_get_args(message
, &error
,
917 DBUS_TYPE_STRING
, &cgroup
,
919 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
921 manager_cgroup_notify_empty(m
, cgroup
);
924 dbus_error_free(&error
);
926 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
929 int manager_send_changed(Manager
*manager
, const char *properties
) {
935 m
= bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties
);
939 if (!dbus_connection_send(manager
->bus
, m
, NULL
))
946 dbus_message_unref(m
);