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 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 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