1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/inotify.h>
29 #include <sys/socket.h>
30 #include <sys/sysmacros.h>
33 #include <linux/tiocl.h>
37 #include <sys/ioctl.h>
38 #include <sys/types.h>
42 #include "alloc-util.h"
50 #include "parse-util.h"
51 #include "process-util.h"
52 #include "socket-util.h"
53 #include "stat-util.h"
54 #include "string-util.h"
56 #include "terminal-util.h"
57 #include "time-util.h"
60 /// Additional includes needed by elogind
61 #include "path-util.h"
63 static volatile unsigned cached_columns = 0;
64 static volatile unsigned cached_lines = 0;
67 _cleanup_close_ int fd;
69 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
75 TIOCL_GETKMSGREDIRECT,
79 if (ioctl(fd, TIOCLINUX, tiocl) < 0)
82 vt = tiocl[0] <= 0 ? 1 : tiocl[0];
85 if (ioctl(fd, VT_ACTIVATE, vt) < 0)
91 #if 0 /// UNNEEDED by elogind
92 int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
93 struct termios old_termios, new_termios;
94 char c, line[LINE_MAX];
99 if (tcgetattr(fileno(f), &old_termios) >= 0) {
100 new_termios = old_termios;
102 new_termios.c_lflag &= ~ICANON;
103 new_termios.c_cc[VMIN] = 1;
104 new_termios.c_cc[VTIME] = 0;
106 if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
109 if (t != USEC_INFINITY) {
110 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
111 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
116 k = fread(&c, 1, 1, f);
118 tcsetattr(fileno(f), TCSADRAIN, &old_termios);
124 *need_nl = c != '\n';
131 if (t != USEC_INFINITY) {
132 if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
137 if (!fgets(line, sizeof(line), f))
138 return errno > 0 ? -errno : -EIO;
142 if (strlen(line) != 1)
152 #define DEFAULT_ASK_REFRESH_USEC (2*USEC_PER_SEC)
154 int ask_char(char *ret, const char *replies, const char *fmt, ...) {
166 if (colors_enabled())
167 fputs(ANSI_HIGHLIGHT, stdout);
175 if (colors_enabled())
176 fputs(ANSI_NORMAL, stdout);
180 r = read_one_char(stdin, &c, DEFAULT_ASK_REFRESH_USEC, &need_nl);
187 puts("Bad input, please try again.");
198 if (strchr(replies, c)) {
203 puts("Read unexpected character, please try again.");
207 int ask_string(char **ret, const char *text, ...) {
215 if (colors_enabled())
216 fputs(ANSI_HIGHLIGHT, stdout);
222 if (colors_enabled())
223 fputs(ANSI_NORMAL, stdout);
228 if (!fgets(line, sizeof(line), stdin))
229 return errno > 0 ? -errno : -EIO;
231 if (!endswith(line, "\n"))
250 int reset_terminal_fd(int fd, bool switch_to_text) {
251 struct termios termios;
254 /* Set terminal to some sane defaults */
258 /* We leave locked terminal attributes untouched, so that
259 * Plymouth may set whatever it wants to set, and we don't
260 * interfere with that. */
262 /* Disable exclusive mode, just in case */
263 (void) ioctl(fd, TIOCNXCL);
265 /* Switch to text mode */
267 (void) ioctl(fd, KDSETMODE, KD_TEXT);
269 /* Set default keyboard mode */
270 (void) vt_reset_keyboard(fd);
272 if (tcgetattr(fd, &termios) < 0) {
277 /* We only reset the stuff that matters to the software. How
278 * hardware is set up we don't touch assuming that somebody
279 * else will do that for us */
281 termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
282 termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
283 termios.c_oflag |= ONLCR;
284 termios.c_cflag |= CREAD;
285 termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
287 termios.c_cc[VINTR] = 03; /* ^C */
288 termios.c_cc[VQUIT] = 034; /* ^\ */
289 termios.c_cc[VERASE] = 0177;
290 termios.c_cc[VKILL] = 025; /* ^X */
291 termios.c_cc[VEOF] = 04; /* ^D */
292 termios.c_cc[VSTART] = 021; /* ^Q */
293 termios.c_cc[VSTOP] = 023; /* ^S */
294 termios.c_cc[VSUSP] = 032; /* ^Z */
295 termios.c_cc[VLNEXT] = 026; /* ^V */
296 termios.c_cc[VWERASE] = 027; /* ^W */
297 termios.c_cc[VREPRINT] = 022; /* ^R */
298 termios.c_cc[VEOL] = 0;
299 termios.c_cc[VEOL2] = 0;
301 termios.c_cc[VTIME] = 0;
302 termios.c_cc[VMIN] = 1;
304 if (tcsetattr(fd, TCSANOW, &termios) < 0)
308 /* Just in case, flush all crap out */
309 (void) tcflush(fd, TCIOFLUSH);
314 int reset_terminal(const char *name) {
315 _cleanup_close_ int fd = -1;
317 /* We open the terminal with O_NONBLOCK here, to ensure we
318 * don't block on carrier if this is a terminal with carrier
321 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
325 return reset_terminal_fd(fd, true);
329 int open_terminal(const char *name, int mode) {
334 * If a TTY is in the process of being closed opening it might
335 * cause EIO. This is horribly awful, but unlikely to be
336 * changed in the kernel. Hence we work around this problem by
337 * retrying a couple of times.
339 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
346 fd = open(name, mode, 0);
353 /* Max 1s in total */
357 usleep(50 * USEC_PER_MSEC);
370 #if 0 /// UNNEEDED by elogind
371 int acquire_terminal(
375 bool ignore_tiocstty_eperm,
378 int fd = -1, notify = -1, r = 0, wd = -1;
383 /* We use inotify to be notified when the tty is closed. We
384 * create the watch before checking if we can actually acquire
385 * it, so that we don't lose any event.
387 * Note: strictly speaking this actually watches for the
388 * device being closed, it does *not* really watch whether a
389 * tty loses its controlling process. However, unless some
390 * rogue process uses TIOCNOTTY on /dev/tty *after* closing
391 * its tty otherwise this will not become a problem. As long
392 * as the administrator makes sure not configure any service
393 * on the same tty as an untrusted user this should not be a
394 * problem. (Which he probably should not do anyway.) */
396 if (timeout != USEC_INFINITY)
397 ts = now(CLOCK_MONOTONIC);
399 if (!fail && !force) {
400 notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0));
406 wd = inotify_add_watch(notify, name, IN_CLOSE);
414 struct sigaction sa_old, sa_new = {
415 .sa_handler = SIG_IGN,
416 .sa_flags = SA_RESTART,
420 r = flush_fd(notify);
425 /* We pass here O_NOCTTY only so that we can check the return
426 * value TIOCSCTTY and have a reliable way to figure out if we
427 * successfully became the controlling process of the tty */
428 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
432 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
433 * if we already own the tty. */
434 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
436 /* First, try to get the tty */
437 if (ioctl(fd, TIOCSCTTY, force) < 0)
440 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
442 /* Sometimes, it makes sense to ignore TIOCSCTTY
443 * returning EPERM, i.e. when very likely we already
444 * are have this controlling terminal. */
445 if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
448 if (r < 0 && (force || fail || r != -EPERM))
459 union inotify_event_buffer buffer;
460 struct inotify_event *e;
463 if (timeout != USEC_INFINITY) {
466 n = now(CLOCK_MONOTONIC);
467 if (ts + timeout < n) {
472 r = fd_wait_for_event(notify, POLLIN, ts + timeout - n);
482 l = read(notify, &buffer, sizeof(buffer));
484 if (IN_SET(errno, EINTR, EAGAIN))
491 FOREACH_INOTIFY_EVENT(e, buffer, l) {
492 if (e->wd != wd || !(e->mask & IN_CLOSE)) {
501 /* We close the tty fd here since if the old session
502 * ended our handle will be dead. It's important that
503 * we do this after sleeping, so that we don't enter
504 * an endless loop. */
520 #if 0 /// UNNEEDED by elogind
521 int release_terminal(void) {
522 static const struct sigaction sa_new = {
523 .sa_handler = SIG_IGN,
524 .sa_flags = SA_RESTART,
527 _cleanup_close_ int fd = -1;
528 struct sigaction sa_old;
531 fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
535 /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
536 * by our own TIOCNOTTY */
537 assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
539 if (ioctl(fd, TIOCNOTTY) < 0)
542 assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
547 int terminal_vhangup_fd(int fd) {
550 if (ioctl(fd, TIOCVHANGUP) < 0)
556 int terminal_vhangup(const char *name) {
557 _cleanup_close_ int fd;
559 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
563 return terminal_vhangup_fd(fd);
566 int vt_disallocate(const char *name) {
567 _cleanup_close_ int fd = -1;
572 /* Deallocate the VT if possible. If not possible
573 * (i.e. because it is the active one), at least clear it
574 * entirely (including the scrollback buffer) */
576 e = path_startswith(name, "/dev/");
580 if (!tty_is_vc(name)) {
581 /* So this is not a VT. I guess we cannot deallocate
582 * it then. But let's at least clear the screen */
584 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
589 "\033[r" /* clear scrolling region */
590 "\033[H" /* move home */
591 "\033[2J", /* clear screen */
596 n = startswith(e, "tty");
600 r = safe_atou(n, &u);
607 /* Try to deallocate */
608 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
612 r = ioctl(fd, VT_DISALLOCATE, u);
621 /* Couldn't deallocate, so let's clear it fully with
623 fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
628 "\033[r" /* clear scrolling region */
629 "\033[H" /* move home */
630 "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
635 int make_console_stdio(void) {
638 /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
640 fd = acquire_terminal("/dev/console", false, true, true, USEC_INFINITY);
642 return log_error_errno(fd, "Failed to acquire terminal: %m");
644 r = reset_terminal_fd(fd, true);
646 log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
650 return log_error_errno(r, "Failed to duplicate terminal fd: %m");
656 bool tty_is_vc(const char *tty) {
659 return vtnr_from_tty(tty) >= 0;
662 bool tty_is_console(const char *tty) {
665 return streq(skip_dev_prefix(tty), "console");
668 int vtnr_from_tty(const char *tty) {
673 tty = skip_dev_prefix(tty);
675 if (!startswith(tty, "tty") )
678 if (tty[3] < '0' || tty[3] > '9')
681 r = safe_atoi(tty+3, &i);
691 #if 0 /// UNNEEDED by elogind
692 char *resolve_dev_console(char **active) {
695 /* Resolve where /dev/console is pointing to, if /sys is actually ours
696 * (i.e. not read-only-mounted which is a sign for container setups) */
698 if (path_is_read_only_fs("/sys") > 0)
701 if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
704 /* If multiple log outputs are configured the last one is what
705 * /dev/console points to */
706 tty = strrchr(*active, ' ');
712 if (streq(tty, "tty0")) {
715 /* Get the active VC (e.g. tty1) */
716 if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
725 int get_kernel_consoles(char ***consoles) {
726 _cleanup_strv_free_ char **con = NULL;
727 _cleanup_free_ char *line = NULL;
733 r = read_one_line_file("/sys/class/tty/console/active", &line);
739 _cleanup_free_ char *tty = NULL;
742 r = extract_first_word(&active, &tty, NULL, 0);
748 if (streq(tty, "tty0")) {
750 r = read_one_line_file("/sys/class/tty/tty0/active", &tty);
755 path = strappend("/dev/", tty);
759 if (access(path, F_OK) < 0) {
760 log_debug_errno(errno, "Console device %s is not accessible, skipping: %m", path);
765 r = strv_consume(&con, path);
770 if (strv_isempty(con)) {
771 log_debug("No devices found for system console");
773 r = strv_extend(&con, "/dev/console");
783 bool tty_is_vc_resolve(const char *tty) {
784 _cleanup_free_ char *active = NULL;
788 tty = skip_dev_prefix(tty);
790 if (streq(tty, "console")) {
791 tty = resolve_dev_console(&active);
796 return tty_is_vc(tty);
799 const char *default_term_for_tty(const char *tty) {
800 return tty && tty_is_vc_resolve(tty) ? "linux" : "vt220";
804 int fd_columns(int fd) {
805 struct winsize ws = {};
807 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
816 unsigned columns(void) {
820 if (_likely_(cached_columns > 0))
821 return cached_columns;
824 e = getenv("COLUMNS");
826 (void) safe_atoi(e, &c);
829 c = fd_columns(STDOUT_FILENO);
835 return cached_columns;
838 int fd_lines(int fd) {
839 struct winsize ws = {};
841 if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
850 unsigned lines(void) {
854 if (_likely_(cached_lines > 0))
860 (void) safe_atoi(e, &l);
863 l = fd_lines(STDOUT_FILENO);
872 /* intended to be used as a SIGWINCH sighandler */
873 #if 0 /// UNNEEDED by elogind
874 void columns_lines_cache_reset(int signum) {
881 static int cached_on_tty = -1;
883 if (_unlikely_(cached_on_tty < 0))
884 cached_on_tty = isatty(STDOUT_FILENO) > 0;
886 return cached_on_tty;
889 int make_stdio(int fd) {
894 if (dup2(fd, STDIN_FILENO) < 0 && r >= 0)
896 if (dup2(fd, STDOUT_FILENO) < 0 && r >= 0)
898 if (dup2(fd, STDERR_FILENO) < 0 && r >= 0)
904 /* Explicitly unset O_CLOEXEC, since if fd was < 3, then dup2() was a NOP and the bit hence possibly set. */
905 stdio_unset_cloexec();
910 int make_null_stdio(void) {
913 null_fd = open("/dev/null", O_RDWR|O_NOCTTY|O_CLOEXEC);
917 return make_stdio(null_fd);
920 int getttyname_malloc(int fd, char **ret) {
930 r = ttyname_r(fd, path, sizeof(path));
934 c = strdup(skip_dev_prefix(path));
951 int getttyname_harder(int fd, char **r) {
955 k = getttyname_malloc(fd, &s);
959 if (streq(s, "tty")) {
961 return get_ctty(0, NULL, r);
968 int get_ctty_devnr(pid_t pid, dev_t *d) {
970 _cleanup_free_ char *line = NULL;
976 p = procfs_file_alloca(pid, "stat");
977 r = read_one_line_file(p, &line);
981 p = strrchr(line, ')');
996 if (major(ttynr) == 0 && minor(ttynr) == 0)
1005 int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
1006 char fn[STRLEN("/dev/char/") + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
1007 _cleanup_free_ char *s = NULL;
1014 k = get_ctty_devnr(pid, &devnr);
1018 sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
1020 k = readlink_malloc(fn, &s);
1026 /* This is an ugly hack */
1027 if (major(devnr) == 136) {
1028 if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
1031 /* Probably something like the ptys which have no
1032 * symlink in /dev/char. Let's return something
1033 * vaguely useful. */
1040 if (startswith(s, "/dev/"))
1042 else if (startswith(s, "../"))
1059 #if 0 /// UNNEEDED by elogind
1060 int ptsname_malloc(int fd, char **ret) {
1073 if (ptsname_r(fd, c, l) == 0) {
1077 if (errno != ERANGE) {
1087 int ptsname_namespace(int pty, char **ret) {
1090 /* Like ptsname(), but doesn't assume that the path is
1091 * accessible in the local namespace. */
1093 r = ioctl(pty, TIOCGPTN, &no);
1100 if (asprintf(ret, "/dev/pts/%i", no) < 0)
1106 int openpt_in_namespace(pid_t pid, int flags) {
1107 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
1108 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1115 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
1119 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1129 pair[0] = safe_close(pair[0]);
1131 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
1133 _exit(EXIT_FAILURE);
1135 master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
1137 _exit(EXIT_FAILURE);
1139 if (unlockpt(master) < 0)
1140 _exit(EXIT_FAILURE);
1142 if (send_one_fd(pair[1], master, 0) < 0)
1143 _exit(EXIT_FAILURE);
1145 _exit(EXIT_SUCCESS);
1148 pair[1] = safe_close(pair[1]);
1150 r = wait_for_terminate(child, &si);
1153 if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1156 return receive_one_fd(pair[0], 0);
1159 int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
1160 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
1161 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1166 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
1170 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1180 pair[0] = safe_close(pair[0]);
1182 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
1184 _exit(EXIT_FAILURE);
1186 master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);
1188 _exit(EXIT_FAILURE);
1190 if (send_one_fd(pair[1], master, 0) < 0)
1191 _exit(EXIT_FAILURE);
1193 _exit(EXIT_SUCCESS);
1196 pair[1] = safe_close(pair[1]);
1198 r = wait_for_terminate(child, &si);
1201 if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1204 return receive_one_fd(pair[0], 0);
1208 static bool getenv_terminal_is_dumb(void) {
1215 return streq(e, "dumb");
1218 bool terminal_is_dumb(void) {
1222 return getenv_terminal_is_dumb();
1225 bool colors_enabled(void) {
1226 static int enabled = -1;
1228 if (_unlikely_(enabled < 0)) {
1229 #if 0 /// elogind does not allow such forcing, and we are never init!
1232 val = getenv_bool("SYSTEMD_COLORS");
1235 else if (getpid_cached() == 1)
1236 /* PID1 outputs to the console without holding it open all the time */
1237 enabled = !getenv_terminal_is_dumb();
1240 enabled = !terminal_is_dumb();
1246 bool underline_enabled(void) {
1247 static int enabled = -1;
1251 /* The Linux console doesn't support underlining, turn it off, but only there. */
1253 if (!colors_enabled())
1256 enabled = !streq_ptr(getenv("TERM"), "linux");
1262 int vt_default_utf8(void) {
1263 _cleanup_free_ char *b = NULL;
1266 /* Read the default VT UTF8 setting from the kernel */
1268 r = read_one_line_file("/sys/module/vt/parameters/default_utf8", &b);
1272 return parse_boolean(b);
1275 int vt_reset_keyboard(int fd) {
1278 /* If we can't read the default, then default to unicode. It's 2017 after all. */
1279 kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE;
1281 if (ioctl(fd, KDSKBMODE, kb) < 0)