xref: /plan9/sys/src/ape/9src/stty.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <tty.h>
4219b2ee8SDavid du Colombier 
5219b2ee8SDavid du Colombier typedef struct Mode Mode;
6219b2ee8SDavid du Colombier struct Mode
7219b2ee8SDavid du Colombier {
8219b2ee8SDavid du Colombier 	char*	name;
9219b2ee8SDavid du Colombier 	int	bit;
10219b2ee8SDavid du Colombier };
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier Mode ou[] =
13219b2ee8SDavid du Colombier {
14219b2ee8SDavid du Colombier 	"opost",	OPOST,
15219b2ee8SDavid du Colombier 	"olcuc",	OLCUC,
16219b2ee8SDavid du Colombier 	"onlcr",	ONLCR,
17219b2ee8SDavid du Colombier 	"ocrnl",	OCRNL,
18219b2ee8SDavid du Colombier 	"onocr",	ONOCR,
19219b2ee8SDavid du Colombier 	"onlret",	ONLRET,
20219b2ee8SDavid du Colombier 	"ofill",	OFILL,
21219b2ee8SDavid du Colombier 	"ofdel",	OFDEL,
22219b2ee8SDavid du Colombier 	0
23219b2ee8SDavid du Colombier };
24219b2ee8SDavid du Colombier 
25219b2ee8SDavid du Colombier Mode in[] =
26219b2ee8SDavid du Colombier {
27219b2ee8SDavid du Colombier 	"brkint",	BRKINT,
28219b2ee8SDavid du Colombier 	"icrnl",	ICRNL,
29219b2ee8SDavid du Colombier 	"ignbrk",	IGNBRK,
30219b2ee8SDavid du Colombier 	"igncr",	IGNCR,
31219b2ee8SDavid du Colombier 	"ignpar",	IGNPAR,
32219b2ee8SDavid du Colombier 	"inlcr",	INLCR,
33219b2ee8SDavid du Colombier 	"inpck",	INPCK,
34219b2ee8SDavid du Colombier 	"istrip",	ISTRIP,
35219b2ee8SDavid du Colombier 	"ixoff",	IXOFF,
36219b2ee8SDavid du Colombier 	"ixon",		IXON,
37219b2ee8SDavid du Colombier 	"parmrk",	PARMRK,
38219b2ee8SDavid du Colombier 	0
39219b2ee8SDavid du Colombier };
40219b2ee8SDavid du Colombier 
41219b2ee8SDavid du Colombier Mode lo[] =
42219b2ee8SDavid du Colombier {
43219b2ee8SDavid du Colombier 	"echo",		ECHO,
44219b2ee8SDavid du Colombier 	"echoe",	ECHOE,
45219b2ee8SDavid du Colombier 	"echok", 	ECHOK,
46219b2ee8SDavid du Colombier 	"echonl",	ECHONL,
47219b2ee8SDavid du Colombier 	"icanon",	ICANON,
48219b2ee8SDavid du Colombier 	"iexten",	IEXTEN,
49219b2ee8SDavid du Colombier 	"isig",		ISIG,
50219b2ee8SDavid du Colombier 	"noflsh",	NOFLSH,
51219b2ee8SDavid du Colombier 	"tostop",	TOSTOP,
52219b2ee8SDavid du Colombier 	0
53219b2ee8SDavid du Colombier };
54219b2ee8SDavid du Colombier 
55219b2ee8SDavid du Colombier Mode cc[] =
56219b2ee8SDavid du Colombier {
57219b2ee8SDavid du Colombier 	"eof",		VEOF,
58219b2ee8SDavid du Colombier 	"eol",		VEOL,
59219b2ee8SDavid du Colombier 	"erase",	VERASE,
60219b2ee8SDavid du Colombier 	"intr",		VINTR,
61219b2ee8SDavid du Colombier 	"kill",		VKILL,
62219b2ee8SDavid du Colombier 	"min",		VMIN,
63219b2ee8SDavid du Colombier 	"quit",		VQUIT,
64219b2ee8SDavid du Colombier 	"susp",		VSUSP,
65219b2ee8SDavid du Colombier 	"time",		VTIME,
66219b2ee8SDavid du Colombier 	"start",	VSTART,
67219b2ee8SDavid du Colombier 	"stop",		VSTOP,
68219b2ee8SDavid du Colombier 	0,
69219b2ee8SDavid du Colombier };
70219b2ee8SDavid du Colombier 
71219b2ee8SDavid du Colombier int	getmode(int, Termios*);
72219b2ee8SDavid du Colombier int	setmode(int, Termios*);
73219b2ee8SDavid du Colombier 
74219b2ee8SDavid du Colombier char*
ctlchar(char c)75219b2ee8SDavid du Colombier ctlchar(char c)
76219b2ee8SDavid du Colombier {
77219b2ee8SDavid du Colombier 	static char buf[10];
78219b2ee8SDavid du Colombier 
79219b2ee8SDavid du Colombier 	if(c == 0x7f)
80219b2ee8SDavid du Colombier 		return "DEL";
81219b2ee8SDavid du Colombier 	if(c == 0)
82219b2ee8SDavid du Colombier 		return "NUL";
83219b2ee8SDavid du Colombier 	if(c < 32) {
84219b2ee8SDavid du Colombier 		buf[0] = '^';
85219b2ee8SDavid du Colombier 		buf[1] = '@'+c;
86219b2ee8SDavid du Colombier 		buf[2] = '\0';
87219b2ee8SDavid du Colombier 		return buf;
88219b2ee8SDavid du Colombier 	}
89219b2ee8SDavid du Colombier 	buf[0] = c;
90219b2ee8SDavid du Colombier 	buf[1] = '\0';
91219b2ee8SDavid du Colombier 	return buf;
92219b2ee8SDavid du Colombier }
93219b2ee8SDavid du Colombier 
94219b2ee8SDavid du Colombier void
showmode(Termios * t)95219b2ee8SDavid du Colombier showmode(Termios *t)
96219b2ee8SDavid du Colombier {
97219b2ee8SDavid du Colombier 	int i;
98219b2ee8SDavid du Colombier 
99219b2ee8SDavid du Colombier 	for(i = 0; cc[i].name; i++) {
100219b2ee8SDavid du Colombier 		switch(cc[i].bit) {
101219b2ee8SDavid du Colombier 		case VMIN:
102219b2ee8SDavid du Colombier 		case VTIME:
103219b2ee8SDavid du Colombier 			if(t->cc[i] != 0)
104219b2ee8SDavid du Colombier 				print("%s %d ", cc[i].name, t->cc[i]);
105219b2ee8SDavid du Colombier 			break;
106219b2ee8SDavid du Colombier 		default:
107219b2ee8SDavid du Colombier 			print("%s %s ", cc[i].name, ctlchar(t->cc[i]));
108219b2ee8SDavid du Colombier 			break;
109219b2ee8SDavid du Colombier 		}
110219b2ee8SDavid du Colombier 	}
111219b2ee8SDavid du Colombier 	print("\n");
112219b2ee8SDavid du Colombier 
113219b2ee8SDavid du Colombier 	for(i = 0; ou[i].name; i++)
114219b2ee8SDavid du Colombier 		if(ou[i].bit & t->oflag)
115219b2ee8SDavid du Colombier 			print("%s ", ou[i].name);
116219b2ee8SDavid du Colombier 
117219b2ee8SDavid du Colombier 	for(i = 0; in[i].name; i++)
118219b2ee8SDavid du Colombier 		if(in[i].bit & t->iflag)
119219b2ee8SDavid du Colombier 			print("%s ", in[i].name);
120219b2ee8SDavid du Colombier 
121219b2ee8SDavid du Colombier 	print("\n");
122219b2ee8SDavid du Colombier 	for(i = 0; lo[i].name; i++)
123219b2ee8SDavid du Colombier 		if(lo[i].bit & t->lflag)
124219b2ee8SDavid du Colombier 			print("%s ", lo[i].name);
125219b2ee8SDavid du Colombier 	print("\n");
126219b2ee8SDavid du Colombier }
127219b2ee8SDavid du Colombier 
128219b2ee8SDavid du Colombier int
setreset(char * mode,int * bits,Mode * t)129219b2ee8SDavid du Colombier setreset(char *mode, int *bits, Mode *t)
130219b2ee8SDavid du Colombier {
131219b2ee8SDavid du Colombier 	int i, clr;
132219b2ee8SDavid du Colombier 
133219b2ee8SDavid du Colombier 	clr = 0;
134219b2ee8SDavid du Colombier 	if(mode[0] == '-') {
135219b2ee8SDavid du Colombier 		mode++;
136219b2ee8SDavid du Colombier 		clr = 1;
137219b2ee8SDavid du Colombier 	}
138219b2ee8SDavid du Colombier 	for(i = 0; t[i].name; i++) {
139219b2ee8SDavid du Colombier 		if(strcmp(mode, t[i].name) == 0) {
140219b2ee8SDavid du Colombier 			if(clr)
141219b2ee8SDavid du Colombier 				*bits &= ~t[i].bit;
142219b2ee8SDavid du Colombier 			else
143219b2ee8SDavid du Colombier 				*bits |= t[i].bit;
144219b2ee8SDavid du Colombier 
145219b2ee8SDavid du Colombier 			return 1;
146219b2ee8SDavid du Colombier 		}
147219b2ee8SDavid du Colombier 	}
148219b2ee8SDavid du Colombier 	return 0;
149219b2ee8SDavid du Colombier }
150219b2ee8SDavid du Colombier 
151219b2ee8SDavid du Colombier int
ccname(char * name)152219b2ee8SDavid du Colombier ccname(char *name)
153219b2ee8SDavid du Colombier {
154219b2ee8SDavid du Colombier 	int i;
155219b2ee8SDavid du Colombier 
156219b2ee8SDavid du Colombier 	for(i = 0; cc[i].name; i++)
157219b2ee8SDavid du Colombier 		if(strcmp(cc[i].name, name) == 0)
158219b2ee8SDavid du Colombier 			return i;
159219b2ee8SDavid du Colombier 
160219b2ee8SDavid du Colombier 	return -1;
161219b2ee8SDavid du Colombier }
162219b2ee8SDavid du Colombier 
163219b2ee8SDavid du Colombier void
main(int argc,char ** argv)164219b2ee8SDavid du Colombier main(int argc, char **argv)
165219b2ee8SDavid du Colombier {
166219b2ee8SDavid du Colombier 	Termios t;
167219b2ee8SDavid du Colombier 	int i, stdin, wmo, cc;
168219b2ee8SDavid du Colombier 
169219b2ee8SDavid du Colombier 	/* Try and get a seek pointer */
170219b2ee8SDavid du Colombier 	stdin = open("/fd/0", ORDWR);
171219b2ee8SDavid du Colombier 	if(stdin < 0)
172219b2ee8SDavid du Colombier 		stdin = 0;
173219b2ee8SDavid du Colombier 
174219b2ee8SDavid du Colombier 	if(getmode(stdin, &t) < 0) {
175219b2ee8SDavid du Colombier 		fprint(2, "stty: tiocget %r\n");
176219b2ee8SDavid du Colombier 		exits("1");
177219b2ee8SDavid du Colombier 	}
178219b2ee8SDavid du Colombier 
179219b2ee8SDavid du Colombier 	if(argc < 2) {
180219b2ee8SDavid du Colombier 		fprint(2, "usage: stty [-a|-g] modes...\n");
181219b2ee8SDavid du Colombier 		exits("1");
182219b2ee8SDavid du Colombier 	}
183219b2ee8SDavid du Colombier 	wmo = 0;
184219b2ee8SDavid du Colombier 	for(i = 1; i < argc; i++) {
185219b2ee8SDavid du Colombier 		if(strcmp(argv[i], "-a") == 0) {
186219b2ee8SDavid du Colombier 			showmode(&t);
187219b2ee8SDavid du Colombier 			continue;
188219b2ee8SDavid du Colombier 		}
189219b2ee8SDavid du Colombier 		if(setreset(argv[i], &t.iflag, in)) {
190219b2ee8SDavid du Colombier 			wmo++;
191219b2ee8SDavid du Colombier 			continue;
192219b2ee8SDavid du Colombier 		}
193219b2ee8SDavid du Colombier 		if(setreset(argv[i], &t.lflag, lo)) {
194219b2ee8SDavid du Colombier 			wmo++;
195219b2ee8SDavid du Colombier 			continue;
196219b2ee8SDavid du Colombier 		}
197219b2ee8SDavid du Colombier 		if(setreset(argv[i], &t.oflag, ou)) {
198219b2ee8SDavid du Colombier 			wmo++;
199219b2ee8SDavid du Colombier 			continue;
200219b2ee8SDavid du Colombier 		}
201219b2ee8SDavid du Colombier 		cc = ccname(argv[i]);
202219b2ee8SDavid du Colombier 		if(cc != -1 && i+1 < argc) {
203219b2ee8SDavid du Colombier 			wmo++;
204219b2ee8SDavid du Colombier 			t.cc[cc] = argv[++i][0];
205219b2ee8SDavid du Colombier 			continue;
206219b2ee8SDavid du Colombier 		}
207219b2ee8SDavid du Colombier 		fprint(2, "stty: bad option/mode %s\n", argv[i]);
208219b2ee8SDavid du Colombier 		exits("1");
209219b2ee8SDavid du Colombier 	}
210219b2ee8SDavid du Colombier 
211219b2ee8SDavid du Colombier 	if(wmo) {
212219b2ee8SDavid du Colombier 		if(setmode(stdin, &t) < 0) {
213219b2ee8SDavid du Colombier 			fprint(2, "stty: cant set mode %r\n");
214219b2ee8SDavid du Colombier 			exits("1");
215219b2ee8SDavid du Colombier 		}
216219b2ee8SDavid du Colombier 	}
217219b2ee8SDavid du Colombier 
218219b2ee8SDavid du Colombier 	exits(0);
219219b2ee8SDavid du Colombier }
220219b2ee8SDavid du Colombier 
221219b2ee8SDavid du Colombier int
setmode(int fd,Termios * t)222219b2ee8SDavid du Colombier setmode(int fd, Termios *t)
223219b2ee8SDavid du Colombier {
224219b2ee8SDavid du Colombier 	int n, i;
225219b2ee8SDavid du Colombier 	char buf[256];
226219b2ee8SDavid du Colombier 
227*7dd7cddfSDavid du Colombier 	n = sprint(buf, "IOW %4.4ux %4.4ux %4.4ux %4.4ux ",
228219b2ee8SDavid du Colombier 		t->iflag, t->oflag, t->cflag, t->lflag);
229219b2ee8SDavid du Colombier 	for(i = 0; i < NCCS; i++)
230219b2ee8SDavid du Colombier 		n += sprint(buf+n, "%2.2ux ", t->cc[i]);
231219b2ee8SDavid du Colombier 
232219b2ee8SDavid du Colombier 	if(seek(fd, -2, 0) != -2)
233219b2ee8SDavid du Colombier 		return -1;
234219b2ee8SDavid du Colombier 
235219b2ee8SDavid du Colombier 	n = write(fd, buf, n);
236219b2ee8SDavid du Colombier 	if(n < 0)
237219b2ee8SDavid du Colombier 		return -1;
238219b2ee8SDavid du Colombier 	return 0;
239219b2ee8SDavid du Colombier }
240219b2ee8SDavid du Colombier 
241219b2ee8SDavid du Colombier /*
242219b2ee8SDavid du Colombier  * Format is: IOR iiii oooo cccc llll xx xx xx xx ...
243219b2ee8SDavid du Colombier  */
244219b2ee8SDavid du Colombier int
getmode(int fd,Termios * t)245219b2ee8SDavid du Colombier getmode(int fd, Termios *t)
246219b2ee8SDavid du Colombier {
247219b2ee8SDavid du Colombier 	int n;
248219b2ee8SDavid du Colombier 	char buf[256];
249219b2ee8SDavid du Colombier 
250219b2ee8SDavid du Colombier 	if(seek(fd, -2, 0) != -2)
251219b2ee8SDavid du Colombier 		return -1;
252219b2ee8SDavid du Colombier 
253219b2ee8SDavid du Colombier 	n = read(fd, buf, 57);
254219b2ee8SDavid du Colombier 	if(n < 0)
255219b2ee8SDavid du Colombier 		return -1;
256219b2ee8SDavid du Colombier 
257219b2ee8SDavid du Colombier 	t->iflag = strtoul(buf+4, 0, 16);
258219b2ee8SDavid du Colombier 	t->oflag = strtoul(buf+9, 0, 16);
259219b2ee8SDavid du Colombier 	t->cflag = strtoul(buf+14, 0, 16);
260219b2ee8SDavid du Colombier 	t->lflag = strtoul(buf+19, 0, 16);
261219b2ee8SDavid du Colombier 
262219b2ee8SDavid du Colombier 	for(n = 0; n < NCCS; n++)
263219b2ee8SDavid du Colombier 		t->cc[n] = strtoul(buf+24+(n*3), 0, 16);
264219b2ee8SDavid du Colombier 
265219b2ee8SDavid du Colombier 	return 0;
266219b2ee8SDavid du Colombier }
267