[PATCH 03/17] lib: avoid use of obsolete getpass() function

Sami Kerola
2014-09-07T12:43:17Z

Reference: http://man7.org/linux/man-pages/man3/getpass.3.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
include/xgetpass.h | 2 +-
lib/xgetpass.c | 56 +++++++++++++++++++++++++-----------------------------
2 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/include/xgetpass.h b/include/xgetpass.h
index b5a3c87..622ba8c 100644
--- a/include/xgetpass.h
+++ b/include/xgetpass.h
@@ -1,6 +1,6 @@
#ifndef UTIL_LINUX_XGETPASS_H
#define UTIL_LINUX_XGETPASS_H

-extern char *xgetpass(int pfd, const char *prompt);
+extern char *xgetpass(FILE *input, const char *prompt);

#endif /* UTIL_LINUX_XGETPASS_H */
diff --git a/lib/xgetpass.c b/lib/xgetpass.c
index ba20894..9c7d431 100644
--- a/lib/xgetpass.c
+++ b/lib/xgetpass.c
@@ -5,42 +5,38 @@
* Public domain.
*/

+#include <err.h>
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
+#include <termios.h>
#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>

-#include "c.h"
-#include "xgetpass.h"
-
-char *xgetpass(int pfd, const char *prompt)
+char *xgetpass(FILE *input, const char *prompt)
{
char *pass = NULL;
- int len = 0, i;
-
- if (pfd < 0) /* terminal */
- return getpass(prompt);
-
- for (i=0; ; i++) {
- if (i >= len-1) {
- char *tmppass = pass;
- len += 128;
-
- pass = realloc(tmppass, len);
- if (!pass) {
- pass = tmppass; /* the old buffer hasn't changed */
- break;
- }
- }
- if (pass && (read(pfd, pass + i, 1) != 1 ||
- pass[i] == '\n' || pass[i] == 0))
- break;
+ struct termios saved, no_echo;
+ const int fd = fileno(input);
+ size_t dummy = 0;
+ ssize_t len;
+
+ fputs(prompt, stdout);
+ if (isatty(fd)) {
+ /* disable echo */
+ tcgetattr(fd, &saved);
+ no_echo = saved;
+ no_echo.c_lflag &= ~ECHO;
+ no_echo.c_lflag |= ECHONL;
+ if (tcsetattr(fd, TCSANOW, &no_echo))
+ err(EXIT_FAILURE, "could not set terminal attributes");
}
-
- if (pass)
- pass[i] = '\0';
+ len = getline(&pass, &dummy, input);
+ if (len < 0)
+ warn("could not getline");
+ if (*(pass + len - 1) == '\n')
+ *(pass + len - 1) = '\0';
+ if (isatty(fd))
+ /* restore terminal */
+ if (tcsetattr(fd, TCSANOW, &saved))
+ err(EXIT_FAILURE, "could not set terminal attributes");
return pass;
}
-
--
2.1.0