From ee451d766a64117a41ec36dd71e61683c9d9b83c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Dec 2014 01:58:49 +0100 Subject: [PATCH] systemd-run: support -t mode when combined with -M For that, ask machined for a container PTY and use that. --- src/machine/machine-dbus.c | 7 ++- src/machine/machinectl.c | 2 +- src/run/run.c | 100 ++++++++++++++++++++++++++----------- src/shared/util.c | 24 +++++++++ src/shared/util.h | 2 + 5 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 7cabe0f2f..76c5dcf73 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -404,6 +404,7 @@ int bus_machine_method_open_pty(sd_bus *bus, sd_bus_message *message, void *user .msg_controllen = sizeof(control), }; Machine *m = userdata; + _cleanup_free_ char *pty_name = NULL; struct cmsghdr *cmsg; siginfo_t si; pid_t child; @@ -479,11 +480,15 @@ int bus_machine_method_open_pty(sd_bus *bus, sd_bus_message *message, void *user if (master < 0) return -EIO; + r = ptsname_malloc(master, &pty_name); + if (r < 0) + return r; + r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; - r = sd_bus_message_append(reply, "hs", master, ptsname(master)); + r = sd_bus_message_append(reply, "hs", master, pty_name); if (r < 0) return r; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index ccee16f2a..b9e8381e6 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1053,7 +1053,7 @@ static int login_machine(int argc, char *argv[], void *userdata) { r = sd_bus_message_read(reply, "hs", &master, &pty); if (r < 0) - return r; + return bus_log_parse_error(r); p = startswith(pty, "/dev/pts/"); if (!p) { diff --git a/src/run/run.c b/src/run/run.c index 242bed0a4..05bfc61be 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -657,26 +657,63 @@ static int transient_timer_set_properties(sd_bus_message *m) { static int start_transient_service( sd_bus *bus, - char **argv, - sd_bus_error *error) { + char **argv) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - _cleanup_free_ char *service = NULL; + _cleanup_free_ char *service = NULL, *pty_path = NULL; _cleanup_close_ int master = -1; - const char *pty_path = NULL; int r; assert(bus); assert(argv); if (arg_pty) { - master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY); - if (master < 0) - return log_error_errno(errno, "Failed to acquire pseudo tty: %m"); - pty_path = ptsname(master); - if (!pty_path) - return log_error_errno(errno, "Failed to determine tty name: %m"); + if (arg_transport == BUS_TRANSPORT_LOCAL) { + master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY); + if (master < 0) + return log_error_errno(errno, "Failed to acquire pseudo tty: %m"); + + r = ptsname_malloc(master, &pty_path); + if (r < 0) + return log_error_errno(r, "Failed to determine tty name: %m"); + + } else if (arg_transport == BUS_TRANSPORT_CONTAINER) { + _cleanup_bus_unref_ sd_bus *system_bus = NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + const char *s; + + r = sd_bus_open_system(&system_bus); + if (r < 0) + log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_call_method(system_bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "OpenMachinePTY", + &error, + &reply, + "s", arg_host); + if (r < 0) { + log_error("Failed to get machine PTY: %s", bus_error_message(&error, -r)); + return r; + } + + r = sd_bus_message_read(reply, "hs", &master, &s); + if (r < 0) + return bus_log_parse_error(r); + + master = fcntl(master, F_DUPFD_CLOEXEC, 3); + if (master < 0) + return log_error_errno(errno, "Failed to duplicate master fd: %m"); + + pty_path = strdup(s); + if (!pty_path) + return log_oom(); + } else + assert_not_reached("Can't allocate tty via ssh"); if (unlockpt(master) < 0) return log_error_errno(errno, "Failed to unlock tty: %m"); @@ -722,9 +759,11 @@ static int start_transient_service( if (r < 0) return bus_log_create_error(r); - r = sd_bus_call(bus, m, 0, error, NULL); - if (r < 0) - return bus_log_create_error(r); + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + log_error("Failed to start transient service unit: %s", bus_error_message(&error, -r)); + return r; + } if (master >= 0) { _cleanup_(pty_forward_freep) PTYForward *forward = NULL; @@ -769,9 +808,9 @@ static int start_transient_service( static int start_transient_scope( sd_bus *bus, - char **argv, - sd_bus_error *error) { + char **argv) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **env = NULL, **user_env = NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; _cleanup_free_ char *scope = NULL; @@ -815,15 +854,16 @@ static int start_transient_scope( if (r < 0) return bus_log_create_error(r); - /* aux */ + /* Auxiliary units */ r = sd_bus_message_append(m, "a(sa(sv))", 0); if (r < 0) return bus_log_create_error(r); - /* send dbus */ - r = sd_bus_call(bus, m, 0, error, NULL); - if (r < 0) - return bus_log_create_error(r); + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r)); + return r; + } if (arg_nice_set) { if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0) @@ -889,9 +929,9 @@ static int start_transient_scope( static int start_transient_timer( sd_bus *bus, - char **argv, - sd_bus_error *error) { + char **argv) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; _cleanup_free_ char *timer = NULL, *service = NULL; int r; @@ -999,10 +1039,11 @@ static int start_transient_timer( if (r < 0) return bus_log_create_error(r); - /* send dbus */ - r = sd_bus_call(bus, m, 0, error, NULL); - if (r < 0) - return bus_log_create_error(r); + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r)); + return r; + } log_info("Running as unit %s.", timer); if (argv[0]) @@ -1012,7 +1053,6 @@ static int start_transient_timer( } int main(int argc, char* argv[]) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_close_unref_ sd_bus *bus = NULL; _cleanup_free_ char *description = NULL, *command = NULL; int r; @@ -1062,11 +1102,11 @@ int main(int argc, char* argv[]) { } if (arg_scope) - r = start_transient_scope(bus, argv + optind, &error); + r = start_transient_scope(bus, argv + optind); else if (with_timer()) - r = start_transient_timer(bus, argv + optind, &error); + r = start_transient_timer(bus, argv + optind); else - r = start_transient_service(bus, argv + optind, &error); + r = start_transient_service(bus, argv + optind); finish: strv_free(arg_environment); diff --git a/src/shared/util.c b/src/shared/util.c index 06b607784..6695a85a1 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -7433,3 +7433,27 @@ int sethostname_idempotent(const char *s) { return 1; } + +int ptsname_malloc(int fd, char **ret) { + size_t l = 100; + + for (;;) { + char *c; + + c = new(char, l); + if (!c) + return -ENOMEM; + + if (ptsname_r(fd, c, l) == 0) { + *ret = c; + return 0; + } + if (errno != ERANGE) { + free(c); + return -errno; + } + + free(c); + l *= 2; + } +} diff --git a/src/shared/util.h b/src/shared/util.h index 1804b8c3a..d3e78e43c 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -1052,3 +1052,5 @@ int sethostname_idempotent(const char *s); (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len)) #define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW) + +int ptsname_malloc(int fd, char **ret); -- 2.30.2