1#include <ctype.h> 2#include <stdio.h> 3#include <stdlib.h> 4#include <sys/mman.h> 5#include <fcntl.h> 6#include <string.h> 7#include <termios.h> 8#include <unistd.h> 9 10struct { 11 char key; 12 char *chars; 13} map[] = { 14 { '1', "_ -1?!,.:;\"'<=>()_" }, 15 { '2', "Cabc2ABC" }, 16 { '3', "Fdef3DEF" }, 17 { '4', "Ighi4GHI" }, 18 { '5', "Ljkl5JKL" }, 19 { '6', "Omno6MNO" }, 20 { '7', "Spqrs7PQRS" }, 21 { '8', "Vtuv8TUV" }, 22 { '9', "Zwxyz9WXYZ" }, 23 { '0', "*+&0@/#*" }, 24}; 25 26char next_char(char key, char current) 27{ 28 int i; 29 char *next; 30 for(i = 0; i < sizeof(map) / sizeof(map[0]); i++) { 31 if(key == map[i].key) { 32 next = strchr(map[i].chars, current); 33 if(next && next[1]) 34 return next[1]; 35 return map[i].chars[1]; 36 } 37 } 38 return key; 39} 40 41char prev_char(char key, char current) 42{ 43 int i; 44 char *next; 45 for(i = 0; i < sizeof(map) / sizeof(map[0]); i++) { 46 if(key == map[i].key) { 47 next = strchr(map[i].chars+1, current); 48 if(next && next[-1]) 49 return next[-1]; 50 return map[i].chars[1]; 51 } 52 } 53 return key; 54} 55 56int readtty_main(int argc, char *argv[]) 57{ 58 int c; 59 //int flags; 60 char buf[1]; 61 int res; 62 struct termios ttyarg; 63 struct termios savedttyarg; 64 int nonblock = 0; 65 int timeout = 0; 66 int flush = 0; 67 int phone = 0; 68 char *accept = NULL; 69 char *rejectstring = NULL; 70 char last_char_in = 0; 71 char current_char = 0; 72 char *exit_string = NULL; 73 int exit_match = 0; 74 75 do { 76 c = getopt(argc, argv, "nt:fa:r:pe:"); 77 if (c == EOF) 78 break; 79 switch (c) { 80 case 't': 81 timeout = atoi(optarg); 82 break; 83 case 'n': 84 nonblock = 1; 85 break; 86 case 'f': 87 flush = 1; 88 break; 89 case 'a': 90 accept = optarg; 91 break; 92 case 'r': 93 rejectstring = optarg; 94 break; 95 case 'p': 96 phone = 1; 97 break; 98 case 'e': 99 exit_string = optarg; 100 break; 101 case '?': 102 fprintf(stderr, "%s: invalid option -%c\n", 103 argv[0], optopt); 104 exit(1); 105 } 106 } while (1); 107 108 if(flush) 109 tcflush(STDIN_FILENO, TCIFLUSH); 110 ioctl(STDIN_FILENO, TCGETS , &savedttyarg) ; /* set changed tty arguments */ 111 ttyarg = savedttyarg; 112 ttyarg.c_cc[VMIN] = (timeout > 0 || nonblock) ? 0 : 1; /* minimum of 0 chars */ 113 ttyarg.c_cc[VTIME] = timeout; /* wait max 15/10 sec */ 114 ttyarg.c_iflag = BRKINT | ICRNL; 115 ttyarg.c_lflag &= ~(ECHO | ICANON); 116 ioctl(STDIN_FILENO, TCSETS , &ttyarg); 117 118 while (1) { 119 res = read(STDIN_FILENO, buf, 1); 120 if(res <= 0) { 121 if(phone) { 122 if(current_char) { 123 write(STDERR_FILENO, ¤t_char, 1); 124 write(STDOUT_FILENO, ¤t_char, 1); 125 if(exit_string && current_char == exit_string[exit_match]) { 126 exit_match++; 127 if(exit_string[exit_match] == '\0') 128 break; 129 } 130 else 131 exit_match = 0; 132 current_char = 0; 133 } 134 continue; 135 } 136 break; 137 } 138 if(accept && strchr(accept, buf[0]) == NULL) { 139 if(rejectstring) { 140 write(STDOUT_FILENO, rejectstring, strlen(rejectstring)); 141 break; 142 } 143 if(flush) 144 tcflush(STDIN_FILENO, TCIFLUSH); 145 continue; 146 } 147 if(phone) { 148 //if(!isprint(buf[0])) { 149 // fprintf(stderr, "got unprintable character 0x%x\n", buf[0]); 150 //} 151 if(buf[0] == '\0') { 152 if(current_char) { 153 current_char = prev_char(last_char_in, current_char); 154 write(STDERR_FILENO, ¤t_char, 1); 155 write(STDERR_FILENO, "\b", 1); 156 } 157 continue; 158 } 159 if(current_char && buf[0] != last_char_in) { 160 write(STDERR_FILENO, ¤t_char, 1); 161 write(STDOUT_FILENO, ¤t_char, 1); 162 if(exit_string && current_char == exit_string[exit_match]) { 163 exit_match++; 164 if(exit_string[exit_match] == '\0') 165 break; 166 } 167 else 168 exit_match = 0; 169 current_char = 0; 170 } 171 last_char_in = buf[0]; 172 current_char = next_char(last_char_in, current_char); 173 write(STDERR_FILENO, ¤t_char, 1); 174 write(STDERR_FILENO, "\b", 1); 175 continue; 176 } 177 write(STDOUT_FILENO, buf, 1); 178 break; 179 } 180 ioctl(STDIN_FILENO, TCSETS , &savedttyarg) ; /* set changed tty arguments */ 181 182 return 0; 183} 184