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