|  | #include <u.h> | 
|  | #define NOPLAN9DEFINES | 
|  | #include <libc.h> | 
|  | #include <termios.h> | 
|  | #include <sys/termios.h> | 
|  |  | 
|  | static int | 
|  | rawx(int fd, int echoing) | 
|  | { | 
|  | int was; | 
|  | static struct termios ttmode; | 
|  |  | 
|  | if(echoing == -1) | 
|  | return -1; | 
|  |  | 
|  | if(tcgetattr(fd, &ttmode) < 0) | 
|  | return -1; | 
|  | was = (ttmode.c_lflag&(ECHO|ICANON)); | 
|  | ttmode.c_lflag &= ~(ECHO|ICANON); | 
|  | ttmode.c_lflag |= echoing; | 
|  | if(tcsetattr(fd, TCSANOW, &ttmode) < 0) | 
|  | return -1; | 
|  | return was; | 
|  | } | 
|  |  | 
|  | char* | 
|  | readcons(char *prompt, char *def, int secret) | 
|  | { | 
|  | int fd, n, raw; | 
|  | char line[10]; | 
|  | char *s, *t; | 
|  | int l; | 
|  |  | 
|  | if((fd = open("/dev/tty", ORDWR)) < 0) | 
|  | return nil; | 
|  |  | 
|  | raw = -1; | 
|  | if(secret){ | 
|  | raw = rawx(fd, 0); | 
|  | if(raw == -1) | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | if(def) | 
|  | fprint(fd, "%s[%s]: ", prompt, def); | 
|  | else | 
|  | fprint(fd, "%s: ", prompt); | 
|  |  | 
|  | s = strdup(""); | 
|  | if(s == nil) | 
|  | return nil; | 
|  |  | 
|  | for(;;){ | 
|  | n = read(fd, line, 1); | 
|  | if(n < 0){ | 
|  | Error: | 
|  | if(secret){ | 
|  | rawx(fd, raw); | 
|  | write(fd, "\n", 1); | 
|  | } | 
|  | close(fd); | 
|  | free(s); | 
|  | return nil; | 
|  | } | 
|  | if(n > 0 && line[0] == 0x7F) | 
|  | goto Error; | 
|  | if(n == 0 || line[0] == 0x04 || line[0] == '\n' || line[0] == '\r'){ | 
|  | if(secret){ | 
|  | rawx(fd, raw); | 
|  | write(fd, "\n", 1); | 
|  | } | 
|  | close(fd); | 
|  | if(*s == 0 && def){ | 
|  | free(s); | 
|  | s = strdup(def); | 
|  | } | 
|  | return s; | 
|  | } | 
|  | if(line[0] == '\b'){ | 
|  | if(strlen(s) > 0) | 
|  | s[strlen(s)-1] = 0; | 
|  | }else if(line[0] == 0x15){	/* ^U: line kill */ | 
|  | if(def != nil) | 
|  | fprint(fd, "\n%s[%s]: ", prompt, def); | 
|  | else | 
|  | fprint(fd, "\n%s: ", prompt); | 
|  | s[0] = 0; | 
|  | }else{ | 
|  | l = strlen(s); | 
|  | t = malloc(l+2); | 
|  | if(t) | 
|  | memmove(t, s, l); | 
|  | memset(s, 'X', l); | 
|  | free(s); | 
|  | if(t == nil) | 
|  | return nil; | 
|  | t[l] = line[0]; | 
|  | t[l+1] = 0; | 
|  | s = t; | 
|  | } | 
|  | } | 
|  | } |