Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/gen add getpassfd() that gives us even more fine gr...



details:   https://anonhg.NetBSD.org/src/rev/1f20bff4ba68
branches:  trunk
changeset: 778760:1f20bff4ba68
user:      christos <christos%NetBSD.org@localhost>
date:      Thu Apr 12 22:07:44 2012 +0000

description:
add getpassfd() that gives us even more fine grain control on how to get
the password.

diffstat:

 lib/libc/gen/getpass.3 |   40 ++++++++++-
 lib/libc/gen/getpass.c |  169 +++++++++++++++++++++++++++++++++---------------
 2 files changed, 152 insertions(+), 57 deletions(-)

diffs (truncated from 365 to 300 lines):

diff -r 022acdaca724 -r 1f20bff4ba68 lib/libc/gen/getpass.3
--- a/lib/libc/gen/getpass.3    Thu Apr 12 20:15:37 2012 +0000
+++ b/lib/libc/gen/getpass.3    Thu Apr 12 22:07:44 2012 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: getpass.3,v 1.15 2012/04/12 20:15:37 wiz Exp $
+.\"    $NetBSD: getpass.3,v 1.16 2012/04/12 22:07:44 christos Exp $
 .\"
 .\" Copyright (c) 1989, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -43,6 +43,8 @@
 .Fn getpass "const char *prompt"
 .Ft char *
 .Fn getpass_r "const char *prompt" "char *buf" "size_t buflen"
+.Ft char *
+.Fn getpassfd "const char *prompt" "char *buf" "size_t buflen" "int fd[3]" "int flags"
 .Sh DESCRIPTION
 The
 .Fn getpass
@@ -71,6 +73,34 @@
 for up to
 .Fa buflen
 characters.
+If the
+.Fa buf
+argument is
+.Dv NULL ,
+then a buffer will be dynamically allocated.
+.Pp
+The
+.Fn getpassfd
+function allows one to specify the file descriptors used to be specified in
+.Fa fd ,
+and provides an extra
+.Fa flags
+argument to control its behavior:
+.Bl -tag -width GETPASS_BUF_LIMIT
+.It Dv GETPASS_NEED_TTY
+Fail if we are unable to set the tty modes like we want.
+.It Dv GETPASS_FAIL_EOF
+Fail if we get the end-of-file character instead of returning the result so far.
+.It Dv GETPASS_BUF_LIMIT
+Beep when the buffer limit is reached, instead of silently absorbing it.
+.It Dv GETPASS_NO_SIGNAL
+Don't make ttychars send signals.
+.It Dv GETPASS_NO_BEEP
+Don't beep if we erase past the beginning of the buffer or we try to enter past
+the end.
+.It Dv GETPASS_ECHO
+Echo characters as they are typed.
+.El
 .Sh RETURN VALUES
 The
 .Fn getpass
@@ -78,7 +108,9 @@
 string on error.
 The
 .Fn getpass_r
-function returns a pointer to the NUL terminated password, or
+and
+.Fn getpassfd
+functions return a pointer to the NUL terminated password, or
 .Dv NULL
 on error.
 .Sh FILES
@@ -103,7 +135,9 @@
 .At v7 .
 The
 .Fn getpass_r
-function appeared in
+and
+.Fn getpassfd
+functions appeared in
 .Nx 7.0 .
 .Sh BUGS
 The
diff -r 022acdaca724 -r 1f20bff4ba68 lib/libc/gen/getpass.c
--- a/lib/libc/gen/getpass.c    Thu Apr 12 20:15:37 2012 +0000
+++ b/lib/libc/gen/getpass.c    Thu Apr 12 22:07:44 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: getpass.c,v 1.18 2012/04/12 20:08:01 christos Exp $    */
+/*     $NetBSD: getpass.c,v 1.19 2012/04/12 22:07:44 christos Exp $    */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: getpass.c,v 1.18 2012/04/12 20:08:01 christos Exp $");
+__RCSID("$NetBSD: getpass.c,v 1.19 2012/04/12 22:07:44 christos Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
@@ -50,6 +50,7 @@
 #include <fcntl.h>
 
 #ifdef __weak_alias
+__weak_alias(getpassfd,_getpassfd)
 __weak_alias(getpass_r,_getpass_r)
 __weak_alias(getpass,_getpass)
 #endif
@@ -58,46 +59,40 @@
  * Notes:
  *     - There is no getpass_r in POSIX
  *     - Historically EOF is documented to be treated as EOL, we provide a
- *       tunable for that DONT_TREAT_EOF_AS_EOL to disable this.
+ *       tunable for that GETPASS_FAIL_EOF to disable this.
  *     - Historically getpass ate extra characters silently, we provide
- *       a tunable for that DONT_DISCARD_SILENTLY to disable this.
+ *       a tunable for that GETPASS_BUF_LIMIT to disable this.
  *     - Historically getpass "worked" by echoing characters when turning
- *       off echo failed, we provide a tunable DONT_WORK_AND_ECHO to
+ *       off echo failed, we provide a tunable GETPASS_NEED_TTY to
  *       disable this.
  *     - Some implementations say that on interrupt the program shall
  *       receive an interrupt signal before the function returns. We
  *       send all the tty signals before we return, but we don't expect
  *       suspend to do something useful unless the caller calls us again.
+ *       We also provide a tunable to disable signal delivery
+ *       GETPASS_NO_SIGNAL.
+ *     - GETPASS_NO_BEEP disables beeping.
+ *     - GETPASS_ECHO will echo the password (as pam likes it)
  */
 char *
-getpass_r(const char *prompt, char *ret, size_t len)
+/*ARGSUSED*/
+getpassfd(const char *prompt, char *buf, size_t len, int fd[], int flags)
 {
        struct termios gt;
        char c;
-       int infd, outfd, sig;
-       bool lnext, havetty;
+       int sig;
+       bool lnext, havetty, allocated;
 
        _DIAGASSERT(prompt != NULL);
 
        sig = 0;
-       /*
-        * Try to use /dev/tty if possible; otherwise read from stdin and
-        * write to stderr.
-        */
-       if ((outfd = infd = open(_PATH_TTY, O_RDWR)) == -1) {
-               infd = STDIN_FILENO;
-               outfd = STDERR_FILENO;
+
+       allocated = buf == NULL;
+       if (tcgetattr(fd[0], &gt) == -1) {
                havetty = false;
-       } else
-               havetty = true;
-
-       if (tcgetattr(infd, &gt) == -1) {
-               havetty = false;
-#ifdef DONT_WORK_AND_ECHO
-               goto out;
-#else
+               if (flags & GETPASS_NEED_TTY)
+                       goto out;
                memset(&gt, -1, sizeof(gt));
-#endif
        } else
                havetty = true;
                
@@ -108,22 +103,33 @@
                st.c_lflag &= ~(ECHO|ECHOK|ECHOE|ECHOKE|ECHOCTL|ISIG|ICANON);
                st.c_cc[VMIN] = 1;
                st.c_cc[VTIME] = 0;
-               if (tcsetattr(infd, TCSAFLUSH|TCSASOFT, &st) == -1)
+               if (tcsetattr(fd[0], TCSAFLUSH|TCSASOFT, &st) == -1)
                        goto out;
        }
 
        if (prompt != NULL) {
                size_t plen = strlen(prompt);
-               (void)write(outfd, prompt, plen);
+               (void)write(fd[1], prompt, plen);
+       }
+
+       if (allocated) {
+               len = 1024;
+               if ((buf = malloc(len)) == NULL)
+                       goto restore;
        }
 
        c = '\1';
        lnext = false;
        for (size_t l = 0; c != '\0'; ) {
-               if (read(infd, &c, 1) != 1)
+               if (read(fd[0], &c, 1) != 1)
                        goto restore;
 
-#define beep() write(outfd, "\a", 1)
+#define beep() do \
+       if (flags & GETPASS_NO_BEEP) \
+               (void)write(fd[2], "\a", 1); \
+       while (/*CONSTCOND*/ 0)
+#define erase() (void)write(fd[1], "\b \b", 3)
+
 #define C(a, b) (gt.c_cc[(a)] == _POSIX_VDISABLE ? (b) : gt.c_cc[(a)])
 
                if (lnext) {
@@ -145,6 +151,10 @@
 
                /* Line or word kill, treat as reset */
                if (c == C(VKILL, CTRL('u')) || c == C(VWERASE, CTRL('w'))) {
+                       if (flags & GETPASS_ECHO) {
+                               while (l--)
+                                       erase();
+                       }
                        l = 0;
                        continue;
                }
@@ -153,8 +163,11 @@
                if (c == C(VERASE, CTRL('h'))) {
                        if (l == 0)
                                beep();
-                       else
+                       else {
                                l--;
+                               if (flags & GETPASS_ECHO)
+                                       erase();
+                       }
                        continue;
                }
 
@@ -174,13 +187,13 @@
 
                /* EOF */
                if (c == C(VEOF, CTRL('d')))  {
-#ifdef DONT_TREAT_EOF_AS_EOL
-                       errno = ENODATA;
-                       goto out;
-#else
-                       c = '\0';
-                       goto add;
-#endif
+                       if (flags & GETPASS_FAIL_EOF) {
+                               errno = ENODATA;
+                               goto out;
+                       } else {
+                               c = '\0';
+                               goto add;
+                       }
                }
 
                /* End of line */
@@ -188,36 +201,78 @@
                        c = '\0';
 add:
                if (l >= len) {
-#ifdef DONT_DISCARD_SILENTLY
-                       beep();
-                       continue;
-#else
-                       if (c == '\0' && l > 0)
-                               l--;
-                       else
-                               continue;
-#endif
+                       if (allocated) {
+                               len += 1024;
+                               char *b = realloc(buf, len);
+                               if (b == NULL)
+                                       goto restore;
+                               buf = b;
+                       } else {
+                               if (flags & GETPASS_BUF_LIMIT) {
+                                       beep();
+                                       continue;
+                               }
+                               if (c == '\0' && l > 0)
+                                       l--;
+                               else
+                                       continue;
+                       }
                }
-               ret[l++] = c;
+               buf[l++] = c;
+               if (c && (flags & GETPASS_ECHO))
+                   (void)write(fd[1], &c, 1);
        }
 
        if (havetty)
-               (void)tcsetattr(infd, TCSAFLUSH|TCSASOFT, &gt);
-       return ret;
+               (void)tcsetattr(fd[0], TCSAFLUSH|TCSASOFT, &gt);
+       return buf;
 restore:
-       c = errno;
-       if (havetty)
-               (void)tcsetattr(infd, TCSAFLUSH|TCSASOFT, &gt);
-       errno = c;
+       if (havetty) {
+               c = errno;
+               (void)tcsetattr(fd[0], TCSAFLUSH|TCSASOFT, &gt);
+               errno = c;
+       }
 out:
        if (sig) {



Home | Main Index | Thread Index | Old Index