]> git.ipfire.org Git - thirdparty/glibc.git/blame - misc/getpass.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / misc / getpass.c
CommitLineData
04277e02 1/* Copyright (C) 1992-2019 Free Software Foundation, Inc.
6d52618b 2 This file is part of the GNU C Library.
28f540f4 3
6d52618b 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
28f540f4 8
6d52618b
UD
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
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4
RM
17
18#include <stdio.h>
2706ee38 19#include <stdio_ext.h>
15a33409 20#include <string.h> /* For string function builtin redirect. */
28f540f4
RM
21#include <termios.h>
22#include <unistd.h>
23
cdbfa9f8
UD
24#include <wchar.h>
25#define flockfile(s) _IO_flockfile (s)
26#define funlockfile(s) _IO_funlockfile (s)
ec999b8e 27#include <libc-lock.h>
50304ef0 28
6d52618b 29/* It is desirable to use this bit on systems that have it.
28f540f4
RM
30 The only bit of terminal state we want to twiddle is echoing, which is
31 done in software; there is no need to change the state of the terminal
32 hardware. */
33
34#ifndef TCSASOFT
35#define TCSASOFT 0
36#endif
37
cdbfa9f8
UD
38static void
39call_fclose (void *arg)
40{
41 if (arg != NULL)
42 fclose (arg);
43}
44
28f540f4 45char *
9d46370c 46getpass (const char *prompt)
28f540f4
RM
47{
48 FILE *in, *out;
df4ef2ab
UD
49 struct termios s, t;
50 int tty_changed;
c4563d2d
UD
51 static char *buf;
52 static size_t bufsize;
28f540f4
RM
53 ssize_t nread;
54
55 /* Try to write to and read from the terminal if we can.
56 If we can't open the terminal, use stderr and stdin. */
57
312be3f9 58 in = fopen ("/dev/tty", "w+ce");
28f540f4
RM
59 if (in == NULL)
60 {
61 in = stdin;
62 out = stderr;
63 }
64 else
2706ee38
UD
65 {
66 /* We do the locking ourselves. */
b4c4f776 67 __fsetlocking (in, FSETLOCKING_BYCALLER);
2706ee38
UD
68
69 out = in;
70 }
28f540f4 71
cdbfa9f8
UD
72 /* Make sure the stream we opened is closed even if the thread is
73 canceled. */
74 __libc_cleanup_push (call_fclose, in == out ? in : NULL);
75
50304ef0
UD
76 flockfile (out);
77
28f540f4
RM
78 /* Turn echoing off if it is on now. */
79
50304ef0 80 if (__tcgetattr (fileno (in), &t) == 0)
28f540f4 81 {
df4ef2ab
UD
82 /* Save the old one. */
83 s = t;
84 /* Tricky, tricky. */
ceb2d9aa 85 t.c_lflag &= ~(ECHO|ISIG);
df4ef2ab 86 tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
28f540f4
RM
87 }
88 else
df4ef2ab 89 tty_changed = 0;
28f540f4
RM
90
91 /* Write the prompt. */
8a259a23 92 __fxprintf (out, "%s", prompt);
eb1fae6a 93 __fflush_unlocked (out);
28f540f4
RM
94
95 /* Read the password. */
96 nread = __getline (&buf, &bufsize, in);
5ca8c0ba 97 if (buf != NULL)
6e4c40ba
UD
98 {
99 if (nread < 0)
100 buf[0] = '\0';
101 else if (buf[nread - 1] == '\n')
102 {
103 /* Remove the newline. */
104 buf[nread - 1] = '\0';
105 if (tty_changed)
df6f8969 106 /* Write the newline that was not echoed. */
8a259a23 107 __fxprintf (out, "\n");
6e4c40ba
UD
108 }
109 }
28f540f4 110
df4ef2ab
UD
111 /* Restore the original setting. */
112 if (tty_changed)
113 (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
28f540f4 114
50304ef0
UD
115 funlockfile (out);
116
cdbfa9f8
UD
117 __libc_cleanup_pop (0);
118
28f540f4
RM
119 if (in != stdin)
120 /* We opened the terminal; now close it. */
121 fclose (in);
122
123 return buf;
124}