1/* vi: set sw=4 ts=4: */ 2/* 3 * Ask for a password 4 * I use a static buffer in this function. Plan accordingly. 5 * 6 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 7 * 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 9 */ 10 11#include "libbb.h" 12 13/* do nothing signal handler */ 14static void askpass_timeout(int UNUSED_PARAM ignore) 15{ 16} 17 18char* FAST_FUNC bb_ask_stdin(const char *prompt) 19{ 20 return bb_ask(STDIN_FILENO, 0, prompt); 21} 22char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) 23{ 24 /* Was static char[BIGNUM] */ 25 enum { sizeof_passwd = 128 }; 26 static char *passwd; 27 28 char *ret; 29 int i; 30 struct sigaction sa, oldsa; 31 struct termios tio, oldtio; 32 33 tcgetattr(fd, &oldtio); 34 tcflush(fd, TCIFLUSH); 35 tio = oldtio; 36#ifndef IUCLC 37# define IUCLC 0 38#endif 39 tio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY); 40 tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP); 41 tcsetattr(fd, TCSANOW, &tio); 42 43 memset(&sa, 0, sizeof(sa)); 44 /* sa.sa_flags = 0; - no SA_RESTART! */ 45 /* SIGINT and SIGALRM will interrupt reads below */ 46 sa.sa_handler = askpass_timeout; 47 sigaction(SIGINT, &sa, &oldsa); 48 if (timeout) { 49 sigaction_set(SIGALRM, &sa); 50 alarm(timeout); 51 } 52 53 fputs(prompt, stdout); 54 fflush_all(); 55 56 if (!passwd) 57 passwd = xmalloc(sizeof_passwd); 58 ret = passwd; 59 i = 0; 60 while (1) { 61 int r = read(fd, &ret[i], 1); 62 if (r < 0) { 63 /* read is interrupted by timeout or ^C */ 64 ret = NULL; 65 break; 66 } 67 if (r == 0 /* EOF */ 68 || ret[i] == '\r' || ret[i] == '\n' /* EOL */ 69 || ++i == sizeof_passwd-1 /* line limit */ 70 ) { 71 ret[i] = '\0'; 72 break; 73 } 74 } 75 76 if (timeout) { 77 alarm(0); 78 } 79 sigaction_set(SIGINT, &oldsa); 80 tcsetattr(fd, TCSANOW, &oldtio); 81 bb_putchar('\n'); 82 fflush_all(); 83 return ret; 84} 85