xref: /original-bsd/lib/libc/gen/getpass.c (revision c3e32dec)
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 *
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