xref: /plan9/sys/src/ape/9src/stty.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include <u.h>
2*219b2ee8SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <tty.h>
4*219b2ee8SDavid du Colombier 
5*219b2ee8SDavid du Colombier typedef struct Mode Mode;
6*219b2ee8SDavid du Colombier struct Mode
7*219b2ee8SDavid du Colombier {
8*219b2ee8SDavid du Colombier 	char*	name;
9*219b2ee8SDavid du Colombier 	int	bit;
10*219b2ee8SDavid du Colombier };
11*219b2ee8SDavid du Colombier 
12*219b2ee8SDavid du Colombier Mode ou[] =
13*219b2ee8SDavid du Colombier {
14*219b2ee8SDavid du Colombier 	"opost",	OPOST,
15*219b2ee8SDavid du Colombier 	"olcuc",	OLCUC,
16*219b2ee8SDavid du Colombier 	"onlcr",	ONLCR,
17*219b2ee8SDavid du Colombier 	"ocrnl",	OCRNL,
18*219b2ee8SDavid du Colombier 	"onocr",	ONOCR,
19*219b2ee8SDavid du Colombier 	"onlret",	ONLRET,
20*219b2ee8SDavid du Colombier 	"ofill",	OFILL,
21*219b2ee8SDavid du Colombier 	"ofdel",	OFDEL,
22*219b2ee8SDavid du Colombier 	0
23*219b2ee8SDavid du Colombier };
24*219b2ee8SDavid du Colombier 
25*219b2ee8SDavid du Colombier Mode in[] =
26*219b2ee8SDavid du Colombier {
27*219b2ee8SDavid du Colombier 	"brkint",	BRKINT,
28*219b2ee8SDavid du Colombier 	"icrnl",	ICRNL,
29*219b2ee8SDavid du Colombier 	"ignbrk",	IGNBRK,
30*219b2ee8SDavid du Colombier 	"igncr",	IGNCR,
31*219b2ee8SDavid du Colombier 	"ignpar",	IGNPAR,
32*219b2ee8SDavid du Colombier 	"inlcr",	INLCR,
33*219b2ee8SDavid du Colombier 	"inpck",	INPCK,
34*219b2ee8SDavid du Colombier 	"istrip",	ISTRIP,
35*219b2ee8SDavid du Colombier 	"ixoff",	IXOFF,
36*219b2ee8SDavid du Colombier 	"ixon",		IXON,
37*219b2ee8SDavid du Colombier 	"parmrk",	PARMRK,
38*219b2ee8SDavid du Colombier 	0
39*219b2ee8SDavid du Colombier };
40*219b2ee8SDavid du Colombier 
41*219b2ee8SDavid du Colombier Mode lo[] =
42*219b2ee8SDavid du Colombier {
43*219b2ee8SDavid du Colombier 	"echo",		ECHO,
44*219b2ee8SDavid du Colombier 	"echoe",	ECHOE,
45*219b2ee8SDavid du Colombier 	"echok", 	ECHOK,
46*219b2ee8SDavid du Colombier 	"echonl",	ECHONL,
47*219b2ee8SDavid du Colombier 	"icanon",	ICANON,
48*219b2ee8SDavid du Colombier 	"iexten",	IEXTEN,
49*219b2ee8SDavid du Colombier 	"isig",		ISIG,
50*219b2ee8SDavid du Colombier 	"noflsh",	NOFLSH,
51*219b2ee8SDavid du Colombier 	"tostop",	TOSTOP,
52*219b2ee8SDavid du Colombier 	0
53*219b2ee8SDavid du Colombier };
54*219b2ee8SDavid du Colombier 
55*219b2ee8SDavid du Colombier Mode cc[] =
56*219b2ee8SDavid du Colombier {
57*219b2ee8SDavid du Colombier 	"eof",		VEOF,
58*219b2ee8SDavid du Colombier 	"eol",		VEOL,
59*219b2ee8SDavid du Colombier 	"erase",	VERASE,
60*219b2ee8SDavid du Colombier 	"intr",		VINTR,
61*219b2ee8SDavid du Colombier 	"kill",		VKILL,
62*219b2ee8SDavid du Colombier 	"min",		VMIN,
63*219b2ee8SDavid du Colombier 	"quit",		VQUIT,
64*219b2ee8SDavid du Colombier 	"susp",		VSUSP,
65*219b2ee8SDavid du Colombier 	"time",		VTIME,
66*219b2ee8SDavid du Colombier 	"start",	VSTART,
67*219b2ee8SDavid du Colombier 	"stop",		VSTOP,
68*219b2ee8SDavid du Colombier 	0,
69*219b2ee8SDavid du Colombier };
70*219b2ee8SDavid du Colombier 
71*219b2ee8SDavid du Colombier int	getmode(int, Termios*);
72*219b2ee8SDavid du Colombier int	setmode(int, Termios*);
73*219b2ee8SDavid du Colombier 
74*219b2ee8SDavid du Colombier char*
75*219b2ee8SDavid du Colombier ctlchar(char c)
76*219b2ee8SDavid du Colombier {
77*219b2ee8SDavid du Colombier 	static char buf[10];
78*219b2ee8SDavid du Colombier 
79*219b2ee8SDavid du Colombier 	if(c == 0x7f)
80*219b2ee8SDavid du Colombier 		return "DEL";
81*219b2ee8SDavid du Colombier 	if(c == 0)
82*219b2ee8SDavid du Colombier 		return "NUL";
83*219b2ee8SDavid du Colombier 	if(c < 32) {
84*219b2ee8SDavid du Colombier 		buf[0] = '^';
85*219b2ee8SDavid du Colombier 		buf[1] = '@'+c;
86*219b2ee8SDavid du Colombier 		buf[2] = '\0';
87*219b2ee8SDavid du Colombier 		return buf;
88*219b2ee8SDavid du Colombier 	}
89*219b2ee8SDavid du Colombier 	buf[0] = c;
90*219b2ee8SDavid du Colombier 	buf[1] = '\0';
91*219b2ee8SDavid du Colombier 	return buf;
92*219b2ee8SDavid du Colombier }
93*219b2ee8SDavid du Colombier 
94*219b2ee8SDavid du Colombier void
95*219b2ee8SDavid du Colombier showmode(Termios *t)
96*219b2ee8SDavid du Colombier {
97*219b2ee8SDavid du Colombier 	int i;
98*219b2ee8SDavid du Colombier 
99*219b2ee8SDavid du Colombier 	for(i = 0; cc[i].name; i++) {
100*219b2ee8SDavid du Colombier 		switch(cc[i].bit) {
101*219b2ee8SDavid du Colombier 		case VMIN:
102*219b2ee8SDavid du Colombier 		case VTIME:
103*219b2ee8SDavid du Colombier 			if(t->cc[i] != 0)
104*219b2ee8SDavid du Colombier 				print("%s %d ", cc[i].name, t->cc[i]);
105*219b2ee8SDavid du Colombier 			break;
106*219b2ee8SDavid du Colombier 		default:
107*219b2ee8SDavid du Colombier 			print("%s %s ", cc[i].name, ctlchar(t->cc[i]));
108*219b2ee8SDavid du Colombier 			break;
109*219b2ee8SDavid du Colombier 		}
110*219b2ee8SDavid du Colombier 	}
111*219b2ee8SDavid du Colombier 	print("\n");
112*219b2ee8SDavid du Colombier 
113*219b2ee8SDavid du Colombier 	for(i = 0; ou[i].name; i++)
114*219b2ee8SDavid du Colombier 		if(ou[i].bit & t->oflag)
115*219b2ee8SDavid du Colombier 			print("%s ", ou[i].name);
116*219b2ee8SDavid du Colombier 
117*219b2ee8SDavid du Colombier 	for(i = 0; in[i].name; i++)
118*219b2ee8SDavid du Colombier 		if(in[i].bit & t->iflag)
119*219b2ee8SDavid du Colombier 			print("%s ", in[i].name);
120*219b2ee8SDavid du Colombier 
121*219b2ee8SDavid du Colombier 	print("\n");
122*219b2ee8SDavid du Colombier 	for(i = 0; lo[i].name; i++)
123*219b2ee8SDavid du Colombier 		if(lo[i].bit & t->lflag)
124*219b2ee8SDavid du Colombier 			print("%s ", lo[i].name);
125*219b2ee8SDavid du Colombier 	print("\n");
126*219b2ee8SDavid du Colombier }
127*219b2ee8SDavid du Colombier 
128*219b2ee8SDavid du Colombier int
129*219b2ee8SDavid du Colombier setreset(char *mode, int *bits, Mode *t)
130*219b2ee8SDavid du Colombier {
131*219b2ee8SDavid du Colombier 	int i, clr;
132*219b2ee8SDavid du Colombier 
133*219b2ee8SDavid du Colombier 	clr = 0;
134*219b2ee8SDavid du Colombier 	if(mode[0] == '-') {
135*219b2ee8SDavid du Colombier 		mode++;
136*219b2ee8SDavid du Colombier 		clr = 1;
137*219b2ee8SDavid du Colombier 	}
138*219b2ee8SDavid du Colombier 	for(i = 0; t[i].name; i++) {
139*219b2ee8SDavid du Colombier 		if(strcmp(mode, t[i].name) == 0) {
140*219b2ee8SDavid du Colombier 			if(clr)
141*219b2ee8SDavid du Colombier 				*bits &= ~t[i].bit;
142*219b2ee8SDavid du Colombier 			else
143*219b2ee8SDavid du Colombier 				*bits |= t[i].bit;
144*219b2ee8SDavid du Colombier 
145*219b2ee8SDavid du Colombier 			return 1;
146*219b2ee8SDavid du Colombier 		}
147*219b2ee8SDavid du Colombier 	}
148*219b2ee8SDavid du Colombier 	return 0;
149*219b2ee8SDavid du Colombier }
150*219b2ee8SDavid du Colombier 
151*219b2ee8SDavid du Colombier int
152*219b2ee8SDavid du Colombier ccname(char *name)
153*219b2ee8SDavid du Colombier {
154*219b2ee8SDavid du Colombier 	int i;
155*219b2ee8SDavid du Colombier 
156*219b2ee8SDavid du Colombier 	for(i = 0; cc[i].name; i++)
157*219b2ee8SDavid du Colombier 		if(strcmp(cc[i].name, name) == 0)
158*219b2ee8SDavid du Colombier 			return i;
159*219b2ee8SDavid du Colombier 
160*219b2ee8SDavid du Colombier 	return -1;
161*219b2ee8SDavid du Colombier }
162*219b2ee8SDavid du Colombier 
163*219b2ee8SDavid du Colombier void
164*219b2ee8SDavid du Colombier main(int argc, char **argv)
165*219b2ee8SDavid du Colombier {
166*219b2ee8SDavid du Colombier 	Termios t;
167*219b2ee8SDavid du Colombier 	int i, stdin, wmo, cc;
168*219b2ee8SDavid du Colombier 
169*219b2ee8SDavid du Colombier 	/* Try and get a seek pointer */
170*219b2ee8SDavid du Colombier 	stdin = open("/fd/0", ORDWR);
171*219b2ee8SDavid du Colombier 	if(stdin < 0)
172*219b2ee8SDavid du Colombier 		stdin = 0;
173*219b2ee8SDavid du Colombier 
174*219b2ee8SDavid du Colombier 	if(getmode(stdin, &t) < 0) {
175*219b2ee8SDavid du Colombier 		fprint(2, "stty: tiocget %r\n");
176*219b2ee8SDavid du Colombier 		exits("1");
177*219b2ee8SDavid du Colombier 	}
178*219b2ee8SDavid du Colombier 
179*219b2ee8SDavid du Colombier 	if(argc < 2) {
180*219b2ee8SDavid du Colombier 		fprint(2, "usage: stty [-a|-g] modes...\n");
181*219b2ee8SDavid du Colombier 		exits("1");
182*219b2ee8SDavid du Colombier 	}
183*219b2ee8SDavid du Colombier 	wmo = 0;
184*219b2ee8SDavid du Colombier 	for(i = 1; i < argc; i++) {
185*219b2ee8SDavid du Colombier 		if(strcmp(argv[i], "-a") == 0) {
186*219b2ee8SDavid du Colombier 			showmode(&t);
187*219b2ee8SDavid du Colombier 			continue;
188*219b2ee8SDavid du Colombier 		}
189*219b2ee8SDavid du Colombier 		if(setreset(argv[i], &t.iflag, in)) {
190*219b2ee8SDavid du Colombier 			wmo++;
191*219b2ee8SDavid du Colombier 			continue;
192*219b2ee8SDavid du Colombier 		}
193*219b2ee8SDavid du Colombier 		if(setreset(argv[i], &t.lflag, lo)) {
194*219b2ee8SDavid du Colombier 			wmo++;
195*219b2ee8SDavid du Colombier 			continue;
196*219b2ee8SDavid du Colombier 		}
197*219b2ee8SDavid du Colombier 		if(setreset(argv[i], &t.oflag, ou)) {
198*219b2ee8SDavid du Colombier 			wmo++;
199*219b2ee8SDavid du Colombier 			continue;
200*219b2ee8SDavid du Colombier 		}
201*219b2ee8SDavid du Colombier 		cc = ccname(argv[i]);
202*219b2ee8SDavid du Colombier 		if(cc != -1 && i+1 < argc) {
203*219b2ee8SDavid du Colombier 			wmo++;
204*219b2ee8SDavid du Colombier 			t.cc[cc] = argv[++i][0];
205*219b2ee8SDavid du Colombier 			continue;
206*219b2ee8SDavid du Colombier 		}
207*219b2ee8SDavid du Colombier 		fprint(2, "stty: bad option/mode %s\n", argv[i]);
208*219b2ee8SDavid du Colombier 		exits("1");
209*219b2ee8SDavid du Colombier 	}
210*219b2ee8SDavid du Colombier 
211*219b2ee8SDavid du Colombier 	if(wmo) {
212*219b2ee8SDavid du Colombier 		if(setmode(stdin, &t) < 0) {
213*219b2ee8SDavid du Colombier 			fprint(2, "stty: cant set mode %r\n");
214*219b2ee8SDavid du Colombier 			exits("1");
215*219b2ee8SDavid du Colombier 		}
216*219b2ee8SDavid du Colombier 	}
217*219b2ee8SDavid du Colombier 
218*219b2ee8SDavid du Colombier 	exits(0);
219*219b2ee8SDavid du Colombier }
220*219b2ee8SDavid du Colombier 
221*219b2ee8SDavid du Colombier int
222*219b2ee8SDavid du Colombier setmode(int fd, Termios *t)
223*219b2ee8SDavid du Colombier {
224*219b2ee8SDavid du Colombier 	int n, i;
225*219b2ee8SDavid du Colombier 	char buf[256];
226*219b2ee8SDavid du Colombier 
227*219b2ee8SDavid du Colombier 	n = sprint(buf, "IOW %4.4lux %4.4lux %4.4lux %4.4lux ",
228*219b2ee8SDavid du Colombier 		t->iflag, t->oflag, t->cflag, t->lflag);
229*219b2ee8SDavid du Colombier 	for(i = 0; i < NCCS; i++)
230*219b2ee8SDavid du Colombier 		n += sprint(buf+n, "%2.2ux ", t->cc[i]);
231*219b2ee8SDavid du Colombier 
232*219b2ee8SDavid du Colombier 	if(seek(fd, -2, 0) != -2)
233*219b2ee8SDavid du Colombier 		return -1;
234*219b2ee8SDavid du Colombier 
235*219b2ee8SDavid du Colombier 	n = write(fd, buf, n);
236*219b2ee8SDavid du Colombier 	if(n < 0)
237*219b2ee8SDavid du Colombier 		return -1;
238*219b2ee8SDavid du Colombier 	return 0;
239*219b2ee8SDavid du Colombier }
240*219b2ee8SDavid du Colombier 
241*219b2ee8SDavid du Colombier /*
242*219b2ee8SDavid du Colombier  * Format is: IOR iiii oooo cccc llll xx xx xx xx ...
243*219b2ee8SDavid du Colombier  */
244*219b2ee8SDavid du Colombier int
245*219b2ee8SDavid du Colombier getmode(int fd, Termios *t)
246*219b2ee8SDavid du Colombier {
247*219b2ee8SDavid du Colombier 	int n;
248*219b2ee8SDavid du Colombier 	char buf[256];
249*219b2ee8SDavid du Colombier 
250*219b2ee8SDavid du Colombier 	if(seek(fd, -2, 0) != -2)
251*219b2ee8SDavid du Colombier 		return -1;
252*219b2ee8SDavid du Colombier 
253*219b2ee8SDavid du Colombier 	n = read(fd, buf, 57);
254*219b2ee8SDavid du Colombier 	if(n < 0)
255*219b2ee8SDavid du Colombier 		return -1;
256*219b2ee8SDavid du Colombier 
257*219b2ee8SDavid du Colombier 	t->iflag = strtoul(buf+4, 0, 16);
258*219b2ee8SDavid du Colombier 	t->oflag = strtoul(buf+9, 0, 16);
259*219b2ee8SDavid du Colombier 	t->cflag = strtoul(buf+14, 0, 16);
260*219b2ee8SDavid du Colombier 	t->lflag = strtoul(buf+19, 0, 16);
261*219b2ee8SDavid du Colombier 
262*219b2ee8SDavid du Colombier 	for(n = 0; n < NCCS; n++)
263*219b2ee8SDavid du Colombier 		t->cc[n] = strtoul(buf+24+(n*3), 0, 16);
264*219b2ee8SDavid du Colombier 
265*219b2ee8SDavid du Colombier 	return 0;
266*219b2ee8SDavid du Colombier }
267