Module Name: src Committed By: christos Date: Sat Apr 14 01:33:44 UTC 2012
Modified Files: src/lib/libc/gen: getpass.3 getpass.c Log Message: - If fd == NULL, do the dance with opening /dev/tty - Add a flag to enter a newline when we are done. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/lib/libc/gen/getpass.3 cvs rdiff -u -r1.24 -r1.25 src/lib/libc/gen/getpass.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/gen/getpass.3 diff -u src/lib/libc/gen/getpass.3:1.19 src/lib/libc/gen/getpass.3:1.20 --- src/lib/libc/gen/getpass.3:1.19 Fri Apr 13 10:39:34 2012 +++ src/lib/libc/gen/getpass.3 Fri Apr 13 21:33:43 2012 @@ -1,4 +1,4 @@ -.\" $NetBSD: getpass.3,v 1.19 2012/04/13 14:39:34 christos Exp $ +.\" $NetBSD: getpass.3,v 1.20 2012/04/14 01:33:43 christos Exp $ .\" .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -44,7 +44,7 @@ .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" "int timeout" +.Fn getpassfd "const char *prompt" "char *buf" "size_t buflen" "int *fd" "int flags" "int timeout" .Sh DESCRIPTION The .Fn getpass @@ -81,11 +81,31 @@ then a buffer will be dynamically alloca .Pp The .Fn getpassfd -function allows one to specify the file descriptors used to be specified in -.Fa fd , -and provides an extra +function allows one to specify the three file descriptors corresponding to +.Dv stdin , +.Dv stdout , +and +.Dv stderr +in the +.Fa fd +argument, or if +.Fa fd +is +.Dv NULL , +.Fn getpassfd +first attempts to open +.Pa /dev/tty +and if that fails, defaults to +.Dv STDIN_FILENO +for input and +.Dv STDERR_FILENO +for output. +.Pp +The behavior of +.Fn getpassfd +is controlled by the .Fa flags -argument to control its behavior: +argument: .Bl -tag -width GETPASS_BUF_LIMIT .It Dv GETPASS_NEED_TTY Fail if we are unable to set the tty modes like we want. @@ -104,6 +124,14 @@ Echo a for each character entered. .It Dv GETPASS_ECHO Echo characters as they are typed. +.It Dv GETPASS_ECHO_NL +Echoes a newline if successful. +.It Dv GETPASS_7BIT +Mask the high bit for each entered character. +.It Dv GETPASS_FORCE_LOWER +Lowcase each entered character. +.It Dv GETPASS_FORCE_UPPER +Upcase each entered character. .El Finally if the .Fa timeout Index: src/lib/libc/gen/getpass.c diff -u src/lib/libc/gen/getpass.c:1.24 src/lib/libc/gen/getpass.c:1.25 --- src/lib/libc/gen/getpass.c:1.24 Fri Apr 13 10:42:18 2012 +++ src/lib/libc/gen/getpass.c Fri Apr 13 21:33:43 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: getpass.c,v 1.24 2012/04/13 14:42:18 christos Exp $ */ +/* $NetBSD: getpass.c,v 1.25 2012/04/14 01:33:43 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.24 2012/04/13 14:42:18 christos Exp $"); +__RCSID("$NetBSD: getpass.c,v 1.25 2012/04/14 01:33:43 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" @@ -76,21 +76,45 @@ __weak_alias(getpass,_getpass) * - GETPASS_NO_BEEP disables beeping. * - GETPASS_ECHO_STAR will echo '*' for each character of the password * - GETPASS_ECHO will echo the password (as pam likes it) + * - GETPASS_7BIT strips the 8th bit + * - GETPASS_FORCE_UPPER forces to uppercase + * - GETPASS_FORCE_LOWER forces to uppercase + * - GETPASS_ECHO_NL echo's a new line on success if echo was off. */ char * /*ARGSUSED*/ -getpassfd(const char *prompt, char *buf, size_t len, int fd[], int flags, +getpassfd(const char *prompt, char *buf, size_t len, int *fd, int flags, int tout) { struct termios gt; char c; int sig; - bool lnext, havetty, allocated; + bool lnext, havetty, allocated, opentty, good; + int fdc[3]; _DIAGASSERT(prompt != NULL); - sig = 0; + if (buf != NULL && len == 0) { + errno = EINVAL; + return NULL; + } + good = false; + opentty = false; + if (fd == NULL) { + /* + * Try to use /dev/tty if possible; otherwise read from stdin + * and write to stderr. + */ + fd = fdc; + if ((fd[0] = fd[1] = fd[2] = open(_PATH_TTY, O_RDWR)) == -1) { + fd[0] = STDIN_FILENO; + fd[1] = fd[2] = STDERR_FILENO; + } else + opentty = true; + } + + sig = 0; allocated = buf == NULL; if (tcgetattr(fd[0], >) == -1) { havetty = false; @@ -100,7 +124,6 @@ getpassfd(const char *prompt, char *buf, } else havetty = true; - if (havetty) { struct termios st = gt; @@ -238,6 +261,14 @@ add: continue; } } + + if (flags & GETPASS_7BIT) + c &= 0x7f; + if ((flags & GETPASS_FORCE_LOWER) && isupper((unsigned char)c)) + c = tolower((unsigned char)c); + if ((flags & GETPASS_FORCE_UPPER) && islower((unsigned char)c)) + c = toupper((unsigned char)c); + buf[l++] = c; if (c) { if (flags & GETPASS_ECHO_STAR) @@ -247,10 +278,8 @@ add: &c : "?", 1); } } + good = true; - if (havetty) - (void)tcsetattr(fd[0], TCSAFLUSH|TCSASOFT, >); - return buf; restore: if (havetty) { c = errno; @@ -258,6 +287,18 @@ restore: errno = c; } out: + if (good && (flags & GETPASS_ECHO_NL)) + (void)write(fd[1], "\n", 1); + + if (opentty) { + c = errno; + (void)close(fd[0]); + errno = c; + } + + if (good) + return buf; + if (sig) { if ((flags & GETPASS_NO_SIGNAL) == 0) (void)raise(sig); @@ -272,29 +313,7 @@ out: char * getpass_r(const char *prompt, char *buf, size_t len) { - bool opentty; - int fd[3]; - char *rv; - - /* - * Try to use /dev/tty if possible; otherwise read from stdin and - * write to stderr. - */ - if ((fd[0] = fd[1] = fd[2] = open(_PATH_TTY, O_RDWR)) == -1) { - opentty = false; - fd[0] = STDIN_FILENO; - fd[1] = fd[2] = STDERR_FILENO; - } else - opentty = true; - - rv = getpassfd(prompt, buf, len, fd, 0, 0); - - if (opentty) { - int serrno = errno; - (void)close(fd[0]); - errno = serrno; - } - return rv; + return getpassfd(prompt, buf, len, NULL, 0, 0); } char * @@ -328,9 +347,8 @@ int main(int argc, char *argv[]) { char buf[28]; - int fd[3] = { 0, 1, 2 }; - printf("[%s]\n", getpassfd("foo>", buf, sizeof(buf), fd, - GETPASS_ECHO_STAR, 2)); + printf("[%s]\n", getpassfd("foo>", buf, sizeof(buf), NULL, + GETPASS_ECHO_STAR|GETPASS_ECHO_NL, 2)); return 0; } #endif