readcons.c - 9base - revived minimalist port of Plan 9 userland to Unix
(HTM) git clone git://git.suckless.org/9base
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
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 }