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>
30 static int property_get_id(
33 const char *interface,
35 sd_bus_message *reply,
37 sd_bus_error *error) {
39 Machine *m = userdata;
46 r = sd_bus_message_append_array(reply, 'y', &m->id, 16);
53 static int property_get_state(
56 const char *interface,
58 sd_bus_message *reply,
60 sd_bus_error *error) {
62 Machine *m = userdata;
70 state = machine_state_to_string(machine_get_state(m));
72 r = sd_bus_message_append_basic(reply, 's', state);
79 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
81 static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
82 Machine *m = userdata;
93 return sd_bus_reply_method_return(message, NULL);
96 static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
97 Machine *m = userdata;
107 r = sd_bus_message_read(message, "si", &swho, &signo);
114 who = kill_who_from_string(swho);
116 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
119 if (signo <= 0 || signo >= _NSIG)
120 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
122 r = machine_kill(m, who, signo);
126 return sd_bus_reply_method_return(message, NULL);
129 const sd_bus_vtable machine_vtable[] = {
130 SD_BUS_VTABLE_START(0),
131 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
132 SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
133 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
134 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
135 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, scope), SD_BUS_VTABLE_PROPERTY_CONST),
136 SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
137 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
138 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
139 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
140 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
141 SD_BUS_METHOD("Kill", "si", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
145 int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
146 Manager *m = userdata;
156 if (streq(path, "/org/freedesktop/machine1/machine/self")) {
157 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
158 sd_bus_message *message;
161 message = sd_bus_get_current(bus);
165 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
169 r = sd_bus_creds_get_pid(creds, &pid);
173 r = manager_get_machine_by_pid(m, pid, &machine);
177 _cleanup_free_ char *e = NULL;
180 p = startswith(path, "/org/freedesktop/machine1/machine/");
184 e = sd_bus_label_unescape(p);
188 machine = hashmap_get(m->machines, e);
197 char *machine_bus_path(Machine *m) {
198 _cleanup_free_ char *e = NULL;
202 e = sd_bus_label_escape(m->name);
206 return strappend("/org/freedesktop/machine1/machine/", e);
209 int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
210 _cleanup_strv_free_ char **l = NULL;
211 Machine *machine = NULL;
212 Manager *m = userdata;
220 HASHMAP_FOREACH(machine, m->machines, i) {
223 p = machine_bus_path(machine);
227 r = strv_push(&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);