summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/terminal-util.c48
-rw-r--r--src/basic/terminal-util.h1
-rw-r--r--src/machine/machine-dbus.c21
-rw-r--r--src/machine/machine.c19
-rw-r--r--src/machine/machine.h1
-rw-r--r--src/machine/machinectl.c2
6 files changed, 82 insertions, 10 deletions
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 50a86a331c..e9097d8ae5 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -1152,3 +1152,51 @@ int openpt_in_namespace(pid_t pid, int flags) {
return receive_one_fd(pair[0], 0);
}
+
+int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
+ _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
+ _cleanup_close_pair_ int pair[2] = { -1, -1 };
+ siginfo_t si;
+ pid_t child;
+ int r;
+
+ r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
+ if (r < 0)
+ return r;
+
+ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
+ return -errno;
+
+ child = fork();
+ if (child < 0)
+ return -errno;
+
+ if (child == 0) {
+ int master;
+
+ pair[0] = safe_close(pair[0]);
+
+ r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
+ if (r < 0)
+ _exit(EXIT_FAILURE);
+
+ master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);
+ if (master < 0)
+ _exit(EXIT_FAILURE);
+
+ if (send_one_fd(pair[1], master, 0) < 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ pair[1] = safe_close(pair[1]);
+
+ r = wait_for_terminate(child, &si);
+ if (r < 0)
+ return r;
+ if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
+ return -EIO;
+
+ return receive_one_fd(pair[0], 0);
+}
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index 050d0524a5..ee0b68b433 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -124,3 +124,4 @@ int ptsname_malloc(int fd, char **ret);
int ptsname_namespace(int pty, char **ret);
int openpt_in_namespace(pid_t pid, int flags);
+int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 21026829a9..6e41e92962 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -639,7 +639,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
_cleanup_free_ char *pty_name = NULL;
_cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = NULL;
sd_bus *container_bus = NULL;
- _cleanup_close_ int master = -1;
+ _cleanup_close_ int master = -1, slave = -1;
_cleanup_strv_free_ char **env = NULL, **args = NULL;
Machine *m = userdata;
const char *p, *unit, *user, *path, *description, *utmp_id;
@@ -700,8 +700,11 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
return r;
p = path_startswith(pty_name, "/dev/pts/");
- if (!p)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
+ assert(p);
+
+ slave = machine_open_terminal(m, pty_name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (slave < 0)
+ return slave;
utmp_id = path_startswith(pty_name, "/dev/");
assert(utmp_id);
@@ -735,16 +738,14 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
description = strjoina("Shell for User ", isempty(user) ? "root" : user);
r = sd_bus_message_append(tm,
- "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)",
+ "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)",
"Description", "s", description,
- "StandardInput", "s", "tty",
- "StandardOutput", "s", "tty",
- "StandardError", "s", "tty",
- "TTYPath", "s", pty_name,
+ "StandardInputFileDescriptor", "h", slave,
+ "StandardOutputFileDescriptor", "h", slave,
+ "StandardErrorFileDescriptor", "h", slave,
"SendSIGHUP", "b", true,
"IgnoreSIGPIPE", "b", false,
"KillMode", "s", "mixed",
- "TTYVHangup", "b", true,
"TTYReset", "b", true,
"UtmpIdentifier", "s", utmp_id,
"UtmpMode", "s", "user",
@@ -845,6 +846,8 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
if (r < 0)
return r;
+ slave = safe_close(slave);
+
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
diff --git a/src/machine/machine.c b/src/machine/machine.c
index 0f1942d1f4..7ab84607fb 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -572,6 +572,25 @@ int machine_openpt(Machine *m, int flags) {
}
}
+int machine_open_terminal(Machine *m, const char *path, int mode) {
+ assert(m);
+
+ switch (m->class) {
+
+ case MACHINE_HOST:
+ return open_terminal(path, mode);
+
+ case MACHINE_CONTAINER:
+ if (m->leader <= 0)
+ return -EINVAL;
+
+ return open_terminal_in_namespace(m->leader, path, mode);
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
MachineOperation *machine_operation_unref(MachineOperation *o) {
if (!o)
return NULL;
diff --git a/src/machine/machine.h b/src/machine/machine.h
index 5f978289f2..ad7f2a162f 100644
--- a/src/machine/machine.h
+++ b/src/machine/machine.h
@@ -123,3 +123,4 @@ const char *kill_who_to_string(KillWho k) _const_;
KillWho kill_who_from_string(const char *s) _pure_;
int machine_openpt(Machine *m, int flags);
+int machine_open_terminal(Machine *m, const char *path, int mode);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index e75b183328..0a21ab4415 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1390,7 +1390,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
- return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, machine);
+ return process_forward(event, &forward, master, 0, machine);
}
static int remove_image(int argc, char *argv[], void *userdata) {