getpass: now we have a /dev/tty use it and also correct some behaviour
authorAlan Cox <alan@linux.intel.com>
Sun, 24 May 2015 22:30:52 +0000 (23:30 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 24 May 2015 22:30:52 +0000 (23:30 +0100)
With this sorted su and passwd now work exactly as expected

Library/libs/getpass.c

index 0b24fe9..8c01e1d 100644 (file)
@@ -5,21 +5,22 @@
 #include <string.h>
 #include <termios.h>
 #include <sys/ioctl.h>
+#include <fcntl.h>
 
 #define EOF    (-1)
 
-static int _getchar(void)
+static int _getchar(int fd)
 {
        static char ch;
-       return (read(0, &ch, 1) == 1) ? ch : EOF;
+       return (read(fd, &ch, 1) == 1) ? ch : EOF;
 }
 
-static char *_gets(char *buf, int len)
+static char *_gets(int fd, char *buf, int len)
 {
        int ch, i = 0;
 
        while (i < len) {
-               if ((ch = _getchar()) == EOF && i == 0)
+               if ((ch = _getchar(fd)) == EOF && i == 0)
                        return NULL;
                if (ch == '\n' || ch == '\r')
                        break;
@@ -29,7 +30,6 @@ static char *_gets(char *buf, int len)
        return buf;
 }
 
-/* FIXME: should use /dev/tty interface eventually */
 char *getpass(char *prompt)
 {
        static char result[128];
@@ -37,19 +37,28 @@ char *getpass(char *prompt)
        tcflag_t ol;
        int tv;
 
+       int fd = open("/dev/tty", O_RDWR);
+
+       if (fd == -1)
+               return NULL;
+
        /* display the prompt */
-       write(2, prompt, strlen(prompt));
+       write(fd, prompt, strlen(prompt));
 
-       tv = tcgetattr(0, &t);
+       tv = tcgetattr(fd, &t);
        ol = t.c_lflag;
        t.c_lflag &= ~ECHO|ECHOE|ECHOK;
        if (tv == 0)
-               tcsetattr(0, TCSANOW, &t);
+               tcsetattr(fd, TCSANOW, &t);
        /* read the input */
-       if (_gets(result, sizeof(result) - 1) == NULL)
+       if (_gets(fd, result, sizeof(result) - 1) == NULL)
                result[0] = 0;
        t.c_lflag = ol;
        if (tv == 0)
                tcsetattr(0, TCSANOW, &t);
+       /* The newline isn't echoed as we have echo off, so we need to
+          output it as the end of the task */
+       write(fd, "\n", 1);
+       close(fd);
        return result;
 }