gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

getpass.c
Go to the documentation of this file.
1 /* Copyright (C) 1992-2001, 2003-2007, 2009-2021 Free Software Foundation, Inc.
2 
3  This file is part of the GNU C Library.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 3, or (at your option)
8  any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, see <https://www.gnu.org/licenses/>. */
17 
18 #ifndef _LIBC
19 /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
20  warns for the null checks on 'prompt' below. */
21 # define _GL_ARG_NONNULL(params)
22 # include <config.h>
23 #endif
24 
25 #include "getpass.h"
26 
27 #include <stdio.h>
28 
29 #if !(defined _WIN32 && !defined __CYGWIN__)
30 
31 # include <stdbool.h>
32 
33 # if HAVE_DECL___FSETLOCKING && HAVE___FSETLOCKING
34 # if HAVE_STDIO_EXT_H
35 # include <stdio_ext.h>
36 # endif
37 # else
38 # define __fsetlocking(stream, type) /* empty */
39 # endif
40 
41 # if HAVE_TERMIOS_H
42 # include <termios.h>
43 # endif
44 
45 # if USE_UNLOCKED_IO
46 # include "unlocked-io.h"
47 # else
48 # if !HAVE_DECL_FFLUSH_UNLOCKED
49 # undef fflush_unlocked
50 # define fflush_unlocked(x) fflush (x)
51 # endif
52 # if !HAVE_DECL_FLOCKFILE
53 # undef flockfile
54 # define flockfile(x) ((void) 0)
55 # endif
56 # if !HAVE_DECL_FUNLOCKFILE
57 # undef funlockfile
58 # define funlockfile(x) ((void) 0)
59 # endif
60 # if !HAVE_DECL_FPUTS_UNLOCKED
61 # undef fputs_unlocked
62 # define fputs_unlocked(str,stream) fputs (str, stream)
63 # endif
64 # if !HAVE_DECL_PUTC_UNLOCKED
65 # undef putc_unlocked
66 # define putc_unlocked(c,stream) putc (c, stream)
67 # endif
68 # endif
69 
70 /* It is desirable to use this bit on systems that have it.
71  The only bit of terminal state we want to twiddle is echoing, which is
72  done in software; there is no need to change the state of the terminal
73  hardware. */
74 
75 # ifndef TCSASOFT
76 # define TCSASOFT 0
77 # endif
78 
79 static void
80 call_fclose (void *arg)
81 {
82  if (arg != NULL)
83  fclose (arg);
84 }
85 
86 char *
87 getpass (const char *prompt)
88 {
89  FILE *tty;
90  FILE *in, *out;
91 # if HAVE_TCGETATTR
92  struct termios s, t;
93 # endif
94  bool tty_changed = false;
95  static char *buf;
96  static size_t bufsize;
97  ssize_t nread;
98 
99  /* Try to write to and read from the terminal if we can.
100  If we can't open the terminal, use stderr and stdin. */
101 
102  tty = fopen ("/dev/tty", "w+e");
103  if (tty == NULL)
104  {
105  in = stdin;
106  out = stderr;
107  }
108  else
109  {
110  /* We do the locking ourselves. */
111  __fsetlocking (tty, FSETLOCKING_BYCALLER);
112 
113  out = in = tty;
114  }
115 
116  flockfile (out);
117 
118  /* Turn echoing off if it is on now. */
119 # if HAVE_TCGETATTR
120  if (tcgetattr (fileno (in), &t) == 0)
121  {
122  /* Save the old one. */
123  s = t;
124  /* Tricky, tricky. */
125  t.c_lflag &= ~(ECHO | ISIG);
126  tty_changed = (tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t) == 0);
127  }
128 # endif
129 
130  if (prompt)
131  {
132  /* Write the prompt. */
133  fputs_unlocked (prompt, out);
134  fflush_unlocked (out);
135  }
136 
137  /* Read the password. */
138  nread = getline (&buf, &bufsize, in);
139 
140  /* According to the C standard, input may not be followed by output
141  on the same stream without an intervening call to a file
142  positioning function. Suppose in == out; then without this fseek
143  call, on Solaris, HP-UX, AIX, OSF/1, the previous input gets
144  echoed, whereas on IRIX, the following newline is not output as
145  it should be. POSIX imposes similar restrictions if fileno (in)
146  == fileno (out). The POSIX restrictions are tricky and change
147  from POSIX version to POSIX version, so play it safe and invoke
148  fseek even if in != out. */
149  fseeko (out, 0, SEEK_CUR);
150 
151  if (buf != NULL)
152  {
153  if (nread < 0)
154  buf[0] = '\0';
155  else if (buf[nread - 1] == '\n')
156  {
157  /* Remove the newline. */
158  buf[nread - 1] = '\0';
159  if (tty_changed)
160  {
161  /* Write the newline that was not echoed. */
162  putc_unlocked ('\n', out);
163  }
164  }
165  }
166 
167  /* Restore the original setting. */
168 # if HAVE_TCSETATTR
169  if (tty_changed)
170  tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &s);
171 # endif
172 
173  funlockfile (out);
174 
175  call_fclose (tty);
176 
177  return buf;
178 }
179 
180 #else /* W32 native */
181 
182 /* Windows implementation by Martin Lambers <marlam@marlam.de>,
183  improved by Simon Josefsson. */
184 
185 /* For PASS_MAX. */
186 # include <limits.h>
187 /* For _getch(). */
188 # include <conio.h>
189 /* For strdup(). */
190 # include <string.h>
191 
192 # ifndef PASS_MAX
193 # define PASS_MAX 512
194 # endif
195 
196 char *
197 getpass (const char *prompt)
198 {
199  char getpassbuf[PASS_MAX + 1];
200  size_t i = 0;
201  int c;
202 
203  if (prompt)
204  {
205  fputs (prompt, stderr);
206  fflush (stderr);
207  }
208 
209  for (;;)
210  {
211  c = _getch ();
212  if (c == '\r')
213  {
214  getpassbuf[i] = '\0';
215  break;
216  }
217  else if (i < PASS_MAX)
218  {
219  getpassbuf[i++] = c;
220  }
221 
222  if (i >= PASS_MAX)
223  {
224  getpassbuf[i] = '\0';
225  break;
226  }
227  }
228 
229  if (prompt)
230  {
231  fputs ("\r\n", stderr);
232  fflush (stderr);
233  }
234 
235  return strdup (getpassbuf);
236 }
237 #endif
_W64 int ssize_t
Definition: ac-stdint.h:18
#define putc_unlocked(c, stream)
Definition: getpass.c:66
#define flockfile(x)
Definition: getpass.c:54
#define funlockfile(x)
Definition: getpass.c:58
#define fputs_unlocked(str, stream)
Definition: getpass.c:62
#define TCSASOFT
Definition: getpass.c:76
char * getpass(const char *prompt)
Definition: getpass.c:87
static void call_fclose(void *arg)
Definition: getpass.c:80
#define __fsetlocking(stream, type)
Definition: getpass.c:38
#define fflush_unlocked(x)
Definition: getpass.c:50
#define fseeko
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
Definition: getline.c:24
#define NULL
Definition: stddef.in.h:72
unsigned char c
char buf[4]
Definition: mbrtowc-impl.h:39
char * strdup(const char *s)
Definition: strdup.c:39