275 lines · 4.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <tty.h> typedef struct Mode Mode;struct Mode{	char*	name;	int	bit;}; Mode ou[] ={	"opost",	OPOST,	"olcuc",	OLCUC,	"onlcr",	ONLCR,	"ocrnl",	OCRNL,	"onocr",	ONOCR,	"onlret",	ONLRET,	"ofill",	OFILL,	"ofdel",	OFDEL,	0}; Mode in[] ={	"brkint",	BRKINT,	"icrnl",	ICRNL,	"ignbrk",	IGNBRK,	"igncr",	IGNCR,	"ignpar",	IGNPAR,	"inlcr",	INLCR,	"inpck",	INPCK,	"istrip",	ISTRIP,	"ixoff",	IXOFF,	"ixon",		IXON,	"parmrk",	PARMRK,	0}; Mode lo[] ={	"echo",		ECHO,	"echoe",	ECHOE,	"echok", 	ECHOK,	"echonl",	ECHONL,	"icanon",	ICANON,	"iexten",	IEXTEN,	"isig",		ISIG,	"noflsh",	NOFLSH,	"tostop",	TOSTOP,	0}; Mode cc[] ={	"eof",		VEOF,	"eol",		VEOL,	"erase",	VERASE,	"intr",		VINTR,	"kill",		VKILL,	"min",		VMIN,	"quit",		VQUIT,	"susp",		VSUSP,	"time",		VTIME,	"start",	VSTART,	"stop",		VSTOP,	0,}; int	getmode(int, Termios*);int	setmode(int, Termios*); char*ctlchar(char c){	static char buf[10]; 	if(c == 0x7f)		return "DEL";	if(c == 0)		return "NUL";	if(c < 32) {		buf[0] = '^';		buf[1] = '@'+c;		buf[2] = '\0';		return buf;	}		buf[0] = c;	buf[1] = '\0';	return buf;} voidshowmode(Termios *t){	int i; 	for(i = 0; cc[i].name; i++) {		switch(cc[i].bit) {		case VMIN:		case VTIME:			if(t->cc[i] != 0)				print("%s %d ", cc[i].name, t->cc[i]);			break;		default:			print("%s %s ", cc[i].name, ctlchar(t->cc[i]));			break;		}	}	print("\n"); 	for(i = 0; ou[i].name; i++)		if(ou[i].bit & t->oflag)			print("%s ", ou[i].name); 	for(i = 0; in[i].name; i++)		if(in[i].bit & t->iflag)			print("%s ", in[i].name); 	print("\n");	for(i = 0; lo[i].name; i++)		if(lo[i].bit & t->lflag)			print("%s ", lo[i].name);	print("\n");} intsetreset(char *mode, int *bits, Mode *t){	int i, clr; 	clr = 0;	if(mode[0] == '-') {		mode++;		clr = 1;	}	for(i = 0; t[i].name; i++) {		if(strcmp(mode, t[i].name) == 0) {			if(clr)				*bits &= ~t[i].bit;			else				*bits |= t[i].bit; 			return 1;		}	}	return 0;} intccname(char *name){	int i; 	for(i = 0; cc[i].name; i++)		if(strcmp(cc[i].name, name) == 0)			return i; 	return -1;} voidmain(int argc, char **argv){	Termios t;	int i, stdin, wmo, cc; 	/* Try and get a seek pointer */	stdin = open("/fd/0", ORDWR);	if(stdin < 0)		stdin = 0; 	if(getmode(stdin, &t) < 0) {		fprint(2, "stty: tiocget %r\n");		exits("1");	} 	if(argc < 2) {		fprint(2, "usage: stty [-a|-g] modes...\n");		exits("1");	}	wmo = 0;	for(i = 1; i < argc; i++) {		if(strcmp(argv[i], "-a") == 0) {			showmode(&t);			continue;		}		if(setreset(argv[i], &t.iflag, in)) {			wmo++;			continue;		}		if(setreset(argv[i], &t.lflag, lo)) {			wmo++;			continue;		}		if(setreset(argv[i], &t.oflag, ou)) {			wmo++;			continue;		}		cc = ccname(argv[i]);		if(cc != -1 && i+1 < argc) {			wmo++;			t.cc[cc] = argv[++i][0];			continue;		}		fprint(2, "stty: bad option/mode %s\n", argv[i]);		exits("1");	} 	if(wmo) {		if(setmode(stdin, &t) < 0) {			fprint(2, "stty: cant set mode %r\n");			exits("1");		}	} 	exits(0);} intsetmode(int fd, Termios *t){	int n, i;	char buf[256]; 	n = sprint(buf, "IOW %4.4ux %4.4ux %4.4ux %4.4ux ",		t->iflag, t->oflag, t->cflag, t->lflag);	for(i = 0; i < NCCS; i++)		n += sprint(buf+n, "%2.2ux ", t->cc[i]); 	if(seek(fd, -2, 0) != -2)		return -1; 	n = write(fd, buf, n);	if(n < 0)		return -1;	return 0;} /* * Format is: IOR iiii oooo cccc llll xx xx xx xx ... */intgetmode(int fd, Termios *t){	int n;	char buf[256]; 	if(seek(fd, -2, 0) != -2)		return -1; 	n = read(fd, buf, 57);	if(n < 0)		return -1; 	t->iflag = strtoul(buf+4, 0, 16);	t->oflag = strtoul(buf+9, 0, 16);	t->cflag = strtoul(buf+14, 0, 16);	t->lflag = strtoul(buf+19, 0, 16); 	for(n = 0; n < NCCS; n++)		t->cc[n] = strtoul(buf+24+(n*3), 0, 16); 	return 0;}