X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=libbb%2Fbb_askpass.c;h=2dcead35ab2149d47de280f562259f81edf67f4e;hb=c2058ec98cf3f6722be4436cae07a386e3c7b48d;hp=f9b918cecef643a070d35a33d6d7aec88f25524d;hpb=8131eea3dce5fba0dfb78e6083d1730423fad20b;p=oweals%2Fbusybox.git diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index f9b918cec..2dcead35a 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c @@ -1,13 +1,11 @@ /* vi: set sw=4 ts=4: */ /* * Ask for a password - * I use a static buffer in this function. Plan accordingly. * * Copyright (C) 1999-2004 by Erik Andersen * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ - #include "libbb.h" /* do nothing signal handler */ @@ -15,38 +13,40 @@ static void askpass_timeout(int UNUSED_PARAM ignore) { } -char* FAST_FUNC bb_ask_stdin(const char *prompt) -{ - return bb_ask(STDIN_FILENO, 0, prompt); -} -char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) +char* FAST_FUNC bb_ask_noecho(int fd, int timeout, const char *prompt) { - /* Was static char[BIGNUM] */ - enum { sizeof_passwd = 128 }; - static char *passwd; - +#define MAX_LINE 0xfff char *ret; int i; struct sigaction sa, oldsa; struct termios tio, oldtio; - if (!passwd) - passwd = xmalloc(sizeof_passwd); - memset(passwd, 0, sizeof_passwd); + tcflush(fd, TCIFLUSH); + /* Was buggy: was printing prompt *before* flushing input, + * which was upsetting "expect" based scripts of some users. + */ + fputs(prompt, stdout); + fflush_all(); tcgetattr(fd, &oldtio); - tcflush(fd, TCIFLUSH); tio = oldtio; -#ifndef IUCLC -# define IUCLC 0 -#endif - tio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY); - tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP); - tcsetattr_stdin_TCSANOW(&tio); + /* Switch off echo. ECHOxyz meaning: + * ECHO echo input chars + * ECHOE echo BS-SP-BS on erase character + * ECHOK echo kill char specially, not as ^c (ECHOKE controls how exactly) + * ECHOKE erase all input via BS-SP-BS on kill char (else go to next line) + * ECHOCTL Echo ctrl chars as ^c (else echo verbatim: + * e.g. up arrow emits "ESC-something" and thus moves cursor up!) + * ECHONL Echo NL even if ECHO is not set + * ECHOPRT On erase, echo erased chars + * [qwe input looks like "qwe\ewq/" on screen] + */ + tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL); + tcsetattr(fd, TCSANOW, &tio); 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) { @@ -54,29 +54,46 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) alarm(timeout); } - 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++]); + i = 0; + while (1) { + int r; + + /* User input is uber-slow, no need to optimize reallocs. + * Grow it on every char. + */ + ret = xrealloc(ret, i + 2); + r = read(fd, &ret[i], 1); + + if ((i == 0 && r == 0) /* EOF (^D) with no password */ + || r < 0 /* read is interrupted by timeout or ^C */ + ) { + ret[i] = '\0'; /* paranoia */ + nuke_str(ret); /* paranoia */ + free(ret); + ret = NULL; + break; + } + + if (r == 0 /* EOF */ + || ret[i] == '\r' || ret[i] == '\n' /* EOL */ + || ++i == MAX_LINE /* line limit */ + ) { + ret[i] = '\0'; + break; + } } if (timeout) { alarm(0); } sigaction_set(SIGINT, &oldsa); - - tcsetattr_stdin_TCSANOW(&oldtio); + tcsetattr(fd, TCSANOW, &oldtio); bb_putchar('\n'); fflush_all(); return ret; } +char* FAST_FUNC bb_ask_noecho_stdin(const char *prompt) +{ + return bb_ask_noecho(STDIN_FILENO, 0, prompt); +}