mirror of
https://github.com/systemd/systemd.git
synced 2026-08-03 14:40:31 +00:00
basic/terminal-util: add a heuristic check whether terminfo file exists
This commit is contained in:
@@ -2584,6 +2584,57 @@ finish:
|
||||
return r;
|
||||
}
|
||||
|
||||
int have_terminfo_file(const char *name) {
|
||||
/* This is a heuristic check if we have the file, using the directory layout used on
|
||||
* current Linux systems. Checks for other layouts can be added later if appropriate. */
|
||||
int r;
|
||||
|
||||
assert(filename_is_valid(name));
|
||||
|
||||
_cleanup_free_ char *p = path_join("/usr/share/terminfo", CHAR_TO_STR(name[0]), name);
|
||||
if (!p)
|
||||
return log_oom_debug();
|
||||
|
||||
r = RET_NERRNO(access(p, F_OK));
|
||||
if (r == -ENOENT)
|
||||
return false;
|
||||
if (r < 0)
|
||||
return r;
|
||||
return true;
|
||||
}
|
||||
|
||||
int query_term_for_tty(const char *tty, char **ret_term) {
|
||||
_cleanup_free_ char *dcs_term = NULL;
|
||||
int r;
|
||||
|
||||
assert(tty);
|
||||
assert(ret_term);
|
||||
|
||||
if (tty_is_vc_resolve(tty))
|
||||
return strdup_to(ret_term, "linux");
|
||||
|
||||
/* Try to query the terminal implementation that we're on. This will not work in all
|
||||
* cases, which is fine, since this is intended to be used as a fallback. */
|
||||
|
||||
_cleanup_close_ int tty_fd = open_terminal(tty, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (tty_fd < 0)
|
||||
return log_debug_errno(tty_fd, "Failed to open %s to query terminfo: %m", tty);
|
||||
|
||||
r = terminal_get_terminfo_by_dcs(tty_fd, &dcs_term);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to query %s for terminfo: %m", tty);
|
||||
|
||||
r = have_terminfo_file(dcs_term);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to look for terminfo %s: %m", dcs_term);
|
||||
if (r == 0)
|
||||
return log_info_errno(SYNTHETIC_ERRNO(ENODATA),
|
||||
"Terminfo %s not found for %s.", dcs_term, tty);
|
||||
|
||||
*ret_term = TAKE_PTR(dcs_term);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int terminal_is_pty_fd(int fd) {
|
||||
int r;
|
||||
|
||||
|
||||
@@ -148,6 +148,8 @@ int terminal_get_size_by_dsr(int input_fd, int output_fd, unsigned *ret_rows, un
|
||||
int terminal_fix_size(int input_fd, int output_fd);
|
||||
|
||||
int terminal_get_terminfo_by_dcs(int fd, char **ret_name);
|
||||
int have_terminfo_file(const char *name);
|
||||
int query_term_for_tty(const char *tty, char **ret_term);
|
||||
|
||||
int terminal_is_pty_fd(int fd);
|
||||
|
||||
|
||||
@@ -242,6 +242,35 @@ TEST(terminal_get_terminfo_by_dcs) {
|
||||
log_info("terminal terminfo via DCS: %s, $TERM: %s", name, strnull(getenv("TERM")));
|
||||
}
|
||||
|
||||
TEST(have_terminfo_file) {
|
||||
int r;
|
||||
|
||||
FOREACH_STRING(s,
|
||||
"linux",
|
||||
"xterm",
|
||||
"vt220",
|
||||
"xterm-256color",
|
||||
"nosuchfile") {
|
||||
r = have_terminfo_file(s);
|
||||
log_info("%s: %s → %s", __func__+5, s, r >= 0 ? yes_no(r) : STRERROR(r));
|
||||
ASSERT_OK(r);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(query_term_for_tty) {
|
||||
int r;
|
||||
|
||||
FOREACH_STRING(s,
|
||||
"/dev/console",
|
||||
"/dev/stdin",
|
||||
"/dev/stdout") {
|
||||
_cleanup_free_ char *term = NULL;
|
||||
|
||||
r = query_term_for_tty(s, &term);
|
||||
log_info("%s: %s → %s/%s", __func__+5, s, STRERROR(r), strnull(term));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(terminal_is_pty_fd) {
|
||||
_cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF;
|
||||
int r;
|
||||
|
||||
Reference in New Issue
Block a user