#include #include #include #include #include /* * getpw4.c: get a password with echo off and show stars for chars * shows how to use signal to catch ^C and reset terminal before exit * v3: restores terminal to original rather than always setting ECHO on * v4: shows how to use -ICANON (an lflag) and c_cc[VMIN] = 1 */ int setup_terminal(int); int restore_terminal(int); int read_a_string_stars(int , char [], int ); void intr_handler(int); #define SLEN 100 int main() { char str[SLEN]; signal(SIGINT, intr_handler); if ( setup_terminal(0) == -1 ) /* fd 0 is stdin */ exit(1); if ( read_a_string_stars(0, str, SLEN) == 0 ) printf("You typed the string: %s\n", str); if ( restore_terminal(0) == -1 ) exit(1); return 0; } /* called when user presses Ctrl-C */ void intr_handler(int s) { printf("interrupted! restoring echo state.\n"); restore_terminal(0); exit(1); } /* * read no more than len-1 chars into array, put a \0 at end. stop at \n or EOF * args: fd, array, space in array * rets: -1 for error or no data, 0 for success * does: class suggestions */ int read_a_string_stars(int fd, char a[], int len) { int nread = 0; char c; while ( read(fd, &c, 1) == 1 ){ // read one char printf("*"); // print one * a[nread++] = c; // store the char if ( c == '\n' ) // break on Enter break; } a[nread] = '\0'; if ( nread > 0 ) return 0; return -1; } static struct termios orig_settings; static int have_orig = 0; /* * get settings for fd, turn off the ECHO bit, set settings */ int setup_terminal(int fd) { struct termios settings; if ( tcgetattr(fd, &settings) == -1 ) return -1; orig_settings = settings; have_orig = 1; settings.c_lflag &= ~ECHO; /* turn off echo bit */ if ( tcsetattr(fd, TCSANOW, &settings) == -1 ) return -1; return 0; } /* * restore terminal to original settings */ int restore_terminal(int fd) { if ( have_orig ) if ( tcsetattr(fd, TCSANOW, &orig_settings) == -1 ) return -1; return 0; }