chiark / gitweb /
nspawn: report back to systemd only very late whether we are OK
[elogind.git] / src / nspawn / nspawn.c
index f1f9b7828d9d876334d785d166fd27ee34e48180..6aaceac30b97a7321d9068688a600369340d8d3d 100644 (file)
@@ -31,7 +31,6 @@
 #include <stdio.h>
 #include <errno.h>
 #include <sys/prctl.h>
-#include <sys/capability.h>
 #include <getopt.h>
 #include <termios.h>
 #include <sys/signalfd.h>
 #include "base-filesystem.h"
 #include "barrier.h"
 #include "event-util.h"
+#include "capability.h"
 #include "cap-list.h"
 #include "btrfs-util.h"
+#include "machine-image.h"
 
 #ifdef HAVE_SECCOMP
 #include "seccomp-util.h"
@@ -2882,15 +2883,33 @@ static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo
 }
 
 static int determine_names(void) {
+        int r;
 
         if (!arg_image && !arg_directory) {
-                if (arg_machine)
-                        arg_directory = strappend("/var/lib/container/", arg_machine);
-                else
+                if (arg_machine) {
+                        _cleanup_(image_unrefp) Image *i = NULL;
+
+                        r = image_find(arg_machine, &i);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to find image for machine '%s': %m", arg_machine);
+                        else if (r == 0) {
+                                log_error("No image for machine '%s': %m", arg_machine);
+                                return -ENOENT;
+                        }
+
+                        if (i->type == IMAGE_GPT)
+                                r = set_sanitized_path(&arg_image, i->path);
+                        else
+                                r = set_sanitized_path(&arg_directory, i->path);
+                        if (r < 0)
+                                return log_error_errno(r, "Invalid image directory: %m");
+
+                        arg_read_only = arg_read_only || i->read_only;
+                } else
                         arg_directory = get_current_dir_name();
 
-                if (!arg_directory) {
-                        log_error("Failed to determine path, please use -D.");
+                if (!arg_directory && !arg_machine) {
+                        log_error("Failed to determine path, please use -D or -i.");
                         return -EINVAL;
                 }
         }
@@ -2931,13 +2950,12 @@ static int determine_names(void) {
 
 int main(int argc, char *argv[]) {
 
-        _cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL;
+        _cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *console = NULL;
         bool root_device_rw = true, home_device_rw = true, srv_device_rw = true;
         _cleanup_close_ int master = -1, image_fd = -1;
         _cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 };
         _cleanup_fdset_free_ FDSet *fds = NULL;
         int r, n_fd_passed, loop_nr = -1;
-        const char *console = NULL;
         char veth_name[IFNAMSIZ];
         bool secondary = false, remove_subvol = false;
         sigset_t mask, mask_chld;
@@ -3094,9 +3112,9 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        console = ptsname(master);
-        if (!console) {
-                r = log_error_errno(errno, "Failed to determine tty name: %m");
+        r = ptsname_malloc(master, &console);
+        if (r < 0) {
+                r = log_error_errno(r, "Failed to determine tty name: %m");
                 goto finish;
         }
 
@@ -3114,10 +3132,6 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Container running.");
-
         assert_se(sigemptyset(&mask) == 0);
         sigset_add_many(&mask, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1);
         assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
@@ -3462,6 +3476,7 @@ int main(int argc, char *argv[]) {
                 if (barrier_place_and_sync(&barrier)) {
                         _cleanup_event_unref_ sd_event *event = NULL;
                         _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
+                        char last_char = 0;
                         int ifi = 0;
 
                         r = move_network_interfaces(pid);
@@ -3498,7 +3513,11 @@ int main(int argc, char *argv[]) {
                         /* Notify the child that the parent is ready with all
                          * its setup, and that the child can now hand over
                          * control to the code to run inside the container. */
-                        (void)barrier_place(&barrier);
+                        (void) barrier_place(&barrier);
+
+                        sd_notify(false,
+                                  "READY=1\n"
+                                  "STATUS=Container running.");
 
                         r = sd_event_new(&event);
                         if (r < 0) {
@@ -3531,9 +3550,11 @@ int main(int argc, char *argv[]) {
                                 goto finish;
                         }
 
+                        pty_forward_last_char(forward, &last_char);
+
                         forward = pty_forward_free(forward);
 
-                        if (!arg_quiet)
+                        if (!arg_quiet && last_char != '\n')
                                 putc('\n', stdout);
 
                         /* Kill if it is not dead yet anyway */