libbb: switch bb_ask_noecho() to "mallocing" string return API
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 7 Apr 2018 13:50:30 +0000 (15:50 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 7 Apr 2018 13:50:30 +0000 (15:50 +0200)
function                                             old     new   delta
bb_ask_noecho                                        313     330     +17
get_cred_or_die                                      125     115     -10
passwd_main                                          995     958     -37
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 17/-47)            Total: -30 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/libbb.h
libbb/bb_askpass.c
loginutils/cryptpw.c
loginutils/passwd.c
mailutils/mail.c

index 5388d9d95ab712a2b09e0a204b732449b7300289..ed9a562ff44368ebd5219fff53ac6883eacb5c56 100644 (file)
@@ -1408,10 +1408,11 @@ extern int set_loop(char **devname, const char *file, unsigned long long offset,
 #define BB_LO_FLAGS_READ_ONLY 1
 #define BB_LO_FLAGS_AUTOCLEAR 4
 
-/* Like bb_ask_noecho below, but asks on stdin with no timeout.  */
+/* Returns malloced str */
+char *bb_ask_noecho(int fd, int timeout, const char *prompt) FAST_FUNC;
+/* Like bb_ask_noecho, but asks on stdin with no timeout.  */
 char *bb_ask_noecho_stdin(const char *prompt) FAST_FUNC;
-//TODO: pass buf pointer or return allocated buf (avoid statics)?
-char *bb_ask_noecho(const int fd, int timeout, const char *prompt) FAST_FUNC;
+
 int bb_ask_y_confirmation_FILE(FILE *fp) FAST_FUNC;
 int bb_ask_y_confirmation(void) FAST_FUNC;
 
index aadc6910811bad1449ec2e5ee1c478469bbb2466..2dcead35ab2149d47de280f562259f81edf67f4e 100644 (file)
@@ -13,16 +13,9 @@ static void askpass_timeout(int UNUSED_PARAM ignore)
 {
 }
 
-char* FAST_FUNC bb_ask_noecho_stdin(const char *prompt)
-{
-       return bb_ask_noecho(STDIN_FILENO, 0, prompt);
-}
-char* FAST_FUNC bb_ask_noecho(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 };
-
-       char *passwd;
+#define MAX_LINE 0xfff
        char *ret;
        int i;
        struct sigaction sa, oldsa;
@@ -37,7 +30,17 @@ char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt)
 
        tcgetattr(fd, &oldtio);
        tio = oldtio;
-       /* Switch off echo */
+       /* 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<BS><BS><BS> input looks like "qwe\ewq/" on screen]
+        */
        tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL);
        tcsetattr(fd, TCSANOW, &tio);
 
@@ -51,20 +54,30 @@ char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt)
                alarm(timeout);
        }
 
-       passwd = auto_string(xmalloc(sizeof_passwd));
-       ret = passwd;
+       ret = NULL;
        i = 0;
        while (1) {
-               int r = read(fd, &ret[i], 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 == sizeof_passwd-1 /* line limit */
+                || ++i == MAX_LINE /* line limit */
                ) {
                        ret[i] = '\0';
                        break;
@@ -80,3 +93,7 @@ char* FAST_FUNC bb_ask_noecho(const int fd, int timeout, const char *prompt)
        fflush_all();
        return ret;
 }
+char* FAST_FUNC bb_ask_noecho_stdin(const char *prompt)
+{
+       return bb_ask_noecho(STDIN_FILENO, 0, prompt);
+}
index 3ca7eda4a8eaa437fcc29aed0f5a0b0d9b67cf53..fbb7f0515f101978c90fabc7ee44c4e622055f83 100644 (file)
@@ -133,7 +133,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv)
        if (!password) {
                /* Only mkpasswd, and only from tty, prompts.
                 * Otherwise it is a plain read. */
-               password = (ENABLE_MKPASSWD && isatty(STDIN_FILENO) && applet_name[0] == 'm')
+               password = (ENABLE_MKPASSWD && applet_name[0] == 'm' && isatty(STDIN_FILENO))
                        ? bb_ask_noecho_stdin("Password: ")
                        : xmalloc_fgetline(stdin)
                ;
index 02303b5755d5a629a4f841314662ac504afc4487..d0408d8b4b9de4cebd870801309748ffbbfeea5a 100644 (file)
@@ -65,11 +65,9 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo
                if (ENABLE_FEATURE_CLEAN_UP)
                        free(encrypted);
        }
-       orig = xstrdup(orig); /* or else bb_ask_noecho_stdin() will destroy it */
        newp = bb_ask_noecho_stdin("New password: "); /* returns ptr to static */
        if (!newp)
                goto err_ret;
-       newp = xstrdup(newp); /* we are going to bb_ask_noecho_stdin() again, so save it */
        if (ENABLE_FEATURE_PASSWD_WEAK_CHECK
         && obscure(orig, newp, pw)
         && myuid != 0
@@ -99,6 +97,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo
        if (ENABLE_FEATURE_CLEAN_UP) free(newp);
 
        nuke_str(cp);
+       if (ENABLE_FEATURE_CLEAN_UP) free(cp);
        return ret;
 }
 
index 0fc615a7f8d7896a53e150a8e1e84b74291b68f6..7af7edd6c9e58cffdcf1f5344c3ce928fc5e7c6f 100644 (file)
@@ -163,8 +163,8 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol)
 void FAST_FUNC get_cred_or_die(int fd)
 {
        if (isatty(fd)) {
-               G.user = xstrdup(bb_ask_noecho(fd, /* timeout: */ 0, "User: "));
-               G.pass = xstrdup(bb_ask_noecho(fd, /* timeout: */ 0, "Password: "));
+               G.user = bb_ask_noecho(fd, /* timeout: */ 0, "User: ");
+               G.pass = bb_ask_noecho(fd, /* timeout: */ 0, "Password: ");
        } else {
                G.user = xmalloc_reads(fd, /* maxsize: */ NULL);
                G.pass = xmalloc_reads(fd, /* maxsize: */ NULL);