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