blob: c311a153a090eebe466463531f8a50755ebc765c [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Copyright (C) 1992-1999,2001,2003,2004,2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19#include <stdio.h>
20#include <string.h>
21#include <termios.h>
22#include <unistd.h>
23
24#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
25
26
27/* It is desirable to use this bit on systems that have it.
28 The only bit of terminal state we want to twiddle is echoing, which is
29 done in software; there is no need to change the state of the terminal
30 hardware. */
31
32#ifndef TCSASOFT
33#define TCSASOFT 0
34#endif
35#define PWD_BUFFER_SIZE 256
36
37char * getpass (const char *prompt)
38{
39 FILE *in, *out;
40 struct termios s, t;
41 int tty_changed;
42 static char buf[PWD_BUFFER_SIZE];
43 int nread;
44
45 /* Try to write to and read from the terminal if we can.
46 If we can't open the terminal, use stderr and stdin. */
47
48 out = in = fopen ("/dev/tty", "r+");
49 if (in == NULL)
50 {
51 in = stdin;
52 out = stderr;
53 }
54 else
55 {
56 /* Disable buffering for read/write FILE to prevent problems with
57 * fseek and buffering for read/write auto-transitioning. */
58 setvbuf(in, NULL, _IONBF, 0);
59 }
60
61 /* Turn echoing off if it is on now. */
62
63 tty_changed = 0;
64 if (tcgetattr (fileno (in), &t) == 0)
65 {
66 /* Save the old one. */
67 s = t;
68 /* Tricky, tricky. */
69 t.c_lflag &= ~(ECHO|ISIG);
70 tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
71 }
72
73 /* Write the prompt. */
74 fputs(prompt, out);
75 fflush(out);
76
77 /* Read the password. */
78 if (!fgets (buf, sizeof(buf), in))
79 buf[0] = '\0';
80 nread = strlen(buf);
81 if (nread > 0 && buf[nread - 1] == '\n')
82 /* Remove the newline. */
83 buf[nread - 1] = '\0';
84
85 if (tty_changed)
86 {
87 /* Write the newline that was not echoed. */
88 putc('\n', out);
89 /* Restore the original setting. */
90 (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
91 }
92
93 if (in != stdin)
94 /* We opened the terminal; now close it. */
95 fclose (in);
96
97 return buf;
98}
99#endif