#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; nread = read(fd, a, len-1); if ( nread <= 0 ) return -1; if ( a[nread-1] == '\n' ) a[nread-1] = '\0'; else a[nread] = '\0'; return 0; } 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; }