chiark / gitweb /
machinectl: implement "bind" command to create additional bind mounts from host to...
[elogind.git] / src / machine / machinectl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 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 <sys/socket.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <getopt.h>
27 #include <pwd.h>
28 #include <locale.h>
29 #include <fcntl.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <net/if.h>
33 #include <sys/mount.h>
34
35 #include "sd-bus.h"
36 #include "log.h"
37 #include "util.h"
38 #include "macro.h"
39 #include "pager.h"
40 #include "bus-util.h"
41 #include "bus-error.h"
42 #include "build.h"
43 #include "strv.h"
44 #include "unit-name.h"
45 #include "cgroup-show.h"
46 #include "cgroup-util.h"
47 #include "ptyfwd.h"
48 #include "event-util.h"
49 #include "path-util.h"
50 #include "mkdir.h"
51
52 static char **arg_property = NULL;
53 static bool arg_all = false;
54 static bool arg_full = false;
55 static bool arg_no_pager = false;
56 static bool arg_legend = true;
57 static const char *arg_kill_who = NULL;
58 static int arg_signal = SIGTERM;
59 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
60 static char *arg_host = NULL;
61 static bool arg_read_only = false;
62 static bool arg_mkdir = false;
63
64 static void pager_open_if_enabled(void) {
65
66         /* Cache result before we open the pager */
67         if (arg_no_pager)
68                 return;
69
70         pager_open(false);
71 }
72
73 static int list_machines(sd_bus *bus, char **args, unsigned n) {
74         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
75         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
76         const char *name, *class, *service, *object;
77         unsigned k = 0;
78         int r;
79
80         pager_open_if_enabled();
81
82         r = sd_bus_call_method(
83                                 bus,
84                                 "org.freedesktop.machine1",
85                                 "/org/freedesktop/machine1",
86                                 "org.freedesktop.machine1.Manager",
87                                 "ListMachines",
88                                 &error,
89                                 &reply,
90                                 "");
91         if (r < 0) {
92                 log_error("Could not get machines: %s", bus_error_message(&error, -r));
93                 return r;
94         }
95
96         if (arg_legend)
97                 printf("%-32s %-9s %-16s\n", "MACHINE", "CONTAINER", "SERVICE");
98
99         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssso)");
100         if (r < 0)
101                 return bus_log_parse_error(r);
102
103         while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) {
104                 printf("%-32s %-9s %-16s\n", name, class, service);
105
106                 k++;
107         }
108         if (r < 0)
109                 return bus_log_parse_error(r);
110
111         r = sd_bus_message_exit_container(reply);
112         if (r < 0)
113                 return bus_log_parse_error(r);
114
115         if (arg_legend)
116                 printf("\n%u machines listed.\n", k);
117
118         return 0;
119 }
120
121 static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
122         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
123         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
124         _cleanup_free_ char *path = NULL;
125         const char *cgroup;
126         int r, output_flags;
127         unsigned c;
128
129         assert(bus);
130         assert(unit);
131
132         if (arg_transport == BUS_TRANSPORT_REMOTE)
133                 return 0;
134
135         path = unit_dbus_path_from_name(unit);
136         if (!path)
137                 return log_oom();
138
139         r = sd_bus_get_property(
140                         bus,
141                         "org.freedesktop.systemd1",
142                         path,
143                         endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service",
144                         "ControlGroup",
145                         &error,
146                         &reply,
147                         "s");
148         if (r < 0) {
149                 log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
150                 return r;
151         }
152
153         r = sd_bus_message_read(reply, "s", &cgroup);
154         if (r < 0)
155                 return bus_log_parse_error(r);
156
157         if (isempty(cgroup))
158                 return 0;
159
160         if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
161                 return 0;
162
163         output_flags =
164                 arg_all * OUTPUT_SHOW_ALL |
165                 arg_full * OUTPUT_FULL_WIDTH;
166
167         c = columns();
168         if (c > 18)
169                 c -= 18;
170         else
171                 c = 0;
172
173         show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t  ", c, false, &leader, leader > 0, output_flags);
174         return 0;
175 }
176
177 static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) {
178         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
179         int r;
180
181         assert(bus);
182         assert(name);
183         assert(prefix);
184         assert(prefix2);
185
186         r = sd_bus_call_method(bus,
187                                "org.freedesktop.machine1",
188                                "/org/freedesktop/machine1",
189                                "org.freedesktop.machine1.Manager",
190                                "GetMachineAddresses",
191                                NULL,
192                                &reply,
193                                "s", name);
194         if (r < 0)
195                 return r;
196
197         r = sd_bus_message_enter_container(reply, 'a', "(iay)");
198         if (r < 0)
199                 return bus_log_parse_error(r);
200
201         while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
202                 int family;
203                 const void *a;
204                 size_t sz;
205                 char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
206
207                 r = sd_bus_message_read(reply, "i", &family);
208                 if (r < 0)
209                         return bus_log_parse_error(r);
210
211                 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
212                 if (r < 0)
213                         return bus_log_parse_error(r);
214
215                 fputs(prefix, stdout);
216                 fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout);
217                 if (family == AF_INET6 && ifi > 0)
218                         printf("%%%i", ifi);
219                 fputc('\n', stdout);
220
221                 r = sd_bus_message_exit_container(reply);
222                 if (r < 0)
223                         return bus_log_parse_error(r);
224
225                 if (prefix != prefix2)
226                         prefix = prefix2;
227         }
228         if (r < 0)
229                 return bus_log_parse_error(r);
230
231         r = sd_bus_message_exit_container(reply);
232         if (r < 0)
233                 return bus_log_parse_error(r);
234
235         return 0;
236 }
237
238 static int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
239         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
240         const char *k, *v, *pretty = NULL;
241         int r;
242
243         assert(bus);
244         assert(name);
245         assert(prefix);
246
247         r = sd_bus_call_method(bus,
248                                "org.freedesktop.machine1",
249                                "/org/freedesktop/machine1",
250                                "org.freedesktop.machine1.Manager",
251                                "GetMachineOSRelease",
252                                NULL,
253                                &reply,
254                                "s", name);
255         if (r < 0)
256                 return r;
257
258         r = sd_bus_message_enter_container(reply, 'a', "{ss}");
259         if (r < 0)
260                 return bus_log_parse_error(r);
261
262         while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
263                 if (streq(k, "PRETTY_NAME"))
264                         pretty = v;
265
266         }
267         if (r < 0)
268                 return bus_log_parse_error(r);
269
270         r = sd_bus_message_exit_container(reply);
271         if (r < 0)
272                 return bus_log_parse_error(r);
273
274         if (pretty)
275                 printf("%s%s\n", prefix, pretty);
276
277         return 0;
278 }
279
280 typedef struct MachineStatusInfo {
281         char *name;
282         sd_id128_t id;
283         char *class;
284         char *service;
285         char *unit;
286         char *root_directory;
287         pid_t leader;
288         usec_t timestamp;
289         int *netif;
290         unsigned n_netif;
291 } MachineStatusInfo;
292
293 static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
294         char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
295         char since2[FORMAT_TIMESTAMP_MAX], *s2;
296         int ifi = -1;
297
298         assert(i);
299
300         fputs(strna(i->name), stdout);
301
302         if (!sd_id128_equal(i->id, SD_ID128_NULL))
303                 printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id));
304         else
305                 putchar('\n');
306
307         s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
308         s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
309
310         if (s1)
311                 printf("\t   Since: %s; %s\n", s2, s1);
312         else if (s2)
313                 printf("\t   Since: %s\n", s2);
314
315         if (i->leader > 0) {
316                 _cleanup_free_ char *t = NULL;
317
318                 printf("\t  Leader: %u", (unsigned) i->leader);
319
320                 get_process_comm(i->leader, &t);
321                 if (t)
322                         printf(" (%s)", t);
323
324                 putchar('\n');
325         }
326
327         if (i->service) {
328                 printf("\t Service: %s", i->service);
329
330                 if (i->class)
331                         printf("; class %s", i->class);
332
333                 putchar('\n');
334         } else if (i->class)
335                 printf("\t   Class: %s\n", i->class);
336
337         if (i->root_directory)
338                 printf("\t    Root: %s\n", i->root_directory);
339
340         if (i->n_netif > 0) {
341                 unsigned c;
342
343                 fputs("\t   Iface:", stdout);
344
345                 for (c = 0; c < i->n_netif; c++) {
346                         char name[IF_NAMESIZE+1] = "";
347
348                         if (if_indextoname(i->netif[c], name)) {
349                                 fputc(' ', stdout);
350                                 fputs(name, stdout);
351
352                                 if (ifi < 0)
353                                         ifi = i->netif[c];
354                                 else
355                                         ifi = 0;
356                         } else
357                                 printf(" %i", i->netif[c]);
358                 }
359
360                 fputc('\n', stdout);
361         }
362
363         print_addresses(bus, i->name, ifi,
364                        "\t Address: ",
365                        "\t          ");
366
367         print_os_release(bus, i->name, "\t      OS: ");
368
369         if (i->unit) {
370                 printf("\t    Unit: %s\n", i->unit);
371                 show_unit_cgroup(bus, i->unit, i->leader);
372         }
373 }
374
375 static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
376         MachineStatusInfo *i = userdata;
377         size_t l;
378         const void *v;
379         int r;
380
381         assert_cc(sizeof(int32_t) == sizeof(int));
382         r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l);
383         if (r < 0)
384                 return r;
385         if (r == 0)
386                 return -EBADMSG;
387
388         i->n_netif = l / sizeof(int32_t);
389         i->netif = memdup(v, l);
390         if (!i->netif)
391                 return -ENOMEM;
392
393         return 0;
394 }
395
396 static int show_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
397
398         static const struct bus_properties_map map[]  = {
399                 { "Name",              "s",  NULL,          offsetof(MachineStatusInfo, name) },
400                 { "Class",             "s",  NULL,          offsetof(MachineStatusInfo, class) },
401                 { "Service",           "s",  NULL,          offsetof(MachineStatusInfo, service) },
402                 { "Unit",              "s",  NULL,          offsetof(MachineStatusInfo, unit) },
403                 { "RootDirectory",     "s",  NULL,          offsetof(MachineStatusInfo, root_directory) },
404                 { "Leader",            "u",  NULL,          offsetof(MachineStatusInfo, leader) },
405                 { "Timestamp",         "t",  NULL,          offsetof(MachineStatusInfo, timestamp) },
406                 { "Id",                "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
407                 { "NetworkInterfaces", "ai", map_netif,     0 },
408                 {}
409         };
410
411         MachineStatusInfo info = {};
412         int r;
413
414         assert(path);
415         assert(new_line);
416
417         r = bus_map_all_properties(bus,
418                                    "org.freedesktop.machine1",
419                                    path,
420                                    map,
421                                    &info);
422         if (r < 0)
423                 return log_error_errno(r, "Could not get properties: %m");
424
425         if (*new_line)
426                 printf("\n");
427         *new_line = true;
428
429         print_machine_status_info(bus, &info);
430
431         free(info.name);
432         free(info.class);
433         free(info.service);
434         free(info.unit);
435         free(info.root_directory);
436         free(info.netif);
437
438         return r;
439 }
440
441 static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
442         int r;
443
444         if (*new_line)
445                 printf("\n");
446
447         *new_line = true;
448
449         r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, arg_property, arg_all);
450         if (r < 0)
451                 log_error_errno(r, "Could not get properties: %m");
452
453         return r;
454 }
455
456 static int show(sd_bus *bus, char **args, unsigned n) {
457         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
458         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
459         int r = 0;
460         unsigned i;
461         bool properties, new_line = false;
462
463         assert(bus);
464         assert(args);
465
466         properties = !strstr(args[0], "status");
467
468         pager_open_if_enabled();
469
470         if (properties && n <= 1) {
471
472                 /* If no argument is specified, inspect the manager
473                  * itself */
474                 r = show_properties(bus, "/org/freedesktop/machine1", &new_line);
475                 if (r < 0)
476                         return r;
477         }
478
479         for (i = 1; i < n; i++) {
480                 const char *path = NULL;
481
482                 r = sd_bus_call_method(
483                                         bus,
484                                         "org.freedesktop.machine1",
485                                         "/org/freedesktop/machine1",
486                                         "org.freedesktop.machine1.Manager",
487                                         "GetMachine",
488                                         &error,
489                                         &reply,
490                                         "s", args[i]);
491                 if (r < 0) {
492                         log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
493                         return r;
494                 }
495
496                 r = sd_bus_message_read(reply, "o", &path);
497                 if (r < 0)
498                         return bus_log_parse_error(r);
499
500                 if (properties)
501                         r = show_properties(bus, path, &new_line);
502                 else
503                         r = show_info(args[0], bus, path, &new_line);
504         }
505
506         return r;
507 }
508
509 static int kill_machine(sd_bus *bus, char **args, unsigned n) {
510         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
511         unsigned i;
512
513         assert(args);
514
515         if (!arg_kill_who)
516                 arg_kill_who = "all";
517
518         for (i = 1; i < n; i++) {
519                 int r;
520
521                 r = sd_bus_call_method(
522                                         bus,
523                                         "org.freedesktop.machine1",
524                                         "/org/freedesktop/machine1",
525                                         "org.freedesktop.machine1.Manager",
526                                         "KillMachine",
527                                         &error,
528                                         NULL,
529                                         "ssi", args[i], arg_kill_who, arg_signal);
530                 if (r < 0) {
531                         log_error("Could not kill machine: %s", bus_error_message(&error, -r));
532                         return r;
533                 }
534         }
535
536         return 0;
537 }
538
539 static int reboot_machine(sd_bus *bus, char **args, unsigned n) {
540         arg_kill_who = "leader";
541         arg_signal = SIGINT; /* sysvinit + systemd */
542
543         return kill_machine(bus, args, n);
544 }
545
546 static int poweroff_machine(sd_bus *bus, char **args, unsigned n) {
547         arg_kill_who = "leader";
548         arg_signal = SIGRTMIN+4; /* only systemd */
549
550         return kill_machine(bus, args, n);
551 }
552
553 static int terminate_machine(sd_bus *bus, char **args, unsigned n) {
554         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
555         unsigned i;
556
557         assert(args);
558
559         for (i = 1; i < n; i++) {
560                 int r;
561
562                 r = sd_bus_call_method(
563                                 bus,
564                                 "org.freedesktop.machine1",
565                                 "/org/freedesktop/machine1",
566                                 "org.freedesktop.machine1.Manager",
567                                 "TerminateMachine",
568                                 &error,
569                                 NULL,
570                                 "s", args[i]);
571                 if (r < 0) {
572                         log_error("Could not terminate machine: %s", bus_error_message(&error, -r));
573                         return r;
574                 }
575         }
576
577         return 0;
578 }
579
580 static int machine_get_leader(sd_bus *bus, const char *name, pid_t *ret) {
581         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
582         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *reply2 = NULL;
583         const char *object;
584         uint32_t leader;
585         int r;
586
587         assert(bus);
588         assert(name);
589         assert(ret);
590
591         r = sd_bus_call_method(
592                         bus,
593                         "org.freedesktop.machine1",
594                         "/org/freedesktop/machine1",
595                         "org.freedesktop.machine1.Manager",
596                         "GetMachine",
597                         &error,
598                         &reply,
599                         "s", name);
600         if (r < 0) {
601                 log_error("Could not get path to machine: %s", bus_error_message(&error, -r));
602                 return r;
603         }
604
605         r = sd_bus_message_read(reply, "o", &object);
606         if (r < 0)
607                 return bus_log_parse_error(r);
608
609         r = sd_bus_get_property(
610                         bus,
611                         "org.freedesktop.machine1",
612                         object,
613                         "org.freedesktop.machine1.Machine",
614                         "Leader",
615                         &error,
616                         &reply2,
617                         "u");
618         if (r < 0)
619                 return log_error_errno(r, "Failed to retrieve PID of leader: %m");
620
621         r = sd_bus_message_read(reply2, "u", &leader);
622         if (r < 0)
623                 return bus_log_parse_error(r);
624
625         *ret = leader;
626         return 0;
627 }
628
629 static int bind_mount(sd_bus *bus, char **args, unsigned n) {
630         char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
631         pid_t child, leader;
632         const char *dest;
633         siginfo_t si;
634         bool mount_slave_created = false, mount_slave_mounted = false,
635                 mount_tmp_created = false, mount_tmp_mounted = false,
636                 mount_outside_created = false, mount_outside_mounted = false;
637         int r;
638
639         /* One day, when bind mounting /proc/self/fd/n works across
640          * namespace boundaries we should rework this logic to make
641          * use of it... */
642
643         if (n > 4) {
644                 log_error("Too many arguments.");
645                 return -EINVAL;
646         }
647
648         dest = args[3] ?: args[2];
649         if (!path_is_absolute(dest)) {
650                 log_error("Destination path not absolute.");
651                 return -EINVAL;
652         }
653
654         p = strappenda("/run/systemd/nspawn/propagate/", args[1], "/");
655         if (access(p, F_OK) < 0) {
656                 log_error("Container does not allow propagation of mount points.");
657                 return -ENOTSUP;
658         }
659
660         r = machine_get_leader(bus, args[1], &leader);
661         if (r < 0)
662                 return r;
663
664         /* Our goal is to install a new bind mount into the container,
665            possibly read-only. This is irritatingly complex
666            unfortunately, currently.
667
668            First, we start by creating a private playground in /tmp,
669            that we can mount MS_SLAVE. (Which is necessary, since
670            MS_MOUNT cannot be applied to mounts with MS_SHARED parent
671            mounts.) */
672
673         if (!mkdtemp(mount_slave))
674                 return log_error_errno(errno, "Failed to create playground: %m");
675
676         mount_slave_created = true;
677
678         if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
679                 r = log_error_errno(errno, "Failed to make bind mount: %m");
680                 goto finish;
681         }
682
683         mount_slave_mounted = true;
684
685         if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
686                 r = log_error_errno(errno, "Failed to remount slave: %m");
687                 goto finish;
688         }
689
690         /* Second, we mount the source directory to a directory inside
691            of our MS_SLAVE playground. */
692         mount_tmp = strappenda(mount_slave, "/mount");
693         if (mkdir(mount_tmp, 0700) < 0) {
694                 r = log_error_errno(errno, "Failed to create temporary mount: %m");
695                 goto finish;
696         }
697
698         mount_tmp_created = true;
699
700         if (mount(args[2], mount_tmp, NULL, MS_BIND, NULL) < 0) {
701                 r = log_error_errno(errno, "Failed to overmount: %m");
702                 goto finish;
703         }
704
705         mount_tmp_mounted = true;
706
707         /* Third, we remount the new bind mount read-only if requested. */
708         if (arg_read_only)
709                 if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
710                         r = log_error_errno(errno, "Failed to mark read-only: %m");
711                         goto finish;
712                 }
713
714         /* Fourth, we move the new bind mount into the propagation
715          * directory. This way it will appear there read-only
716          * right-away. */
717
718         mount_outside = strappenda("/run/systemd/nspawn/propagate/", args[1], "/XXXXXX");
719         if (!mkdtemp(mount_outside)) {
720                 r = log_error_errno(errno, "Cannot create propagation directory: %m");
721                 goto finish;
722         }
723
724         mount_outside_created = true;
725
726         if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
727                 r = log_error_errno(errno, "Failed to move: %m");
728                 goto finish;
729         }
730
731         mount_outside_mounted = true;
732         mount_tmp_mounted = false;
733
734         (void) rmdir(mount_tmp);
735         mount_tmp_created = false;
736
737         (void) umount(mount_slave);
738         mount_slave_mounted = false;
739
740         (void) rmdir(mount_slave);
741         mount_slave_created = false;
742
743         child = fork();
744         if (child < 0) {
745                 r = log_error_errno(errno, "Failed to fork(): %m");
746                 goto finish;
747         }
748
749         if (child == 0) {
750                 const char *mount_inside;
751                 int mntfd;
752                 const char *q;
753
754                 q = procfs_file_alloca(leader, "ns/mnt");
755                 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
756                 if (mntfd < 0) {
757                         log_error_errno(errno, "Failed to open mount namespace of leader: %m");
758                         _exit(EXIT_FAILURE);
759                 }
760
761                 if (setns(mntfd, CLONE_NEWNS) < 0) {
762                         log_error_errno(errno, "Failed to join namespace of leader: %m");
763                         _exit(EXIT_FAILURE);
764                 }
765
766                 if (arg_mkdir)
767                         mkdir_p(dest, 0755);
768
769                 /* Fifth, move the mount to the right place inside */
770                 mount_inside = strappenda("/run/systemd/nspawn/incoming/", basename(mount_outside));
771                 if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
772                         log_error_errno(errno, "Failed to mount: %m");
773                         _exit(EXIT_FAILURE);
774                 }
775
776                 _exit(EXIT_SUCCESS);
777         }
778
779         r = wait_for_terminate(child, &si);
780         if (r < 0) {
781                 log_error_errno(r, "Failed to wait for client: %m");
782                 goto finish;
783         }
784         if (si.si_code != CLD_EXITED) {
785                 log_error("Client died abnormally.");
786                 r = -EIO;
787                 goto finish;
788         }
789         if (si.si_status != EXIT_SUCCESS) {
790                 r = -EIO;
791                 goto finish;
792         }
793
794         r = 0;
795
796 finish:
797         if (mount_outside_mounted)
798                 umount(mount_outside);
799         if (mount_outside_created)
800                 rmdir(mount_outside);
801
802         if (mount_tmp_mounted)
803                 umount(mount_tmp);
804         if (mount_tmp_created)
805                 umount(mount_tmp);
806
807         if (mount_slave_mounted)
808                 umount(mount_slave);
809         if (mount_slave_created)
810                 umount(mount_slave);
811
812         return r;
813 }
814
815 static int openpt_in_namespace(pid_t pid, int flags) {
816         _cleanup_close_pair_ int pair[2] = { -1, -1 };
817         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
818         union {
819                 struct cmsghdr cmsghdr;
820                 uint8_t buf[CMSG_SPACE(sizeof(int))];
821         } control = {};
822         struct msghdr mh = {
823                 .msg_control = &control,
824                 .msg_controllen = sizeof(control),
825         };
826         struct cmsghdr *cmsg;
827         int master = -1, r;
828         pid_t child;
829         siginfo_t si;
830
831         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
832         if (r < 0)
833                 return r;
834
835         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
836                 return -errno;
837
838         child = fork();
839         if (child < 0)
840                 return -errno;
841
842         if (child == 0) {
843                 pair[0] = safe_close(pair[0]);
844
845                 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
846                 if (r < 0)
847                         _exit(EXIT_FAILURE);
848
849                 master = posix_openpt(flags);
850                 if (master < 0)
851                         _exit(EXIT_FAILURE);
852
853                 cmsg = CMSG_FIRSTHDR(&mh);
854                 cmsg->cmsg_level = SOL_SOCKET;
855                 cmsg->cmsg_type = SCM_RIGHTS;
856                 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
857                 memcpy(CMSG_DATA(cmsg), &master, sizeof(int));
858
859                 mh.msg_controllen = cmsg->cmsg_len;
860
861                 if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
862                         _exit(EXIT_FAILURE);
863
864                 _exit(EXIT_SUCCESS);
865         }
866
867         pair[1] = safe_close(pair[1]);
868
869         r = wait_for_terminate(child, &si);
870         if (r < 0)
871                 return r;
872         if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
873                 return -EIO;
874
875         if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
876                 return -errno;
877
878         for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg))
879                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
880                         int *fds;
881                         unsigned n_fds;
882
883                         fds = (int*) CMSG_DATA(cmsg);
884                         n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
885
886                         if (n_fds != 1) {
887                                 close_many(fds, n_fds);
888                                 return -EIO;
889                         }
890
891                         master = fds[0];
892                 }
893
894         if (master < 0)
895                 return -EIO;
896
897         return master;
898 }
899
900 static int login_machine(sd_bus *bus, char **args, unsigned n) {
901         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
902         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
903         _cleanup_bus_close_unref_ sd_bus *container_bus = NULL;
904         _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
905         _cleanup_event_unref_ sd_event *event = NULL;
906         _cleanup_close_ int master = -1;
907         _cleanup_free_ char *getty = NULL;
908         const char *pty, *p;
909         pid_t leader;
910         sigset_t mask;
911         int r, ret = 0;
912
913         assert(bus);
914         assert(args);
915
916         if (arg_transport != BUS_TRANSPORT_LOCAL) {
917                 log_error("Login only supported on local machines.");
918                 return -ENOTSUP;
919         }
920
921         r = sd_event_default(&event);
922         if (r < 0)
923                 return log_error_errno(r, "Failed to get event loop: %m");
924
925         r = sd_bus_attach_event(bus, event, 0);
926         if (r < 0)
927                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
928
929         r = machine_get_leader(bus, args[1], &leader);
930         if (r < 0)
931                 return r;
932
933         master = openpt_in_namespace(leader, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
934         if (master < 0)
935                 return log_error_errno(master, "Failed to acquire pseudo tty: %m");
936
937         pty = ptsname(master);
938         if (!pty)
939                 return log_error_errno(errno, "Failed to get pty name: %m");
940
941         p = startswith(pty, "/dev/pts/");
942         if (!p) {
943                 log_error("Invalid pty name %s.", pty);
944                 return -EIO;
945         }
946
947         r = sd_bus_open_system_container(&container_bus, args[1]);
948         if (r < 0)
949                 return log_error_errno(r, "Failed to get container bus: %m");
950
951         getty = strjoin("container-getty@", p, ".service", NULL);
952         if (!getty)
953                 return log_oom();
954
955         if (unlockpt(master) < 0)
956                 return log_error_errno(errno, "Failed to unlock tty: %m");
957
958         r = sd_bus_call_method(container_bus,
959                                "org.freedesktop.systemd1",
960                                "/org/freedesktop/systemd1",
961                                "org.freedesktop.systemd1.Manager",
962                                "StartUnit",
963                                &error, &reply,
964                                "ss", getty, "replace");
965         if (r < 0) {
966                 log_error("Failed to start getty service: %s", bus_error_message(&error, r));
967                 return r;
968         }
969
970         container_bus = sd_bus_unref(container_bus);
971
972         assert_se(sigemptyset(&mask) == 0);
973         sigset_add_many(&mask, SIGWINCH, SIGTERM, SIGINT, -1);
974         assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
975
976         log_info("Connected to container %s. Press ^] three times within 1s to exit session.", args[1]);
977
978         sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
979         sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
980
981         r = pty_forward_new(event, master, &forward);
982         if (r < 0)
983                 return log_error_errno(r, "Failed to create PTY forwarder: %m");
984
985         r = sd_event_loop(event);
986         if (r < 0)
987                 return log_error_errno(r, "Failed to run event loop: %m");
988
989         forward = pty_forward_free(forward);
990
991         fputc('\n', stdout);
992
993         log_info("Connection to container %s terminated.", args[1]);
994
995         sd_event_get_exit_code(event, &ret);
996         return ret;
997 }
998
999 static void help(void) {
1000         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
1001                "Send control commands to or query the virtual machine and container registration manager.\n\n"
1002                "  -h --help              Show this help\n"
1003                "     --version           Show package version\n"
1004                "     --no-pager          Do not pipe output into a pager\n"
1005                "     --no-legend         Do not show the headers and footers\n"
1006                "  -H --host=[USER@]HOST  Operate on remote host\n"
1007                "  -M --machine=CONTAINER Operate on local container\n"
1008                "  -p --property=NAME     Show only properties by this name\n"
1009                "  -a --all               Show all properties, including empty ones\n"
1010                "  -l --full              Do not ellipsize output\n"
1011                "     --kill-who=WHO      Who to send signal to\n"
1012                "  -s --signal=SIGNAL     Which signal to send\n"
1013                "     --read-only         Create read-only bind mount\n"
1014                "     --mkdir             Create directory before bind mounting, if missing\n\n"
1015                "Commands:\n"
1016                "  list                   List running VMs and containers\n"
1017                "  status NAME...         Show VM/container status\n"
1018                "  show NAME...           Show properties of one or more VMs/containers\n"
1019                "  login NAME             Get a login prompt on a container\n"
1020                "  poweroff NAME...       Power off one or more containers\n"
1021                "  reboot NAME...         Reboot one or more containers\n"
1022                "  kill NAME...           Send signal to processes of a VM/container\n"
1023                "  terminate NAME...      Terminate one or more VMs/containers\n"
1024                "  bind NAME PATH [PATH]  Bind mount a path from the host into a container\n",
1025                program_invocation_short_name);
1026 }
1027
1028 static int parse_argv(int argc, char *argv[]) {
1029
1030         enum {
1031                 ARG_VERSION = 0x100,
1032                 ARG_NO_PAGER,
1033                 ARG_NO_LEGEND,
1034                 ARG_KILL_WHO,
1035                 ARG_READ_ONLY,
1036                 ARG_MKDIR,
1037         };
1038
1039         static const struct option options[] = {
1040                 { "help",            no_argument,       NULL, 'h'                 },
1041                 { "version",         no_argument,       NULL, ARG_VERSION         },
1042                 { "property",        required_argument, NULL, 'p'                 },
1043                 { "all",             no_argument,       NULL, 'a'                 },
1044                 { "full",            no_argument,       NULL, 'l'                 },
1045                 { "no-pager",        no_argument,       NULL, ARG_NO_PAGER        },
1046                 { "no-legend",       no_argument,       NULL, ARG_NO_LEGEND       },
1047                 { "kill-who",        required_argument, NULL, ARG_KILL_WHO        },
1048                 { "signal",          required_argument, NULL, 's'                 },
1049                 { "host",            required_argument, NULL, 'H'                 },
1050                 { "machine",         required_argument, NULL, 'M'                 },
1051                 { "read-only",       no_argument,       NULL, ARG_READ_ONLY       },
1052                 { "mkdir",           no_argument,       NULL, ARG_MKDIR           },
1053                 {}
1054         };
1055
1056         int c, r;
1057
1058         assert(argc >= 0);
1059         assert(argv);
1060
1061         while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0)
1062
1063                 switch (c) {
1064
1065                 case 'h':
1066                         help();
1067                         return 0;
1068
1069                 case ARG_VERSION:
1070                         puts(PACKAGE_STRING);
1071                         puts(SYSTEMD_FEATURES);
1072                         return 0;
1073
1074                 case 'p':
1075                         r = strv_extend(&arg_property, optarg);
1076                         if (r < 0)
1077                                 return log_oom();
1078
1079                         /* If the user asked for a particular
1080                          * property, show it to him, even if it is
1081                          * empty. */
1082                         arg_all = true;
1083                         break;
1084
1085                 case 'a':
1086                         arg_all = true;
1087                         break;
1088
1089                 case 'l':
1090                         arg_full = true;
1091                         break;
1092
1093                 case ARG_NO_PAGER:
1094                         arg_no_pager = true;
1095                         break;
1096
1097                 case ARG_NO_LEGEND:
1098                         arg_legend = false;
1099                         break;
1100
1101                 case ARG_KILL_WHO:
1102                         arg_kill_who = optarg;
1103                         break;
1104
1105                 case 's':
1106                         arg_signal = signal_from_string_try_harder(optarg);
1107                         if (arg_signal < 0) {
1108                                 log_error("Failed to parse signal string %s.", optarg);
1109                                 return -EINVAL;
1110                         }
1111                         break;
1112
1113                 case 'H':
1114                         arg_transport = BUS_TRANSPORT_REMOTE;
1115                         arg_host = optarg;
1116                         break;
1117
1118                 case 'M':
1119                         arg_transport = BUS_TRANSPORT_CONTAINER;
1120                         arg_host = optarg;
1121                         break;
1122
1123                 case ARG_READ_ONLY:
1124                         arg_read_only = true;
1125                         break;
1126
1127                 case ARG_MKDIR:
1128                         arg_mkdir = true;
1129                         break;
1130
1131                 case '?':
1132                         return -EINVAL;
1133
1134                 default:
1135                         assert_not_reached("Unhandled option");
1136                 }
1137
1138         return 1;
1139 }
1140
1141 static int machinectl_main(sd_bus *bus, int argc, char *argv[]) {
1142
1143         static const struct {
1144                 const char* verb;
1145                 const enum {
1146                         MORE,
1147                         LESS,
1148                         EQUAL
1149                 } argc_cmp;
1150                 const int argc;
1151                 int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
1152         } verbs[] = {
1153                 { "list",                  LESS,   1, list_machines     },
1154                 { "status",                MORE,   2, show              },
1155                 { "show",                  MORE,   1, show              },
1156                 { "terminate",             MORE,   2, terminate_machine },
1157                 { "reboot",                MORE,   2, reboot_machine    },
1158                 { "poweroff",              MORE,   2, poweroff_machine  },
1159                 { "kill",                  MORE,   2, kill_machine      },
1160                 { "login",                 MORE,   2, login_machine     },
1161                 { "bind",                  MORE,   3, bind_mount        },
1162         };
1163
1164         int left;
1165         unsigned i;
1166
1167         assert(argc >= 0);
1168         assert(argv);
1169
1170         left = argc - optind;
1171
1172         if (left <= 0)
1173                 /* Special rule: no arguments means "list" */
1174                 i = 0;
1175         else {
1176                 if (streq(argv[optind], "help")) {
1177                         help();
1178                         return 0;
1179                 }
1180
1181                 for (i = 0; i < ELEMENTSOF(verbs); i++)
1182                         if (streq(argv[optind], verbs[i].verb))
1183                                 break;
1184
1185                 if (i >= ELEMENTSOF(verbs)) {
1186                         log_error("Unknown operation %s", argv[optind]);
1187                         return -EINVAL;
1188                 }
1189         }
1190
1191         switch (verbs[i].argc_cmp) {
1192
1193         case EQUAL:
1194                 if (left != verbs[i].argc) {
1195                         log_error("Invalid number of arguments.");
1196                         return -EINVAL;
1197                 }
1198
1199                 break;
1200
1201         case MORE:
1202                 if (left < verbs[i].argc) {
1203                         log_error("Too few arguments.");
1204                         return -EINVAL;
1205                 }
1206
1207                 break;
1208
1209         case LESS:
1210                 if (left > verbs[i].argc) {
1211                         log_error("Too many arguments.");
1212                         return -EINVAL;
1213                 }
1214
1215                 break;
1216
1217         default:
1218                 assert_not_reached("Unknown comparison operator.");
1219         }
1220
1221         return verbs[i].dispatch(bus, argv + optind, left);
1222 }
1223
1224 int main(int argc, char*argv[]) {
1225         _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1226         int r;
1227
1228         setlocale(LC_ALL, "");
1229         log_parse_environment();
1230         log_open();
1231
1232         r = parse_argv(argc, argv);
1233         if (r <= 0)
1234                 goto finish;
1235
1236         r = bus_open_transport(arg_transport, arg_host, false, &bus);
1237         if (r < 0) {
1238                 log_error_errno(r, "Failed to create bus connection: %m");
1239                 goto finish;
1240         }
1241
1242         r = machinectl_main(bus, argc, argv);
1243
1244 finish:
1245         pager_close();
1246
1247         strv_free(arg_property);
1248
1249         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1250 }