Enhance fix of 0b81a300d9e7cf78b6bc11d8c870f57fa81fcdc4.
[mmh] / sbr / getpass.c
1 /*
2 ** Portions of this code are Copyright (c) 1988, 1993
3 **      The Regents of the University of California.  All rights reserved.
4 **
5 ** Redistribution and use in source and binary forms, with or without
6 ** modification, are permitted provided that the following conditions
7 ** are met:
8 ** 1. Redistributions of source code must retain the above copyright
9 **    notice, this list of conditions and the following disclaimer.
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 **    notice, this list of conditions and the following disclaimer in the
12 **    documentation and/or other materials provided with the distribution.
13 ** 3. All advertising materials mentioning features or use of this software
14 **    must display the following acknowledgement:
15 **      This product includes software developed by the University of
16 **      California, Berkeley and its contributors.
17 ** 4. Neither the name of the University nor the names of its contributors
18 **    may be used to endorse or promote products derived from this software
19 **    without specific prior written permission.
20 **
21 ** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 ** SUCH DAMAGE.
32 */
33
34 #include <stdio.h>
35 #include <termios.h>
36 #include <unistd.h>   /* for isatty() */
37 #include "h/mh.h"     /* for adios() */
38
39 /*
40 ** We don't use MAX_PASS here because the maximum password length on a remote
41 ** POP daemon will have nothing to do with the length on our OS.  256 is
42 ** arbitrary but hopefully big enough to accomodate everyone.
43 */
44 #define MAX_PASSWORD_LEN 256
45
46 #ifndef TCSANOW
47 # define TCSANOW 0
48 #endif
49
50 char *
51 nmh_getpass(const char *prompt)
52 {
53         struct termios oterm, term;
54         int ch;
55         char *p;
56         FILE *fout, *fin;
57         static char buf[MAX_PASSWORD_LEN + 1];
58         int istty = isatty(fileno(stdin));
59
60         /*
61         ** Find if stdin is connect to a terminal. If so, read directly from
62         ** the terminal, and turn off echo. Otherwise read from stdin.
63         */
64
65         if (!istty || !(fout = fin = fopen("/dev/tty", "w+"))) {
66                 fout = stderr;
67                 fin = stdin;
68         } else {  /* Reading directly from terminal here */
69                 tcgetattr(fileno(fin), &oterm);
70                 term = oterm; /* Save original info */
71                 term.c_lflag &= ~ECHO;
72                 fputs(prompt, fout);
73                 rewind(fout);  /* implied flush */
74                 tcsetattr(fileno(fin), TCSANOW, &term);
75         }
76
77         for (p = buf; (ch = getc(fin)) != EOF && ch != '\n' &&
78                 p < buf + MAX_PASSWORD_LEN;)
79                 *p++ = ch;
80         *p = '\0';
81
82         if (istty) {
83                 tcsetattr(fileno(fin), TCSANOW, &oterm);
84                 rewind(fout);
85                 fputc('\n', fout);
86                 fclose(fin);
87         }
88         return buf;
89 }