summaryrefslogtreecommitdiffstats
path: root/toolbox/readtty.c
diff options
context:
space:
mode:
Diffstat (limited to 'toolbox/readtty.c')
-rw-r--r--toolbox/readtty.c183
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, &current_char, 1);
+ write(STDOUT_FILENO, &current_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, &current_char, 1);
+ write(STDERR_FILENO, "\b", 1);
+ }
+ continue;
+ }
+ if(current_char && buf[0] != last_char_in) {
+ write(STDERR_FILENO, &current_char, 1);
+ write(STDOUT_FILENO, &current_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, &current_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;
+}