X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetpass.c;h=1aac4b7147f37c837d8fd1968f268d173d75616f;hb=d1fb15ba12436afdd742eaff1ec46f75ee397bda;hp=7367251e27ede214e7f04089216b55047cc34269;hpb=267a39bafd249d7eb9c37df06dc6defcf41cb343;p=gnulib.git diff --git a/lib/getpass.c b/lib/getpass.c index 7367251e2..1aac4b714 100644 --- a/lib/getpass.c +++ b/lib/getpass.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1992-2001, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1992-2001, 2003-2007, 2009-2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify @@ -15,47 +16,31 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#if HAVE_CONFIG_H +#ifndef _LIBC # include #endif -#if !_LIBC -# include "getpass.h" -#endif +#include "getpass.h" -#if _LIBC -# define HAVE_STDIO_EXT_H 1 -#endif +#include + +#if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) #include -#include -#if HAVE_STDIO_EXT_H -# include +#if HAVE_DECL___FSETLOCKING && HAVE___FSETLOCKING +# if HAVE_STDIO_EXT_H +# include +# endif #else -# define __fsetlocking(stream, type) /* empty */ -#endif -#if !_LIBC -# include "getline.h" -#endif - -#include -#include - -#if _LIBC -# include +# define __fsetlocking(stream, type) /* empty */ #endif -#if _LIBC -# define NOTCANCEL_MODE "c" -#else -# define NOTCANCEL_MODE +#if HAVE_TERMIOS_H +# include #endif -#if _LIBC -# define flockfile(s) _IO_flockfile (s) -# define funlockfile(s) _IO_funlockfile (s) -#elif USE_UNLOCKED_IO +#if USE_UNLOCKED_IO # include "unlocked-io.h" #else # if !HAVE_DECL_FFLUSH_UNLOCKED @@ -80,18 +65,6 @@ # endif #endif -#if _LIBC -# include -#else -# define __libc_cleanup_push(function, arg) /* empty */ -# define __libc_cleanup_pop(execute) /* empty */ -#endif - -#if !_LIBC -# define __getline getline -# define __tcgetattr tcgetattr -#endif - /* It is desirable to use this bit on systems that have it. The only bit of terminal state we want to twiddle is echoing, which is done in software; there is no need to change the state of the terminal @@ -114,7 +87,7 @@ getpass (const char *prompt) FILE *tty; FILE *in, *out; struct termios s, t; - bool tty_changed; + bool tty_changed = false; static char *buf; static size_t bufsize; ssize_t nread; @@ -122,7 +95,7 @@ getpass (const char *prompt) /* Try to write to and read from the terminal if we can. If we can't open the terminal, use stderr and stdin. */ - tty = fopen ("/dev/tty", "w+" NOTCANCEL_MODE); + tty = fopen ("/dev/tty", "w+"); if (tty == NULL) { in = stdin; @@ -136,39 +109,26 @@ getpass (const char *prompt) out = in = tty; } - /* Make sure the stream we opened is closed even if the thread is - canceled. */ - __libc_cleanup_push (call_fclose, tty); - flockfile (out); /* Turn echoing off if it is on now. */ - - if (__tcgetattr (fileno (in), &t) == 0) +#if HAVE_TCGETATTR + if (tcgetattr (fileno (in), &t) == 0) { /* Save the old one. */ s = t; /* Tricky, tricky. */ - t.c_lflag &= ~(ECHO|ISIG); - tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); + t.c_lflag &= ~(ECHO | ISIG); + tty_changed = (tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t) == 0); } - else - tty_changed = false; +#endif /* Write the prompt. */ -#ifdef USE_IN_LIBIO - if (_IO_fwide (out, 0) > 0) - __fwprintf (out, L"%s", prompt); - else -#endif - fputs_unlocked (prompt, out); + fputs_unlocked (prompt, out); fflush_unlocked (out); /* Read the password. */ - nread = __getline (&buf, &bufsize, in); - -#if !_LIBC - /* As far as is known, glibc doesn't need this no-op fseek. */ + nread = getline (&buf, &bufsize, in); /* According to the C standard, input may not be followed by output on the same stream without an intervening call to a file @@ -179,39 +139,92 @@ getpass (const char *prompt) == fileno (out). The POSIX restrictions are tricky and change from POSIX version to POSIX version, so play it safe and invoke fseek even if in != out. */ - fseek (out, 0, SEEK_CUR); -#endif + fseeko (out, 0, SEEK_CUR); if (buf != NULL) { if (nread < 0) - buf[0] = '\0'; + buf[0] = '\0'; else if (buf[nread - 1] == '\n') - { - /* Remove the newline. */ - buf[nread - 1] = '\0'; - if (tty_changed) - { - /* Write the newline that was not echoed. */ -#ifdef USE_IN_LIBIO - if (_IO_fwide (out, 0) > 0) - putwc_unlocked (L'\n', out); - else -#endif - putc_unlocked ('\n', out); - } - } + { + /* Remove the newline. */ + buf[nread - 1] = '\0'; + if (tty_changed) + { + /* Write the newline that was not echoed. */ + putc_unlocked ('\n', out); + } + } } /* Restore the original setting. */ +#if HAVE_TCSETATTR if (tty_changed) - (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); + tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &s); +#endif funlockfile (out); - __libc_cleanup_pop (0); - call_fclose (tty); return buf; } + +#else /* W32 native */ + +/* Windows implementation by Martin Lambers , + improved by Simon Josefsson. */ + +/* For PASS_MAX. */ +#include +/* For _getch(). */ +#include +/* For strdup(). */ +#include + +#ifndef PASS_MAX +# define PASS_MAX 512 +#endif + +char * +getpass (const char *prompt) +{ + char getpassbuf[PASS_MAX + 1]; + size_t i = 0; + int c; + + if (prompt) + { + fputs (prompt, stderr); + fflush (stderr); + } + + for (;;) + { + c = _getch (); + if (c == '\r') + { + getpassbuf[i] = '\0'; + break; + } + else if (i < PASS_MAX) + { + getpassbuf[i++] = c; + } + + if (i >= PASS_MAX) + { + getpassbuf[i] = '\0'; + break; + } + } + + if (prompt) + { + fputs ("\r\n", stderr); + fflush (stderr); + } + + return strdup (getpassbuf); +} +#endif