diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index c2aa75c6a82..ba3b9524c6d 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -81,14 +81,16 @@ int chvt(int vt) { } int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { - struct termios old_termios, new_termios; - char c, line[LINE_MAX]; + _cleanup_free_ char *line = NULL; + struct termios old_termios; + int r; assert(f); assert(ret); + /* If this is a terminal, then switch canonical mode off, so that we can read a single character */ if (tcgetattr(fileno(f), &old_termios) >= 0) { - new_termios = old_termios; + struct termios new_termios = old_termios; new_termios.c_lflag &= ~ICANON; new_termios.c_cc[VMIN] = 1; @@ -124,11 +126,13 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { return -ETIMEDOUT; } - errno = 0; - if (!fgets(line, sizeof(line), f)) - return errno > 0 ? -errno : -EIO; + /* If this is not a terminal, then read a full line instead */ - truncate_nl(line); + r = read_line(f, 16, &line); /* longer than necessary, to eat up UTF-8 chars/vt100 key sequences */ + if (r < 0) + return r; + if (r == 0) + return -EIO; if (strlen(line) != 1) return -EBADMSG; @@ -196,11 +200,13 @@ int ask_char(char *ret, const char *replies, const char *fmt, ...) { } int ask_string(char **ret, const char *text, ...) { + int r; + assert(ret); assert(text); for (;;) { - char line[LINE_MAX]; + _cleanup_free_ char *line = NULL; va_list ap; if (colors_enabled()) @@ -215,24 +221,14 @@ int ask_string(char **ret, const char *text, ...) { fflush(stdout); - errno = 0; - if (!fgets(line, sizeof(line), stdin)) - return errno > 0 ? -errno : -EIO; + r = read_line(stdin, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + return -EIO; - if (!endswith(line, "\n")) - putchar('\n'); - else { - char *s; - - if (isempty(line)) - continue; - - truncate_nl(line); - s = strdup(line); - if (!s) - return -ENOMEM; - - *ret = s; + if (!isempty(line)) { + *ret = TAKE_PTR(line); return 0; } }