tree-wide: various terminal related fixlets (#38544)

Fixes #38524.
Fixes #38527.
Fixes #38552.
This commit is contained in:
Yu Watanabe
2025-08-14 03:40:44 +09:00
committed by GitHub
11 changed files with 98 additions and 76 deletions
+9 -32
View File
@@ -128,26 +128,6 @@ static int flag_fds(
return 0;
}
static bool is_terminal_input(ExecInput i) {
return IN_SET(i,
EXEC_INPUT_TTY,
EXEC_INPUT_TTY_FORCE,
EXEC_INPUT_TTY_FAIL);
}
static bool is_terminal_output(ExecOutput o) {
return IN_SET(o,
EXEC_OUTPUT_TTY,
EXEC_OUTPUT_KMSG_AND_CONSOLE,
EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
}
static bool is_kmsg_output(ExecOutput o) {
return IN_SET(o,
EXEC_OUTPUT_KMSG,
EXEC_OUTPUT_KMSG_AND_CONSOLE);
}
static int open_null_as(int flags, int nfd) {
int fd;
@@ -252,8 +232,8 @@ static int connect_logger_as(
context->syslog_priority,
!!context->syslog_level_prefix,
false,
is_kmsg_output(output),
is_terminal_output(output)) < 0)
exec_output_is_kmsg(output),
exec_output_is_terminal(output)) < 0)
return -errno;
return move_fd(TAKE_FD(fd), nfd, false);
@@ -325,7 +305,7 @@ static int fixup_input(
std_input = context->std_input;
if (is_terminal_input(std_input) && !apply_tty_stdin)
if (exec_input_is_terminal(std_input) && !apply_tty_stdin)
return EXEC_INPUT_NULL;
if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
@@ -531,7 +511,7 @@ static int setup_output(
if (e == EXEC_OUTPUT_INHERIT &&
o == EXEC_OUTPUT_INHERIT &&
i == EXEC_INPUT_NULL &&
!is_terminal_input(context->std_input) &&
!exec_input_is_terminal(context->std_input) &&
getppid() != 1)
return fileno;
@@ -543,7 +523,7 @@ static int setup_output(
} else if (o == EXEC_OUTPUT_INHERIT) {
/* If input got downgraded, inherit the original value */
if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
if (i == EXEC_INPUT_NULL && exec_input_is_terminal(context->std_input))
return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
/* If the input is connected to anything that's not a /dev/null or a data fd, inherit that... */
@@ -564,7 +544,7 @@ static int setup_output(
return open_null_as(O_WRONLY, fileno);
case EXEC_OUTPUT_TTY:
if (is_terminal_input(i))
if (exec_input_is_terminal(i))
return RET_NERRNO(dup2(STDIN_FILENO, fileno));
return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
@@ -4880,8 +4860,8 @@ static void prepare_terminal(
assert(p);
/* We only try to reset things if we there's the chance our stdout points to a TTY */
if (!(is_terminal_output(context->std_output) ||
(context->std_output == EXEC_OUTPUT_INHERIT && is_terminal_input(context->std_input)) ||
if (!(context->std_output == EXEC_OUTPUT_TTY ||
(context->std_output == EXEC_OUTPUT_INHERIT && exec_input_is_terminal(context->std_input)) ||
context->std_output == EXEC_OUTPUT_NAMED_FD ||
p->stdout_fd >= 0))
return;
@@ -4921,10 +4901,7 @@ static int setup_term_environment(const ExecContext *context, char ***env) {
return 0;
/* Do we need $TERM at all? */
if (!is_terminal_input(context->std_input) &&
!is_terminal_output(context->std_output) &&
!is_terminal_output(context->std_error) &&
!context->tty_path)
if (!exec_context_has_tty(context))
return 0;
const char *tty_path = exec_context_tty_path(context);
+8 -20
View File
@@ -65,20 +65,6 @@
#include "utmp-wtmp.h"
#include "vpick.h"
static bool is_terminal_input(ExecInput i) {
return IN_SET(i,
EXEC_INPUT_TTY,
EXEC_INPUT_TTY_FORCE,
EXEC_INPUT_TTY_FAIL);
}
static bool is_terminal_output(ExecOutput o) {
return IN_SET(o,
EXEC_OUTPUT_TTY,
EXEC_OUTPUT_KMSG_AND_CONSOLE,
EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
}
const char* exec_context_tty_path(const ExecContext *context) {
assert(context);
@@ -151,8 +137,7 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *pa
if (parameters && parameters->stdout_fd >= 0 && isatty_safe(parameters->stdout_fd))
fd = parameters->stdout_fd;
else if (path && (context->tty_path || is_terminal_input(context->std_input) ||
is_terminal_output(context->std_output) || is_terminal_output(context->std_error))) {
else if (path && exec_context_has_tty(context)) {
fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return (void) log_debug_errno(fd, "Failed to open terminal '%s', ignoring: %m", path);
@@ -180,7 +165,7 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *pa
if (r < 0)
log_debug_errno(r, "Failed to configure TTY dimensions, ignoring: %m");
if (!sd_id128_is_null(invocation_id)) {
if (!sd_id128_is_null(invocation_id) && exec_context_shall_ansi_seq_reset(context)) {
sd_id128_t context_id;
r = osc_context_id_from_invocation_id(invocation_id, &context_id);
@@ -1000,9 +985,9 @@ static bool exec_context_may_touch_tty(const ExecContext *ec) {
return ec->tty_reset ||
ec->tty_vhangup ||
ec->tty_vt_disallocate ||
is_terminal_input(ec->std_input) ||
is_terminal_output(ec->std_output) ||
is_terminal_output(ec->std_error);
exec_input_is_terminal(ec->std_input) ||
ec->std_output == EXEC_OUTPUT_TTY ||
ec->std_error == EXEC_OUTPUT_TTY;
}
bool exec_context_may_touch_console(const ExecContext *ec) {
@@ -1024,6 +1009,9 @@ bool exec_context_shall_ansi_seq_reset(const ExecContext *c) {
if (!c->tty_reset)
return false;
/* FIXME:
* On invocation, we generate $TERM based on settings for StandardOutput= and friends and the kernel
* command line options, or propagate $TERM from the service manager. See setup_term_environment(). */
return !streq_ptr(strv_env_get(c->environment, "TERM"), "dumb");
}
+30
View File
@@ -458,6 +458,36 @@ typedef struct ExecParameters {
.pidref_transport_fd = -EBADF, \
}
static inline bool exec_input_is_terminal(ExecInput i) {
return IN_SET(i,
EXEC_INPUT_TTY,
EXEC_INPUT_TTY_FORCE,
EXEC_INPUT_TTY_FAIL);
}
static inline bool exec_output_is_terminal(ExecOutput o) {
return IN_SET(o,
EXEC_OUTPUT_TTY,
EXEC_OUTPUT_KMSG_AND_CONSOLE,
EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
}
static inline bool exec_output_is_kmsg(ExecOutput o) {
return IN_SET(o,
EXEC_OUTPUT_KMSG,
EXEC_OUTPUT_KMSG_AND_CONSOLE);
}
static inline bool exec_context_has_tty(const ExecContext *context) {
assert(context);
return
context->tty_path ||
exec_input_is_terminal(context->std_input) ||
context->std_output == EXEC_OUTPUT_TTY ||
context->std_error == EXEC_OUTPUT_TTY;
}
int exec_spawn(
Unit *unit,
ExecCommand *command,