1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-26 17:27:41 +03:00

Merge pull request #33707 from poettering/terminal-size-by-ansi-seq

pid1: try to initialize terminal dimensions from data gathered via ANSI sequences + many clean-ups/refactorings
This commit is contained in:
Lennart Poettering 2024-07-19 14:35:55 +02:00 committed by GitHub
commit 32dee192a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 1129 additions and 548 deletions

View File

@ -3322,7 +3322,8 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
<term><varname>TTYReset=</varname></term>
<listitem><para>Reset the terminal device specified with <varname>TTYPath=</varname> before and after
execution. Defaults to <literal>no</literal>.</para></listitem>
execution. This does not erase the screen (see <varname>TTYVTDisallocate=</varname> below for
that). Defaults to <literal>no</literal>.</para></listitem>
</varlistentry>
<varlistentry>
@ -3333,11 +3334,12 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
</varlistentry>
<varlistentry>
<term><varname>TTYRows=</varname></term>
<term><varname>TTYColumns=</varname></term>
<term><varname>TTYRows=</varname></term>
<listitem><para>Configure the size of the TTY specified with <varname>TTYPath=</varname>. If unset or
set to the empty string, the kernel default is used.</para>
set to the empty string, it is attempted to retrieve the dimensions of the terminal screen via ANSI
sequences, and if that fails the kernel defaults (typically 80x24) are used.</para>
<xi:include href="version-info.xml" xpointer="v250"/></listitem>
</varlistentry>
@ -3345,9 +3347,10 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
<varlistentry>
<term><varname>TTYVTDisallocate=</varname></term>
<listitem><para>If the terminal device specified with <varname>TTYPath=</varname> is a virtual console
terminal, try to deallocate the TTY before and after execution. This ensures that the screen and scrollback
buffer is cleared. Defaults to <literal>no</literal>.</para></listitem>
<listitem><para>If the terminal device specified with <varname>TTYPath=</varname> is a virtual
console terminal, try to deallocate the TTY before and after execution. This ensures that the screen
and scrollback buffer is cleared. If the terminal device is of any other type of TTY an attempt is
made to clear the screen via ANSI sequences. Defaults to <literal>no</literal>.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

162
src/basic/ansi-color.h Normal file
View File

@ -0,0 +1,162 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "terminal-util.h"
/* Regular colors */
#define ANSI_BLACK "\x1B[0;30m" /* Some type of grey usually. */
#define ANSI_RED "\x1B[0;31m"
#define ANSI_GREEN "\x1B[0;32m"
#define ANSI_YELLOW "\x1B[0;33m"
#define ANSI_BLUE "\x1B[0;34m"
#define ANSI_MAGENTA "\x1B[0;35m"
#define ANSI_CYAN "\x1B[0;36m"
#define ANSI_WHITE "\x1B[0;37m" /* This is actually rendered as light grey, legible even on a white
* background. See ANSI_HIGHLIGHT_WHITE for real white. */
#define ANSI_BRIGHT_BLACK "\x1B[0;90m"
#define ANSI_BRIGHT_RED "\x1B[0;91m"
#define ANSI_BRIGHT_GREEN "\x1B[0;92m"
#define ANSI_BRIGHT_YELLOW "\x1B[0;93m"
#define ANSI_BRIGHT_BLUE "\x1B[0;94m"
#define ANSI_BRIGHT_MAGENTA "\x1B[0;95m"
#define ANSI_BRIGHT_CYAN "\x1B[0;96m"
#define ANSI_BRIGHT_WHITE "\x1B[0;97m"
#define ANSI_GREY "\x1B[0;38;5;245m"
/* Bold/highlighted */
#define ANSI_HIGHLIGHT_BLACK "\x1B[0;1;30m"
#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m"
#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m"
#define _ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" /* This yellow is currently not displayed well by some terminals */
#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
#define ANSI_HIGHLIGHT_CYAN "\x1B[0;1;36m"
#define ANSI_HIGHLIGHT_WHITE "\x1B[0;1;37m"
#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38:5:100m"
#define ANSI_HIGHLIGHT_KHAKI3 "\x1B[0;1;38:5:185m"
#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38:5:245m"
#define ANSI_HIGHLIGHT_YELLOW ANSI_HIGHLIGHT_KHAKI3 /* Replacement yellow that is more legible */
/* Underlined */
#define ANSI_GREY_UNDERLINE "\x1B[0;4;38:5:245m"
#define ANSI_BRIGHT_BLACK_UNDERLINE "\x1B[0;4;90m"
#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;38:5:185m"
#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38:5:245m"
/* Other ANSI codes */
#define ANSI_UNDERLINE "\x1B[0;4m"
#define ANSI_ADD_UNDERLINE "\x1B[4m"
#define ANSI_ADD_UNDERLINE_GREY ANSI_ADD_UNDERLINE "\x1B[58:5:245m"
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
/* Fallback colors: 256 → 16 */
#define ANSI_HIGHLIGHT_GREY_FALLBACK "\x1B[0;1;90m"
#define ANSI_HIGHLIGHT_GREY_FALLBACK_UNDERLINE "\x1B[0;1;4;90m"
#define ANSI_HIGHLIGHT_YELLOW_FALLBACK "\x1B[0;1;33m"
#define ANSI_HIGHLIGHT_YELLOW_FALLBACK_UNDERLINE "\x1B[0;1;4;33m"
/* Background colors */
#define ANSI_BACKGROUND_BLUE "\x1B[44m"
/* Reset/clear ANSI styles */
#define ANSI_NORMAL "\x1B[0m"
#define DEFINE_ANSI_FUNC(name, NAME) \
static inline const char* ansi_##name(void) { \
return colors_enabled() ? ANSI_##NAME : ""; \
}
#define DEFINE_ANSI_FUNC_256(name, NAME, FALLBACK) \
static inline const char* ansi_##name(void) { \
switch (get_color_mode()) { \
case COLOR_OFF: return ""; \
case COLOR_16: return ANSI_##FALLBACK; \
default : return ANSI_##NAME; \
} \
}
static inline const char* ansi_underline(void) {
return underline_enabled() ? ANSI_UNDERLINE : "";
}
static inline const char* ansi_add_underline(void) {
return underline_enabled() ? ANSI_ADD_UNDERLINE : "";
}
static inline const char* ansi_add_underline_grey(void) {
return underline_enabled() ?
(colors_enabled() ? ANSI_ADD_UNDERLINE_GREY : ANSI_ADD_UNDERLINE) : "";
}
#define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME) \
static inline const char* ansi_##name(void) { \
return underline_enabled() ? ANSI_##NAME##_UNDERLINE : \
colors_enabled() ? ANSI_##NAME : ""; \
}
#define DEFINE_ANSI_FUNC_UNDERLINE_256(name, NAME, FALLBACK) \
static inline const char* ansi_##name(void) { \
switch (get_color_mode()) { \
case COLOR_OFF: return ""; \
case COLOR_16: return underline_enabled() ? ANSI_##FALLBACK##_UNDERLINE : ANSI_##FALLBACK; \
default : return underline_enabled() ? ANSI_##NAME##_UNDERLINE: ANSI_##NAME; \
} \
}
DEFINE_ANSI_FUNC(normal, NORMAL);
DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
DEFINE_ANSI_FUNC(black, BLACK);
DEFINE_ANSI_FUNC(red, RED);
DEFINE_ANSI_FUNC(green, GREEN);
DEFINE_ANSI_FUNC(yellow, YELLOW);
DEFINE_ANSI_FUNC(blue, BLUE);
DEFINE_ANSI_FUNC(magenta, MAGENTA);
DEFINE_ANSI_FUNC(cyan, CYAN);
DEFINE_ANSI_FUNC(white, WHITE);
DEFINE_ANSI_FUNC_256(grey, GREY, BRIGHT_BLACK);
DEFINE_ANSI_FUNC(bright_black, BRIGHT_BLACK);
DEFINE_ANSI_FUNC(bright_red, BRIGHT_RED);
DEFINE_ANSI_FUNC(bright_green, BRIGHT_GREEN);
DEFINE_ANSI_FUNC(bright_yellow, BRIGHT_YELLOW);
DEFINE_ANSI_FUNC(bright_blue, BRIGHT_BLUE);
DEFINE_ANSI_FUNC(bright_magenta, BRIGHT_MAGENTA);
DEFINE_ANSI_FUNC(bright_cyan, BRIGHT_CYAN);
DEFINE_ANSI_FUNC(bright_white, BRIGHT_WHITE);
DEFINE_ANSI_FUNC(highlight_black, HIGHLIGHT_BLACK);
DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC_256(highlight_yellow, HIGHLIGHT_YELLOW, HIGHLIGHT_YELLOW_FALLBACK);
DEFINE_ANSI_FUNC_256(highlight_yellow4, HIGHLIGHT_YELLOW4, HIGHLIGHT_YELLOW_FALLBACK);
DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC(highlight_cyan, HIGHLIGHT_CYAN);
DEFINE_ANSI_FUNC_256(highlight_grey, HIGHLIGHT_GREY, HIGHLIGHT_GREY_FALLBACK);
DEFINE_ANSI_FUNC(highlight_white, HIGHLIGHT_WHITE);
static inline const char* _ansi_highlight_yellow(void) {
return colors_enabled() ? _ANSI_HIGHLIGHT_YELLOW : "";
}
DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT);
DEFINE_ANSI_FUNC_UNDERLINE_256(grey_underline, GREY, BRIGHT_BLACK);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline, HIGHLIGHT_RED);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC_UNDERLINE_256(highlight_yellow_underline, HIGHLIGHT_YELLOW, HIGHLIGHT_YELLOW_FALLBACK);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline, HIGHLIGHT_BLUE);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_magenta_underline, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC_UNDERLINE_256(highlight_grey_underline, HIGHLIGHT_GREY, HIGHLIGHT_GREY_FALLBACK);
static inline const char* ansi_highlight_green_red(bool b) {
return b ? ansi_highlight_green() : ansi_highlight_red();
}

View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "build.h"
#include "extract-word.h"
#include "macro.h"

View File

@ -1146,5 +1146,10 @@ int setenvf(const char *name, bool overwrite, const char *valuef, ...) {
if (r < 0)
return -ENOMEM;
/* Try to suppress writes if the value is already set correctly (simply because memory management of
* environment variables sucks a bit. */
if (streq_ptr(getenv(name), value))
return 0;
return RET_NERRNO(setenv(name, value, overwrite));
}

View File

@ -16,6 +16,7 @@
#include "sd-messages.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "argv-util.h"
#include "env-util.h"
#include "errno-util.h"

File diff suppressed because it is too large Load Diff

View File

@ -11,72 +11,6 @@
#include "macro.h"
#include "time-util.h"
/* Regular colors */
#define ANSI_BLACK "\x1B[0;30m" /* Some type of grey usually. */
#define ANSI_RED "\x1B[0;31m"
#define ANSI_GREEN "\x1B[0;32m"
#define ANSI_YELLOW "\x1B[0;33m"
#define ANSI_BLUE "\x1B[0;34m"
#define ANSI_MAGENTA "\x1B[0;35m"
#define ANSI_CYAN "\x1B[0;36m"
#define ANSI_WHITE "\x1B[0;37m" /* This is actually rendered as light grey, legible even on a white
* background. See ANSI_HIGHLIGHT_WHITE for real white. */
#define ANSI_BRIGHT_BLACK "\x1B[0;90m"
#define ANSI_BRIGHT_RED "\x1B[0;91m"
#define ANSI_BRIGHT_GREEN "\x1B[0;92m"
#define ANSI_BRIGHT_YELLOW "\x1B[0;93m"
#define ANSI_BRIGHT_BLUE "\x1B[0;94m"
#define ANSI_BRIGHT_MAGENTA "\x1B[0;95m"
#define ANSI_BRIGHT_CYAN "\x1B[0;96m"
#define ANSI_BRIGHT_WHITE "\x1B[0;97m"
#define ANSI_GREY "\x1B[0;38;5;245m"
/* Bold/highlighted */
#define ANSI_HIGHLIGHT_BLACK "\x1B[0;1;30m"
#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m"
#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m"
#define _ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" /* This yellow is currently not displayed well by some terminals */
#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
#define ANSI_HIGHLIGHT_CYAN "\x1B[0;1;36m"
#define ANSI_HIGHLIGHT_WHITE "\x1B[0;1;37m"
#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38:5:100m"
#define ANSI_HIGHLIGHT_KHAKI3 "\x1B[0;1;38:5:185m"
#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38:5:245m"
#define ANSI_HIGHLIGHT_YELLOW ANSI_HIGHLIGHT_KHAKI3 /* Replacement yellow that is more legible */
/* Underlined */
#define ANSI_GREY_UNDERLINE "\x1B[0;4;38:5:245m"
#define ANSI_BRIGHT_BLACK_UNDERLINE "\x1B[0;4;90m"
#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;38:5:185m"
#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38:5:245m"
/* Other ANSI codes */
#define ANSI_UNDERLINE "\x1B[0;4m"
#define ANSI_ADD_UNDERLINE "\x1B[4m"
#define ANSI_ADD_UNDERLINE_GREY ANSI_ADD_UNDERLINE "\x1B[58:5:245m"
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
/* Fallback colors: 256 -> 16 */
#define ANSI_HIGHLIGHT_GREY_FALLBACK "\x1B[0;1;90m"
#define ANSI_HIGHLIGHT_GREY_FALLBACK_UNDERLINE "\x1B[0;1;4;90m"
#define ANSI_HIGHLIGHT_YELLOW_FALLBACK "\x1B[0;1;33m"
#define ANSI_HIGHLIGHT_YELLOW_FALLBACK_UNDERLINE "\x1B[0;1;4;33m"
/* Background colors */
#define ANSI_BACKGROUND_BLUE "\x1B[44m"
/* Reset/clear ANSI styles */
#define ANSI_NORMAL "\x1B[0m"
/* Erase characters until the end of the line */
#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
@ -95,10 +29,10 @@
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);
int terminal_reset_ansi_seq(int fd);
int terminal_reset_defensive(int fd, bool switch_to_text);
int terminal_reset_defensive_locked(int fd, bool switch_to_text);
int terminal_set_cursor_position(int fd, unsigned row, unsigned column);
int open_terminal(const char *name, int mode);
@ -117,6 +51,9 @@ typedef enum AcquireTerminalFlags {
ACQUIRE_TERMINAL_PERMISSIVE = 1 << 2,
} AcquireTerminalFlags;
int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
int release_terminal(void);
/* Limits the use of ANSI colors to a subset. */
typedef enum ColorMode {
COLOR_OFF, /* No colors, monochrome output. */
@ -130,11 +67,7 @@ typedef enum ColorMode {
const char* color_mode_to_string(ColorMode m) _const_;
ColorMode color_mode_from_string(const char *s) _pure_;
int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
int release_terminal(void);
int terminal_vhangup_fd(int fd);
int terminal_vhangup(const char *name);
int terminal_set_size_fd(int fd, const char *ident, unsigned rows, unsigned cols);
int proc_cmdline_tty_size(const char *tty, unsigned *ret_rows, unsigned *ret_cols);
@ -155,6 +88,8 @@ bool tty_is_console(const char *tty) _pure_;
int vtnr_from_tty(const char *tty);
const char* default_term_for_tty(const char *tty);
void reset_dev_console_fd(int fd, bool switch_to_text);
int lock_dev_console(void);
int make_console_stdio(void);
int fd_columns(int fd);
@ -177,99 +112,11 @@ static inline bool colors_enabled(void) {
return get_color_mode() != COLOR_OFF;
}
#define DEFINE_ANSI_FUNC(name, NAME) \
static inline const char *ansi_##name(void) { \
return colors_enabled() ? ANSI_##NAME : ""; \
}
int get_ctty_devnr(pid_t pid, dev_t *ret);
int get_ctty(pid_t, dev_t *ret_devnr, char **ret);
#define DEFINE_ANSI_FUNC_256(name, NAME, FALLBACK) \
static inline const char *ansi_##name(void) { \
switch (get_color_mode()) { \
case COLOR_OFF: return ""; \
case COLOR_16: return ANSI_##FALLBACK; \
default : return ANSI_##NAME; \
} \
}
static inline const char* ansi_underline(void) {
return underline_enabled() ? ANSI_UNDERLINE : "";
}
static inline const char* ansi_add_underline(void) {
return underline_enabled() ? ANSI_ADD_UNDERLINE : "";
}
static inline const char* ansi_add_underline_grey(void) {
return underline_enabled() ?
(colors_enabled() ? ANSI_ADD_UNDERLINE_GREY : ANSI_ADD_UNDERLINE) : "";
}
#define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME) \
static inline const char *ansi_##name(void) { \
return underline_enabled() ? ANSI_##NAME##_UNDERLINE : \
colors_enabled() ? ANSI_##NAME : ""; \
}
#define DEFINE_ANSI_FUNC_UNDERLINE_256(name, NAME, FALLBACK) \
static inline const char *ansi_##name(void) { \
switch (get_color_mode()) { \
case COLOR_OFF: return ""; \
case COLOR_16: return underline_enabled() ? ANSI_##FALLBACK##_UNDERLINE : ANSI_##FALLBACK; \
default : return underline_enabled() ? ANSI_##NAME##_UNDERLINE: ANSI_##NAME; \
} \
}
DEFINE_ANSI_FUNC(normal, NORMAL);
DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
DEFINE_ANSI_FUNC(black, BLACK);
DEFINE_ANSI_FUNC(red, RED);
DEFINE_ANSI_FUNC(green, GREEN);
DEFINE_ANSI_FUNC(yellow, YELLOW);
DEFINE_ANSI_FUNC(blue, BLUE);
DEFINE_ANSI_FUNC(magenta, MAGENTA);
DEFINE_ANSI_FUNC(cyan, CYAN);
DEFINE_ANSI_FUNC(white, WHITE);
DEFINE_ANSI_FUNC_256(grey, GREY, BRIGHT_BLACK);
DEFINE_ANSI_FUNC(bright_black, BRIGHT_BLACK);
DEFINE_ANSI_FUNC(bright_red, BRIGHT_RED);
DEFINE_ANSI_FUNC(bright_green, BRIGHT_GREEN);
DEFINE_ANSI_FUNC(bright_yellow, BRIGHT_YELLOW);
DEFINE_ANSI_FUNC(bright_blue, BRIGHT_BLUE);
DEFINE_ANSI_FUNC(bright_magenta, BRIGHT_MAGENTA);
DEFINE_ANSI_FUNC(bright_cyan, BRIGHT_CYAN);
DEFINE_ANSI_FUNC(bright_white, BRIGHT_WHITE);
DEFINE_ANSI_FUNC(highlight_black, HIGHLIGHT_BLACK);
DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC_256(highlight_yellow, HIGHLIGHT_YELLOW, HIGHLIGHT_YELLOW_FALLBACK);
DEFINE_ANSI_FUNC_256(highlight_yellow4, HIGHLIGHT_YELLOW4, HIGHLIGHT_YELLOW_FALLBACK);
DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC(highlight_cyan, HIGHLIGHT_CYAN);
DEFINE_ANSI_FUNC_256(highlight_grey, HIGHLIGHT_GREY, HIGHLIGHT_GREY_FALLBACK);
DEFINE_ANSI_FUNC(highlight_white, HIGHLIGHT_WHITE);
static inline const char* _ansi_highlight_yellow(void) {
return colors_enabled() ? _ANSI_HIGHLIGHT_YELLOW : "";
}
DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT);
DEFINE_ANSI_FUNC_UNDERLINE_256(grey_underline, GREY, BRIGHT_BLACK);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline, HIGHLIGHT_RED);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC_UNDERLINE_256(highlight_yellow_underline, HIGHLIGHT_YELLOW, HIGHLIGHT_YELLOW_FALLBACK);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline, HIGHLIGHT_BLUE);
DEFINE_ANSI_FUNC_UNDERLINE(highlight_magenta_underline, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC_UNDERLINE_256(highlight_grey_underline, HIGHLIGHT_GREY, HIGHLIGHT_GREY_FALLBACK);
int get_ctty_devnr(pid_t pid, dev_t *d);
int get_ctty(pid_t, dev_t *_devnr, char **r);
int getttyname_malloc(int fd, char **r);
int getttyname_harder(int fd, char **r);
int getttyname_malloc(int fd, char **ret);
int getttyname_harder(int fd, char **ret);
int ptsname_malloc(int fd, char **ret);
@ -277,20 +124,19 @@ int openpt_allocate(int flags, char **ret_slave);
int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_slave);
int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
int vt_default_utf8(void);
int vt_reset_keyboard(int fd);
int vt_restore(int fd);
int vt_release(int fd, bool restore_vt);
void get_log_colors(int priority, const char **on, const char **off, const char **highlight);
static inline const char* ansi_highlight_green_red(bool b) {
return b ? ansi_highlight_green() : ansi_highlight_red();
}
/* This assumes there is a 'tty' group */
#define TTY_MODE 0620
void termios_disable_echo(struct termios *termios);
int get_default_background_color(double *ret_red, double *ret_green, double *ret_blue);
int terminal_get_size_by_dsr(int input_fd, int output_fd, unsigned *ret_rows, unsigned *ret_columns);
int terminal_fix_size(int input_fd, int output_fd);
int terminal_is_pty_fd(int fd);

View File

@ -2,6 +2,7 @@
#include <sys/reboot.h>
#include "ansi-color.h"
#include "bus-error.h"
#include "bus-util.h"
#include "emergency-action.h"

View File

@ -353,16 +353,10 @@ static int setup_input(
if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
return -errno;
/* Try to make this the controlling tty, if it is a tty, and reset it */
if (isatty(STDIN_FILENO)) {
/* Try to make this the controlling tty, if it is a tty */
if (isatty(STDIN_FILENO))
(void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
if (context->tty_reset)
(void) reset_terminal_fd(STDIN_FILENO, /* switch_to_text= */ true);
(void) exec_context_apply_tty_size(context, STDIN_FILENO, /* tty_path= */ NULL);
}
return STDIN_FILENO;
}
@ -389,10 +383,6 @@ static int setup_input(
if (tty_fd < 0)
return tty_fd;
r = exec_context_apply_tty_size(context, tty_fd, tty_path);
if (r < 0)
return r;
r = move_fd(tty_fd, STDIN_FILENO, /* cloexec= */ false);
if (r < 0)
return r;
@ -554,7 +544,6 @@ static int setup_output(
if (is_terminal_input(i))
return RET_NERRNO(dup2(STDIN_FILENO, fileno));
/* We don't reset the terminal if this is just about output */
return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno);
case EXEC_OUTPUT_KMSG:
@ -659,11 +648,11 @@ static int setup_confirm_stdio(
assert(ret_saved_stdin);
assert(ret_saved_stdout);
saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
saved_stdin = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 3);
if (saved_stdin < 0)
return -errno;
saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 3);
if (saved_stdout < 0)
return -errno;
@ -671,15 +660,19 @@ static int setup_confirm_stdio(
if (fd < 0)
return fd;
_cleanup_close_ int lock_fd = lock_dev_console();
if (lock_fd < 0)
log_debug_errno(lock_fd, "Failed to lock /dev/console, ignoring: %m");
r = chown_terminal(fd, getuid());
if (r < 0)
return r;
r = reset_terminal_fd(fd, /* switch_to_text= */ true);
r = terminal_reset_defensive(fd, /* switch_to_text= */ true);
if (r < 0)
return r;
r = exec_context_apply_tty_size(context, fd, vc);
r = exec_context_apply_tty_size(context, fd, fd, vc);
if (r < 0)
return r;
@ -694,15 +687,16 @@ static int setup_confirm_stdio(
}
static void write_confirm_error_fd(int err, int fd, const char *unit_id) {
assert(err < 0);
assert(err != 0);
assert(fd >= 0);
assert(unit_id);
if (err == -ETIMEDOUT)
errno = abs(err);
if (errno == ETIMEDOUT)
dprintf(fd, "Confirmation question timed out for %s, assuming positive response.\n", unit_id);
else {
errno = -err;
dprintf(fd, "Couldn't ask confirmation for %s: %m, assuming positive response.\n", unit_id);
}
else
dprintf(fd, "Couldn't ask confirmation for %s, assuming positive response: %m\n", unit_id);
}
static void write_confirm_error(int err, const char *vc, const char *unit_id) {
@ -750,7 +744,7 @@ static bool confirm_spawn_disabled(void) {
}
static int ask_for_confirmation(const ExecContext *context, const ExecParameters *params, const char *cmdline) {
int saved_stdout = -1, saved_stdin = -1, r;
int saved_stdout = -EBADF, saved_stdin = -EBADF, r;
_cleanup_free_ char *e = NULL;
char c;
@ -4031,6 +4025,39 @@ static int send_handoff_timestamp(
return 1;
}
static void prepare_terminal(
const ExecContext *context,
ExecParameters *p) {
_cleanup_close_ int lock_fd = -EBADF;
/* This is the "constructive" reset, i.e. is about preparing things for our invocation rather than
* cleaning up things from older invocations. */
assert(context);
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)) ||
context->std_output == EXEC_OUTPUT_NAMED_FD ||
p->stdout_fd >= 0))
return;
if (context->tty_reset) {
/* When we are resetting the TTY, then let's create a lock first, to synchronize access. This
* in particular matters as concurrent resets and the TTY size ANSI DSR logic done by the
* exec_context_apply_tty_size() below might interfere */
lock_fd = lock_dev_console();
if (lock_fd < 0)
log_exec_debug_errno(context, p, lock_fd, "Failed to lock /dev/console, ignoring: %m");
(void) terminal_reset_defensive(STDOUT_FILENO, /* switch_to_text= */ false);
}
(void) exec_context_apply_tty_size(context, STDIN_FILENO, STDOUT_FILENO, /* tty_path= */ NULL);
}
int exec_invoke(
const ExecCommand *command,
const ExecContext *context,
@ -4198,6 +4225,11 @@ int exec_invoke(
return log_exec_error_errno(context, params, errno, "Failed to create new process session: %m");
}
/* Now, reset the TTY associated to this service "destructively" (i.e. possibly even hang up or
* disallocate the VT), to get rid of any prior uses of the device. Note that we do not keep any fd
* open here, hence some of the settings made here might vanish again, depending on the TTY driver
* used. A 2nd ("constructive") initialization after we opened the input/output fds we actually want
* will fix this. */
exec_context_tty_reset(context, params);
if (params->shall_confirm_spawn && exec_context_shall_confirm_spawn(context)) {
@ -4381,6 +4413,12 @@ int exec_invoke(
return log_exec_error_errno(context, params, r, "Failed to set up standard error output: %m");
}
/* Now that stdin/stdout are definiely opened, properly initialize it with our desired
* settings. Note: this is a "constructive" reset, it prepares things for us to use. This is
* different from the "destructive" TTY reset further up. Also note: we apply this on stdin/stdout in
* case this is a tty, regardless if we opened it ourselves or got it passed in pre-opened. */
prepare_terminal(context, params);
if (context->oom_score_adjust_set) {
/* When we can't make this change due to EPERM, then let's silently skip over it. User
* namespaces prohibit write access to this file, and we shouldn't trip up over that. */

View File

@ -25,7 +25,6 @@
#include "cgroup-setup.h"
#include "constants.h"
#include "cpu-set-util.h"
#include "dev-setup.h"
#include "env-file.h"
#include "env-util.h"
#include "errno-list.h"
@ -99,56 +98,65 @@ const char* exec_context_tty_path(const ExecContext *context) {
return "/dev/console";
}
static void exec_context_determine_tty_size(
int exec_context_apply_tty_size(
const ExecContext *context,
const char *tty_path,
unsigned *ret_rows,
unsigned *ret_cols) {
int input_fd,
int output_fd,
const char *tty_path) {
unsigned rows, cols;
int r;
assert(context);
assert(ret_rows);
assert(ret_cols);
assert(input_fd >= 0);
assert(output_fd >= 0);
if (!isatty_safe(output_fd))
return 0;
if (!tty_path)
tty_path = exec_context_tty_path(context);
/* Preferably use explicitly configured data */
rows = context->tty_rows;
cols = context->tty_cols;
/* Fill in data from kernel command line if anything is unspecified */
if (tty_path && (rows == UINT_MAX || cols == UINT_MAX))
(void) proc_cmdline_tty_size(
tty_path,
rows == UINT_MAX ? &rows : NULL,
cols == UINT_MAX ? &cols : NULL);
*ret_rows = rows;
*ret_cols = cols;
/* If we got nothing so far and we are talking to a physical device, and the TTY reset logic is on,
* then let's query dimensions from the ANSI driver. */
if (rows == UINT_MAX && cols == UINT_MAX &&
context->tty_reset &&
terminal_is_pty_fd(output_fd) == 0 &&
isatty_safe(input_fd)) {
r = terminal_get_size_by_dsr(input_fd, output_fd, &rows, &cols);
if (r < 0)
log_debug_errno(r, "Failed to get terminal size by DSR, ignoring: %m");
}
return terminal_set_size_fd(output_fd, tty_path, rows, cols);
}
int exec_context_apply_tty_size(
const ExecContext *context,
int tty_fd,
const char *tty_path) {
unsigned rows, cols;
exec_context_determine_tty_size(context, tty_path, &rows, &cols);
return terminal_set_size_fd(tty_fd, tty_path, rows, cols);
}
void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) {
_cleanup_close_ int _fd = -EBADF, lock_fd = -EBADF;
int fd;
int fd, r;
assert(context);
/* Note that this is potentially a "destructive" reset of a TTY device. It's about getting rid of the
* remains of previous uses of the TTY. It's *not* about getting things set up for coming uses. We'll
* potentially invalidate the TTY here through hangups or VT disallocations, and hence do not keep a
* continous fd open. */
const char *path = exec_context_tty_path(context);
if (p && p->stdin_fd >= 0 && isatty_safe(p->stdin_fd))
fd = p->stdin_fd;
if (p && p->stdout_fd >= 0 && isatty_safe(p->stdout_fd))
fd = p->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))) {
fd = _fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
@ -168,13 +176,19 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p)
else if (lock_fd < 0)
log_warning_errno(lock_fd, "Failed to lock /dev/console, proceeding without lock: %m");
if (context->tty_reset)
(void) terminal_reset_defensive(fd, /* switch_to_text= */ true);
r = exec_context_apply_tty_size(context, fd, fd, path);
if (r < 0)
log_debug_errno(r, "Failed to configure TTY dimensions, ignoring: %m");
if (context->tty_vhangup)
(void) terminal_vhangup_fd(fd);
if (context->tty_reset)
(void) reset_terminal_fd(fd, /* switch_to_text= */ true);
(void) exec_context_apply_tty_size(context, fd, path);
/* We don't need the fd anymore now, and it potentially points to a hungup TTY anyway, let's close it
* hence. */
_fd = safe_close(_fd);
if (context->tty_vt_disallocate && path)
(void) vt_disallocate(path);

View File

@ -526,7 +526,7 @@ int exec_context_get_clean_directories(ExecContext *c, char **prefix, ExecCleanM
int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret);
const char* exec_context_tty_path(const ExecContext *context);
int exec_context_apply_tty_size(const ExecContext *context, int tty_fd, const char *tty_path);
int exec_context_apply_tty_size(const ExecContext *context, int input_fd, int output_fd, const char *tty_path);
void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p);
uint64_t exec_context_get_rlimit(const ExecContext *c, const char *name);

View File

@ -6,6 +6,7 @@
#include "sd-messages.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "async.h"
#include "cgroup.h"
#include "dbus-job.h"

View File

@ -204,33 +204,58 @@ static int manager_find_user_config_paths(char ***ret_files, char ***ret_dirs) {
return 0;
}
static int console_setup(void) {
_cleanup_close_ int tty_fd = -EBADF;
unsigned rows, cols;
static int save_console_winsize_in_environment(int tty_fd) {
int r;
tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
assert(tty_fd >= 0);
struct winsize ws = {};
if (ioctl(tty_fd, TIOCGWINSZ, &ws) < 0) {
log_debug_errno(errno, "Failed to acquire console window size, ignoring.");
goto unset;
}
if (ws.ws_col <= 0 && ws.ws_row <= 0) {
log_debug("No console window size set, ignoring.");
goto unset;
}
r = setenvf("COLUMNS", /* overwrite= */ true, "%u", ws.ws_col);
if (r < 0) {
log_debug_errno(r, "Failed to set $COLUMNS, ignoring: %m");
goto unset;
}
r = setenvf("LINES", /* overwrite= */ true, "%u", ws.ws_row);
if (r < 0) {
log_debug_errno(r, "Failed to set $LINES, ignoring: %m");
goto unset;
}
log_debug("Recorded console dimensions in environment: $COLUMNS=%u $LINES=%u.", ws.ws_col, ws.ws_row);
return 1;
unset:
(void) unsetenv("COLUMNS");
(void) unsetenv("LINES");
return 0;
}
static int console_setup(void) {
if (getpid_cached() != 1)
return 0;
_cleanup_close_ int tty_fd = -EBADF;
tty_fd = open_terminal("/dev/console", O_RDWR|O_NOCTTY|O_CLOEXEC);
if (tty_fd < 0)
return log_error_errno(tty_fd, "Failed to open /dev/console: %m");
/* We don't want to force text mode. plymouth may be showing
* pictures already from initrd. */
r = reset_terminal_fd(tty_fd, false);
if (r < 0)
return log_error_errno(r, "Failed to reset /dev/console: %m");
/* We don't want to force text mode. Plymouth may be showing pictures already from initrd. */
reset_dev_console_fd(tty_fd, /* switch_to_text= */ false);
r = proc_cmdline_tty_size("/dev/console", &rows, &cols);
if (r < 0)
log_warning_errno(r, "Failed to get /dev/console size, ignoring: %m");
else {
r = terminal_set_size_fd(tty_fd, NULL, rows, cols);
if (r < 0)
log_warning_errno(r, "Failed to set /dev/console size, ignoring: %m");
}
r = terminal_reset_ansi_seq(tty_fd);
if (r < 0)
log_warning_errno(r, "Failed to reset /dev/console using ANSI sequences, ignoring: %m");
save_console_winsize_in_environment(tty_fd);
return 0;
}
@ -2910,7 +2935,7 @@ static void setup_console_terminal(bool skip_setup) {
(void) release_terminal();
/* Reset the console, but only if this is really init and we are freshly booted */
if (getpid_cached() == 1 && !skip_setup)
if (!skip_setup)
(void) console_setup();
}

View File

@ -72,8 +72,14 @@ int status_vprintf(const char *status, ShowStatusFlags flags, const char *format
int c;
c = fd_columns(fd);
if (c <= 0)
c = 80;
if (c <= 0) {
const char *env = getenv("COLUMNS");
if (env)
(void) safe_atoi(env, &c);
if (c <= 0)
c = 80;
}
sl = status ? strlen(status_indent) : 0;

View File

@ -4,6 +4,7 @@
#include <unistd.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "dbus-unit.h"

View File

@ -10,6 +10,7 @@
#include "all-units.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "bpf-firewall.h"
#include "bpf-foreign.h"
#include "bpf-socket-bind.h"

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "cryptenroll-recovery.h"
#include "glyph-util.h"
#include "json-util.h"

View File

@ -133,7 +133,7 @@ static void print_welcome(int rfd) {
pn = os_release_pretty_name(pretty_name, os_name);
ac = isempty(ansi_color) ? "0" : ansi_color;
(void) reset_terminal_fd(STDIN_FILENO, /* switch_to_text= */ false);
(void) terminal_reset_defensive_locked(STDOUT_FILENO, /* switch_to_text= */ false);
if (colors_enabled())
printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ac, pn);

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "errno-util.h"
#include "glyph-util.h"
#include "homectl-recovery-key.h"

View File

@ -2438,7 +2438,7 @@ static int create_interactively(void) {
(void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
(void) reset_terminal_fd(STDIN_FILENO, /* switch_to_text= */ false);
(void) terminal_reset_defensive_locked(STDOUT_FILENO, /* switch_to_text= */ false);
for (;;) {
username = mfree(username);

View File

@ -7,6 +7,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "build.h"
#include "discover-image.h"
#include "export-raw.h"

View File

@ -4,6 +4,7 @@
#include <locale.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "build.h"
#include "btrfs-util.h"
#include "discover-image.h"

View File

@ -7,6 +7,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "build.h"
#include "discover-image.h"
#include "env-util.h"

View File

@ -7,6 +7,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "build.h"
#include "discover-image.h"
#include "env-util.h"

View File

@ -185,7 +185,7 @@ static int display_emergency_message_fullscreen(const char *message) {
if (r < 0)
log_warning_errno(r, "Failed to clear terminal, ignoring: %m");
r = set_terminal_cursor_position(fd, 2, 4);
r = terminal_set_cursor_position(fd, 2, 4);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");
@ -197,7 +197,7 @@ static int display_emergency_message_fullscreen(const char *message) {
qr_code_start_row = w.ws_row * 3U / 5U;
qr_code_start_column = w.ws_col * 3U / 4U;
r = set_terminal_cursor_position(fd, 4, 4);
r = terminal_set_cursor_position(fd, 4, 4);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");
@ -217,7 +217,7 @@ static int display_emergency_message_fullscreen(const char *message) {
if (r < 0)
log_warning_errno(r, "QR code could not be printed, ignoring: %m");
r = set_terminal_cursor_position(fd, w.ws_row - 1, w.ws_col * 2U / 5U);
r = terminal_set_cursor_position(fd, w.ws_row - 1, w.ws_col * 2U / 5U);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "chattr-util.h"
#include "errno-util.h"
#include "fd-util.h"

View File

@ -4,6 +4,7 @@
#include "sd-event.h"
#include "ansi-color.h"
#include "fileio.h"
#include "journalctl.h"
#include "journalctl-filter.h"

View File

@ -3,6 +3,7 @@
#include <sys/time.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "bus-dump.h"
#include "bus-internal.h"
#include "bus-message.h"

View File

@ -6,6 +6,7 @@
#include <unistd.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "compress.h"
#include "fd-util.h"
#include "fileio.h"

View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <unistd.h>
#include "ansi-color.h"
#include "chattr-util.h"
#include "fd-util.h"
#include "iovec-util.h"

View File

@ -10,6 +10,7 @@
#include "sd-messages.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "errno-util.h"
#include "escape.h"
#include "ether-addr-util.h"

View File

@ -2,6 +2,7 @@
#include "sd-varlink-idl.h"
#include "ansi-color.h"
#include "json-util.h"
#include "memstream-util.h"
#include "set.h"

View File

@ -19,6 +19,7 @@
#include <unistd.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "ask-password-api.h"
#include "creds-util.h"
#include "fd-util.h"

View File

@ -2,6 +2,7 @@
#include "sd-device.h"
#include "ansi-color.h"
#include "blockdev-list.h"
#include "blockdev-util.h"
#include "device-util.h"

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "bus-locator.h"
#include "bus-unit-procs.h"
#include "glyph-util.h"

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "bus-error.h"
#include "bus-util.h"
#include "cgroup-show.h"

View File

@ -18,23 +18,6 @@
#include "umask-util.h"
#include "user-util.h"
int lock_dev_console(void) {
_cleanup_close_ int fd = -EBADF;
int r;
/* NB: We do not use O_NOFOLLOW here, because some container managers might place a symlink to some
* pty in /dev/console, in which case it should be fine to lock the target TTY. */
fd = open_terminal("/dev/console", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return fd;
r = lock_generic(fd, LOCK_BSD, LOCK_EX);
if (r < 0)
return r;
return TAKE_FD(fd);
}
int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
static const char symlinks[] =
"-/proc/kcore\0" "/dev/core\0"

View File

@ -3,8 +3,6 @@
#include <sys/types.h>
int lock_dev_console(void);
int dev_setup(const char *prefix, uid_t uid, gid_t gid);
int make_inaccessible_nodes(const char *parent_dir, uid_t uid, gid_t gid);

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "ansi-color.h"
#include "glyph-util.h"
#include "terminal-util.h"

View File

@ -17,6 +17,7 @@
#include "sd-event.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "env-util.h"
#include "errno-util.h"
#include "extract-word.h"

View File

@ -5,6 +5,7 @@
#if HAVE_QRENCODE
#include <qrencode.h>
#include "ansi-color.h"
#include "dlfcn-util.h"
#include "locale-util.h"
#include "log.h"
@ -52,7 +53,7 @@ static void print_border(FILE *output, unsigned width, unsigned row, unsigned co
if (fd < 0)
return (void)log_debug_errno(errno, "Failed to get file descriptor from the file stream: %m");
r = set_terminal_cursor_position(fd, row, column);
r = terminal_set_cursor_position(fd, row, column);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");
@ -64,7 +65,7 @@ static void print_border(FILE *output, unsigned width, unsigned row, unsigned co
fputs(UNICODE_FULL_BLOCK, output);
fputs(ANSI_NORMAL "\n", output);
r = set_terminal_cursor_position(fd, row + 1, column);
r = terminal_set_cursor_position(fd, row + 1, column);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");
}
@ -96,7 +97,7 @@ static void write_qrcode(FILE *output, QRcode *qr, unsigned int row, unsigned in
if (fd < 0)
return (void)log_debug_errno(errno, "Failed to get file descriptor from the file stream: %m");
r = set_terminal_cursor_position(fd, row + move_down, column);
r = terminal_set_cursor_position(fd, row + move_down, column);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");
@ -127,7 +128,7 @@ static void write_qrcode(FILE *output, QRcode *qr, unsigned int row, unsigned in
for (unsigned x = 0; x < 4; x++)
fputs(UNICODE_FULL_BLOCK, output);
r = set_terminal_cursor_position(fd, row + move_down, column);
r = terminal_set_cursor_position(fd, row + move_down, column);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");
move_down += 1;
@ -206,7 +207,7 @@ int print_qrcode_full(FILE *out, const char *header, const char *string, unsigne
row = tty_height - (qr_code_height / 2 ) - 1;
if (header) {
r = set_terminal_cursor_position(fd, row - 2, tty_width - qr_code_width - 2);
r = terminal_set_cursor_position(fd, row - 2, tty_width - qr_code_width - 2);
if (r < 0)
log_warning_errno(r, "Failed to move terminal cursor position, ignoring: %m");

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "locale-util.h"
#include "sort-util.h"
#include "special.h"

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "bus-error.h"
#include "bus-locator.h"
#include "locale-util.h"

View File

@ -4,6 +4,7 @@
#include "sd-login.h"
#include "ansi-color.h"
#include "bus-map-properties.h"
#include "hostname-util.h"
#include "locale-util.h"

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "bus-error.h"
#include "bus-locator.h"
#include "sort-util.h"

View File

@ -2,6 +2,7 @@
#include "sd-login.h"
#include "ansi-color.h"
#include "bus-error.h"
#include "bus-locator.h"
#include "format-table.h"

View File

@ -2,6 +2,7 @@
#include "sd-bus.h"
#include "ansi-color.h"
#include "bus-common-errors.h"
#include "bus-error.h"
#include "bus-locator.h"

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "glyph-util.h"
#include "sysupdate-update-set-flags.h"
#include "terminal-util.h"

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "ansi-color.h"
#include "alloc-util.h"
#include "string-util.h"
#include "sysupdate-update-set.h"

View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "constants.h"
#include "escape.h"
#include "string-util.h"

View File

@ -3,10 +3,13 @@
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
#include "alloc-util.h"
#include "ansi-color.h"
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
@ -176,6 +179,77 @@ TEST(get_default_background_color) {
log_notice("R=%g G=%g B=%g", red, green, blue);
}
TEST(terminal_get_size_by_dsr) {
unsigned rows, columns;
int r;
r = terminal_get_size_by_dsr(STDIN_FILENO, STDOUT_FILENO, &rows, &columns);
if (r < 0)
log_notice_errno(r, "Can't get screen dimensions via DSR: %m");
else {
log_notice("terminal size via DSR: rows=%u columns=%u", rows, columns);
struct winsize ws = {};
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
log_warning_errno(errno, "Can't get terminal size via ioctl, ignoring: %m");
else
log_notice("terminal size via ioctl: rows=%u columns=%u", ws.ws_row, ws.ws_col);
}
}
TEST(terminal_fix_size) {
int r;
r = terminal_fix_size(STDIN_FILENO, STDOUT_FILENO);
if (r < 0)
log_warning_errno(r, "Failed to fix terminal size: %m");
else if (r == 0)
log_notice("Not fixing terminal size, nothing to do.");
else
log_notice("Fixed terminal size.");
}
TEST(terminal_is_pty_fd) {
_cleanup_close_ int fd1 = -EBADF, fd2 = -EBADF;
_cleanup_free_ char *peer = NULL;
int r;
fd1 = openpt_allocate(O_RDWR, &peer);
assert_se(fd1 >= 0);
assert_se(terminal_is_pty_fd(fd1) > 0);
fd2 = open_terminal(peer, O_RDWR|O_CLOEXEC|O_NOCTTY);
assert_se(fd2 >= 0);
assert_se(terminal_is_pty_fd(fd2) > 0);
fd1 = safe_close(fd1);
fd2 = safe_close(fd2);
fd1 = open("/dev/null", O_RDONLY|O_CLOEXEC);
assert_se(fd1 >= 0);
assert_se(terminal_is_pty_fd(fd1) == 0);
/* In container managers real tty devices might be weird, avoid them. */
r = path_is_read_only_fs("/sys");
if (r != 0)
return;
FOREACH_STRING(p, "/dev/ttyS0", "/dev/tty1") {
_cleanup_close_ int tfd = -EBADF;
tfd = open_terminal(p, O_CLOEXEC|O_NOCTTY|O_RDONLY|O_NONBLOCK);
if (tfd == -ENOENT)
continue;
if (tfd < 0) {
log_notice_errno(tfd, "Failed to open '%s', skipping: %m", p);
continue;
}
assert_se(terminal_is_pty_fd(tfd) <= 0);
}
}
static void test_get_color_mode_with_env(const char *key, const char *val, ColorMode expected) {
ASSERT_OK(setenv(key, val, true));
reset_terminal_feature_caches();
@ -209,4 +283,12 @@ TEST(get_color_mode) {
reset_terminal_feature_caches();
}
TEST(terminal_reset_defensive) {
int r;
r = terminal_reset_defensive(STDOUT_FILENO, /* switch_to_text= */ false);
if (r < 0)
log_notice_errno(r, "Failed to reset terminal: %m");
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -150,9 +150,7 @@ static int agent_ask_password_tty(
if (tty_fd < 0)
return log_error_errno(tty_fd, "Failed to acquire %s: %m", con);
r = reset_terminal_fd(tty_fd, true);
if (r < 0)
log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
(void) terminal_reset_defensive_locked(tty_fd, /* switch_to_text= */ true);
log_info("Starting password query on %s.", con);
}

View File

@ -13,6 +13,7 @@
#include "sd-json.h"
#include "alloc-util.h"
#include "ansi-color.h"
#include "device-enumerator-private.h"
#include "device-private.h"
#include "device-util.h"

View File

@ -14,6 +14,7 @@
#include "sd-device.h"
#include "ansi-color.h"
#include "device-private.h"
#include "device-util.h"
#include "format-util.h"

View File

@ -20,9 +20,10 @@ Before=getty.target
ConditionPathExists=/dev/console
[Service]
# The '-o' option value tells agetty to replace 'login' arguments with an option to preserve environment (-p),
# followed by '--' for safety, and then the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear --keep-baud - 115200,38400,9600 $TERM
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --noreset --noclear --keep-baud 115200,57600,38400,9600 - ${TERM}
Type=idle
Restart=always
UtmpIdentifier=cons

View File

@ -25,9 +25,10 @@ Conflicts=rescue.service
Before=rescue.service
[Service]
# The '-o' option value tells agetty to replace 'login' arguments with an option to preserve environment (-p),
# followed by '--' for safety, and then the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear - $TERM
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --noreset --noclear - ${TERM}
Type=idle
Restart=always
RestartSec=0

View File

@ -34,11 +34,10 @@ Before=rescue.service
ConditionPathExists=/dev/tty0
[Service]
# the VT is cleared by TTYVTDisallocate
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear - $TERM
ExecStart=-/sbin/agetty -o '-p -- \\u' --noreset --noclear - ${TERM}
Type=idle
Restart=always
RestartSec=0

View File

@ -33,7 +33,7 @@ Before=rescue.service
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,57600,38400,9600 - $TERM
ExecStart=-/sbin/agetty -o '-p -- \\u' --noreset --noclear --keep-baud 115200,57600,38400,9600 - ${TERM}
Type=idle
Restart=always
UtmpIdentifier=%I