#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; | |
} | |
} | |
} |