terminal-util.c revision 1ba239315ff449779189bde77361f323851dc39f
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2010 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic volatile unsigned cached_columns = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic volatile unsigned cached_lines = 0;
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poetteringint read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering if (tcgetattr(fileno(f), &old_termios) >= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering tcsetattr(fileno(f), TCSADRAIN, &old_termios);
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering tcsetattr(fileno(f), TCSADRAIN, &old_termios);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint ask_char(char *ret, const char *replies, const char *text, ...) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = read_one_char(stdin, &c, USEC_INFINITY, &need_nl);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering puts("Read unexpected character, please try again.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint ask_string(char **ret, const char *text, ...) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen if (!fgets(line, sizeof(line), stdin))
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringint reset_terminal_fd(int fd, bool switch_to_text) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Set terminal to some sane defaults */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* We leave locked terminal attributes untouched, so that
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * Plymouth may set whatever it wants to set, and we don't
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * interfere with that. */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* Disable exclusive mode, just in case */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Switch to text mode */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Enable console unicode mode */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* We only reset the stuff that matters to the software. How
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * hardware is set up we don't touch assuming that somebody
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * else will do that for us */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (tcsetattr(fd, TCSANOW, &termios) < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering /* Just in case, flush all crap out */
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering /* We open the terminal with O_NONBLOCK here, to ensure we
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * don't block on carrier if this is a terminal with carrier
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * configured. */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringint open_terminal(const char *name, int mode) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering unsigned c = 0;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * If a TTY is in the process of being closed opening it might
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * cause EIO. This is horribly awful, but unlikely to be
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * changed in the kernel. Hence we work around this problem by
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * retrying a couple of times.
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
8937e7b68940d0fa0d0aab90eb7425fa7dccebc9Lennart Poettering /* Max 1s in total */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int fd = -1, notify = -1, r = 0, wd = -1;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* We use inotify to be notified when the tty is closed. We
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * create the watch before checking if we can actually acquire
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * it, so that we don't lose any event.
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * Note: strictly speaking this actually watches for the
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * device being closed, it does *not* really watch whether a
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * tty loses its controlling process. However, unless some
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * rogue process uses TIOCNOTTY on /dev/tty *after* closing
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * its tty otherwise this will not become a problem. As long
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * as the administrator makes sure not configure any service
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * on the same tty as an untrusted user this should not be a
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering * problem. (Which he probably should not do anyway.) */
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering wd = inotify_add_watch(notify, name, IN_CLOSE);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* We pass here O_NOCTTY only so that we can check the return
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * value TIOCSCTTY and have a reliable way to figure out if we
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * successfully became the controlling process of the tty */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering * if we already own the tty. */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* First, try to get the tty */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Sometimes it makes sense to ignore TIOCSCTTY
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering * returning EPERM, i.e. when very likely we already
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * are have this controlling terminal. */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0 && (force || fail || r != -EPERM))
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering l = read(notify, &buffer, sizeof(buffer));
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (e->wd != wd || !(e->mask & IN_CLOSE)) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* We close the tty fd here since if the old session
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * ended our handle will be dead. It's important that
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * we do this after sleeping, so that we don't enter
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * an endless loop. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * by our own TIOCNOTTY */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Deallocate the VT if possible. If not possible
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * (i.e. because it is the active one), at least clear it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * entirely (including the scrollback buffer) */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* So this is not a VT. I guess we cannot deallocate
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering * it then. But let's at least clear the screen */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Try to deallocate */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering /* Couldn't deallocate, so let's clear it fully with
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering * scrollback */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return log_error_errno(fd, "Failed to acquire terminal: %m");
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek r = reset_terminal_fd(fd, true);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return log_error_errno(r, "Failed to duplicate terminal fd: %m");
a6c616024db23fef34152c1432892824a07799ccLennart Poetteringint status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers static const char status_indent[] = " "; /* "[" STATUS "] " */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering /* This is independent of logging, as status messages are
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering * optional and go exclusively to the console. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering IOVEC_SET_STRING(iovec[n++], status_indent);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = status_vprintf(status, ellipse, ephemeral, format, ap);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (i < 0 || i > 63)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringchar *resolve_dev_console(char **active) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Resolve where /dev/console is pointing to, if /sys is actually ours
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * (i.e. not read-only-mounted which is a sign for container setups) */
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* If multiple log outputs are configured the last one is what
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * /dev/console points to */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Get the active VC (e.g. tty1) */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringconst char *default_term_for_tty(const char *tty) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220";
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringunsigned columns(void) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering const char *e;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringunsigned lines(void) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *e;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering/* intended to be used as a SIGWINCH sighandler */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringvoid columns_lines_cache_reset(int signum) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering cached_on_tty = isatty(STDOUT_FILENO) > 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (r < 0 || s < 0 || t < 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering * dup2() was a NOP and the bit hence possibly set. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringint getttyname_malloc(int fd, char **ret) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *p;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *p;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering unsigned long ttynr;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (major(ttynr) == 0 && minor(ttynr) == 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringint get_ctty(pid_t pid, dev_t *_devnr, char **r) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering const char *p;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering /* This is an ugly hack */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Probably something like the ptys which have no
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * symlink in /dev/char. Let's return something
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering * vaguely useful. */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringint ptsname_namespace(int pty, char **ret) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* Like ptsname(), but doesn't assume that the path is
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering * accessible in the local namespace. */
2723b3b51d409340558e46e37e90525d4f880fe1Lennart Poettering if (asprintf(ret, "/dev/pts/%i", no) < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poetteringint openpt_in_namespace(pid_t pid, int flags) {
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering _cleanup_close_pair_ int pair[2] = { -1, -1 };
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_close_pair_ int pair[2] = { -1, -1 };
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);