]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/9src/stty.c
merge
[plan9front.git] / sys / src / ape / 9src / stty.c
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*
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
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
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
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
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
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
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 }