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