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