1 |
/* Copyright (C) 1992-2001, 2003, 2004 Free Software Foundation, Inc. |
/* Copyright (C) 1992-2001, 2003, 2004, 2005 Free Software Foundation, Inc. |
2 |
This file is part of the GNU C Library. |
This file is part of the GNU C Library. |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
19 |
# include <config.h> |
# include <config.h> |
20 |
#endif |
#endif |
21 |
|
|
22 |
#if !_LIBC |
#include "getpass.h" |
|
# include "getpass.h" |
|
|
#endif |
|
23 |
|
|
24 |
#if _LIBC |
#include <stdio.h> |
25 |
# define HAVE_STDIO_EXT_H 1 |
|
26 |
#endif |
#if !defined _WIN32 |
27 |
|
|
28 |
#include <stdbool.h> |
#include <stdbool.h> |
29 |
|
|
|
#include <stdio.h> |
|
30 |
#if HAVE_STDIO_EXT_H |
#if HAVE_STDIO_EXT_H |
31 |
# include <stdio_ext.h> |
# include <stdio_ext.h> |
|
#else |
|
|
# define __fsetlocking(stream, type) /* empty */ |
|
32 |
#endif |
#endif |
33 |
#if !_LIBC |
#if !HAVE___FSETLOCKING |
34 |
# include "getline.h" |
# define __fsetlocking(stream, type) /* empty */ |
35 |
#endif |
#endif |
36 |
|
|
37 |
#include <termios.h> |
#if HAVE_TERMIOS_H |
38 |
#include <unistd.h> |
# include <termios.h> |
|
|
|
|
#if _LIBC |
|
|
# include <wchar.h> |
|
39 |
#endif |
#endif |
40 |
|
|
41 |
#if _LIBC |
#include "getline.h" |
|
# define NOTCANCEL_MODE "c" |
|
|
#else |
|
|
# define NOTCANCEL_MODE |
|
|
#endif |
|
42 |
|
|
43 |
#if _LIBC |
#if USE_UNLOCKED_IO |
|
# define flockfile(s) _IO_flockfile (s) |
|
|
# define funlockfile(s) _IO_funlockfile (s) |
|
|
#elif USE_UNLOCKED_IO |
|
44 |
# include "unlocked-io.h" |
# include "unlocked-io.h" |
45 |
#else |
#else |
46 |
# if !HAVE_DECL_FFLUSH_UNLOCKED |
# if !HAVE_DECL_FFLUSH_UNLOCKED |
65 |
# endif |
# endif |
66 |
#endif |
#endif |
67 |
|
|
|
#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 |
|
|
|
|
68 |
/* It is desirable to use this bit on systems that have it. |
/* It is desirable to use this bit on systems that have it. |
69 |
The only bit of terminal state we want to twiddle is echoing, which is |
The only bit of terminal state we want to twiddle is echoing, which is |
70 |
done in software; there is no need to change the state of the terminal |
done in software; there is no need to change the state of the terminal |
87 |
FILE *tty; |
FILE *tty; |
88 |
FILE *in, *out; |
FILE *in, *out; |
89 |
struct termios s, t; |
struct termios s, t; |
90 |
bool tty_changed; |
bool tty_changed = false; |
91 |
static char *buf; |
static char *buf; |
92 |
static size_t bufsize; |
static size_t bufsize; |
93 |
ssize_t nread; |
ssize_t nread; |
95 |
/* Try to write to and read from the terminal if we can. |
/* Try to write to and read from the terminal if we can. |
96 |
If we can't open the terminal, use stderr and stdin. */ |
If we can't open the terminal, use stderr and stdin. */ |
97 |
|
|
98 |
tty = fopen ("/dev/tty", "w+" NOTCANCEL_MODE); |
tty = fopen ("/dev/tty", "w+"); |
99 |
if (tty == NULL) |
if (tty == NULL) |
100 |
{ |
{ |
101 |
in = stdin; |
in = stdin; |
109 |
out = in = tty; |
out = in = tty; |
110 |
} |
} |
111 |
|
|
|
/* Make sure the stream we opened is closed even if the thread is |
|
|
canceled. */ |
|
|
__libc_cleanup_push (call_fclose, tty); |
|
|
|
|
112 |
flockfile (out); |
flockfile (out); |
113 |
|
|
114 |
/* Turn echoing off if it is on now. */ |
/* Turn echoing off if it is on now. */ |
115 |
|
#if HAVE_TCGETATTR |
116 |
if (__tcgetattr (fileno (in), &t) == 0) |
if (tcgetattr (fileno (in), &t) == 0) |
117 |
{ |
{ |
118 |
/* Save the old one. */ |
/* Save the old one. */ |
119 |
s = t; |
s = t; |
120 |
/* Tricky, tricky. */ |
/* Tricky, tricky. */ |
121 |
t.c_lflag &= ~(ECHO|ISIG); |
t.c_lflag &= ~(ECHO | ISIG); |
122 |
tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); |
tty_changed = (tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t) == 0); |
123 |
} |
} |
124 |
else |
#endif |
|
tty_changed = false; |
|
125 |
|
|
126 |
/* Write the prompt. */ |
/* Write the prompt. */ |
127 |
#ifdef USE_IN_LIBIO |
fputs_unlocked (prompt, out); |
|
if (_IO_fwide (out, 0) > 0) |
|
|
__fwprintf (out, L"%s", prompt); |
|
|
else |
|
|
#endif |
|
|
fputs_unlocked (prompt, out); |
|
128 |
fflush_unlocked (out); |
fflush_unlocked (out); |
129 |
|
|
130 |
/* Read the password. */ |
/* Read the password. */ |
131 |
nread = __getline (&buf, &bufsize, in); |
nread = getline (&buf, &bufsize, in); |
|
|
|
|
#if !_LIBC |
|
|
/* As far as is known, glibc doesn't need this no-op fseek. */ |
|
132 |
|
|
133 |
/* According to the C standard, input may not be followed by output |
/* According to the C standard, input may not be followed by output |
134 |
on the same stream without an intervening call to a file |
on the same stream without an intervening call to a file |
140 |
from POSIX version to POSIX version, so play it safe and invoke |
from POSIX version to POSIX version, so play it safe and invoke |
141 |
fseek even if in != out. */ |
fseek even if in != out. */ |
142 |
fseek (out, 0, SEEK_CUR); |
fseek (out, 0, SEEK_CUR); |
|
#endif |
|
143 |
|
|
144 |
if (buf != NULL) |
if (buf != NULL) |
145 |
{ |
{ |
152 |
if (tty_changed) |
if (tty_changed) |
153 |
{ |
{ |
154 |
/* Write the newline that was not echoed. */ |
/* Write the newline that was not echoed. */ |
155 |
#ifdef USE_IN_LIBIO |
putc_unlocked ('\n', out); |
|
if (_IO_fwide (out, 0) > 0) |
|
|
putwc_unlocked (L'\n', out); |
|
|
else |
|
|
#endif |
|
|
putc_unlocked ('\n', out); |
|
156 |
} |
} |
157 |
} |
} |
158 |
} |
} |
159 |
|
|
160 |
/* Restore the original setting. */ |
/* Restore the original setting. */ |
161 |
|
#if TCSETATTR |
162 |
if (tty_changed) |
if (tty_changed) |
163 |
(void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); |
tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &s); |
164 |
|
#endif |
165 |
|
|
166 |
funlockfile (out); |
funlockfile (out); |
167 |
|
|
|
__libc_cleanup_pop (0); |
|
|
|
|
168 |
call_fclose (tty); |
call_fclose (tty); |
169 |
|
|
170 |
return buf; |
return buf; |
171 |
} |
} |
172 |
|
|
173 |
|
#else /* WIN32 */ |
174 |
|
|
175 |
|
/* Windows implementation by Martin Lambers <marlam@marlam.de>, |
176 |
|
improved by Simon Josefsson. */ |
177 |
|
|
178 |
|
/* For PASS_MAX. */ |
179 |
|
#include <limits.h> |
180 |
|
|
181 |
|
#ifndef PASS_MAX |
182 |
|
# define PASS_MAX 512 |
183 |
|
#endif |
184 |
|
|
185 |
|
char * |
186 |
|
getpass (const char *prompt) |
187 |
|
{ |
188 |
|
char getpassbuf[PASS_MAX + 1]; |
189 |
|
size_t i = 0; |
190 |
|
int c; |
191 |
|
|
192 |
|
if (prompt) |
193 |
|
{ |
194 |
|
fputs (prompt, stderr); |
195 |
|
fflush (stderr); |
196 |
|
} |
197 |
|
|
198 |
|
for (;;) |
199 |
|
{ |
200 |
|
c = _getch (); |
201 |
|
if (c == '\r') |
202 |
|
{ |
203 |
|
getpassbuf[i] = '\0'; |
204 |
|
break; |
205 |
|
} |
206 |
|
else if (i < PASS_MAX) |
207 |
|
{ |
208 |
|
getpassbuf[i++] = c; |
209 |
|
} |
210 |
|
|
211 |
|
if (i >= PASS_MAX) |
212 |
|
{ |
213 |
|
getpassbuf[i] = '\0'; |
214 |
|
break; |
215 |
|
} |
216 |
|
} |
217 |
|
|
218 |
|
if (prompt) |
219 |
|
{ |
220 |
|
fputs ("\r\n", stderr); |
221 |
|
fflush (stderr); |
222 |
|
} |
223 |
|
|
224 |
|
return strdup (getpassbuf); |
225 |
|
} |
226 |
|
#endif |