mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
terminal-util: tweak any_key_to_proceed() a bit
1. Make the message a bit more visible, by adding ANSI color. This matters in particular during boot, where the message otherwise might be overprinted by other output 2. Let's turn off terminal echo so that whatever key is entered is not made visible on screen, and we can handle newline and other keys reasonably uniformly.
This commit is contained in:
@@ -103,22 +103,25 @@ int chvt(int vt) {
|
||||
return RET_NERRNO(ioctl(fd, VT_ACTIVATE, vt));
|
||||
}
|
||||
|
||||
int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
|
||||
int read_one_char(FILE *f, char *ret, usec_t t, bool echo, bool *need_nl) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
struct termios old_termios;
|
||||
int r, fd;
|
||||
|
||||
assert(f);
|
||||
assert(ret);
|
||||
|
||||
if (!f)
|
||||
f = stdin;
|
||||
|
||||
/* If this is a terminal, then switch canonical mode off, so that we can read a single
|
||||
* character. (Note that fmemopen() streams do not have an fd associated with them, let's handle that
|
||||
* nicely.) */
|
||||
* nicely.) If 'echo' is false we'll also disable ECHO mode so that the pressed key is not made
|
||||
* visible to the user. */
|
||||
fd = fileno(f);
|
||||
if (fd >= 0 && tcgetattr(fd, &old_termios) >= 0) {
|
||||
struct termios new_termios = old_termios;
|
||||
|
||||
new_termios.c_lflag &= ~ICANON;
|
||||
new_termios.c_lflag &= ~(ICANON|(echo ? 0 : ECHO));
|
||||
new_termios.c_cc[VMIN] = 1;
|
||||
new_termios.c_cc[VTIME] = 0;
|
||||
|
||||
@@ -201,7 +204,7 @@ int ask_char(char *ret, const char *replies, const char *fmt, ...) {
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
r = read_one_char(stdin, &c, DEFAULT_ASK_REFRESH_USEC, &need_nl);
|
||||
r = read_one_char(stdin, &c, DEFAULT_ASK_REFRESH_USEC, /* echo= */ true, &need_nl);
|
||||
if (r < 0) {
|
||||
|
||||
if (r == -ETIMEDOUT)
|
||||
@@ -257,20 +260,23 @@ int ask_string(char **ret, const char *text, ...) {
|
||||
}
|
||||
|
||||
bool any_key_to_proceed(void) {
|
||||
|
||||
/* Insert a new line here as well as to when the user inputs, as this is also used during the boot up
|
||||
* sequence when status messages may be interleaved with the current program output. This ensures
|
||||
* that the status messages aren't appended on the same line as this message. */
|
||||
|
||||
fputc('\n', stdout);
|
||||
fputs(ansi_highlight_magenta(), stdout);
|
||||
fputs("-- Press any key to proceed --", stdout);
|
||||
fputs(ansi_normal(), stdout);
|
||||
fflush(stdout);
|
||||
|
||||
char key = 0;
|
||||
bool need_nl = true;
|
||||
(void) read_one_char(stdin, &key, USEC_INFINITY, /* echo= */ false, /* need_nl= */ NULL);
|
||||
|
||||
/*
|
||||
* Insert a new line here as well as to when the user inputs, as this is also used during the
|
||||
* boot up sequence when status messages may be interleaved with the current program output.
|
||||
* This ensures that the status messages aren't appended on the same line as this message.
|
||||
*/
|
||||
puts("-- Press any key to proceed --");
|
||||
|
||||
(void) read_one_char(stdin, &key, USEC_INFINITY, &need_nl);
|
||||
|
||||
if (need_nl)
|
||||
putchar('\n');
|
||||
fputc('\n', stdout);
|
||||
fputc('\n', stdout);
|
||||
fflush(stdout);
|
||||
|
||||
return key != 'q';
|
||||
}
|
||||
@@ -312,10 +318,9 @@ int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage)
|
||||
putchar('\n');
|
||||
|
||||
/* on the first screen we reserve 2 extra lines for the title */
|
||||
if (i % break_lines == break_modulo) {
|
||||
if (i % break_lines == break_modulo)
|
||||
if (!any_key_to_proceed())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -80,7 +80,7 @@ int proc_cmdline_tty_size(const char *tty, unsigned *ret_rows, unsigned *ret_col
|
||||
|
||||
int chvt(int vt);
|
||||
|
||||
int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
|
||||
int read_one_char(FILE *f, char *ret, usec_t timeout, bool echo, bool *need_nl);
|
||||
int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4);
|
||||
int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
|
||||
bool any_key_to_proceed(void);
|
||||
|
||||
@@ -954,7 +954,7 @@ static int loop(const char *root) {
|
||||
if (arg_batch)
|
||||
(void) usleep_safe(usec_add(usec_sub_unsigned(last_refresh, t), arg_delay));
|
||||
else {
|
||||
r = read_one_char(stdin, &key, usec_add(usec_sub_unsigned(last_refresh, t), arg_delay), NULL);
|
||||
r = read_one_char(stdin, &key, usec_add(usec_sub_unsigned(last_refresh, t), arg_delay), /* echo= */ false, /* need_nl= */ NULL);
|
||||
if (r == -ETIMEDOUT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
|
||||
@@ -128,7 +128,7 @@ static void print_welcome(int rfd) {
|
||||
else
|
||||
printf("\nWelcome to your new installation of %s!\n", pn);
|
||||
|
||||
printf("\nPlease configure your system!\n\n");
|
||||
printf("\nPlease configure your system!\n");
|
||||
|
||||
any_key_to_proceed();
|
||||
|
||||
|
||||
@@ -2485,7 +2485,12 @@ static int create_interactively(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
any_key_to_proceed();
|
||||
printf("\nPlease create your user account!\n");
|
||||
|
||||
if (!any_key_to_proceed()) {
|
||||
log_notice("Skipping.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) terminal_reset_defensive_locked(STDOUT_FILENO, /* switch_to_text= */ false);
|
||||
|
||||
|
||||
@@ -228,9 +228,9 @@ static int display_emergency_message_fullscreen(const char *message) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = read_one_char(f, &read_character_buffer, USEC_INFINITY, NULL);
|
||||
r = read_one_char(f, &read_character_buffer, USEC_INFINITY, /* echo= */ true, /* need_nl= */ NULL);
|
||||
if (r < 0 && r != -EINTR)
|
||||
log_error_errno(r, "Failed to read character: %m");
|
||||
log_warning_errno(r, "Failed to read character, ignoring: %m");
|
||||
|
||||
r = 0;
|
||||
|
||||
|
||||
@@ -55,20 +55,20 @@ TEST(read_one_char) {
|
||||
|
||||
assert_se(fputs("c\n", file) >= 0);
|
||||
rewind(file);
|
||||
assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0);
|
||||
assert_se(read_one_char(file, &r, 1000000, /* echo= */ true, &need_nl) >= 0);
|
||||
assert_se(!need_nl);
|
||||
assert_se(r == 'c');
|
||||
assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
|
||||
assert_se(read_one_char(file, &r, 1000000, /* echo= */ true, &need_nl) < 0);
|
||||
|
||||
rewind(file);
|
||||
assert_se(fputs("foobar\n", file) >= 0);
|
||||
rewind(file);
|
||||
assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
|
||||
assert_se(read_one_char(file, &r, 1000000, /* echo= */ true, &need_nl) < 0);
|
||||
|
||||
rewind(file);
|
||||
assert_se(fputs("\n", file) >= 0);
|
||||
rewind(file);
|
||||
assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0);
|
||||
assert_se(read_one_char(file, &r, 1000000, /* echo= */ true, &need_nl) < 0);
|
||||
}
|
||||
|
||||
TEST(getttyname_malloc) {
|
||||
|
||||
Reference in New Issue
Block a user