]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
terminal-util: tweak any_key_to_proceed() a bit
authorLennart Poettering <lennart@poettering.net>
Wed, 5 Feb 2025 08:35:51 +0000 (09:35 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 17 Feb 2025 14:07:38 +0000 (15:07 +0100)
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.

src/basic/terminal-util.c
src/basic/terminal-util.h
src/cgtop/cgtop.c
src/firstboot/firstboot.c
src/home/homectl.c
src/journal/bsod.c
src/test/test-terminal-util.c

index 678cd4ed4dd4f54262aabfaa6412aeb6342bc9b0..b2cbadb579cb4f86d655e9b0de912635c52b107e 100644 (file)
@@ -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) {
-        char key = 0;
-        bool need_nl = true;
 
-        /*
-         * 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 --");
+        /* 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);
 
-        (void) read_one_char(stdin, &key, USEC_INFINITY, &need_nl);
+        char key = 0;
+        (void) read_one_char(stdin, &key, USEC_INFINITY, /* echo= */ false, /* need_nl= */ NULL);
 
-        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;
index d6dd394bcf466e021db3805fa9d3a33a4d0f9dde..d11daefb561fde525ee8510e916cad541a2972af 100644 (file)
@@ -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);
index 08eae5988b0c43b0bb1a65e439e8e714c03dcb69..ce73599d90228f377ab0eb22ad55af0f86c56a73 100644 (file)
@@ -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)
index d00886fb808b81fab73233b848c5d92c7e7f02fc..aaff8a8e8855f254e8ed2db69a13888b8ee20bb0 100644 (file)
@@ -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();
 
index bfd4b3b574b4b1e723e723b8cdc792c26bba53f1..89e9c8b82b117f05fdb3eff369bacff085329df9 100644 (file)
@@ -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);
 
index 2f06808cd4c02d512d08eba93365eb5aed34e913..68361b084a6e6a16f9dba8872481343fe898daa5 100644 (file)
@@ -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;
 
index ac7eacb01a05869dadfa129473ac0cc9d60bb470..87304346e9e1e41e0de36f435ee24db523461270 100644 (file)
@@ -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) {