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("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST),
136 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
137 SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
138 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
139 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
140 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
141 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
142 SD_BUS_METHOD("Kill", "si", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
146 int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
147 Manager *m = userdata;
157 if (streq(path, "/org/freedesktop/machine1/machine/self")) {
158 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
159 sd_bus_message *message;
162 message = sd_bus_get_current(bus);
166 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
170 r = sd_bus_creds_get_pid(creds, &pid);
174 r = manager_get_machine_by_pid(m, pid, &machine);
178 _cleanup_free_ char *e = NULL;
181 p = startswith(path, "/org/freedesktop/machine1/machine/");
185 e = sd_bus_label_unescape(p);
189 machine = hashmap_get(m->machines, e);
198 char *machine_bus_path(Machine *m) {
199 _cleanup_free_ char *e = NULL;
203 e = sd_bus_label_escape(m->name);
207 return strappend("/org/freedesktop/machine1/machine/", e);
210 int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
211 _cleanup_strv_free_ char **l = NULL;
212 Machine *machine = NULL;
213 Manager *m = userdata;
221 HASHMAP_FOREACH(machine, m->machines, i) {
224 p = machine_bus_path(machine);
228 r = strv_consume(&l, p);
239 int machine_send_signal(Machine *m, bool new_machine) {
240 _cleanup_free_ char *p = NULL;
244 p = machine_bus_path(m);
248 return sd_bus_emit_signal(
250 "/org/freedesktop/machine1",
251 "org.freedesktop.machine1.Manager",
252 new_machine ? "MachineNew" : "MachineRemoved",
256 int machine_send_create_reply(Machine *m, sd_bus_error *error) {
257 _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
258 _cleanup_free_ char *p = NULL;
262 if (!m->create_message)
265 c = m->create_message;
266 m->create_message = NULL;
269 return sd_bus_reply_method_error(c, error);
271 /* Update the machine state file before we notify the client
272 * about the result. */
275 p = machine_bus_path(m);
279 return sd_bus_reply_method_return(c, "o", p);