plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

readcons.c (1708B)


      1 #include <u.h>
      2 #define NOPLAN9DEFINES
      3 #include <libc.h>
      4 #include <termios.h>
      5 #ifdef HAS_SYS_TERMIOS
      6 #include <sys/termios.h>
      7 #endif
      8 
      9 static int
     10 rawx(int fd, int echoing)
     11 {
     12 	int was;
     13 	static struct termios ttmode;
     14 
     15 	if(echoing == -1)
     16 		return -1;
     17 
     18 	if(tcgetattr(fd, &ttmode) < 0)
     19 		return -1;
     20 	was = (ttmode.c_lflag&(ECHO|ICANON));
     21 	ttmode.c_lflag &= ~(ECHO|ICANON);
     22 	ttmode.c_lflag |= echoing;
     23 	if(tcsetattr(fd, TCSANOW, &ttmode) < 0)
     24 		return -1;
     25 	return was;
     26 }
     27 
     28 char*
     29 readcons(char *prompt, char *def, int secret)
     30 {
     31 	int fd, n, raw;
     32 	char line[10];
     33 	char *s, *t;
     34 	int l;
     35 
     36 	if((fd = open("/dev/tty", ORDWR)) < 0)
     37 		return nil;
     38 
     39 	raw = -1;
     40 	if(secret){
     41 		raw = rawx(fd, 0);
     42 		if(raw == -1)
     43 			return nil;
     44 	}
     45 
     46 	if(def)
     47 		fprint(fd, "%s[%s]: ", prompt, def);
     48 	else
     49 		fprint(fd, "%s: ", prompt);
     50 
     51 	s = strdup("");
     52 	if(s == nil)
     53 		return nil;
     54 
     55 	for(;;){
     56 		n = read(fd, line, 1);
     57 		if(n < 0){
     58 		Error:
     59 			if(secret){
     60 				rawx(fd, raw);
     61 				write(fd, "\n", 1);
     62 			}
     63 			close(fd);
     64 			free(s);
     65 			return nil;
     66 		}
     67 		if(n > 0 && line[0] == 0x7F)
     68 			goto Error;
     69 		if(n == 0 || line[0] == 0x04 || line[0] == '\n' || line[0] == '\r'){
     70 			if(secret){
     71 				rawx(fd, raw);
     72 				write(fd, "\n", 1);
     73 			}
     74 			close(fd);
     75 			if(*s == 0 && def){
     76 				free(s);
     77 				s = strdup(def);
     78 			}
     79 			return s;
     80 		}
     81 		if(line[0] == '\b'){
     82 			if(strlen(s) > 0)
     83 				s[strlen(s)-1] = 0;
     84 		}else if(line[0] == 0x15){	/* ^U: line kill */
     85 			if(def != nil)
     86 				fprint(fd, "\n%s[%s]: ", prompt, def);
     87 			else
     88 				fprint(fd, "\n%s: ", prompt);
     89 			s[0] = 0;
     90 		}else{
     91 			l = strlen(s);
     92 			t = malloc(l+2);
     93 			if(t)
     94 				memmove(t, s, l);
     95 			memset(s, 'X', l);
     96 			free(s);
     97 			if(t == nil)
     98 				return nil;
     99 			t[l] = line[0];
    100 			t[l+1] = 0;
    101 			s = t;
    102 		}
    103 	}
    104 }