]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/machine/machined-dbus.c
hwdb: update
[thirdparty/systemd.git] / src / machine / machined-dbus.c
CommitLineData
1ee306e1
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
22#include <errno.h>
23#include <string.h>
24#include <unistd.h>
25#include <pwd.h>
adacb957 26#include <sys/capability.h>
1ee306e1 27
c3350683
LP
28#include "sd-id128.h"
29#include "sd-messages.h"
1ee306e1
LP
30#include "strv.h"
31#include "mkdir.h"
32#include "path-util.h"
33#include "special.h"
1ee306e1
LP
34#include "fileio-label.h"
35#include "label.h"
36#include "utf8.h"
37#include "unit-name.h"
c3350683 38#include "bus-util.h"
718db961 39#include "bus-errors.h"
c3350683 40#include "time-util.h"
23c80348 41#include "cgroup-util.h"
c3350683 42#include "machined.h"
1ee306e1 43
ebcf1f97 44static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683
LP
45 _cleanup_free_ char *p = NULL;
46 Manager *m = userdata;
47 Machine *machine;
48 const char *name;
49 int r;
50
51 assert(bus);
52 assert(message);
53 assert(m);
54
55 r = sd_bus_message_read(message, "s", &name);
56 if (r < 0)
ebcf1f97 57 return r;
c3350683
LP
58
59 machine = hashmap_get(m->machines, name);
60 if (!machine)
ebcf1f97 61 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
c3350683
LP
62
63 p = machine_bus_path(machine);
64 if (!p)
ebcf1f97 65 return -ENOMEM;
c3350683 66
df2d202e 67 return sd_bus_reply_method_return(message, "o", p);
c3350683
LP
68}
69
ebcf1f97 70static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683
LP
71 _cleanup_free_ char *p = NULL;
72 Manager *m = userdata;
73 Machine *machine = NULL;
4e724d9c 74 pid_t pid;
c3350683
LP
75 int r;
76
77 assert(bus);
78 assert(message);
79 assert(m);
80
4e724d9c
LP
81 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
82
c3350683
LP
83 r = sd_bus_message_read(message, "u", &pid);
84 if (r < 0)
ebcf1f97 85 return r;
c3350683 86
4e724d9c 87 if (pid == 0) {
5b12334d
LP
88 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
89
90 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
91 if (r < 0)
92 return r;
93
94 r = sd_bus_creds_get_pid(creds, &pid);
4e724d9c 95 if (r < 0)
ebcf1f97 96 return r;
4e724d9c
LP
97 }
98
c3350683
LP
99 r = manager_get_machine_by_pid(m, pid, &machine);
100 if (r < 0)
ebcf1f97 101 return r;
c3350683 102 if (!machine)
de0671ee 103 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
c3350683
LP
104
105 p = machine_bus_path(machine);
106 if (!p)
ebcf1f97 107 return -ENOMEM;
c3350683 108
df2d202e 109 return sd_bus_reply_method_return(message, "o", p);
c3350683
LP
110}
111
ebcf1f97 112static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683
LP
113 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
114 Manager *m = userdata;
115 Machine *machine;
116 Iterator i;
117 int r;
118
119 assert(bus);
120 assert(message);
121 assert(m);
122
df2d202e 123 r = sd_bus_message_new_method_return(message, &reply);
c3350683 124 if (r < 0)
ebcf1f97 125 return sd_bus_error_set_errno(error, r);
c3350683
LP
126
127 r = sd_bus_message_open_container(reply, 'a', "(ssso)");
128 if (r < 0)
ebcf1f97 129 return sd_bus_error_set_errno(error, r);
c3350683
LP
130
131 HASHMAP_FOREACH(machine, m->machines, i) {
132 _cleanup_free_ char *p = NULL;
133
134 p = machine_bus_path(machine);
135 if (!p)
ebcf1f97 136 return -ENOMEM;
c3350683
LP
137
138 r = sd_bus_message_append(reply, "(ssso)",
139 machine->name,
140 strempty(machine_class_to_string(machine->class)),
141 machine->service,
142 p);
143 if (r < 0)
ebcf1f97 144 return sd_bus_error_set_errno(error, r);
c3350683 145 }
1ee306e1 146
c3350683
LP
147 r = sd_bus_message_close_container(reply);
148 if (r < 0)
ebcf1f97 149 return sd_bus_error_set_errno(error, r);
c3350683
LP
150
151 return sd_bus_send(bus, reply, NULL);
152}
153
89f7c846 154static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, Machine **_m, sd_bus_error *error) {
8aec412f 155 const char *name, *service, *class, *root_directory;
1ee306e1
LP
156 MachineClass c;
157 uint32_t leader;
158 sd_id128_t id;
c3350683 159 const void *v;
1ee306e1 160 Machine *m;
c3350683
LP
161 size_t n;
162 int r;
1ee306e1 163
c3350683 164 assert(manager);
89f7c846
LP
165 assert(message);
166 assert(_m);
1ee306e1 167
c3350683
LP
168 r = sd_bus_message_read(message, "s", &name);
169 if (r < 0)
ebcf1f97 170 return r;
7f0d207d 171 if (!machine_name_is_valid(name))
ebcf1f97 172 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
1ee306e1 173
c3350683
LP
174 r = sd_bus_message_read_array(message, 'y', &v, &n);
175 if (r < 0)
ebcf1f97 176 return r;
1ee306e1
LP
177 if (n == 0)
178 id = SD_ID128_NULL;
179 else if (n == 16)
180 memcpy(&id, v, n);
181 else
ebcf1f97 182 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
1ee306e1 183
c3350683
LP
184 r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
185 if (r < 0)
ebcf1f97 186 return r;
1ee306e1
LP
187
188 if (isempty(class))
189 c = _MACHINE_CLASS_INVALID;
190 else {
191 c = machine_class_from_string(class);
192 if (c < 0)
ebcf1f97 193 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
1ee306e1
LP
194 }
195
c3350683 196 if (leader == 1)
ebcf1f97 197 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
1ee306e1 198
c3350683 199 if (!isempty(root_directory) && !path_is_absolute(root_directory))
ebcf1f97 200 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
1ee306e1 201
c3350683 202 if (leader == 0) {
5b12334d
LP
203 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
204
205 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
206 if (r < 0)
207 return r;
208
c3350683 209 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
554604b3 210
5b12334d 211 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
c3350683 212 if (r < 0)
ebcf1f97 213 return r;
c3350683 214 }
554604b3 215
1ee306e1 216 if (hashmap_get(manager->machines, name))
ebcf1f97 217 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
1ee306e1
LP
218
219 r = manager_add_machine(manager, name, &m);
220 if (r < 0)
ebcf1f97 221 return r;
1ee306e1
LP
222
223 m->leader = leader;
224 m->class = c;
225 m->id = id;
206e7a5f 226 m->registered = true;
1ee306e1
LP
227
228 if (!isempty(service)) {
229 m->service = strdup(service);
230 if (!m->service) {
ebcf1f97 231 r = -ENOMEM;
1ee306e1
LP
232 goto fail;
233 }
234 }
235
236 if (!isempty(root_directory)) {
237 m->root_directory = strdup(root_directory);
238 if (!m->root_directory) {
ebcf1f97 239 r = -ENOMEM;
1ee306e1
LP
240 goto fail;
241 }
242 }
243
89f7c846
LP
244 *_m = m;
245
246 return 1;
247
248fail:
249 machine_add_to_gc_queue(m);
250 return r;
251}
252
253static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
254 Manager *manager = userdata;
255 Machine *m = NULL;
256 int r;
257
258 r = method_create_or_register_machine(manager, message, &m, error);
259 if (r < 0)
260 return r;
261
262 r = sd_bus_message_enter_container(message, 'a', "(sv)");
263 if (r < 0)
264 goto fail;
265
ebcf1f97
LP
266 r = machine_start(m, message, error);
267 if (r < 0)
1ee306e1
LP
268 goto fail;
269
c3350683 270 m->create_message = sd_bus_message_ref(message);
c3350683 271 return 1;
1ee306e1
LP
272
273fail:
a3e7f417 274 machine_add_to_gc_queue(m);
89f7c846
LP
275 return r;
276}
1ee306e1 277
89f7c846
LP
278static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
279 Manager *manager = userdata;
280 _cleanup_free_ char *p = NULL;
281 Machine *m = NULL;
282 int r;
283
284 r = method_create_or_register_machine(manager, message, &m, error);
285 if (r < 0)
286 return r;
287
288 r = cg_pid_get_unit(m->leader, &m->unit);
289 if (r < 0) {
290 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
291 goto fail;
292 }
293
294 r = machine_start(m, NULL, error);
295 if (r < 0)
296 goto fail;
297
298 p = machine_bus_path(m);
299 if (!p) {
300 r = -ENOMEM;
301 goto fail;
302 }
303
304 return sd_bus_reply_method_return(message, "o", p);
305
306fail:
307 machine_add_to_gc_queue(m);
1ee306e1
LP
308 return r;
309}
310
ebcf1f97 311static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1ee306e1 312 Manager *m = userdata;
c3350683
LP
313 Machine *machine;
314 const char *name;
1ee306e1
LP
315 int r;
316
c3350683 317 assert(bus);
1ee306e1
LP
318 assert(message);
319 assert(m);
320
c3350683
LP
321 r = sd_bus_message_read(message, "s", &name);
322 if (r < 0)
ebcf1f97 323 return sd_bus_error_set_errno(error, r);
1ee306e1 324
c3350683
LP
325 machine = hashmap_get(m->machines, name);
326 if (!machine)
ebcf1f97 327 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1ee306e1 328
878cd7e9 329 return bus_machine_method_terminate(bus, message, machine, error);
c3350683 330}
1ee306e1 331
ebcf1f97 332static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683
LP
333 Manager *m = userdata;
334 Machine *machine;
335 const char *name;
c3350683 336 int r;
1ee306e1 337
c3350683
LP
338 assert(bus);
339 assert(message);
340 assert(m);
1ee306e1 341
878cd7e9 342 r = sd_bus_message_read(message, "s", &name);
c3350683 343 if (r < 0)
ebcf1f97 344 return sd_bus_error_set_errno(error, r);
1ee306e1 345
c3350683
LP
346 machine = hashmap_get(m->machines, name);
347 if (!machine)
ebcf1f97 348 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
1ee306e1 349
878cd7e9
LP
350 return bus_machine_method_kill(bus, message, machine, error);
351}
352
353static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
354 Manager *m = userdata;
355 Machine *machine;
356 const char *name;
357 int r;
358
359 assert(bus);
360 assert(message);
361 assert(m);
362
363 r = sd_bus_message_read(message, "s", &name);
c3350683 364 if (r < 0)
ebcf1f97 365 return sd_bus_error_set_errno(error, r);
1ee306e1 366
878cd7e9
LP
367 machine = hashmap_get(m->machines, name);
368 if (!machine)
369 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
370
371 return bus_machine_method_get_addresses(bus, message, machine, error);
c3350683 372}
1ee306e1 373
c3350683
LP
374const sd_bus_vtable manager_vtable[] = {
375 SD_BUS_VTABLE_START(0),
adacb957
LP
376 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
377 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
378 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
c3350683 379 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
89f7c846 380 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
adacb957
LP
381 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
382 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
878cd7e9 383 SD_BUS_METHOD("GetMachineAddresses", "s", "a(yay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
c3350683
LP
384 SD_BUS_SIGNAL("MachineNew", "so", 0),
385 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
386 SD_BUS_VTABLE_END
387};
1ee306e1 388
ebcf1f97 389int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683 390 const char *path, *result, *unit;
1ee306e1 391 Manager *m = userdata;
c3350683
LP
392 Machine *machine;
393 uint32_t id;
394 int r;
1ee306e1 395
c3350683 396 assert(bus);
1ee306e1 397 assert(message);
c3350683 398 assert(m);
1ee306e1 399
c3350683
LP
400 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
401 if (r < 0) {
ebcf1f97
LP
402 bus_log_parse_error(r);
403 return r;
c3350683 404 }
6797c324 405
c3350683
LP
406 machine = hashmap_get(m->machine_units, unit);
407 if (!machine)
408 return 0;
6797c324 409
c3350683
LP
410 if (streq_ptr(path, machine->scope_job)) {
411 free(machine->scope_job);
412 machine->scope_job = NULL;
6797c324 413
c3350683
LP
414 if (machine->started) {
415 if (streq(result, "done"))
416 machine_send_create_reply(machine, NULL);
417 else {
ebcf1f97 418 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
6797c324 419
ebcf1f97 420 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
6797c324 421
ebcf1f97 422 machine_send_create_reply(machine, &e);
c3350683
LP
423 }
424 } else
425 machine_save(machine);
1ee306e1
LP
426 }
427
c3350683
LP
428 machine_add_to_gc_queue(machine);
429 return 0;
1ee306e1
LP
430}
431
ebcf1f97 432int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683
LP
433 _cleanup_free_ char *unit = NULL;
434 Manager *m = userdata;
435 Machine *machine;
436 const char *path;
ebcf1f97 437 int r;
554604b3 438
c3350683
LP
439 assert(bus);
440 assert(message);
441 assert(m);
554604b3 442
c3350683
LP
443 path = sd_bus_message_get_path(message);
444 if (!path)
554604b3 445 return 0;
554604b3 446
ebcf1f97
LP
447 r = unit_name_from_dbus_path(path, &unit);
448 if (r < 0)
449 return r;
554604b3 450
c3350683
LP
451 machine = hashmap_get(m->machine_units, unit);
452 if (machine)
453 machine_add_to_gc_queue(machine);
554604b3 454
c3350683
LP
455 return 0;
456}
554604b3 457
ebcf1f97 458int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683
LP
459 const char *path, *unit;
460 Manager *m = userdata;
461 Machine *machine;
462 int r;
554604b3 463
c3350683
LP
464 assert(bus);
465 assert(message);
466 assert(m);
554604b3 467
c3350683
LP
468 r = sd_bus_message_read(message, "so", &unit, &path);
469 if (r < 0) {
ebcf1f97
LP
470 bus_log_parse_error(r);
471 return r;
554604b3
LP
472 }
473
c3350683
LP
474 machine = hashmap_get(m->machine_units, unit);
475 if (machine)
476 machine_add_to_gc_queue(machine);
554604b3 477
c3350683
LP
478 return 0;
479}
554604b3 480
ebcf1f97 481int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
c3350683 482 Manager *m = userdata;
a658cafa
LP
483 Machine *machine;
484 Iterator i;
c3350683 485 int b, r;
554604b3 486
c3350683 487 assert(bus);
554604b3 488
c3350683
LP
489 r = sd_bus_message_read(message, "b", &b);
490 if (r < 0) {
ebcf1f97
LP
491 bus_log_parse_error(r);
492 return r;
554604b3 493 }
a658cafa
LP
494 if (b)
495 return 0;
554604b3 496
a658cafa
LP
497 /* systemd finished reloading, let's recheck all our machines */
498 log_debug("System manager has been reloaded, rechecking machines...");
554604b3 499
a658cafa
LP
500 HASHMAP_FOREACH(machine, m->machines, i)
501 machine_add_to_gc_queue(machine);
554604b3
LP
502
503 return 0;
504}
505
1ee306e1
LP
506int manager_start_scope(
507 Manager *manager,
508 const char *scope,
509 pid_t pid,
510 const char *slice,
511 const char *description,
c3350683
LP
512 sd_bus_message *more_properties,
513 sd_bus_error *error,
1ee306e1
LP
514 char **job) {
515
c3350683 516 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
554604b3 517 int r;
1ee306e1
LP
518
519 assert(manager);
520 assert(scope);
521 assert(pid > 1);
522
c3350683
LP
523 r = sd_bus_message_new_method_call(
524 manager->bus,
151b9b96 525 &m,
1ee306e1
LP
526 "org.freedesktop.systemd1",
527 "/org/freedesktop/systemd1",
528 "org.freedesktop.systemd1.Manager",
151b9b96 529 "StartTransientUnit");
c3350683
LP
530 if (r < 0)
531 return r;
1ee306e1 532
a658cafa 533 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
c3350683
LP
534 if (r < 0)
535 return r;
1ee306e1 536
c3350683
LP
537 r = sd_bus_message_open_container(m, 'a', "(sv)");
538 if (r < 0)
539 return r;
1ee306e1
LP
540
541 if (!isempty(slice)) {
c3350683
LP
542 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
543 if (r < 0)
544 return r;
1ee306e1
LP
545 }
546
547 if (!isempty(description)) {
c3350683
LP
548 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
549 if (r < 0)
550 return r;
1ee306e1
LP
551 }
552
c3350683
LP
553 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
554 if (r < 0)
555 return r;
554604b3
LP
556
557 if (more_properties) {
c3350683 558 r = sd_bus_message_copy(m, more_properties, true);
554604b3
LP
559 if (r < 0)
560 return r;
561 }
562
c3350683
LP
563 r = sd_bus_message_close_container(m);
564 if (r < 0)
565 return r;
1ee306e1 566
86b8d289
LP
567 r = sd_bus_message_append(m, "a(sa(sv))", 0);
568 if (r < 0)
569 return r;
570
c49b30a2 571 r = sd_bus_call(manager->bus, m, 0, error, &reply);
c3350683
LP
572 if (r < 0)
573 return r;
1ee306e1
LP
574
575 if (job) {
576 const char *j;
577 char *copy;
578
c3350683
LP
579 r = sd_bus_message_read(reply, "o", &j);
580 if (r < 0)
581 return r;
1ee306e1
LP
582
583 copy = strdup(j);
584 if (!copy)
585 return -ENOMEM;
586
587 *job = copy;
588 }
589
c3350683 590 return 1;
1ee306e1
LP
591}
592
c3350683
LP
593int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
594 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1
LP
595 int r;
596
597 assert(manager);
598 assert(unit);
599
c3350683 600 r = sd_bus_call_method(
1ee306e1
LP
601 manager->bus,
602 "org.freedesktop.systemd1",
603 "/org/freedesktop/systemd1",
604 "org.freedesktop.systemd1.Manager",
605 "StopUnit",
1ee306e1 606 error,
c3350683
LP
607 &reply,
608 "ss", unit, "fail");
1ee306e1 609 if (r < 0) {
c3350683
LP
610 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
611 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
6797c324
LP
612
613 if (job)
614 *job = NULL;
615
c3350683 616 sd_bus_error_free(error);
6797c324
LP
617 return 0;
618 }
619
1ee306e1
LP
620 return r;
621 }
622
623 if (job) {
624 const char *j;
625 char *copy;
626
c3350683
LP
627 r = sd_bus_message_read(reply, "o", &j);
628 if (r < 0)
629 return r;
1ee306e1
LP
630
631 copy = strdup(j);
632 if (!copy)
633 return -ENOMEM;
634
635 *job = copy;
636 }
637
6797c324 638 return 1;
1ee306e1
LP
639}
640
de58a50e 641int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1ee306e1
LP
642 assert(manager);
643 assert(unit);
644
a658cafa 645 return sd_bus_call_method(
1ee306e1
LP
646 manager->bus,
647 "org.freedesktop.systemd1",
648 "/org/freedesktop/systemd1",
649 "org.freedesktop.systemd1.Manager",
650 "KillUnit",
1ee306e1 651 error,
a658cafa 652 NULL,
de58a50e 653 "ssi", unit, "all", signo);
1ee306e1
LP
654}
655
656int manager_unit_is_active(Manager *manager, const char *unit) {
c3350683
LP
657 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
658 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1 659 _cleanup_free_ char *path = NULL;
1ee306e1 660 const char *state;
1ee306e1
LP
661 int r;
662
663 assert(manager);
664 assert(unit);
665
1ee306e1
LP
666 path = unit_dbus_path_from_name(unit);
667 if (!path)
668 return -ENOMEM;
669
c3350683 670 r = sd_bus_get_property(
1ee306e1
LP
671 manager->bus,
672 "org.freedesktop.systemd1",
673 path,
c3350683
LP
674 "org.freedesktop.systemd1.Unit",
675 "ActiveState",
1ee306e1 676 &error,
c3350683
LP
677 &reply,
678 "s");
1ee306e1 679 if (r < 0) {
c3350683
LP
680 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
681 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
6797c324 682 return true;
6797c324 683
c3350683
LP
684 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
685 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
6797c324 686 return false;
6797c324 687
1ee306e1
LP
688 return r;
689 }
690
c3350683
LP
691 r = sd_bus_message_read(reply, "s", &state);
692 if (r < 0)
1ee306e1 693 return -EINVAL;
1ee306e1
LP
694
695 return !streq(state, "inactive") && !streq(state, "failed");
696}
bd16acf3 697
c3350683
LP
698int manager_job_is_active(Manager *manager, const char *path) {
699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
701 int r;
bd16acf3 702
c3350683
LP
703 assert(manager);
704 assert(path);
bd16acf3 705
c3350683
LP
706 r = sd_bus_get_property(
707 manager->bus,
708 "org.freedesktop.systemd1",
709 path,
710 "org.freedesktop.systemd1.Job",
711 "State",
712 &error,
713 &reply,
714 "s");
715 if (r < 0) {
716 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
717 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
718 return true;
bd16acf3 719
c3350683
LP
720 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
721 return false;
bd16acf3 722
bd16acf3 723 return r;
c3350683 724 }
bd16acf3 725
c3350683
LP
726 /* We don't actually care about the state really. The fact
727 * that we could read the job state is enough for us */
bd16acf3 728
c3350683 729 return true;
bd16acf3 730}
ab49725f
KS
731
732int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
733 _cleanup_free_ char *unit = NULL;
734 Machine *mm;
735 int r;
736
737 assert(m);
738 assert(pid >= 1);
739 assert(machine);
740
741 r = cg_pid_get_unit(pid, &unit);
742 if (r < 0)
743 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
744 else
745 mm = hashmap_get(m->machine_units, unit);
746
747 if (!mm)
748 return 0;
749
750 *machine = mm;
751 return 1;
752}
753
754int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
755 Machine *machine;
756
757 assert(m);
758 assert(name);
759
760 machine = hashmap_get(m->machines, name);
761 if (!machine) {
762 machine = machine_new(m, name);
763 if (!machine)
764 return -ENOMEM;
765 }
766
767 if (_machine)
768 *_machine = machine;
769
770 return 0;
771}