1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

Merge pull request #30585 from YHNdnzj/isatty-handling

various: clean up isatty() handling
This commit is contained in:
Yu Watanabe 2023-12-23 03:19:19 +09:00 committed by GitHub
commit 2b575c0c95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 53 additions and 47 deletions

View File

@ -28,6 +28,7 @@
#include "stdio-util.h"
#include "string-util.h"
#include "sync-util.h"
#include "terminal-util.h"
#include "tmpfile-util.h"
/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
@ -1459,7 +1460,7 @@ int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
* and don't call isatty() on an invalid fd */
flags |= READ_LINE_NOT_A_TTY;
else
flags |= isatty(fd) ? READ_LINE_IS_A_TTY : READ_LINE_NOT_A_TTY;
flags |= isatty_safe(fd) ? READ_LINE_IS_A_TTY : READ_LINE_NOT_A_TTY;
}
if (FLAGS_SET(flags, READ_LINE_IS_A_TTY))
break;

View File

@ -414,7 +414,7 @@ static bool check_console_fd_is_tty(void) {
return false;
if (console_fd_is_tty < 0)
console_fd_is_tty = isatty(console_fd) > 0;
console_fd_is_tty = isatty_safe(console_fd);
return console_fd_is_tty;
}

View File

@ -54,6 +54,18 @@ static volatile int cached_on_dev_null = -1;
static volatile int cached_color_mode = _COLOR_INVALID;
static volatile int cached_underline_enabled = -1;
bool isatty_safe(int fd) {
assert(fd >= 0);
if (isatty(fd))
return true;
/* Be resilient if we're working on stdio, since they're set up by parent process. */
assert(errno != EBADF || IN_SET(fd, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO));
return false;
}
int chvt(int vt) {
_cleanup_close_ int fd = -EBADF;
@ -240,7 +252,7 @@ int reset_terminal_fd(int fd, bool switch_to_text) {
assert(fd >= 0);
if (isatty(fd) < 1)
if (!isatty_safe(fd))
return log_debug_errno(errno, "Asked to reset a terminal that actually isn't a terminal: %m");
/* We leave locked terminal attributes untouched, so that Plymouth may set whatever it wants to set,
@ -347,7 +359,7 @@ int open_terminal(const char *name, int mode) {
c++;
}
if (isatty(fd) < 1)
if (!isatty_safe(fd))
return negative_errno();
return TAKE_FD(fd);
@ -1447,38 +1459,33 @@ int vt_reset_keyboard(int fd) {
}
int vt_restore(int fd) {
static const struct vt_mode mode = {
.mode = VT_AUTO,
};
int r, q = 0;
if (isatty(fd) < 1)
int r, ret = 0;
assert(fd >= 0);
if (!isatty_safe(fd))
return log_debug_errno(errno, "Asked to restore the VT for an fd that does not refer to a terminal: %m");
if (ioctl(fd, KDSETMODE, KD_TEXT) < 0)
q = log_debug_errno(errno, "Failed to set VT in text mode, ignoring: %m");
RET_GATHER(ret, log_debug_errno(errno, "Failed to set VT to text mode, ignoring: %m"));
r = vt_reset_keyboard(fd);
if (r < 0) {
log_debug_errno(r, "Failed to reset keyboard mode, ignoring: %m");
if (q >= 0)
q = r;
}
if (r < 0)
RET_GATHER(ret, log_debug_errno(r, "Failed to reset keyboard mode, ignoring: %m"));
if (ioctl(fd, VT_SETMODE, &mode) < 0) {
log_debug_errno(errno, "Failed to set VT_AUTO mode, ignoring: %m");
if (q >= 0)
q = -errno;
}
if (ioctl(fd, VT_SETMODE, &mode) < 0)
RET_GATHER(ret, log_debug_errno(errno, "Failed to set VT_AUTO mode, ignoring: %m"));
r = fchmod_and_chown(fd, TTY_MODE, 0, GID_INVALID);
if (r < 0) {
log_debug_errno(r, "Failed to chmod()/chown() VT, ignoring: %m");
if (q >= 0)
q = r;
}
if (r < 0)
RET_GATHER(ret, log_debug_errno(r, "Failed to chmod()/chown() VT, ignoring: %m"));
return q;
return ret;
}
int vt_release(int fd, bool restore) {
@ -1488,7 +1495,7 @@ int vt_release(int fd, bool restore) {
* sent by the kernel and optionally reset the VT in text and auto
* VT-switching modes. */
if (isatty(fd) < 1)
if (!isatty_safe(fd))
return log_debug_errno(errno, "Asked to release the VT for an fd that does not refer to a terminal: %m");
if (ioctl(fd, VT_RELDISP, 1) < 0)
@ -1698,7 +1705,7 @@ int get_default_background_color(double *ret_red, double *ret_green, double *ret
if (!colors_enabled())
return -EOPNOTSUPP;
if (isatty(STDOUT_FILENO) < 1 || isatty(STDIN_FILENO) < 1)
if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))
return -EOPNOTSUPP;
if (streq_ptr(getenv("TERM"), "linux")) {

View File

@ -86,6 +86,8 @@
/* Set cursor to top left corner and clear screen */
#define ANSI_HOME_CLEAR "\x1B[H\x1B[2J"
bool isatty_safe(int fd);
int reset_terminal_fd(int fd, bool switch_to_text);
int reset_terminal(const char *name);
int set_terminal_cursor_position(int fd, unsigned int row, unsigned int column);

View File

@ -1369,7 +1369,7 @@ static int verb_capture(int argc, char **argv, void *userdata) {
"busctl (systemd) " STRINGIFY(PROJECT_VERSION) " (Git " GIT_VERSION ")";
int r;
if (isatty(fileno(stdout)) > 0)
if (isatty(STDOUT_FILENO))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Refusing to write message data to console, please redirect output to a file.");

View File

@ -670,12 +670,8 @@ static int chown_terminal(int fd, uid_t uid) {
assert(fd >= 0);
/* Before we chown/chmod the TTY, let's ensure this is actually a tty */
if (isatty(fd) < 1) {
if (IN_SET(errno, EINVAL, ENOTTY))
return 0; /* not a tty */
return -errno;
}
if (!isatty_safe(fd))
return 0;
/* This might fail. What matters are the results. */
r = fchmod_and_chown(fd, TTY_MODE, uid, GID_INVALID);

View File

@ -147,7 +147,7 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p)
const char *path = exec_context_tty_path(context);
if (p && p->stdin_fd >= 0 && isatty(p->stdin_fd))
if (p && p->stdin_fd >= 0 && isatty_safe(p->stdin_fd))
fd = p->stdin_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))) {

View File

@ -315,7 +315,7 @@ static int print_newline(FILE *f, const char *data, size_t l) {
/* Don't bother unless this is a tty */
fd = fileno(f);
if (fd >= 0 && isatty(fd) <= 0)
if (fd >= 0 && !isatty_safe(fd))
return 0;
if (fputc('\n', f) != '\n')

View File

@ -94,9 +94,8 @@ static int verify_tty(const char *name) {
if (fd < 0)
return -errno;
errno = 0;
if (isatty(fd) <= 0)
return errno_or_else(EIO);
if (!isatty_safe(fd))
return -errno;
return 0;
}

View File

@ -13,6 +13,7 @@
#include "main-func.h"
#include "process-util.h"
#include "sigbus.h"
#include "terminal-util.h"
static int run(int argc, char *argv[]) {
_cleanup_(server_freep) Server *s = NULL;
@ -35,7 +36,7 @@ static int run(int argc, char *argv[]) {
* daemon when it comes to logging hence LOG_TARGET_AUTO won't do the right thing for
* us. Hence explicitly log to the console if we're started from a console or to kmsg
* otherwise. */
log_target = isatty(STDERR_FILENO) > 0 ? LOG_TARGET_CONSOLE : LOG_TARGET_KMSG;
log_target = isatty(STDERR_FILENO) ? LOG_TARGET_CONSOLE : LOG_TARGET_KMSG;
log_set_prohibit_ipc(true); /* better safe than sorry */
log_set_target(log_target);

View File

@ -289,7 +289,7 @@ static int handle_arg_console(const char *arg) {
else if (streq(arg, "passive"))
arg_console_mode = CONSOLE_PASSIVE;
else if (streq(arg, "pipe")) {
if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0)
if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
log_full(arg_quiet ? LOG_DEBUG : LOG_NOTICE,
"Console mode 'pipe' selected, but standard input/output are connected to an interactive TTY. "
"Most likely you want to use 'interactive' console mode for proper interactivity and shell job control. "
@ -297,7 +297,7 @@ static int handle_arg_console(const char *arg) {
arg_console_mode = CONSOLE_PIPE;
} else if (streq(arg, "autopipe")) {
if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0)
if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))
arg_console_mode = CONSOLE_INTERACTIVE;
else
arg_console_mode = CONSOLE_PIPE;
@ -5766,9 +5766,8 @@ static int run(int argc, char *argv[]) {
goto finish;
if (arg_console_mode < 0)
arg_console_mode =
isatty(STDIN_FILENO) > 0 &&
isatty(STDOUT_FILENO) > 0 ? CONSOLE_INTERACTIVE : CONSOLE_READ_ONLY;
arg_console_mode = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) ?
CONSOLE_INTERACTIVE : CONSOLE_READ_ONLY;
if (arg_console_mode == CONSOLE_PIPE) /* if we pass STDERR on to the container, don't add our own logs into it too */
arg_quiet = true;

View File

@ -30,8 +30,9 @@ static int write_to_terminal(const char *tty, const char *message) {
fd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return -errno;
if (!isatty(fd))
return -ENOTTY;
if (!isatty_safe(fd))
return -errno;
return loop_write_full(fd, message, SIZE_MAX, TIMEOUT_USEC);
}

View File

@ -1043,7 +1043,7 @@ static int on_display_refresh(sd_event_source *s, uint64_t usec, void *userdata)
c->display_refresh_scheduled = false;
if (isatty(STDERR_FILENO) > 0)
if (isatty(STDERR_FILENO))
fputs(ANSI_HOME_CLEAR, stderr);
/* If we have both IPv4 and IPv6, we display IPv4 info via Plymouth, since it doesn't have much
@ -1224,7 +1224,7 @@ static int run(int argc, char* argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to subscribe to RTM_DELADDR events: %m");
if (isatty(0) > 0)
if (isatty(STDIN_FILENO))
log_info("Hit Ctrl-C to exit target mode.");
_unused_ _cleanup_(notify_on_cleanup) const char *notify_message =