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 Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/capability.h>
27 #include "bus-label.h"
31 static int property_get_id(
34 const char *interface
,
36 sd_bus_message
*reply
,
38 sd_bus_error
*error
) {
40 Machine
*m
= userdata
;
47 r
= sd_bus_message_append_array(reply
, 'y', &m
->id
, 16);
54 static int property_get_state(
57 const char *interface
,
59 sd_bus_message
*reply
,
61 sd_bus_error
*error
) {
63 Machine
*m
= userdata
;
71 state
= machine_state_to_string(machine_get_state(m
));
73 r
= sd_bus_message_append_basic(reply
, 's', state
);
80 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class
, machine_class
, MachineClass
);
82 static int method_terminate(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
83 Machine
*m
= userdata
;
94 return sd_bus_reply_method_return(message
, NULL
);
97 static int method_kill(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
98 Machine
*m
= userdata
;
108 r
= sd_bus_message_read(message
, "si", &swho
, &signo
);
115 who
= kill_who_from_string(swho
);
117 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid kill parameter '%s'", swho
);
120 if (signo
<= 0 || signo
>= _NSIG
)
121 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid signal %i", signo
);
123 r
= machine_kill(m
, who
, signo
);
127 return sd_bus_reply_method_return(message
, NULL
);
130 const sd_bus_vtable machine_vtable
[] = {
131 SD_BUS_VTABLE_START(0),
132 SD_BUS_PROPERTY("Name", "s", NULL
, offsetof(Machine
, name
), SD_BUS_VTABLE_PROPERTY_CONST
),
133 SD_BUS_PROPERTY("Id", "ay", property_get_id
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
134 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine
, timestamp
), SD_BUS_VTABLE_PROPERTY_CONST
),
135 SD_BUS_PROPERTY("Service", "s", NULL
, offsetof(Machine
, service
), SD_BUS_VTABLE_PROPERTY_CONST
),
136 SD_BUS_PROPERTY("Unit", "s", NULL
, offsetof(Machine
, unit
), SD_BUS_VTABLE_PROPERTY_CONST
),
137 SD_BUS_PROPERTY("Scope", "s", NULL
, offsetof(Machine
, unit
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
138 SD_BUS_PROPERTY("Leader", "u", NULL
, offsetof(Machine
, leader
), SD_BUS_VTABLE_PROPERTY_CONST
),
139 SD_BUS_PROPERTY("Class", "s", property_get_class
, offsetof(Machine
, class), SD_BUS_VTABLE_PROPERTY_CONST
),
140 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(Machine
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
141 SD_BUS_PROPERTY("State", "s", property_get_state
, 0, 0),
142 SD_BUS_METHOD("Terminate", NULL
, NULL
, method_terminate
, SD_BUS_VTABLE_CAPABILITY(CAP_KILL
)),
143 SD_BUS_METHOD("Kill", "si", NULL
, method_kill
, SD_BUS_VTABLE_CAPABILITY(CAP_KILL
)),
147 int machine_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
148 Manager
*m
= userdata
;
158 if (streq(path
, "/org/freedesktop/machine1/machine/self")) {
159 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
160 sd_bus_message
*message
;
163 message
= sd_bus_get_current(bus
);
167 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
171 r
= sd_bus_creds_get_pid(creds
, &pid
);
175 r
= manager_get_machine_by_pid(m
, pid
, &machine
);
179 _cleanup_free_
char *e
= NULL
;
182 p
= startswith(path
, "/org/freedesktop/machine1/machine/");
186 e
= bus_label_unescape(p
);
190 machine
= hashmap_get(m
->machines
, e
);
199 char *machine_bus_path(Machine
*m
) {
200 _cleanup_free_
char *e
= NULL
;
204 e
= bus_label_escape(m
->name
);
208 return strappend("/org/freedesktop/machine1/machine/", e
);
211 int machine_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
212 _cleanup_strv_free_
char **l
= NULL
;
213 Machine
*machine
= NULL
;
214 Manager
*m
= userdata
;
222 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
225 p
= machine_bus_path(machine
);
229 r
= strv_consume(&l
, p
);
240 int machine_send_signal(Machine
*m
, bool new_machine
) {
241 _cleanup_free_
char *p
= NULL
;
245 p
= machine_bus_path(m
);
249 return sd_bus_emit_signal(
251 "/org/freedesktop/machine1",
252 "org.freedesktop.machine1.Manager",
253 new_machine
? "MachineNew" : "MachineRemoved",
257 int machine_send_create_reply(Machine
*m
, sd_bus_error
*error
) {
258 _cleanup_bus_message_unref_ sd_bus_message
*c
= NULL
;
259 _cleanup_free_
char *p
= NULL
;
263 if (!m
->create_message
)
266 c
= m
->create_message
;
267 m
->create_message
= NULL
;
270 return sd_bus_reply_method_error(c
, error
);
272 /* Update the machine state file before we notify the client
273 * about the result. */
276 p
= machine_bus_path(m
);
280 return sd_bus_reply_method_return(c
, "o", p
);