xref: /original-bsd/lib/libc/gen/getpass.c (revision 35d77a20)
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.9 (Berkeley) 05/06/91";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/termios.h>
13 #include <sys/signal.h>
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <pwd.h>
17 
18 char *
19 getpass(prompt)
20 	const char *prompt;
21 {
22 	struct termios term;
23 	register int ch;
24 	register char *p;
25 	FILE *fp, *outfp;
26 	long omask;
27 	int echo;
28 	static char buf[_PASSWORD_LEN + 1];
29 
30 	/*
31 	 * read and write to /dev/tty if possible; else read from
32 	 * stdin and write to stderr.
33 	 */
34 	if ((outfp = fp = fopen("/dev/tty", "w+")) == NULL) {
35 		outfp = stderr;
36 		fp = stdin;
37 	}
38 	/*
39 	 * note - blocking signals isn't necessarily the
40 	 * right thing, but we leave it for now.
41 	 */
42 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGTSTP));
43 	(void)tcgetattr(fileno(fp), &term);
44 	if (echo = (term.c_lflag & ECHO)) {
45 		term.c_lflag &= ~ECHO;
46 		(void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &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 		tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
58 	}
59 	(void)sigsetmask(omask);
60 	if (fp != stdin)
61 		(void)fclose(fp);
62 	return(buf);
63 }
64