9base

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