1 /* Copyright (C) 1992-2001, 2003, 2004, 2005, 2006 Free Software
4 This file is part of the GNU C Library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
28 #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
32 #if HAVE_DECL___FSETLOCKING && HAVE___FSETLOCKING
34 # include <stdio_ext.h>
37 # define __fsetlocking(stream, type) /* empty */
47 # include "unlocked-io.h"
49 # if !HAVE_DECL_FFLUSH_UNLOCKED
50 # undef fflush_unlocked
51 # define fflush_unlocked(x) fflush (x)
53 # if !HAVE_DECL_FLOCKFILE
55 # define flockfile(x) ((void) 0)
57 # if !HAVE_DECL_FUNLOCKFILE
59 # define funlockfile(x) ((void) 0)
61 # if !HAVE_DECL_FPUTS_UNLOCKED
62 # undef fputs_unlocked
63 # define fputs_unlocked(str,stream) fputs (str, stream)
65 # if !HAVE_DECL_PUTC_UNLOCKED
67 # define putc_unlocked(c,stream) putc (c, stream)
71 /* It is desirable to use this bit on systems that have it.
72 The only bit of terminal state we want to twiddle is echoing, which is
73 done in software; there is no need to change the state of the terminal
81 call_fclose (void *arg
)
88 getpass (const char *prompt
)
93 bool tty_changed
= false;
95 static size_t bufsize
;
98 /* Try to write to and read from the terminal if we can.
99 If we can't open the terminal, use stderr and stdin. */
101 tty
= fopen ("/dev/tty", "w+");
109 /* We do the locking ourselves. */
110 __fsetlocking (tty
, FSETLOCKING_BYCALLER
);
117 /* Turn echoing off if it is on now. */
119 if (tcgetattr (fileno (in
), &t
) == 0)
121 /* Save the old one. */
123 /* Tricky, tricky. */
124 t
.c_lflag
&= ~(ECHO
| ISIG
);
125 tty_changed
= (tcsetattr (fileno (in
), TCSAFLUSH
| TCSASOFT
, &t
) == 0);
129 /* Write the prompt. */
130 fputs_unlocked (prompt
, out
);
131 fflush_unlocked (out
);
133 /* Read the password. */
134 nread
= getline (&buf
, &bufsize
, in
);
136 /* According to the C standard, input may not be followed by output
137 on the same stream without an intervening call to a file
138 positioning function. Suppose in == out; then without this fseek
139 call, on Solaris, HP-UX, AIX, OSF/1, the previous input gets
140 echoed, whereas on IRIX, the following newline is not output as
141 it should be. POSIX imposes similar restrictions if fileno (in)
142 == fileno (out). The POSIX restrictions are tricky and change
143 from POSIX version to POSIX version, so play it safe and invoke
144 fseek even if in != out. */
145 fseek (out
, 0, SEEK_CUR
);
151 else if (buf
[nread
- 1] == '\n')
153 /* Remove the newline. */
154 buf
[nread
- 1] = '\0';
157 /* Write the newline that was not echoed. */
158 putc_unlocked ('\n', out
);
163 /* Restore the original setting. */
166 tcsetattr (fileno (in
), TCSAFLUSH
| TCSASOFT
, &s
);
176 #else /* W32 native */
178 /* Windows implementation by Martin Lambers <marlam@marlam.de>,
179 improved by Simon Josefsson. */
189 # define PASS_MAX 512
193 getpass (const char *prompt
)
195 char getpassbuf
[PASS_MAX
+ 1];
201 fputs (prompt
, stderr
);
210 getpassbuf
[i
] = '\0';
213 else if (i
< PASS_MAX
)
220 getpassbuf
[i
] = '\0';
227 fputs ("\r\n", stderr
);
231 return strdup (getpassbuf
);