aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/bb_askpass.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c
index f9b918cec..bdb756659 100644
--- a/libbb/bb_askpass.c
+++ b/libbb/bb_askpass.c
@@ -30,10 +30,6 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
struct sigaction sa, oldsa;
struct termios tio, oldtio;
- if (!passwd)
- passwd = xmalloc(sizeof_passwd);
- memset(passwd, 0, sizeof_passwd);
-
tcgetattr(fd, &oldtio);
tcflush(fd, TCIFLUSH);
tio = oldtio;
@@ -46,7 +42,7 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
memset(&sa, 0, sizeof(sa));
/* sa.sa_flags = 0; - no SA_RESTART! */
- /* SIGINT and SIGALRM will interrupt read below */
+ /* SIGINT and SIGALRM will interrupt reads below */
sa.sa_handler = askpass_timeout;
sigaction(SIGINT, &sa, &oldsa);
if (timeout) {
@@ -56,18 +52,26 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
fputs(prompt, stdout);
fflush_all();
- ret = NULL;
- /* On timeout or Ctrl-C, read will hopefully be interrupted,
- * and we return NULL */
- if (read(fd, passwd, sizeof_passwd - 1) > 0) {
- ret = passwd;
- i = 0;
- /* Last byte is guaranteed to be 0
- (read did not overwrite it) */
- do {
- if (passwd[i] == '\r' || passwd[i] == '\n')
- passwd[i] = '\0';
- } while (passwd[i++]);
+
+ if (!passwd)
+ passwd = xmalloc(sizeof_passwd);
+ memset(passwd, 0, sizeof_passwd);
+ ret = passwd;
+ i = 0;
+ while (1) {
+ int r = read(fd, &ret[i], 1);
+ if (r < 0) {
+ /* read is interrupted by timeout or ^C */
+ ret = NULL;
+ break;
+ }
+ if (r == 0 /* EOF */
+ || ret[i] == '\r' || ret[i] == '\n' /* EOL */
+ || ++i == sizeof_passwd-1 /* line limit */
+ ) {
+ ret[i] = '\0';
+ break;
+ }
}
if (timeout) {