Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save konsolebox/ed71274d4dfe7c809a597d08770d89f1 to your computer and use it in GitHub Desktop.
Save konsolebox/ed71274d4dfe7c809a597d08770d89f1 to your computer and use it in GitHub Desktop.
diff --git a/src/utils_password.c b/src/utils_password.c
index 58f3a7b..5a055a8 100644
--- a/src/utils_password.c
+++ b/src/utils_password.c
@@ -106,33 +106,60 @@ static int tools_check_password(const char *password)
/* Password reading helpers */
-static ssize_t read_tty_eol(int fd, char *pass, size_t maxlen)
+static ssize_t read_tty_eol(int fd, int ofd, char *pass, size_t maxlen)
{
bool eol = false;
size_t read_size = 0;
ssize_t r;
+ const char *p;
+
+ if (maxlen < 1)
+ return -1;
do {
- r = read(fd, pass, maxlen - read_size);
+ r = read(fd, pass + read_size, maxlen - read_size);
+
if ((r == -1 && errno != EINTR) || quit)
return -1;
- if (r >= 0) {
- if (!r || pass[r-1] == '\n')
+
+ if (r == 0)
+ break;
+
+ for (p = pass + read_size; r > 0 && read_size < maxlen && !eol; --r,
+ ++p) {
+ switch (*p) {
+ case '\n':
+ pass[read_size++] = '\n';
+ case '\0':
eol = true;
- read_size += (size_t)r;
- pass = pass + r;
+ break;
+ case '\b':
+ case CERASE:
+ if (read_size > 0) {
+ --read_size;
+ if (write(ofd, "\b \b", 3) == -1)
+ return -1;
+ }
+
+ break;
+ default:
+ pass[read_size++] = *p;
+ if (write(ofd, "*", 1) == -1)
+ return -1;
+ };
}
- } while (!eol && read_size != maxlen);
+ } while (read_size < maxlen && !eol);
+ pass[read_size] = '\0';
return (ssize_t)read_size;
}
/* The pass buffer is zeroed and has trailing \0 already " */
-static int untimed_read(int fd, char *pass, size_t maxlen)
+static int untimed_read(int fd, int ofd, char *pass, size_t maxlen)
{
ssize_t i;
- i = read_tty_eol(fd, pass, maxlen);
+ i = read_tty_eol(fd, ofd, pass, maxlen);
if (i > 0) {
if (pass[i-1] == '\n')
pass[i-1] = '\0';
@@ -143,7 +170,7 @@ static int untimed_read(int fd, char *pass, size_t maxlen)
return i;
}
-static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
+static int timed_read(int fd, int ofd, char *pass, size_t maxlen, long timeout)
{
struct timeval t;
fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
@@ -155,11 +182,30 @@ static int timed_read(int fd, char *pass, size_t maxlen, long timeout)
t.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL, &t) > 0)
- failed = untimed_read(fd, pass, maxlen);
+ failed = untimed_read(fd, ofd, pass, maxlen);
return failed;
}
+/* Copied from bash's shtty.c
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ * Licensed under GPL v2 or later version */
+static void tt_setonechar(struct termios *ttp)
+{
+ ttp->c_lflag &= ~ICANON;
+ ttp->c_lflag |= ISIG;
+ ttp->c_lflag |= IEXTEN;
+ ttp->c_iflag |= ICRNL;
+ ttp->c_iflag &= ~INLCR;
+ ttp->c_oflag |= OPOST;
+ ttp->c_oflag |= ONLCR;
+ ttp->c_oflag &= ~OCRNL;
+ ttp->c_oflag &= ~ONOCR;
+ ttp->c_oflag &= ~ONLRET;
+ ttp->c_cc[VMIN] = 1;
+ ttp->c_cc[VTIME] = 0;
+}
+
static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
long timeout)
{
@@ -182,6 +228,7 @@ static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
goto out;
memcpy(&tmp, &orig, sizeof(tmp));
+ tt_setonechar(&tmp);
tmp.c_lflag &= ~ECHO;
if (prompt && write(outfd, prompt, strlen(prompt)) < 0)
@@ -189,9 +236,9 @@ static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
tcsetattr(infd, TCSAFLUSH, &tmp);
if (timeout)
- failed = timed_read(infd, pass, maxlen, timeout);
+ failed = timed_read(infd, outfd, pass, maxlen, timeout);
else
- failed = untimed_read(infd, pass, maxlen);
+ failed = untimed_read(infd, outfd, pass, maxlen);
tcsetattr(infd, TCSAFLUSH, &orig);
out:
if (!failed && write(outfd, "\n", 1)) {};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment