chiark / gitweb /
e264dacbe6ed14999f188c6d70c121111a667e80
[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', "(ssbtto)");
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, "(ssbtto)",
503                                           image->name,
504                                           image_type_to_string(image->type),
505                                           image->read_only,
506                                           image->crtime,
507                                           image->mtime,
508                                           p);
509                 if (r < 0)
510                         return r;
511         }
512
513         r = sd_bus_message_close_container(reply);
514         if (r < 0)
515                 return r;
516
517         return sd_bus_send(bus, reply, NULL);
518 }
519
520 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
521         Manager *m = userdata;
522         Machine *machine;
523         const char *name;
524         int r;
525
526         assert(bus);
527         assert(message);
528         assert(m);
529
530         r = sd_bus_message_read(message, "s", &name);
531         if (r < 0)
532                 return sd_bus_error_set_errno(error, r);
533
534         machine = hashmap_get(m->machines, name);
535         if (!machine)
536                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
537
538         return bus_machine_method_open_pty(bus, message, machine, error);
539 }
540
541 static int method_open_machine_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
542         Manager *m = userdata;
543         Machine *machine;
544         const char *name;
545         int r;
546
547         assert(bus);
548         assert(message);
549         assert(m);
550
551         r = sd_bus_message_read(message, "s", &name);
552         if (r < 0)
553                 return sd_bus_error_set_errno(error, r);
554
555         machine = hashmap_get(m->machines, name);
556         if (!machine)
557                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
558
559         return bus_machine_method_open_login(bus, message, machine, error);
560 }
561
562 const sd_bus_vtable manager_vtable[] = {
563         SD_BUS_VTABLE_START(0),
564         SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
565         SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
566         SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
567         SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
568         SD_BUS_METHOD("ListImages", NULL, "a(ssbtto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
569         SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
570         SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
571         SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
572         SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
573         SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
574         SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
575         SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
576         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
577         SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
578         SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
579         SD_BUS_SIGNAL("MachineNew", "so", 0),
580         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
581         SD_BUS_VTABLE_END
582 };
583
584 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
585         const char *path, *result, *unit;
586         Manager *m = userdata;
587         Machine *machine;
588         uint32_t id;
589         int r;
590
591         assert(bus);
592         assert(message);
593         assert(m);
594
595         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
596         if (r < 0) {
597                 bus_log_parse_error(r);
598                 return r;
599         }
600
601         machine = hashmap_get(m->machine_units, unit);
602         if (!machine)
603                 return 0;
604
605         if (streq_ptr(path, machine->scope_job)) {
606                 free(machine->scope_job);
607                 machine->scope_job = NULL;
608
609                 if (machine->started) {
610                         if (streq(result, "done"))
611                                 machine_send_create_reply(machine, NULL);
612                         else {
613                                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
614
615                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
616
617                                 machine_send_create_reply(machine, &e);
618                         }
619                 } else
620                         machine_save(machine);
621         }
622
623         machine_add_to_gc_queue(machine);
624         return 0;
625 }
626
627 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
628         _cleanup_free_ char *unit = NULL;
629         Manager *m = userdata;
630         Machine *machine;
631         const char *path;
632         int r;
633
634         assert(bus);
635         assert(message);
636         assert(m);
637
638         path = sd_bus_message_get_path(message);
639         if (!path)
640                 return 0;
641
642         r = unit_name_from_dbus_path(path, &unit);
643         if (r < 0)
644                 return r;
645
646         machine = hashmap_get(m->machine_units, unit);
647         if (machine)
648                 machine_add_to_gc_queue(machine);
649
650         return 0;
651 }
652
653 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
654         const char *path, *unit;
655         Manager *m = userdata;
656         Machine *machine;
657         int r;
658
659         assert(bus);
660         assert(message);
661         assert(m);
662
663         r = sd_bus_message_read(message, "so", &unit, &path);
664         if (r < 0) {
665                 bus_log_parse_error(r);
666                 return r;
667         }
668
669         machine = hashmap_get(m->machine_units, unit);
670         if (machine)
671                 machine_add_to_gc_queue(machine);
672
673         return 0;
674 }
675
676 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
677         Manager *m = userdata;
678         Machine *machine;
679         Iterator i;
680         int b, r;
681
682         assert(bus);
683
684         r = sd_bus_message_read(message, "b", &b);
685         if (r < 0) {
686                 bus_log_parse_error(r);
687                 return r;
688         }
689         if (b)
690                 return 0;
691
692         /* systemd finished reloading, let's recheck all our machines */
693         log_debug("System manager has been reloaded, rechecking machines...");
694
695         HASHMAP_FOREACH(machine, m->machines, i)
696                 machine_add_to_gc_queue(machine);
697
698         return 0;
699 }
700
701 int manager_start_scope(
702                 Manager *manager,
703                 const char *scope,
704                 pid_t pid,
705                 const char *slice,
706                 const char *description,
707                 sd_bus_message *more_properties,
708                 sd_bus_error *error,
709                 char **job) {
710
711         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
712         int r;
713
714         assert(manager);
715         assert(scope);
716         assert(pid > 1);
717
718         r = sd_bus_message_new_method_call(
719                         manager->bus,
720                         &m,
721                         "org.freedesktop.systemd1",
722                         "/org/freedesktop/systemd1",
723                         "org.freedesktop.systemd1.Manager",
724                         "StartTransientUnit");
725         if (r < 0)
726                 return r;
727
728         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
729         if (r < 0)
730                 return r;
731
732         r = sd_bus_message_open_container(m, 'a', "(sv)");
733         if (r < 0)
734                 return r;
735
736         if (!isempty(slice)) {
737                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
738                 if (r < 0)
739                         return r;
740         }
741
742         if (!isempty(description)) {
743                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
744                 if (r < 0)
745                         return r;
746         }
747
748         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
749         if (r < 0)
750                 return r;
751
752         r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
753         if (r < 0)
754                 return r;
755
756         if (more_properties) {
757                 r = sd_bus_message_copy(m, more_properties, true);
758                 if (r < 0)
759                         return r;
760         }
761
762         r = sd_bus_message_close_container(m);
763         if (r < 0)
764                 return r;
765
766         r = sd_bus_message_append(m, "a(sa(sv))", 0);
767         if (r < 0)
768                 return r;
769
770         r = sd_bus_call(manager->bus, m, 0, error, &reply);
771         if (r < 0)
772                 return r;
773
774         if (job) {
775                 const char *j;
776                 char *copy;
777
778                 r = sd_bus_message_read(reply, "o", &j);
779                 if (r < 0)
780                         return r;
781
782                 copy = strdup(j);
783                 if (!copy)
784                         return -ENOMEM;
785
786                 *job = copy;
787         }
788
789         return 1;
790 }
791
792 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
793         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
794         int r;
795
796         assert(manager);
797         assert(unit);
798
799         r = sd_bus_call_method(
800                         manager->bus,
801                         "org.freedesktop.systemd1",
802                         "/org/freedesktop/systemd1",
803                         "org.freedesktop.systemd1.Manager",
804                         "StopUnit",
805                         error,
806                         &reply,
807                         "ss", unit, "fail");
808         if (r < 0) {
809                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
810                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
811
812                         if (job)
813                                 *job = NULL;
814
815                         sd_bus_error_free(error);
816                         return 0;
817                 }
818
819                 return r;
820         }
821
822         if (job) {
823                 const char *j;
824                 char *copy;
825
826                 r = sd_bus_message_read(reply, "o", &j);
827                 if (r < 0)
828                         return r;
829
830                 copy = strdup(j);
831                 if (!copy)
832                         return -ENOMEM;
833
834                 *job = copy;
835         }
836
837         return 1;
838 }
839
840 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
841         assert(manager);
842         assert(unit);
843
844         return sd_bus_call_method(
845                         manager->bus,
846                         "org.freedesktop.systemd1",
847                         "/org/freedesktop/systemd1",
848                         "org.freedesktop.systemd1.Manager",
849                         "KillUnit",
850                         error,
851                         NULL,
852                         "ssi", unit, "all", signo);
853 }
854
855 int manager_unit_is_active(Manager *manager, const char *unit) {
856         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
857         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
858         _cleanup_free_ char *path = NULL;
859         const char *state;
860         int r;
861
862         assert(manager);
863         assert(unit);
864
865         path = unit_dbus_path_from_name(unit);
866         if (!path)
867                 return -ENOMEM;
868
869         r = sd_bus_get_property(
870                         manager->bus,
871                         "org.freedesktop.systemd1",
872                         path,
873                         "org.freedesktop.systemd1.Unit",
874                         "ActiveState",
875                         &error,
876                         &reply,
877                         "s");
878         if (r < 0) {
879                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
880                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
881                         return true;
882
883                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
884                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
885                         return false;
886
887                 return r;
888         }
889
890         r = sd_bus_message_read(reply, "s", &state);
891         if (r < 0)
892                 return -EINVAL;
893
894         return !streq(state, "inactive") && !streq(state, "failed");
895 }
896
897 int manager_job_is_active(Manager *manager, const char *path) {
898         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
899         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
900         int r;
901
902         assert(manager);
903         assert(path);
904
905         r = sd_bus_get_property(
906                         manager->bus,
907                         "org.freedesktop.systemd1",
908                         path,
909                         "org.freedesktop.systemd1.Job",
910                         "State",
911                         &error,
912                         &reply,
913                         "s");
914         if (r < 0) {
915                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
916                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
917                         return true;
918
919                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
920                         return false;
921
922                 return r;
923         }
924
925         /* We don't actually care about the state really. The fact
926          * that we could read the job state is enough for us */
927
928         return true;
929 }
930
931 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
932         _cleanup_free_ char *unit = NULL;
933         Machine *mm;
934         int r;
935
936         assert(m);
937         assert(pid >= 1);
938         assert(machine);
939
940         r = cg_pid_get_unit(pid, &unit);
941         if (r < 0)
942                 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
943         else
944                 mm = hashmap_get(m->machine_units, unit);
945
946         if (!mm)
947                 return 0;
948
949         *machine = mm;
950         return 1;
951 }
952
953 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
954         Machine *machine;
955
956         assert(m);
957         assert(name);
958
959         machine = hashmap_get(m->machines, name);
960         if (!machine) {
961                 machine = machine_new(m, name);
962                 if (!machine)
963                         return -ENOMEM;
964         }
965
966         if (_machine)
967                 *_machine = machine;
968
969         return 0;
970 }