/* * maskread.c * Pieter Droogendijk */ #include #include #include #include #include int set_cbreak (struct termios *save_termios) { struct termios buf; /* Remove line buffering from stdin */ if (setvbuf (stdin, NULL, _IONBF, 0) != 0) return -1; /* Store previous terminal settins of fd 0 (stdin) */ if (tcgetattr (0, save_termios)) return -1; /* Modify terminal settings. */ buf = *save_termios; buf.c_lflag &= ~(ICANON|ECHO); buf.c_cc[VMIN] = 1; buf.c_cc[VTIME] = 0; /* Set new terminal settings on fd 0. */ if (tcsetattr (0, TCSAFLUSH, &buf) < 0) return -1; return 0; } int unset_cbreak (struct termios *save_termios) { /* Return line buffering to stdin. */ if (setvbuf (stdin, NULL, _IOLBF, 0) != 0) return -1; /* Return original terminal settings to fd 0. */ if (tcsetattr (0, TCSAFLUSH, save_termios) < 0) return -1; return 0; } int mask_read (char *buf, size_t bufsize) { size_t rv = 0, bufpos = 0; struct termios save_termios; int inch; if (set_cbreak (&save_termios) == -1) { rv = -1; } else { while ( rv == 0 && (inch = getchar()) != EOF && inch != '\n' && bufpos < bufsize-1 ) { if (putchar ('*') == EOF) { rv = -1; } else if (fflush (stdout) == EOF) { rv = -1; } else { buf[bufpos] = inch; bufpos ++; } } buf[bufpos] = '\0'; if (ferror (stdin) || unset_cbreak (&save_termios) == -1) { rv = -1; } } return rv; } int main (void) { int rv = EXIT_SUCCESS; char hop[32]; if (mask_read (hop, sizeof hop) == -1) { (void)fprintf (stderr, "mask_read() failed: %s.\n", strerror (errno)); rv = EXIT_FAILURE; } else { (void)printf ("Went and read: '%s'\n", hop); } return rv; }