Initial Contribution
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;
+}