diff options
author | Simon Josefsson <simon@josefsson.org> | 2004-08-15 10:28:45 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2004-08-15 10:28:45 +0000 |
commit | d30a9c7494351bb538acbecb13cddcaefbbe2f45 (patch) | |
tree | f84af7482d7bad396d7d3f091d35ebdb197f5d82 /gl | |
parent | ecf58cb15a0e3c7ff410d4517395256ba9e50d1a (diff) | |
download | gnutls-d30a9c7494351bb538acbecb13cddcaefbbe2f45.tar.gz |
Replace ad-hoc 'read_pass' with gnulib module 'getpass-gnu'.
Diffstat (limited to 'gl')
-rw-r--r-- | gl/Makefile.am | 13 | ||||
-rw-r--r-- | gl/getpass.c | 196 | ||||
-rw-r--r-- | gl/getpass.h | 31 | ||||
-rw-r--r-- | gl/m4/getpass.m4 | 38 | ||||
-rw-r--r-- | gl/m4/gnulib.m4 | 2 | ||||
-rw-r--r-- | gl/m4/stdbool.m4 | 95 | ||||
-rw-r--r-- | gl/stdbool_.h | 93 |
7 files changed, 468 insertions, 0 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am index b1cad13b1c..c4988f8c9d 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -31,9 +31,22 @@ libgnu_la_SOURCES += exit.h libgnu_la_SOURCES += getline.h EXTRA_DIST += getndelim2.h getndelim2.c +libgnu_la_SOURCES += getpass.h + libgnu_la_SOURCES += gettext.h libgnu_la_SOURCES += progname.h progname.c +BUILT_SOURCES += $(STDBOOL_H) +EXTRA_DIST += stdbool_.h + +# We need the following in order to create an <stdbool.h> when the system +# doesn't have one that works. +all-local $(libgnu_la_OBJECTS): $(STDBOOL_H) +stdbool.h: stdbool_.h + sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool_.h > $@-t + mv $@-t $@ +MOSTLYCLEANFILES += stdbool.h stdbool.h-t + libgnu_la_SOURCES += unlocked-io.h diff --git a/gl/getpass.c b/gl/getpass.c new file mode 100644 index 0000000000..9ac01f2277 --- /dev/null +++ b/gl/getpass.c @@ -0,0 +1,196 @@ +/* Copyright (C) 1992-2001, 2003 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 + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if !_LIBC +# include "getpass.h" +#endif + +#if _LIBC +# define HAVE_STDIO_EXT_H 1 +#endif + +#include <stdbool.h> + +#include <stdio.h> +#if HAVE_STDIO_EXT_H +# include <stdio_ext.h> +#else +# define __fsetlocking(stream, type) /* empty */ +#endif +#if !_LIBC +# include "getline.h" +#endif + +#include <termios.h> +#include <unistd.h> + +#if _LIBC +# include <wchar.h> +#endif + +#if _LIBC +# define NOTCANCEL_MODE "c" +#else +# define NOTCANCEL_MODE +#endif + +#if _LIBC +# define flockfile(s) _IO_flockfile (s) +# define funlockfile(s) _IO_funlockfile (s) +#else +# include "unlocked-io.h" +#endif + +#if _LIBC +# include <bits/libc-lock.h> +#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 + hardware. */ + +#ifndef TCSASOFT +# define TCSASOFT 0 +#endif + +static void +call_fclose (void *arg) +{ + if (arg != NULL) + fclose (arg); +} + +char * +getpass (const char *prompt) +{ + FILE *tty; + FILE *in, *out; + struct termios s, t; + bool tty_changed; + static char *buf; + static size_t bufsize; + ssize_t nread; + + /* 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); + if (tty == NULL) + { + in = stdin; + out = stderr; + } + else + { + /* We do the locking ourselves. */ + __fsetlocking (tty, FSETLOCKING_BYCALLER); + + 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) + { + /* Save the old one. */ + s = t; + /* Tricky, tricky. */ + t.c_lflag &= ~(ECHO|ISIG); + tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); + } + else + tty_changed = false; + + /* Write the prompt. */ +#ifdef USE_IN_LIBIO + if (_IO_fwide (out, 0) > 0) + __fwprintf (out, L"%s", prompt); + else +#endif + 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. */ + + /* According to the C standard, input may not be followed by output + on the same stream without an intervening call to a file + positioning function. Suppose in == out; then without this fseek + call, on Solaris, HP-UX, AIX, OSF/1, the previous input gets + echoed, whereas on IRIX, the following newline is not output as + it should be. POSIX imposes similar restrictions if fileno (in) + == 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 + + if (buf != NULL) + { + if (nread < 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); + } + } + } + + /* Restore the original setting. */ + if (tty_changed) + (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); + + funlockfile (out); + + __libc_cleanup_pop (0); + + call_fclose (tty); + + return buf; +} diff --git a/gl/getpass.h b/gl/getpass.h new file mode 100644 index 0000000000..6502126497 --- /dev/null +++ b/gl/getpass.h @@ -0,0 +1,31 @@ +/* getpass.h -- Read a password of arbitrary length from /dev/tty or stdin. + Copyright (C) 2004 Free Software Foundation, Inc. + Contributed by Simon Josefsson <jas@extundo.com>, 2004. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GETPASS_H +#define GETPASS_H + +/* Get getpass declaration, if available. */ +#include <unistd.h> + +#if defined HAVE_DECL_GETPASS && !HAVE_DECL_GETPASS +/* Read a password of arbitrary length from /dev/tty or stdin. */ +char *getpass (const char *prompt); + +#endif + +#endif /* GETPASS_H */ diff --git a/gl/m4/getpass.m4 b/gl/m4/getpass.m4 new file mode 100644 index 0000000000..0c4d8050f2 --- /dev/null +++ b/gl/m4/getpass.m4 @@ -0,0 +1,38 @@ +# getpass.m4 serial 4 +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# Provide a getpass() function if the system doesn't have it. +AC_DEFUN([gl_FUNC_GETPASS], +[ + AC_REPLACE_FUNCS(getpass) + AC_CHECK_DECLS_ONCE(getpass) + if test $ac_cv_func_getpass = no; then + gl_PREREQ_GETPASS + fi +]) + +# Provide the GNU getpass() implementation. It supports passwords of +# arbitrary length (not just 8 bytes as on HP-UX). +AC_DEFUN([gl_FUNC_GETPASS_GNU], +[ + AC_CHECK_DECLS_ONCE(getpass) + dnl TODO: Detect when GNU getpass() is already found in glibc. + AC_LIBOBJ(getpass) + gl_PREREQ_GETPASS + dnl We must choose a different name for our function, since on ELF systems + dnl an unusable getpass() in libc.so would override our getpass() if it is + dnl compiled into a shared library. + AC_DEFINE([getpass], [gnu_getpass], + [Define to a replacement function name for getpass().]) +]) + +# Prerequisites of lib/getpass.c. +AC_DEFUN([gl_PREREQ_GETPASS], [ + AC_CHECK_HEADERS_ONCE(stdio_ext.h) + : +]) diff --git a/gl/m4/gnulib.m4 b/gl/m4/gnulib.m4 index 58e69eb100..38a1ad5af6 100644 --- a/gl/m4/gnulib.m4 +++ b/gl/m4/gnulib.m4 @@ -20,7 +20,9 @@ AC_DEFUN([gl_INIT], gl_ERROR dnl gl_USE_SYSTEM_EXTENSIONS must be added quite early to configure.ac. AM_FUNC_GETLINE + gl_FUNC_GETPASS_GNU dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac. + AM_STDBOOL_H gl_FUNC_GLIBC_UNLOCKED_IO ]) diff --git a/gl/m4/stdbool.m4 b/gl/m4/stdbool.m4 new file mode 100644 index 0000000000..b25b7d2440 --- /dev/null +++ b/gl/m4/stdbool.m4 @@ -0,0 +1,95 @@ +# Check for stdbool.h that conforms to C99. + +# Copyright (C) 2002-2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# Prepare for substituting <stdbool.h> if it is not supported. + +AC_DEFUN([AM_STDBOOL_H], +[ + AC_REQUIRE([AC_HEADER_STDBOOL]) + + # Define two additional variables used in the Makefile substitution. + + if test "$ac_cv_header_stdbool_h" = yes; then + STDBOOL_H='' + else + STDBOOL_H='stdbool.h' + fi + AC_SUBST([STDBOOL_H]) + + if test "$ac_cv_type__Bool" = yes; then + HAVE__BOOL=1 + else + HAVE__BOOL=0 + fi + AC_SUBST([HAVE__BOOL]) +]) + +# This macro is only needed in autoconf <= 2.59. Newer versions of autoconf +# have this macro built-in. + +AC_DEFUN([AC_HEADER_STDBOOL], + [AC_CACHE_CHECK([for stdbool.h that conforms to C99], + [ac_cv_header_stdbool_h], + [AC_TRY_COMPILE( + [ + #include <stdbool.h> + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #endif + #ifndef true + "error: true is not defined" + #endif + #if true != 1 + "error: true is not 1" + #endif + #ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" + #endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) -0.5 == true ? 1 : -1]; + bool e = &s; + char f[(_Bool) -0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + _Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + ], + [ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !j + !k + !l + + !m + !n + !o); + ], + [ac_cv_header_stdbool_h=yes], + [ac_cv_header_stdbool_h=no])]) + AC_CHECK_TYPES([_Bool]) + if test $ac_cv_header_stdbool_h = yes; then + AC_DEFINE(HAVE_STDBOOL_H, 1, [Define to 1 if stdbool.h conforms to C99.]) + fi]) diff --git a/gl/stdbool_.h b/gl/stdbool_.h new file mode 100644 index 0000000000..e33715a615 --- /dev/null +++ b/gl/stdbool_.h @@ -0,0 +1,93 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Written by Bruno Haible <haible@clisp.cons.org>, 2001. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _STDBOOL_H +#define _STDBOOL_H + +/* ISO C 99 <stdbool.h> for platforms that lack it. */ + +/* Usage suggestions: + + Programs that use <stdbool.h> should be aware of some limitations + and standards compliance issues. + + Standards compliance: + + - <stdbool.h> must be #included before 'bool', 'false', 'true' + can be used. + + - You cannot assume that sizeof (bool) == 1. + + - Programs should not undefine the macros bool, true, and false, + as C99 lists that as an "obsolescent feature". + + Limitations of this substitute, when used in a C89 environment: + + - <stdbool.h> must be #included before the '_Bool' type can be used. + + - You cannot assume that _Bool is a typedef; it might be a macro. + + - In C99, casts and automatic conversions to '_Bool' or 'bool' are + performed in such a way that every nonzero value gets converted + to 'true', and zero gets converted to 'false'. This doesn't work + with this substitute. With this substitute, only the values 0 and 1 + give the expected result when converted to _Bool' or 'bool'. + + Also, it is suggested that programs use 'bool' rather than '_Bool'; + this isn't required, but 'bool' is more common. */ + + +/* 7.16. Boolean type and values */ + +/* BeOS <sys/socket.h> already #defines false 0, true 1. We use the same + definitions below, but temporarily we have to #undef them. */ +#ifdef __BEOS__ +# include <OS.h> /* defines bool but not _Bool */ +# undef false +# undef true +#endif + +/* For the sake of symbolic names in gdb, we define true and false as + enum constants, not only as macros. + It is tempting to write + typedef enum { false = 0, true = 1 } _Bool; + so that gdb prints values of type 'bool' symbolically. But if we do + this, values of type '_Bool' may promote to 'int' or 'unsigned int' + (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int' + (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the + enum; this ensures that '_Bool' promotes to 'int'. */ +#if !(defined __cplusplus || defined __BEOS__) +# if !@HAVE__BOOL@ +# if defined __SUNPRO_C && (__SUNPRO_C < 0x550 || __STDC__ == 1) + /* Avoid stupid "warning: _Bool is a keyword in ISO C99". */ +# define _Bool signed char +enum { false = 0, true = 1 }; +# else +typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; +# endif +# endif +#else +typedef bool _Bool; +#endif +#define bool _Bool + +/* The other macros must be usable in preprocessor directives. */ +#define false 0 +#define true 1 +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H */ |