chiark / gitweb /
systemd-run: support -t mode when combined with -M
[elogind.git] / src / machine / machined-dbus.c
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>
26 #include <sys/capability.h>
27
28 #include "sd-id128.h"
29 #include "sd-messages.h"
30 #include "strv.h"
31 #include "mkdir.h"
32 #include "path-util.h"
33 #include "special.h"
34 #include "fileio-label.h"
35 #include "label.h"
36 #include "utf8.h"
37 #include "unit-name.h"
38 #include "bus-util.h"
39 #include "bus-common-errors.h"
40 #include "time-util.h"
41 #include "cgroup-util.h"
42 #include "image.h"
43 #include "machined.h"
44
45 static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
46         _cleanup_free_ char *p = NULL;
47         Manager *m = userdata;
48         Machine *machine;
49         const char *name;
50         int r;
51
52         assert(bus);
53         assert(message);
54         assert(m);
55
56         r = sd_bus_message_read(message, "s", &name);
57         if (r < 0)
58                 return r;
59
60         machine = hashmap_get(m->machines, name);
61         if (!machine)
62                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
63
64         p = machine_bus_path(machine);
65         if (!p)
66                 return -ENOMEM;
67
68         return sd_bus_reply_method_return(message, "o", p);
69 }
70
71 static int method_get_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
72         _cleanup_free_ char *p = NULL;
73         Manager *m = userdata;
74         const char *name;
75         int r;
76
77         assert(bus);
78         assert(message);
79         assert(m);
80
81         r = sd_bus_message_read(message, "s", &name);
82         if (r < 0)
83                 return r;
84
85         r = image_find(name, NULL);
86         if (r == 0)
87                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
88         if (r < 0)
89                 return r;
90
91         p = image_bus_path(name);
92         if (!p)
93                 return -ENOMEM;
94
95         return sd_bus_reply_method_return(message, "o", p);
96 }
97
98 static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
99         _cleanup_free_ char *p = NULL;
100         Manager *m = userdata;
101         Machine *machine = NULL;
102         pid_t pid;
103         int r;
104
105         assert(bus);
106         assert(message);
107         assert(m);
108
109         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
110
111         r = sd_bus_message_read(message, "u", &pid);
112         if (r < 0)
113                 return r;
114
115         if (pid == 0) {
116                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
117
118                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
119                 if (r < 0)
120                         return r;
121
122                 r = sd_bus_creds_get_pid(creds, &pid);
123                 if (r < 0)
124                         return r;
125         }
126
127         r = manager_get_machine_by_pid(m, pid, &machine);
128         if (r < 0)
129                 return r;
130         if (!machine)
131                 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
132
133         p = machine_bus_path(machine);
134         if (!p)
135                 return -ENOMEM;
136
137         return sd_bus_reply_method_return(message, "o", p);
138 }
139
140 static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
141         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
142         Manager *m = userdata;
143         Machine *machine;
144         Iterator i;
145         int r;
146
147         assert(bus);
148         assert(message);
149         assert(m);
150
151         r = sd_bus_message_new_method_return(message, &reply);
152         if (r < 0)
153                 return sd_bus_error_set_errno(error, r);
154
155         r = sd_bus_message_open_container(reply, 'a', "(ssso)");
156         if (r < 0)
157                 return sd_bus_error_set_errno(error, r);
158
159         HASHMAP_FOREACH(machine, m->machines, i) {
160                 _cleanup_free_ char *p = NULL;
161
162                 p = machine_bus_path(machine);
163                 if (!p)
164                         return -ENOMEM;
165
166                 r = sd_bus_message_append(reply, "(ssso)",
167                                           machine->name,
168                                           strempty(machine_class_to_string(machine->class)),
169                                           machine->service,
170                                           p);
171                 if (r < 0)
172                         return sd_bus_error_set_errno(error, r);
173         }
174
175         r = sd_bus_message_close_container(reply);
176         if (r < 0)
177                 return sd_bus_error_set_errno(error, r);
178
179         return sd_bus_send(bus, reply, NULL);
180 }
181
182 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
183         const char *name, *service, *class, *root_directory;
184         const int32_t *netif = NULL;
185         MachineClass c;
186         uint32_t leader;
187         sd_id128_t id;
188         const void *v;
189         Machine *m;
190         size_t n, n_netif = 0;
191         int r;
192
193         assert(manager);
194         assert(message);
195         assert(_m);
196
197         r = sd_bus_message_read(message, "s", &name);
198         if (r < 0)
199                 return r;
200         if (!machine_name_is_valid(name))
201                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
202
203         r = sd_bus_message_read_array(message, 'y', &v, &n);
204         if (r < 0)
205                 return r;
206         if (n == 0)
207                 id = SD_ID128_NULL;
208         else if (n == 16)
209                 memcpy(&id, v, n);
210         else
211                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
212
213         r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
214         if (r < 0)
215                 return r;
216
217         if (read_network) {
218                 size_t i;
219
220                 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
221                 if (r < 0)
222                         return r;
223
224                 n_netif /= sizeof(int32_t);
225
226                 for (i = 0; i < n_netif; i++) {
227                         if (netif[i] <= 0)
228                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
229                 }
230         }
231
232         if (isempty(class))
233                 c = _MACHINE_CLASS_INVALID;
234         else {
235                 c = machine_class_from_string(class);
236                 if (c < 0)
237                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
238         }
239
240         if (leader == 1)
241                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
242
243         if (!isempty(root_directory) && !path_is_absolute(root_directory))
244                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
245
246         if (leader == 0) {
247                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
248
249                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
250                 if (r < 0)
251                         return r;
252
253                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
254
255                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
256                 if (r < 0)
257                         return r;
258         }
259
260         if (hashmap_get(manager->machines, name))
261                 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
262
263         r = manager_add_machine(manager, name, &m);
264         if (r < 0)
265                 return r;
266
267         m->leader = leader;
268         m->class = c;
269         m->id = id;
270
271         if (!isempty(service)) {
272                 m->service = strdup(service);
273                 if (!m->service) {
274                         r = -ENOMEM;
275                         goto fail;
276                 }
277         }
278
279         if (!isempty(root_directory)) {
280                 m->root_directory = strdup(root_directory);
281                 if (!m->root_directory) {
282                         r = -ENOMEM;
283                         goto fail;
284                 }
285         }
286
287         if (n_netif > 0) {
288                 assert_cc(sizeof(int32_t) == sizeof(int));
289                 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
290                 if (!m->netif) {
291                         r = -ENOMEM;
292                         goto fail;
293                 }
294
295                 m->n_netif = n_netif;
296         }
297
298         *_m = m;
299
300         return 1;
301
302 fail:
303         machine_add_to_gc_queue(m);
304         return r;
305 }
306
307 static int method_create_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
308         Manager *manager = userdata;
309         Machine *m = NULL;
310         int r;
311
312         r = method_create_or_register_machine(manager, message, read_network, &m, error);
313         if (r < 0)
314                 return r;
315
316         r = sd_bus_message_enter_container(message, 'a', "(sv)");
317         if (r < 0)
318                 goto fail;
319
320         r = machine_start(m, message, error);
321         if (r < 0)
322                 goto fail;
323
324         m->create_message = sd_bus_message_ref(message);
325         return 1;
326
327 fail:
328         machine_add_to_gc_queue(m);
329         return r;
330 }
331
332 static int method_create_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
333         return method_create_machine_internal(bus, message, true, userdata, error);
334 }
335
336 static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
337         return method_create_machine_internal(bus, message, false, userdata, error);
338 }
339
340 static int method_register_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
341         Manager *manager = userdata;
342         _cleanup_free_ char *p = NULL;
343         Machine *m = NULL;
344         int r;
345
346         r = method_create_or_register_machine(manager, message, read_network, &m, error);
347         if (r < 0)
348                 return r;
349
350         r = cg_pid_get_unit(m->leader, &m->unit);
351         if (r < 0) {
352                 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
353                 goto fail;
354         }
355
356         m->registered = true;
357
358         r = machine_start(m, NULL, error);
359         if (r < 0)
360                 goto fail;
361
362         p = machine_bus_path(m);
363         if (!p) {
364                 r = -ENOMEM;
365                 goto fail;
366         }
367
368         return sd_bus_reply_method_return(message, "o", p);
369
370 fail:
371         machine_add_to_gc_queue(m);
372         return r;
373 }
374
375 static int method_register_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
376         return method_register_machine_internal(bus, message, true, userdata, error);
377 }
378
379 static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
380         return method_register_machine_internal(bus, message, false, userdata, error);
381 }
382
383 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
384         Manager *m = userdata;
385         Machine *machine;
386         const char *name;
387         int r;
388
389         assert(bus);
390         assert(message);
391         assert(m);
392
393         r = sd_bus_message_read(message, "s", &name);
394         if (r < 0)
395                 return sd_bus_error_set_errno(error, r);
396
397         machine = hashmap_get(m->machines, name);
398         if (!machine)
399                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
400
401         return bus_machine_method_terminate(bus, message, machine, error);
402 }
403
404 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
405         Manager *m = userdata;
406         Machine *machine;
407         const char *name;
408         int r;
409
410         assert(bus);
411         assert(message);
412         assert(m);
413
414         r = sd_bus_message_read(message, "s", &name);
415         if (r < 0)
416                 return sd_bus_error_set_errno(error, r);
417
418         machine = hashmap_get(m->machines, name);
419         if (!machine)
420                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
421
422         return bus_machine_method_kill(bus, message, machine, error);
423 }
424
425 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
426         Manager *m = userdata;
427         Machine *machine;
428         const char *name;
429         int r;
430
431         assert(bus);
432         assert(message);
433         assert(m);
434
435         r = sd_bus_message_read(message, "s", &name);
436         if (r < 0)
437                 return sd_bus_error_set_errno(error, r);
438
439         machine = hashmap_get(m->machines, name);
440         if (!machine)
441                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
442
443         return bus_machine_method_get_addresses(bus, message, machine, error);
444 }
445
446 static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
447         Manager *m = userdata;
448         Machine *machine;
449         const char *name;
450         int r;
451
452         assert(bus);
453         assert(message);
454         assert(m);
455
456         r = sd_bus_message_read(message, "s", &name);
457         if (r < 0)
458                 return sd_bus_error_set_errno(error, r);
459
460         machine = hashmap_get(m->machines, name);
461         if (!machine)
462                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
463
464         return bus_machine_method_get_os_release(bus, message, machine, error);
465 }
466
467 static int method_list_images(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
468         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
469         _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
470         Manager *m = userdata;
471         Image *image;
472         Iterator i;
473         int r;
474
475         assert(bus);
476         assert(message);
477         assert(m);
478
479         images = hashmap_new(&string_hash_ops);
480         if (!images)
481                 return -ENOMEM;
482
483         r = image_discover(images);
484         if (r < 0)
485                 return r;
486
487         r = sd_bus_message_new_method_return(message, &reply);
488         if (r < 0)
489                 return r;
490
491         r = sd_bus_message_open_container(reply, 'a', "(ssbo)");
492         if (r < 0)
493                 return r;
494
495         HASHMAP_FOREACH(image, images, i) {
496                 _cleanup_free_ char *p = NULL;
497
498                 p = image_bus_path(image->name);
499                 if (!p)
500                         return -ENOMEM;
501
502                 r = sd_bus_message_append(reply, "(ssbo)",
503                                           image->name,
504                                           image_type_to_string(image->type),
505                                           image->read_only,
506                                           p);
507                 if (r < 0)
508                         return r;
509         }
510
511         r = sd_bus_message_close_container(reply);
512         if (r < 0)
513                 return r;
514
515         return sd_bus_send(bus, reply, NULL);
516 }
517
518 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
519         Manager *m = userdata;
520         Machine *machine;
521         const char *name;
522         int r;
523
524         assert(bus);
525         assert(message);
526         assert(m);
527
528         r = sd_bus_message_read(message, "s", &name);
529         if (r < 0)
530                 return sd_bus_error_set_errno(error, r);
531
532         machine = hashmap_get(m->machines, name);
533         if (!machine)
534                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
535
536         return bus_machine_method_open_pty(bus, message, machine, error);
537 }
538
539 const sd_bus_vtable manager_vtable[] = {
540         SD_BUS_VTABLE_START(0),
541         SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
542         SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
543         SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
544         SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
545         SD_BUS_METHOD("ListImages", NULL, "a(ssbo)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
546         SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
547         SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
548         SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
549         SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
550         SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
551         SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
552         SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
553         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
554         SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
555         SD_BUS_SIGNAL("MachineNew", "so", 0),
556         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
557         SD_BUS_VTABLE_END
558 };
559
560 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
561         const char *path, *result, *unit;
562         Manager *m = userdata;
563         Machine *machine;
564         uint32_t id;
565         int r;
566
567         assert(bus);
568         assert(message);
569         assert(m);
570
571         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
572         if (r < 0) {
573                 bus_log_parse_error(r);
574                 return r;
575         }
576
577         machine = hashmap_get(m->machine_units, unit);
578         if (!machine)
579                 return 0;
580
581         if (streq_ptr(path, machine->scope_job)) {
582                 free(machine->scope_job);
583                 machine->scope_job = NULL;
584
585                 if (machine->started) {
586                         if (streq(result, "done"))
587                                 machine_send_create_reply(machine, NULL);
588                         else {
589                                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
590
591                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
592
593                                 machine_send_create_reply(machine, &e);
594                         }
595                 } else
596                         machine_save(machine);
597         }
598
599         machine_add_to_gc_queue(machine);
600         return 0;
601 }
602
603 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
604         _cleanup_free_ char *unit = NULL;
605         Manager *m = userdata;
606         Machine *machine;
607         const char *path;
608         int r;
609
610         assert(bus);
611         assert(message);
612         assert(m);
613
614         path = sd_bus_message_get_path(message);
615         if (!path)
616                 return 0;
617
618         r = unit_name_from_dbus_path(path, &unit);
619         if (r < 0)
620                 return r;
621
622         machine = hashmap_get(m->machine_units, unit);
623         if (machine)
624                 machine_add_to_gc_queue(machine);
625
626         return 0;
627 }
628
629 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
630         const char *path, *unit;
631         Manager *m = userdata;
632         Machine *machine;
633         int r;
634
635         assert(bus);
636         assert(message);
637         assert(m);
638
639         r = sd_bus_message_read(message, "so", &unit, &path);
640         if (r < 0) {
641                 bus_log_parse_error(r);
642                 return r;
643         }
644
645         machine = hashmap_get(m->machine_units, unit);
646         if (machine)
647                 machine_add_to_gc_queue(machine);
648
649         return 0;
650 }
651
652 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
653         Manager *m = userdata;
654         Machine *machine;
655         Iterator i;
656         int b, r;
657
658         assert(bus);
659
660         r = sd_bus_message_read(message, "b", &b);
661         if (r < 0) {
662                 bus_log_parse_error(r);
663                 return r;
664         }
665         if (b)
666                 return 0;
667
668         /* systemd finished reloading, let's recheck all our machines */
669         log_debug("System manager has been reloaded, rechecking machines...");
670
671         HASHMAP_FOREACH(machine, m->machines, i)
672                 machine_add_to_gc_queue(machine);
673
674         return 0;
675 }
676
677 int manager_start_scope(
678                 Manager *manager,
679                 const char *scope,
680                 pid_t pid,
681                 const char *slice,
682                 const char *description,
683                 sd_bus_message *more_properties,
684                 sd_bus_error *error,
685                 char **job) {
686
687         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
688         int r;
689
690         assert(manager);
691         assert(scope);
692         assert(pid > 1);
693
694         r = sd_bus_message_new_method_call(
695                         manager->bus,
696                         &m,
697                         "org.freedesktop.systemd1",
698                         "/org/freedesktop/systemd1",
699                         "org.freedesktop.systemd1.Manager",
700                         "StartTransientUnit");
701         if (r < 0)
702                 return r;
703
704         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
705         if (r < 0)
706                 return r;
707
708         r = sd_bus_message_open_container(m, 'a', "(sv)");
709         if (r < 0)
710                 return r;
711
712         if (!isempty(slice)) {
713                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
714                 if (r < 0)
715                         return r;
716         }
717
718         if (!isempty(description)) {
719                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
720                 if (r < 0)
721                         return r;
722         }
723
724         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
725         if (r < 0)
726                 return r;
727
728         r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
729         if (r < 0)
730                 return r;
731
732         if (more_properties) {
733                 r = sd_bus_message_copy(m, more_properties, true);
734                 if (r < 0)
735                         return r;
736         }
737
738         r = sd_bus_message_close_container(m);
739         if (r < 0)
740                 return r;
741
742         r = sd_bus_message_append(m, "a(sa(sv))", 0);
743         if (r < 0)
744                 return r;
745
746         r = sd_bus_call(manager->bus, m, 0, error, &reply);
747         if (r < 0)
748                 return r;
749
750         if (job) {
751                 const char *j;
752                 char *copy;
753
754                 r = sd_bus_message_read(reply, "o", &j);
755                 if (r < 0)
756                         return r;
757
758                 copy = strdup(j);
759                 if (!copy)
760                         return -ENOMEM;
761
762                 *job = copy;
763         }
764
765         return 1;
766 }
767
768 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
769         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
770         int r;
771
772         assert(manager);
773         assert(unit);
774
775         r = sd_bus_call_method(
776                         manager->bus,
777                         "org.freedesktop.systemd1",
778                         "/org/freedesktop/systemd1",
779                         "org.freedesktop.systemd1.Manager",
780                         "StopUnit",
781                         error,
782                         &reply,
783                         "ss", unit, "fail");
784         if (r < 0) {
785                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
786                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
787
788                         if (job)
789                                 *job = NULL;
790
791                         sd_bus_error_free(error);
792                         return 0;
793                 }
794
795                 return r;
796         }
797
798         if (job) {
799                 const char *j;
800                 char *copy;
801
802                 r = sd_bus_message_read(reply, "o", &j);
803                 if (r < 0)
804                         return r;
805
806                 copy = strdup(j);
807                 if (!copy)
808                         return -ENOMEM;
809
810                 *job = copy;
811         }
812
813         return 1;
814 }
815
816 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
817         assert(manager);
818         assert(unit);
819
820         return sd_bus_call_method(
821                         manager->bus,
822                         "org.freedesktop.systemd1",
823                         "/org/freedesktop/systemd1",
824                         "org.freedesktop.systemd1.Manager",
825                         "KillUnit",
826                         error,
827                         NULL,
828                         "ssi", unit, "all", signo);
829 }
830
831 int manager_unit_is_active(Manager *manager, const char *unit) {
832         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
833         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
834         _cleanup_free_ char *path = NULL;
835         const char *state;
836         int r;
837
838         assert(manager);
839         assert(unit);
840
841         path = unit_dbus_path_from_name(unit);
842         if (!path)
843                 return -ENOMEM;
844
845         r = sd_bus_get_property(
846                         manager->bus,
847                         "org.freedesktop.systemd1",
848                         path,
849                         "org.freedesktop.systemd1.Unit",
850                         "ActiveState",
851                         &error,
852                         &reply,
853                         "s");
854         if (r < 0) {
855                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
856                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
857                         return true;
858
859                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
860                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
861                         return false;
862
863                 return r;
864         }
865
866         r = sd_bus_message_read(reply, "s", &state);
867         if (r < 0)
868                 return -EINVAL;
869
870         return !streq(state, "inactive") && !streq(state, "failed");
871 }
872
873 int manager_job_is_active(Manager *manager, const char *path) {
874         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
875         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
876         int r;
877
878         assert(manager);
879         assert(path);
880
881         r = sd_bus_get_property(
882                         manager->bus,
883                         "org.freedesktop.systemd1",
884                         path,
885                         "org.freedesktop.systemd1.Job",
886                         "State",
887                         &error,
888                         &reply,
889                         "s");
890         if (r < 0) {
891                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
892                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
893                         return true;
894
895                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
896                         return false;
897
898                 return r;
899         }
900
901         /* We don't actually care about the state really. The fact
902          * that we could read the job state is enough for us */
903
904         return true;
905 }
906
907 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
908         _cleanup_free_ char *unit = NULL;
909         Machine *mm;
910         int r;
911
912         assert(m);
913         assert(pid >= 1);
914         assert(machine);
915
916         r = cg_pid_get_unit(pid, &unit);
917         if (r < 0)
918                 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
919         else
920                 mm = hashmap_get(m->machine_units, unit);
921
922         if (!mm)
923                 return 0;
924
925         *machine = mm;
926         return 1;
927 }
928
929 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
930         Machine *machine;
931
932         assert(m);
933         assert(name);
934
935         machine = hashmap_get(m->machines, name);
936         if (!machine) {
937                 machine = machine_new(m, name);
938                 if (!machine)
939                         return -ENOMEM;
940         }
941
942         if (_machine)
943                 *_machine = machine;
944
945         return 0;
946 }