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 }