1 /* Copyright (C) 1992-2001, 2003, 2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
27 # define HAVE_STDIO_EXT_H 1
34 # include <stdio_ext.h>
36 # define __fsetlocking(stream, type) /* empty */
50 # define NOTCANCEL_MODE "c"
52 # define NOTCANCEL_MODE
56 # define flockfile(s) _IO_flockfile (s)
57 # define funlockfile(s) _IO_funlockfile (s)
59 # include "unlocked-io.h"
61 # if !HAVE_DECL_FFLUSH_UNLOCKED
62 # undef fflush_unlocked
63 # define fflush_unlocked(x) fflush (x)
65 # if !HAVE_DECL_FLOCKFILE
67 # define flockfile(x) ((void) 0)
69 # if !HAVE_DECL_FUNLOCKFILE
71 # define funlockfile(x) ((void) 0)
73 # if !HAVE_DECL_FPUTS_UNLOCKED
74 # undef fputs_unlocked
75 # define fputs_unlocked(str,stream) fputs (str, stream)
77 # if !HAVE_DECL_PUTC_UNLOCKED
79 # define putc_unlocked(c,stream) putc (c, stream)
84 # include <bits/libc-lock.h>
86 # define __libc_cleanup_push(function, arg) /* empty */
87 # define __libc_cleanup_pop(execute) /* empty */
91 # define __getline getline
92 # define __tcgetattr tcgetattr
95 /* It is desirable to use this bit on systems that have it.
96 The only bit of terminal state we want to twiddle is echoing, which is
97 done in software; there is no need to change the state of the terminal
105 call_fclose (void *arg)
112 getpass (const char *prompt)
119 static size_t bufsize;
122 /* Try to write to and read from the terminal if we can.
123 If we can't open the terminal, use stderr and stdin. */
125 tty = fopen ("/dev/tty", "w+" NOTCANCEL_MODE);
133 /* We do the locking ourselves. */
134 __fsetlocking (tty, FSETLOCKING_BYCALLER);
139 /* Make sure the stream we opened is closed even if the thread is
141 __libc_cleanup_push (call_fclose, tty);
145 /* Turn echoing off if it is on now. */
147 if (__tcgetattr (fileno (in), &t) == 0)
149 /* Save the old one. */
151 /* Tricky, tricky. */
152 t.c_lflag &= ~(ECHO|ISIG);
153 tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
158 /* Write the prompt. */
160 if (_IO_fwide (out, 0) > 0)
161 __fwprintf (out, L"%s", prompt);
164 fputs_unlocked (prompt, out);
165 fflush_unlocked (out);
167 /* Read the password. */
168 nread = __getline (&buf, &bufsize, in);
171 /* As far as is known, glibc doesn't need this no-op fseek. */
173 /* According to the C standard, input may not be followed by output
174 on the same stream without an intervening call to a file
175 positioning function. Suppose in == out; then without this fseek
176 call, on Solaris, HP-UX, AIX, OSF/1, the previous input gets
177 echoed, whereas on IRIX, the following newline is not output as
178 it should be. POSIX imposes similar restrictions if fileno (in)
179 == fileno (out). The POSIX restrictions are tricky and change
180 from POSIX version to POSIX version, so play it safe and invoke
181 fseek even if in != out. */
182 fseek (out, 0, SEEK_CUR);
189 else if (buf[nread - 1] == '\n')
191 /* Remove the newline. */
192 buf[nread - 1] = '\0';
195 /* Write the newline that was not echoed. */
197 if (_IO_fwide (out, 0) > 0)
198 putwc_unlocked (L'\n', out);
201 putc_unlocked ('\n', out);
206 /* Restore the original setting. */
208 (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
212 __libc_cleanup_pop (0);