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