diff options
Diffstat (limited to 'toolbox/readtty.c')
-rw-r--r-- | toolbox/readtty.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/toolbox/readtty.c b/toolbox/readtty.c new file mode 100644 index 0000000..2b27548 --- /dev/null +++ b/toolbox/readtty.c @@ -0,0 +1,183 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +struct { + char key; + char *chars; +} map[] = { + { '1', "_ -1?!,.:;\"'<=>()_" }, + { '2', "Cabc2ABC" }, + { '3', "Fdef3DEF" }, + { '4', "Ighi4GHI" }, + { '5', "Ljkl5JKL" }, + { '6', "Omno6MNO" }, + { '7', "Spqrs7PQRS" }, + { '8', "Vtuv8TUV" }, + { '9', "Zwxyz9WXYZ" }, + { '0', "*+&0@/#*" }, +}; + +char next_char(char key, char current) +{ + int i; + char *next; + for(i = 0; i < sizeof(map) / sizeof(map[0]); i++) { + if(key == map[i].key) { + next = strchr(map[i].chars, current); + if(next && next[1]) + return next[1]; + return map[i].chars[1]; + } + } + return key; +} + +char prev_char(char key, char current) +{ + int i; + char *next; + for(i = 0; i < sizeof(map) / sizeof(map[0]); i++) { + if(key == map[i].key) { + next = strchr(map[i].chars+1, current); + if(next && next[-1]) + return next[-1]; + return map[i].chars[1]; + } + } + return key; +} + +int readtty_main(int argc, char *argv[]) +{ + int c; + //int flags; + char buf[1]; + int res; + struct termios ttyarg; + struct termios savedttyarg; + int nonblock = 0; + int timeout = 0; + int flush = 0; + int phone = 0; + char *accept = NULL; + char *rejectstring = NULL; + char last_char_in = 0; + char current_char = 0; + char *exit_string = NULL; + int exit_match = 0; + + do { + c = getopt(argc, argv, "nt:fa:r:pe:"); + if (c == EOF) + break; + switch (c) { + case 't': + timeout = atoi(optarg); + break; + case 'n': + nonblock = 1; + break; + case 'f': + flush = 1; + break; + case 'a': + accept = optarg; + break; + case 'r': + rejectstring = optarg; + break; + case 'p': + phone = 1; + break; + case 'e': + exit_string = optarg; + break; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + argv[0], optopt); + exit(1); + } + } while (1); + + if(flush) + tcflush(STDIN_FILENO, TCIFLUSH); + ioctl(STDIN_FILENO, TCGETS , &savedttyarg) ; /* set changed tty arguments */ + ttyarg = savedttyarg; + ttyarg.c_cc[VMIN] = (timeout > 0 || nonblock) ? 0 : 1; /* minimum of 0 chars */ + ttyarg.c_cc[VTIME] = timeout; /* wait max 15/10 sec */ + ttyarg.c_iflag = BRKINT | ICRNL; + ttyarg.c_lflag &= ~(ECHO | ICANON); + ioctl(STDIN_FILENO, TCSETS , &ttyarg); + + while (1) { + res = read(STDIN_FILENO, buf, 1); + if(res <= 0) { + if(phone) { + if(current_char) { + write(STDERR_FILENO, ¤t_char, 1); + write(STDOUT_FILENO, ¤t_char, 1); + if(exit_string && current_char == exit_string[exit_match]) { + exit_match++; + if(exit_string[exit_match] == '\0') + break; + } + else + exit_match = 0; + current_char = 0; + } + continue; + } + break; + } + if(accept && strchr(accept, buf[0]) == NULL) { + if(rejectstring) { + write(STDOUT_FILENO, rejectstring, strlen(rejectstring)); + break; + } + if(flush) + tcflush(STDIN_FILENO, TCIFLUSH); + continue; + } + if(phone) { + //if(!isprint(buf[0])) { + // fprintf(stderr, "got unprintable character 0x%x\n", buf[0]); + //} + if(buf[0] == '\0') { + if(current_char) { + current_char = prev_char(last_char_in, current_char); + write(STDERR_FILENO, ¤t_char, 1); + write(STDERR_FILENO, "\b", 1); + } + continue; + } + if(current_char && buf[0] != last_char_in) { + write(STDERR_FILENO, ¤t_char, 1); + write(STDOUT_FILENO, ¤t_char, 1); + if(exit_string && current_char == exit_string[exit_match]) { + exit_match++; + if(exit_string[exit_match] == '\0') + break; + } + else + exit_match = 0; + current_char = 0; + } + last_char_in = buf[0]; + current_char = next_char(last_char_in, current_char); + write(STDERR_FILENO, ¤t_char, 1); + write(STDERR_FILENO, "\b", 1); + continue; + } + write(STDOUT_FILENO, buf, 1); + break; + } + ioctl(STDIN_FILENO, TCSETS , &savedttyarg) ; /* set changed tty arguments */ + + return 0; +} |