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