readcons.c (1708B)
1 #include <u.h> 2 #define NOPLAN9DEFINES 3 #include <libc.h> 4 #include <termios.h> 5 #ifdef HAS_SYS_TERMIOS 6 #include <sys/termios.h> 7 #endif 8 9 static int 10 rawx(int fd, int echoing) 11 { 12 int was; 13 static struct termios ttmode; 14 15 if(echoing == -1) 16 return -1; 17 18 if(tcgetattr(fd, &ttmode) < 0) 19 return -1; 20 was = (ttmode.c_lflag&(ECHO|ICANON)); 21 ttmode.c_lflag &= ~(ECHO|ICANON); 22 ttmode.c_lflag |= echoing; 23 if(tcsetattr(fd, TCSANOW, &ttmode) < 0) 24 return -1; 25 return was; 26 } 27 28 char* 29 readcons(char *prompt, char *def, int secret) 30 { 31 int fd, n, raw; 32 char line[10]; 33 char *s, *t; 34 int l; 35 36 if((fd = open("/dev/tty", ORDWR)) < 0) 37 return nil; 38 39 raw = -1; 40 if(secret){ 41 raw = rawx(fd, 0); 42 if(raw == -1) 43 return nil; 44 } 45 46 if(def) 47 fprint(fd, "%s[%s]: ", prompt, def); 48 else 49 fprint(fd, "%s: ", prompt); 50 51 s = strdup(""); 52 if(s == nil) 53 return nil; 54 55 for(;;){ 56 n = read(fd, line, 1); 57 if(n < 0){ 58 Error: 59 if(secret){ 60 rawx(fd, raw); 61 write(fd, "\n", 1); 62 } 63 close(fd); 64 free(s); 65 return nil; 66 } 67 if(n > 0 && line[0] == 0x7F) 68 goto Error; 69 if(n == 0 || line[0] == 0x04 || line[0] == '\n' || line[0] == '\r'){ 70 if(secret){ 71 rawx(fd, raw); 72 write(fd, "\n", 1); 73 } 74 close(fd); 75 if(*s == 0 && def){ 76 free(s); 77 s = strdup(def); 78 } 79 return s; 80 } 81 if(line[0] == '\b'){ 82 if(strlen(s) > 0) 83 s[strlen(s)-1] = 0; 84 }else if(line[0] == 0x15){ /* ^U: line kill */ 85 if(def != nil) 86 fprint(fd, "\n%s[%s]: ", prompt, def); 87 else 88 fprint(fd, "\n%s: ", prompt); 89 s[0] = 0; 90 }else{ 91 l = strlen(s); 92 t = malloc(l+2); 93 if(t) 94 memmove(t, s, l); 95 memset(s, 'X', l); 96 free(s); 97 if(t == nil) 98 return nil; 99 t[l] = line[0]; 100 t[l+1] = 0; 101 s = t; 102 } 103 } 104 }