xref: /minix3/minix/lib/libc/gen/getpass.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 /*	getpass() - read a password		Author: Kees J. Bot
2  *							Feb 16 1993
3  */
4 #include <sys/cdefs.h>
5 #include "namespace.h"
6 
7 #include <sys/types.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <signal.h>
11 #include <termios.h>
12 #include <string.h>
13 
14 #ifdef __weak_alias
__weak_alias(getpass,_getpass)15 __weak_alias(getpass, _getpass)
16 #endif
17 
18 static int intr;
19 
20 static void catch(int sig)
21 {
22 	intr= 1;
23 }
24 
getpass(const char * prompt)25 char *getpass(const char *prompt)
26 {
27 	struct sigaction osa, sa;
28 	struct termios cooked, raw;
29 	static char password[32+1];
30 	int fd, n= 0;
31 
32 	/* Try to open the controlling terminal. */
33 	if ((fd= open("/dev/tty", O_RDONLY)) < 0) return NULL;
34 
35 	/* Trap interrupts unless ignored. */
36 	intr= 0;
37 	sigaction(SIGINT, NULL, &osa);
38 	if (osa.sa_handler != SIG_IGN) {
39 		sigemptyset(&sa.sa_mask);
40 		sa.sa_flags= 0;
41 		sa.sa_handler= catch;
42 		sigaction(SIGINT, &sa, &osa);
43 	}
44 
45 	/* Set the terminal to non-echo mode. */
46 	tcgetattr(fd, &cooked);
47 	raw= cooked;
48 	raw.c_iflag|= ICRNL;
49 	raw.c_lflag&= ~ECHO;
50 	raw.c_lflag|= ECHONL;
51 	raw.c_oflag|= OPOST | ONLCR;
52 	tcsetattr(fd, TCSANOW, &raw);
53 
54 	/* Print the prompt.  (After setting non-echo!) */
55 	write(2, prompt, strlen(prompt));
56 
57 	/* Read the password, 32 characters max. */
58 	while (read(fd, password+n, 1) > 0) {
59 		if (password[n] == '\n') break;
60 		if (n < 32) n++;
61 	}
62 	password[n]= 0;
63 
64 	/* Terminal back to cooked mode. */
65 	tcsetattr(fd, TCSANOW, &cooked);
66 
67 	close(fd);
68 
69 	/* Interrupt? */
70 	sigaction(SIGINT, &osa, NULL);
71 	if (intr) raise(SIGINT);
72 
73 	return password;
74 }
75