bea2ac0d089c200c7f24463818e96ad67fc8335d
[kopensolaris-gnu/glibc.git] / misc / getpass.c
1 /* Copyright (C) 1992, 1993, 1994, 1995 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 #include <stdio.h>
20 #include <termios.h>
21 #include <unistd.h>
22
23 /* It is desireable to use this bit on systems that have it.
24    The only bit of terminal state we want to twiddle is echoing, which is
25    done in software; there is no need to change the state of the terminal
26    hardware.  */
27
28 #ifndef TCSASOFT
29 #define TCSASOFT 0
30 #endif
31
32 char *
33 getpass (prompt)
34      const char *prompt;
35 {
36   FILE *in, *out;
37   struct termios t;
38   int echo_off;
39   static char *buf = NULL;
40   static size_t bufsize = 0;
41   ssize_t nread;
42
43   /* Try to write to and read from the terminal if we can.
44      If we can't open the terminal, use stderr and stdin.  */
45
46   in = fopen ("/dev/tty", "w+");
47   if (in == NULL)
48     {
49       in = stdin;
50       out = stderr;
51     }
52   else
53     out = in;
54
55   /* Turn echoing off if it is on now.  */
56
57   if (tcgetattr (fileno (in), &t) == 0)
58     {
59       if (t.c_lflag & ECHO)
60         {
61           t.c_lflag &= ~ECHO;
62           echo_off = tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0;
63           t.c_lflag |= ECHO;
64         }
65       else
66         echo_off = 0;
67     }
68   else
69     echo_off = 0;
70
71   /* Write the prompt.  */
72   fputs (prompt, out);
73   fflush (out);
74
75   /* Read the password.  */
76   nread = __getline (&buf, &bufsize, in);
77   if (nread < 0 && buf != NULL)
78     buf[0] = '\0';
79   else if (buf[nread - 1] == '\n')
80     {
81       /* Remove the newline.  */
82       buf[nread - 1] = '\0';
83       if (echo_off)
84         /* Write the newline that was not echoed.  */
85         putc ('\n', out);
86     }
87
88   /* Restore echoing.  */
89   if (echo_off)
90     (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t);
91
92   if (in != stdin)
93     /* We opened the terminal; now close it.  */
94     fclose (in);
95
96   return buf;
97 }