| #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; | |
| } |