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