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