1 /*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)getpass.c 8.1 (Berkeley) 06/04/93";
10 #endif /* LIBC_SCCS and not lint */
11
12 #include <sys/termios.h>
13 #include <sys/signal.h>
14
15 #include <paths.h>
16 #include <pwd.h>
17 #include <stdio.h>
18 #include <unistd.h>
19
20 char *
getpass(prompt)21 getpass(prompt)
22 const char *prompt;
23 {
24 struct termios term;
25 register int ch;
26 register char *p;
27 FILE *fp, *outfp;
28 long omask;
29 int echo;
30 static char buf[_PASSWORD_LEN + 1];
31
32 /*
33 * read and write to /dev/tty if possible; else read from
34 * stdin and write to stderr.
35 */
36 if ((outfp = fp = fopen(_PATH_TTY, "w+")) == NULL) {
37 outfp = stderr;
38 fp = stdin;
39 }
40 /*
41 * note - blocking signals isn't necessarily the
42 * right thing, but we leave it for now.
43 */
44 omask = sigblock(sigmask(SIGINT)|sigmask(SIGTSTP));
45 (void)tcgetattr(fileno(fp), &term);
46 if (echo = (term.c_lflag & ECHO)) {
47 term.c_lflag &= ~ECHO;
48 (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
49 }
50 (void)fputs(prompt, outfp);
51 rewind(outfp); /* implied flush */
52 for (p = buf; (ch = getc(fp)) != EOF && ch != '\n';)
53 if (p < buf + _PASSWORD_LEN)
54 *p++ = ch;
55 *p = '\0';
56 (void)write(fileno(outfp), "\n", 1);
57 if (echo) {
58 term.c_lflag |= ECHO;
59 (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
60 }
61 (void)sigsetmask(omask);
62 if (fp != stdin)
63 (void)fclose(fp);
64 return(buf);
65 }
66