1 /*
2 * stty - set the options for a terminal
3 *
4 * Gunnar Ritter, Freiburg i. Br., Germany, May 2003.
5 */
6 /*
7 * Copyright (c) 2003 Gunnar Ritter
8 *
9 * This software is provided 'as-is', without any express or implied
10 * warranty. In no event will the authors be held liable for any damages
11 * arising from the use of this software.
12 *
13 * Permission is granted to anyone to use this software for any purpose,
14 * including commercial applications, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
16 *
17 * 1. The origin of this software must not be misrepresented; you must not
18 * claim that you wrote the original software. If you use this software
19 * in a product, an acknowledgment in the product documentation would be
20 * appreciated but is not required.
21 *
22 * 2. Altered source versions must be plainly marked as such, and must not be
23 * misrepresented as being the original software.
24 *
25 * 3. This notice may not be removed or altered from any source distribution.
26 */
27
28 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
29 #define USED __attribute__ ((used))
30 #elif defined __GNUC__
31 #define USED __attribute__ ((unused))
32 #else
33 #define USED
34 #endif
35 #ifndef UCB
36 static const char sccsid[] USED = "@(#)stty.sl 1.23 (gritter) 1/22/06";
37 #else /* UCB */
38 static const char sccsid[] USED = "@(#)/usr/ucb/stty.sl 1.23 (gritter) 1/22/06";
39 #endif /* UCB */
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <termios.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <libgen.h>
51 #include <ctype.h>
52 #include <locale.h>
53 #include <pathconf.h>
54 #ifndef TIOCGWINSZ
55 #include <sys/ioctl.h>
56 #endif
57
58 #ifndef VSWTCH
59 #ifdef VSWTC
60 #define VSWTCH VSWTC
61 #endif
62 #endif
63
64 #ifdef TABDLY
65 static void tabs(int);
66 #endif
67 static void evenp(int);
68 static void oddp(int);
69 static void spacep(int);
70 static void markp(int);
71 static void raw(int);
72 static void cooked(int);
73 static void nl(int);
74 static void sane(int);
75 #ifdef OFDEL
76 static void fill(int);
77 #endif
78 #ifdef XCASE
79 static void lcase(int);
80 #endif
81 static void ek(int);
82 #if 0
83 static void tty33(int);
84 static void tty37(int);
85 static void vt05(int);
86 static void tn300(int);
87 static void ti700(int);
88 static void tek(int);
89 #endif
90 static void rows(int);
91 static void columns(int);
92 static void ypixels(int);
93 static void xpixels(int);
94 static void vmin(int);
95 static void vtime(int);
96 static void line(int);
97 #ifdef UCB
98 static void litout(int);
99 static void pass8(int);
100 static void crt(int);
101 static void dec(int);
102 #endif /* UCB */
103
104 static const struct mode {
105 const char *m_name; /* name of mode */
106 void (*m_func)(int); /* handler function */
107 long m_val; /* flag value */
108 long m_dfl; /* default (not sane!) value */
109 int m_flg; /* print flags:
110 01 print regardless of difference
111 02 print only if -a is not set
112 04 print only if -a is set
113 010 print under all circumstances
114 020 print only if equal
115 040 ignore for printing
116 0100 ignore for setting
117 0200 use m_dfl as mask
118 0400 print only if equal even if -a
119 01000 negate for setting
120 */
121 enum {
122 M_SEPAR, /* separator */
123 M_NSEPAR, /* new separator */
124 M_IFLAG, /* in c_iflag */
125 M_OFLAG, /* in c_oflag */
126 M_CFLAG, /* in c_cflag */
127 M_PCFLAG, /* in c_cflag, but printed w/o -a */
128 M_LFLAG, /* in c_lflag */
129 M_CC, /* in c_cc */
130 M_FUNCT, /* handled via function */
131 M_INVAL /* invalid */
132 } m_type;
133 } modes[] = {
134 { "oddp", 0, PARENB|PARODD,PARENB|PARODD,0122, M_PCFLAG },
135 { "evenp", 0, PARENB|PARODD,PARENB, 0122, M_PCFLAG },
136 { "parity", 0, PARENB, 0, 0122, M_PCFLAG },
137 { "cstopb", 0, CSTOPB, 0, 02, M_PCFLAG },
138 { "hupcl", 0, HUPCL, 0, 02, M_PCFLAG },
139 { "cread", 0, CREAD, CREAD, 02, M_PCFLAG },
140 { "clocal", 0, CLOCAL, 0, 02, M_PCFLAG },
141 { "intr", 0, VINTR, '\177', 0, M_CC },
142 { "quit", 0, VQUIT, '\34', 0, M_CC },
143 { "erase", 0, VERASE, '#', 0, M_CC },
144 { "kill", 0, VKILL, '@', 0, M_CC },
145 { "\n", 0, 0, 0, 04, M_NSEPAR },
146 { "eof", 0, VEOF, '\4', 0, M_CC },
147 { "eol", 0, VEOL, '\0', 0, M_CC },
148 { "eol2", 0, VEOL2, '\0', 0, M_CC },
149 #ifdef VSWTCH
150 { "swtch", 0, VSWTCH, '\32', 0, M_CC },
151 #endif
152 { "\n", 0, 0, 0, 04, M_NSEPAR },
153 { "start", 0, VSTART, '\21', 0, M_CC },
154 { "stop", 0, VSTOP, '\23', 0, M_CC },
155 { "susp", 0, VSUSP, '\32', 0, M_CC },
156 #ifdef VDSUSP
157 { "dsusp", 0, VDSUSP, '\31', 0, M_CC },
158 #else
159 { "dsusp", 0, -1, '\0', 0, M_CC },
160 #endif
161 { "\n", 0, 0, 0, 04, M_NSEPAR },
162 #ifdef VREPRINT
163 { "rprnt", 0, VREPRINT,'\22', 0, M_CC },
164 #else
165 { "rprnt", 0, -1, '\0', 0, M_CC },
166 #endif
167 #ifdef VDISCARD
168 { "flush", 0, VDISCARD,'\17', 0, M_CC },
169 #else
170 { "flush", 0, -1, '\0', 0, M_CC },
171 #endif
172 #ifdef VWERASE
173 { "werase", 0, VWERASE,'\27', 0, M_CC },
174 #else
175 { "werase", 0, -1, '\0', 0, M_CC },
176 #endif
177 { "lnext", 0, VLNEXT, '\26', 0, M_CC },
178 { "\n", 0, 0, 0, 010, M_SEPAR },
179 { "parenb", 0, PARENB, 0, 04, M_CFLAG },
180 { "parodd", 0, PARODD, 0, 04, M_CFLAG },
181 { "cs5", 0, CS5, CSIZE, 0604, M_CFLAG },
182 { "cs6", 0, CS6, CSIZE, 0604, M_CFLAG },
183 { "cs7", 0, CS7, CSIZE, 0604, M_CFLAG },
184 { "cs8", 0, CS8, CSIZE, 0604, M_CFLAG },
185 { "cstopb", 0, CSTOPB, 0, 04, M_CFLAG },
186 { "hupcl", 0, HUPCL, 0, 04, M_CFLAG },
187 { "hup", 0, HUPCL, 0, 040, M_CFLAG },
188 { "cread", 0, CREAD, CREAD, 04, M_CFLAG },
189 { "clocal", 0, CLOCAL, 0, 04, M_CFLAG },
190 #ifdef LOBLK
191 { "loblk", 0, LOBLK, 0, 04, M_CFLAG },
192 #else
193 { "loblk", 0, 0, 0, 04, M_INVAL },
194 #endif
195 #ifdef PAREXT
196 { "parext", 0, PAREXT, 0, 04, M_CFLAG },
197 #else
198 { "parext", 0, 0, 0, 04, M_INVAL },
199 #endif
200 { "\n", 0, 0, 0, 04, M_SEPAR },
201 { "ignbrk", 0, IGNBRK, 0, 0, M_IFLAG },
202 { "brkint", 0, BRKINT, 0, 04, M_IFLAG },
203 #ifndef UCB
204 { "brkint", 0,IGNBRK|BRKINT,BRKINT, 0122, M_IFLAG },
205 #else /* UCB */
206 { "brkint", 0, 0, BRKINT, 0122, M_IFLAG },
207 #endif /* UCB */
208 { "ignpar", 0, IGNPAR, IGNPAR, 04, M_IFLAG },
209 { "inpck", 0, INPCK, INPCK, 0102, M_IFLAG },
210 { "ignpar", 0,INPCK|IGNPAR, IGNPAR, 0102, M_IFLAG },
211 { "parmrk", 0, PARMRK, 0, 0, M_IFLAG },
212 { "inpck", 0, INPCK, INPCK, 04, M_IFLAG },
213 { "istrip", 0, ISTRIP, ISTRIP, 0, M_IFLAG },
214 { "inlcr", 0, INLCR, 0, 0, M_IFLAG },
215 { "igncr", 0, IGNCR, 0, 0, M_IFLAG },
216 #ifndef UCB
217 { "icrnl", 0, ICRNL, 0, 0, M_IFLAG },
218 #else /* UCB */
219 { "icrnl", 0, ICRNL, ICRNL, 0, M_IFLAG },
220 #endif /* UCB */
221 #ifdef IUCLC
222 { "iuclc", 0, IUCLC, 0, 0, M_IFLAG },
223 #endif
224 { "\n", 0, 0, 0, 04, M_SEPAR },
225 { "ixon", 0, IXON, IXON, 04, M_IFLAG },
226 #ifndef UCB
227 { "ixany", 0, IXANY, IXANY, 04, M_IFLAG },
228 #else /* UCB */
229 { "ixany", 0, IXANY, 0, 0, M_IFLAG },
230 { "decctlq", 0, IXANY, 0, 01040, M_IFLAG },
231 #endif /* UCB */
232 { "ixon", 0, 0, IXON, 0302, M_IFLAG },
233 { "ixoff", 0, IXOFF, 0, 0, M_IFLAG },
234 #ifdef UCB
235 { "tandem", 0, IXOFF, 0, 040, M_IFLAG },
236 #endif /* UCB */
237 { "imaxbel", 0, IMAXBEL,0, 0, M_IFLAG },
238 #ifdef IUTF8
239 { "iutf8", 0, IUTF8, 0, 0, M_IFLAG },
240 #endif
241 { "\n", 0, 0, 0, 04, M_SEPAR },
242 { "isig", 0, ISIG, ISIG, 04, M_LFLAG },
243 { "icanon", 0, ICANON, ICANON, 04, M_LFLAG },
244 { "cbreak", 0, ICANON, 0, 01040, M_LFLAG },
245 #ifdef XCASE
246 { "xcase", 0, XCASE, 0, 04, M_LFLAG },
247 #endif
248 { "opost", 0, OPOST, OPOST, 0102, M_OFLAG },
249 #ifdef OLCUC
250 { "olcuc", 0, OLCUC, 0, 0102, M_OFLAG },
251 #endif
252 #ifndef UCB
253 { "onlcr", 0, ONLCR, 0, 0102, M_OFLAG },
254 #else /* UCB */
255 { "onlcr", 0, ONLCR, ONLCR, 0102, M_OFLAG },
256 #endif /* UCB */
257 { "ocrnl", 0, OCRNL, 0, 0102, M_OFLAG },
258 { "onocr", 0, ONOCR, 0, 0102, M_OFLAG },
259 { "onlret", 0, ONLRET, 0, 0102, M_OFLAG },
260 #if defined (OFILL) && defined (OFDEL)
261 { "nul-fill", 0, OFILL,OFILL|OFDEL,0202, M_OFLAG },
262 { "del-fill", 0,OFILL|OFDEL,OFILL|OFDEL,0202, M_OFLAG },
263 #endif
264 #ifdef TAB1
265 { "tab1", 0, TAB1, TABDLY, 0302, M_OFLAG },
266 #endif
267 #ifdef TAB2
268 { "tab2", 0, TAB2, TABDLY, 0302, M_OFLAG },
269 #endif
270 #ifdef TAB3
271 { "tab3", 0, TAB3, TABDLY, 0302, M_OFLAG },
272 #endif
273 { "\n", 0, 0, 0, 02, M_SEPAR },
274 { "isig", 0, ISIG, ISIG, 0102, M_LFLAG },
275 { "icanon", 0, ICANON, ICANON, 0102, M_LFLAG },
276 #ifdef XCASE
277 { "xcase", 0, XCASE, 0, 0102, M_LFLAG },
278 #endif
279 #ifndef UCB
280 { "echo", 0, ECHO, ECHO, 01, M_LFLAG },
281 { "echoe", 0, ECHOE, ECHOE, 01, M_LFLAG },
282 { "echok", 0, ECHOK, ECHOK, 01, M_LFLAG },
283 #else /* UCB */
284 { "echo", 0, ECHO, ECHO, 0, M_LFLAG },
285 { "echoe", 0, ECHOE, ECHOE, 04, M_LFLAG },
286 { "crterase", 0, ECHOE, 0, 040, M_LFLAG },
287 { "echok", 0, ECHOK, ECHOK, 0, M_LFLAG },
288 { "lfkc", 0, ECHOK, 0, 040, M_LFLAG },
289 { "echoe", 0,ECHOE|ECHOKE, ECHOE, 0122, M_LFLAG },
290 { "-echoke", 0,ECHOE|ECHOKE, ECHOE, 0122, M_LFLAG },
291 { "echoprt", 0,ECHOE|ECHOPRT,0, 0122, M_LFLAG },
292 { "crt", 0,ECHOE|ECHOKE,ECHOE|ECHOKE,0302,M_LFLAG },
293 #endif /* UCB */
294 { "lfkc", 0, ECHOK, 0, 040, M_LFLAG },
295 { "echonl", 0, ECHONL, 0, 0, M_LFLAG },
296 { "noflsh", 0, NOFLSH, 0, 0, M_LFLAG },
297 { "\n", 0, 0, 0, 04, M_NSEPAR },
298 { "tostop", 0, TOSTOP, 0, 0, M_LFLAG },
299 #ifndef UCB
300 { "echoctl", 0, ECHOCTL,0, 0, M_LFLAG },
301 #else /* UCB */
302 { "echoctl", 0, ECHOCTL,ECHOCTL,0, M_LFLAG },
303 { "ctlecho", 0, ECHOCTL,0, 040, M_LFLAG },
304 { "prterase", 0, ECHOPRT,0, 040, M_LFLAG },
305 #endif /* UCB */
306 { "echoprt", 0, ECHOPRT,0, 04, M_LFLAG },
307 #ifndef UCB
308 { "echoke", 0, ECHOKE, 0, 0, M_LFLAG },
309 #else /* UCB */
310 { "echoke", 0, ECHOKE, 0, 04, M_LFLAG },
311 { "crtkill", 0, ECHOKE, 0, 040, M_LFLAG },
312 #endif /* UCB */
313 { "defecho", 0, 0, 0, 0, M_INVAL },
314 { "flusho", 0, FLUSHO, 0, 0, M_LFLAG },
315 { "pendin", 0, PENDIN, 0, 0, M_LFLAG },
316 { "iexten", 0, IEXTEN, 0, 0, M_LFLAG },
317 { "\n", 0, 0, 0, 04, M_SEPAR },
318 { "opost", 0, OPOST, OPOST, 04, M_OFLAG },
319 #ifdef OLCUC
320 { "olcuc", 0, OLCUC, 0, 04, M_OFLAG },
321 #endif
322 { "onlcr", 0, ONLCR, 0, 04, M_OFLAG },
323 { "ocrnl", 0, OCRNL, 0, 04, M_OFLAG },
324 { "onocr", 0, ONOCR, 0, 04, M_OFLAG },
325 { "onlret", 0, ONLRET, 0, 04, M_OFLAG },
326 #ifdef OFILL
327 { "ofill", 0, OFILL, 0, 04, M_OFLAG },
328 #endif
329 #ifdef OFDEL
330 { "ofdel", 0, OFDEL, 0, 04, M_OFLAG },
331 #endif
332 #ifdef TAB1
333 { "tab1", 0, TAB1, TABDLY, 0704, M_OFLAG },
334 #endif
335 #ifdef TAB2
336 { "tab2", 0, TAB2, TABDLY, 0704, M_OFLAG },
337 #endif
338 #ifdef TAB3
339 { "tab3", 0, TAB3, TABDLY, 0704, M_OFLAG },
340 #endif
341 { "\n", 0, 0, 0, 04, M_SEPAR },
342 #ifdef NL0
343 { "nl0", 0, NL0, NLDLY, 0240, M_OFLAG },
344 #endif
345 #ifdef NL1
346 { "nl1", 0, NL1, NLDLY, 0240, M_OFLAG },
347 #endif
348 #ifdef CR0
349 { "cr0", 0, CR0, CRDLY, 0240, M_OFLAG },
350 #endif
351 #ifdef CR1
352 { "cr1", 0, CR1, CRDLY, 0240, M_OFLAG },
353 #endif
354 #ifdef CR2
355 { "cr2", 0, CR2, CRDLY, 0240, M_OFLAG },
356 #endif
357 #ifdef CR3
358 { "cr3", 0, CR3, CRDLY, 0240, M_OFLAG },
359 #endif
360 #ifdef TAB0
361 { "tab0", 0, TAB0, TABDLY, 0240, M_OFLAG },
362 #endif
363 #ifdef TAB1
364 { "tab1", 0, TAB1, TABDLY, 0240, M_OFLAG },
365 #endif
366 #ifdef TAB2
367 { "tab2", 0, TAB2, TABDLY, 0240, M_OFLAG },
368 #endif
369 #ifdef TAB3
370 { "tab3", 0, TAB3, TABDLY, 0240, M_OFLAG },
371 #endif
372 #ifdef TABDLY
373 { "tabs", tabs, 0, 0, 0240, M_FUNCT },
374 #endif
375 #ifdef BS0
376 { "bs0", 0, BS0, BSDLY, 0240, M_OFLAG },
377 #endif
378 #ifdef BS1
379 { "bs1", 0, BS1, BSDLY, 0240, M_OFLAG },
380 #endif
381 #ifdef FF0
382 { "ff0", 0, FF0, FFDLY, 0240, M_OFLAG },
383 #endif
384 #ifdef FF1
385 { "ff1", 0, FF1, FFDLY, 0240, M_OFLAG },
386 #endif
387 #ifdef VT0
388 { "vt0", 0, VT0, VTDLY, 0240, M_OFLAG },
389 #endif
390 #ifdef VT1
391 { "vt1", 0, VT1, VTDLY, 0240, M_OFLAG },
392 #endif
393 #ifdef CRTSCTS
394 { "ctsxon", 0, CRTSCTS,0, 040, M_OFLAG },
395 #endif /* CRTSCTS */
396 { "evenp", evenp, 0, 0, 040, M_FUNCT },
397 { "parity", evenp, 0, 0, 040, M_FUNCT },
398 { "oddp", oddp, 0, 0, 040, M_FUNCT },
399 { "spacep", spacep, 0, 0, 040, M_FUNCT },
400 { "markp", markp, 0, 0, 040, M_FUNCT },
401 { "raw", raw, 0, 0, 040, M_FUNCT },
402 { "cooked", cooked, 0, 0, 040, M_FUNCT },
403 { "nl", nl, 0, 0, 040, M_FUNCT },
404 #ifdef XCASE
405 { "lcase", lcase, 0, 0, 040, M_FUNCT },
406 { "LCASE", lcase, 0, 0, 040, M_FUNCT },
407 #endif
408 { "ek", ek, 0, 0, 040, M_FUNCT },
409 { "sane", sane, 0, 0, 040, M_FUNCT },
410 #ifdef OFDEL
411 { "fill", fill, 0, 0, 040, M_FUNCT },
412 #endif
413 #if 0
414 { "tty33", tty33, 0, 0, 040, M_FUNCT },
415 { "tty37", tty37, 0, 0, 040, M_FUNCT },
416 { "vt05", vt05, 0, 0, 040, M_FUNCT },
417 { "tn300", tn300, 0, 0, 040, M_FUNCT },
418 { "ti700", ti700, 0, 0, 040, M_FUNCT },
419 { "tek", tek, 0, 0, 040, M_FUNCT },
420 #endif
421 { "rows", rows, 0, 0, 040, M_FUNCT },
422 { "columns", columns,0, 0, 040, M_FUNCT },
423 #ifdef UCB
424 { "cols", columns,0, 0, 040, M_FUNCT },
425 #endif /* UCB */
426 { "ypixels", ypixels,0, 0, 040, M_FUNCT },
427 { "xpixels", xpixels,0, 0, 040, M_FUNCT },
428 { "min", vmin, 0, 0, 040, M_FUNCT },
429 { "time", vtime, 0, 0, 040, M_FUNCT },
430 { "line", line, 0, 0, 040, M_FUNCT },
431 #ifdef UCB
432 { "litout", litout, 0, 0, 040, M_FUNCT },
433 { "pass8", pass8, 0, 0, 040, M_FUNCT },
434 { "crt", crt, 0, 0, 040, M_FUNCT },
435 { "dec", dec, 0, 0, 040, M_FUNCT },
436 #endif /* UCB */
437 { 0, 0, 0, 0, 0, M_INVAL }
438 };
439
440 static const struct {
441 const char *s_str;
442 speed_t s_val;
443 } speeds[] = {
444 { "0", B0 },
445 { "50", B50 },
446 { "75", B75 },
447 { "110", B110 },
448 { "134", B134 },
449 { "134.5", B134 },
450 { "150", B150 },
451 { "200", B200 },
452 { "300", B300 },
453 { "600", B600 },
454 { "1200", B1200 },
455 { "1800", B1800 },
456 { "2400", B2400 },
457 { "4800", B4800 },
458 { "9600", B9600 },
459 { "19200", B19200 },
460 { "19.2", B19200 },
461 { "38400", B38400 },
462 { "38.4", B38400 },
463 #ifdef B57600
464 { "57600", B57600 },
465 #endif /* B57600 */
466 #ifdef B115200
467 { "115200", B115200 },
468 #endif /* B115200 */
469 #ifdef B230400
470 { "230400", B230400 },
471 #endif /* B230400 */
472 #ifdef B460800
473 { "460800", B460800 },
474 #endif /* B460800 */
475 #ifdef B500000
476 { "500000", B500000 },
477 #endif /* B500000 */
478 #ifdef B576000
479 { "576000", B576000 },
480 #endif /* B576000 */
481 #ifdef B921600
482 { "921600", B921600 },
483 #endif /* B921600 */
484 #ifdef B1000000
485 { "1000000", B1000000 },
486 #endif /* B1000000 */
487 #ifdef B1152000
488 { "1152000", B1152000 },
489 #endif /* B1152000 */
490 #ifdef B1500000
491 { "1500000", B1500000 },
492 #endif /* B1500000 */
493 #ifdef B2000000
494 { "2000000", B2000000 },
495 #endif /* B2000000 */
496 #ifdef B2500000
497 { "2500000", B2500000 },
498 #endif /* B2500000 */
499 #ifdef B3000000
500 { "3000000", B3000000 },
501 #endif /* B3000000 */
502 #ifdef B3500000
503 { "3500000", B3500000 },
504 #endif /* B3500000 */
505 #ifdef B4000000
506 { "4000000", B4000000 },
507 #endif /* B4000000 */
508 #ifdef EXTA
509 { "exta", EXTA },
510 #endif /* EXTA */
511 #ifdef EXTB
512 { "extb", EXTB },
513 #endif /* EXTB */
514 { 0, 0 }
515 };
516
517 static const char *progname;
518 static const char **args;
519 static struct termios ts;
520 static struct winsize ws;
521 static int wschange; /* ws was changed */
522 static long vdis; /* VDISABLE character */
523 extern int sysv3;
524
525 static void usage(void);
526 static void getattr(int);
527 static void list(int, int);
528 static int listmode(tcflag_t, struct mode, int, int);
529 static int listchar(cc_t *, struct mode, int, int);
530 static const char *baudrate(speed_t c);
531 static void set(void);
532 static void setmod(tcflag_t *, struct mode, int);
533 static void setchr(cc_t *, struct mode);
534 static void inval(void);
535 static void glist(void);
536 static void gset(void);
537 #ifdef UCB
538 static void hlist(int);
539 static void speed(void);
540 static void size(void);
541 #endif /* UCB */
542
543 #ifndef UCB
544 #define STTYFD 0
545 #else /* UCB */
546 #define STTYFD 1
547 #endif /* UCB */
548
549 int
main(int argc,char ** argv)550 main(int argc, char **argv)
551 {
552 int dds;
553
554 progname = basename(argv[0]);
555 setlocale(LC_CTYPE, "");
556 #ifndef UCB
557 if (getenv("SYSV3") != NULL)
558 sysv3 = 1;
559 getattr(STTYFD);
560 #endif /* !UCB */
561 if (argc >= 2 && strcmp(argv[1], "--") == 0) {
562 argc--, argv++;
563 dds = 1;
564 } else
565 dds = 0;
566 args = argc ? (const char **)&argv[1] : (const char **)&argv[0];
567 if(!dds && argc == 2 && argv[1][0] == '-' && argv[1][1] &&
568 argv[1][2] == '\0') {
569 switch (argv[1][1]) {
570 case 'a':
571 #ifdef UCB
572 getattr(STTYFD);
573 #endif /* UCB */
574 list(1, 0);
575 break;
576 case 'g':
577 #ifdef UCB
578 getattr(-1);
579 #endif /* UCB */
580 glist();
581 break;
582 #ifdef UCB
583 case 'h':
584 getattr(STTYFD);
585 hlist(1);
586 break;
587 #endif /* UCB */
588 default:
589 usage();
590 }
591 } else if (argc == 1) {
592 #ifdef UCB
593 getattr(STTYFD);
594 #endif /* UCB */
595 list(0, 0);
596 #ifdef UCB
597 } else if (argc == 2 && strcmp(argv[1], "all") == 0) {
598 getattr(STTYFD);
599 hlist(0);
600 } else if (argc == 2 && strcmp(argv[1], "everything") == 0) {
601 getattr(STTYFD);
602 hlist(1);
603 } else if (argc == 2 && strcmp(argv[1], "speed") == 0) {
604 getattr(-1);
605 speed();
606 } else if (argc == 2 && strcmp(argv[1], "size") == 0) {
607 getattr(-1);
608 size();
609 #endif /* UCB */
610 } else {
611 #ifdef UCB
612 getattr(STTYFD);
613 #endif /* UCB */
614 set();
615 if (tcsetattr(STTYFD, TCSADRAIN, &ts) < 0 ||
616 wschange && ioctl(STTYFD, TIOCSWINSZ, &ws) < 0)
617 perror(progname);
618 }
619 return 0;
620 }
621
622 static void
usage(void)623 usage(void)
624 {
625 fprintf(stderr, "usage: %s [-ag] [modes]\n", progname);
626 exit(2);
627 }
628
629 static void
getattr(int fd)630 getattr(int fd)
631 {
632 #ifdef UCB
633 const char devtty[] = "/dev/tty";
634
635 if (fd < 0 && (fd = open(devtty, O_RDONLY)) < 0) {
636 fprintf(stderr, "%s: Cannot open %s: %s\n",
637 progname, devtty, strerror(errno));
638 exit(2);
639 }
640 #endif /* UCB */
641 if (tcgetattr(fd, &ts) < 0) {
642 perror(progname);
643 exit(2);
644 }
645 if (ioctl(fd, TIOCGWINSZ, &ws) < 0) {
646 ws.ws_row = 0;
647 ws.ws_col = 0;
648 ws.ws_xpixel = 0;
649 ws.ws_ypixel = 0;
650 }
651 #if !defined (__FreeBSD__) && !defined (__DragonFly__) && !defined (__APPLE__)
652 vdis = fpathconf(fd, _PC_VDISABLE) & 0377;
653 #else
654 vdis = '\377' & 0377;
655 #endif
656 }
657
658 static void
list(int aflag,int hflag)659 list(int aflag, int hflag)
660 {
661 int i, d = 0;
662 speed_t is, os;
663
664 is = cfgetispeed(&ts);
665 os = cfgetospeed(&ts);
666 if (is == os)
667 printf("speed %s baud;", baudrate(is));
668 else
669 printf("ispeed %s baud; ospeed %s baud;",
670 baudrate(is), baudrate(os));
671 if (aflag == 0) {
672 for (i = 0; modes[i].m_name; i++) {
673 if (modes[i].m_type == M_PCFLAG)
674 d += listmode(ts.c_cflag, modes[i], aflag, 1);
675 }
676 d = 0;
677 }
678 if (sysv3 && aflag == 0) {
679 putchar('\n');
680 } else {
681 putchar(sysv3 ? ' ' : '\n');
682 printf("rows = %d%s columns = %d; "
683 "ypixels = %d%s xpixels = %d%s\n",
684 (int)ws.ws_row,
685 aflag&&hflag ? "" : ";",
686 (int)ws.ws_col,
687 (int)ws.ws_ypixel,
688 aflag&&hflag ? "" : ";",
689 (int)ws.ws_xpixel,
690 aflag&&hflag ? "" : ";");
691 }
692 if ((ts.c_lflag&ICANON) == 0)
693 printf("min = %d; time = %d;\n",
694 (int)ts.c_cc[VMIN], (int)ts.c_cc[VTIME]);
695 for (i = 0; modes[i].m_name; i++) {
696 if (modes[i].m_flg&040)
697 continue;
698 switch (modes[i].m_type) {
699 case M_NSEPAR:
700 if (sysv3)
701 break;
702 case M_SEPAR:
703 if (d && (modes[i].m_flg&8 ||
704 (modes[i].m_flg&(aflag?2:4)) == 0)) {
705 fputs(modes[i].m_name, stdout);
706 d = 0;
707 }
708 break;
709 case M_IFLAG:
710 d += listmode(ts.c_iflag, modes[i], aflag, d);
711 break;
712 case M_OFLAG:
713 d += listmode(ts.c_oflag, modes[i], aflag, d);
714 break;
715 case M_CFLAG:
716 d += listmode(ts.c_cflag, modes[i], aflag, d);
717 break;
718 case M_LFLAG:
719 d += listmode(ts.c_lflag, modes[i], aflag, d);
720 break;
721 case M_CC:
722 if (hflag == 0)
723 d += listchar(ts.c_cc, modes[i], aflag, d);
724 break;
725 }
726 if (d >= 72 && aflag == 0) {
727 putchar('\n');
728 d = 0;
729 }
730 }
731 if (d && aflag == 0)
732 putchar('\n');
733 }
734
735 static int
listmode(tcflag_t flag,struct mode m,int aflag,int space)736 listmode(tcflag_t flag, struct mode m, int aflag, int space)
737 {
738 int n = 0;
739
740 if (m.m_flg&010 || (m.m_flg & (aflag?2:4)) == 0 &&
741 (m.m_flg&0200 ? (flag&m.m_dfl) == m.m_val :
742 m.m_flg&020 ? (flag&m.m_val) == m.m_dfl :
743 (flag&m.m_val) != m.m_dfl)
744 | m.m_flg&1 |
745 (aflag != 0) ^ ((m.m_flg&(aflag?0400:0)) != 0)) {
746 if (space) {
747 putchar(' ');
748 n++;
749 }
750 if ((flag&m.m_val) == 0) {
751 putchar('-');
752 n++;
753 }
754 n += printf("%s", m.m_name);
755 }
756 return n;
757 }
758
759 static int
listchar(cc_t * cc,struct mode m,int aflag,int space)760 listchar(cc_t *cc, struct mode m, int aflag, int space)
761 {
762 int n = 0;
763 char c = m.m_val >= 0 ? cc[m.m_val] : vdis;
764
765 if (m.m_flg&8 || (m.m_flg & (aflag?2:4)) == 0 &&
766 c != (m.m_dfl?m.m_dfl:vdis) | m.m_flg&1 |
767 (aflag != 0) ^ ((m.m_flg&(aflag?0400:0)) != 0)) {
768 if (space) {
769 putchar(' ');
770 n++;
771 }
772 n += printf("%s ", m.m_name);
773 if ((c&0377) == vdis)
774 n += printf(sysv3 ? "<undef>" : "= <undef>");
775 else {
776 printf("= ");
777 if (c & 0200) {
778 c &= 0177;
779 putchar('-');
780 n++;
781 }
782 if ((c&037) == c)
783 n += printf("^%c", c | (sysv3 ? 0100 : 0140));
784 else if (c == '\177')
785 n += printf("DEL");
786 else {
787 putchar(c & 0377);
788 n++;
789 }
790 }
791 putchar(';');
792 n++;
793 }
794 return n;
795 }
796
797 static const char *
baudrate(speed_t c)798 baudrate(speed_t c)
799 {
800 int i;
801
802 for (i = 0; speeds[i].s_str; i++)
803 if (speeds[i].s_val == c)
804 return speeds[i].s_str;
805 return "-1";
806 }
807
808 static void
set(void)809 set(void)
810 {
811 int i, gotcha, not, sspeed = 0;
812 speed_t ispeed0, ospeed0, ispeed1, ospeed1;
813 const char *ap;
814 struct termios tc;
815
816 ispeed0 = ispeed1 = cfgetispeed(&ts);
817 ospeed0 = ospeed1 = cfgetospeed(&ts);
818 while (*args) {
819 for (i = 0; speeds[i].s_str; i++)
820 if (strcmp(speeds[i].s_str, *args) == 0) {
821 ispeed1 = ospeed1 = speeds[i].s_val;
822 sspeed |= 3;
823 goto next;
824 }
825 gotcha = 0;
826 if (**args == '-') {
827 not = 1;
828 ap = &args[0][1];
829 } else {
830 not = 0;
831 ap = *args;
832 }
833 for (i = 0; modes[i].m_name; i++) {
834 if (modes[i].m_type == M_SEPAR || modes[i].m_flg&0100)
835 continue;
836 if (strcmp(modes[i].m_name, ap) == 0) {
837 gotcha++;
838 switch (modes[i].m_type) {
839 case M_IFLAG:
840 setmod(&ts.c_iflag, modes[i], not);
841 break;
842 case M_OFLAG:
843 setmod(&ts.c_oflag, modes[i], not);
844 break;
845 case M_CFLAG:
846 case M_PCFLAG:
847 setmod(&ts.c_cflag, modes[i], not);
848 break;
849 case M_LFLAG:
850 setmod(&ts.c_lflag, modes[i], not);
851 break;
852 case M_CC:
853 if (not)
854 inval();
855 setchr(ts.c_cc, modes[i]);
856 break;
857 case M_FUNCT:
858 modes[i].m_func(not);
859 break;
860 }
861 }
862 }
863 if (gotcha)
864 goto next;
865 if (strcmp(*args, "ispeed") == 0) {
866 if (*++args == NULL)
867 break;
868 if (atol(*args) == 0) {
869 ispeed1 = ospeed1;
870 sspeed |= 1;
871 goto next;
872 } else for (i = 0; speeds[i].s_str; i++)
873 if (strcmp(speeds[i].s_str, *args) == 0) {
874 ispeed1 = speeds[i].s_val;
875 sspeed |= 1;
876 goto next;
877 }
878 inval();
879 }
880 if (strcmp(*args, "ospeed") == 0) {
881 if (*++args == NULL)
882 break;
883 for (i = 0; speeds[i].s_str; i++)
884 if (strcmp(speeds[i].s_str, *args) == 0) {
885 ospeed1 = speeds[i].s_val;
886 sspeed |= 2;
887 goto next;
888 }
889 inval();
890 }
891 gset();
892 next: args++;
893 }
894 if (sspeed) {
895 if (sspeed == 3 && ispeed1 != ospeed1 && ospeed1 != B0) {
896 tc = ts;
897 cfsetispeed(&tc, ispeed1);
898 if (cfgetospeed(&tc) == cfgetospeed(&ts)) {
899 tc = ts;
900 cfsetospeed(&tc, ospeed1);
901 if (cfgetispeed(&tc) == cfgetispeed(&ts)) {
902 cfsetispeed(&ts, ispeed1);
903 cfsetospeed(&ts, ospeed1);
904 }
905 }
906 } else {
907 if (ispeed0 != ispeed1)
908 cfsetispeed(&ts, ispeed1);
909 if (ospeed0 != ospeed1)
910 cfsetospeed(&ts, ospeed1);
911 }
912 }
913 }
914
915 static void
setmod(tcflag_t * t,struct mode m,int not)916 setmod(tcflag_t *t, struct mode m, int not)
917 {
918 if (m.m_flg&0200) {
919 if (not)
920 inval();
921 *t = *t&~(tcflag_t)m.m_dfl | m.m_val;
922 } else {
923 if (not ^ (m.m_flg&01000) != 0)
924 *t &= ~(tcflag_t)m.m_val;
925 else
926 *t |= m.m_val;
927 }
928 }
929
930 static void
setchr(cc_t * cc,struct mode m)931 setchr(cc_t *cc, struct mode m)
932 {
933 if (args[1] == NULL)
934 return;
935 args++;
936 if (m.m_val < 0)
937 return;
938 if (**args == '^') {
939 if (args[0][1] == '-')
940 cc[m.m_val] = vdis;
941 else if (args[0][1] == '?')
942 cc[m.m_val] = '\177';
943 else
944 cc[m.m_val] = args[0][1] & 037;
945 } else if (strcmp(*args, "undef") == 0)
946 cc[m.m_val] = vdis;
947 else
948 cc[m.m_val] = **args;
949 }
950
951 static void
inval(void)952 inval(void)
953 {
954 fprintf(stderr, "unknown mode: %s\n", *args);
955 exit(2);
956 }
957
958 #ifdef TABDLY
959 static void
tabs(int not)960 tabs(int not)
961 {
962 ts.c_oflag &= ~(tcflag_t)TABDLY;
963 ts.c_oflag |= not ? TAB3 : TAB0;
964 }
965 #endif
966
967 static void
evenp(int not)968 evenp(int not)
969 {
970 if (not) {
971 ts.c_cflag &= ~(tcflag_t)PARENB;
972 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS8;
973 } else {
974 ts.c_cflag |= PARENB;
975 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS7;
976 }
977 }
978
979 static void
oddp(int not)980 oddp(int not)
981 {
982 if (not) {
983 ts.c_cflag &= ~(tcflag_t)(PARENB|PARODD);
984 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS8;
985 } else {
986 ts.c_cflag |= PARENB|PARODD;
987 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS7;
988 }
989 }
990
991 static void
spacep(int not)992 spacep(int not)
993 {
994 evenp(not);
995 }
996
997 static void
markp(int not)998 markp(int not)
999 {
1000 oddp(not);
1001 }
1002
1003 static void
raw(int not)1004 raw(int not)
1005 {
1006 if (not) {
1007 ts.c_cc[VEOF] = ts.c_cc[VMIN] = '\4';
1008 ts.c_cc[VEOL] = ts.c_cc[VTIME] = vdis;
1009 ts.c_oflag |= OPOST;
1010 ts.c_lflag |= ISIG|ICANON;
1011 } else {
1012 ts.c_cc[VEOF] = ts.c_cc[VMIN] = 1;
1013 ts.c_cc[VEOL] = ts.c_cc[VTIME] = 1;
1014 ts.c_oflag &= ~(tcflag_t)OPOST;
1015 ts.c_lflag &= ~(tcflag_t)(ISIG|ICANON);
1016 }
1017 }
1018
1019 static void
cooked(int not)1020 cooked(int not)
1021 {
1022 if (not)
1023 inval();
1024 raw(1);
1025 }
1026
1027 static void
nl(int not)1028 nl(int not)
1029 {
1030 if (not) {
1031 ts.c_iflag |= ICRNL;
1032 ts.c_oflag |= ONLCR;
1033 ts.c_iflag &= ~(tcflag_t)(INLCR|IGNCR);
1034 ts.c_oflag &= ~(tcflag_t)(OCRNL|ONLRET);
1035 } else {
1036 ts.c_iflag &= ~(tcflag_t)ICRNL;
1037 ts.c_oflag &= ~(tcflag_t)ONLCR;
1038 }
1039 }
1040
1041 static void
sane(int not)1042 sane(int not)
1043 {
1044 speed_t ispeed, ospeed;
1045
1046 if (not)
1047 inval();
1048 ispeed = cfgetispeed(&ts);
1049 ospeed = cfgetospeed(&ts);
1050 ts.c_cc[VINTR] = '\3';
1051 ts.c_cc[VQUIT] = '\34';
1052 ts.c_cc[VERASE] = '\10';
1053 ts.c_cc[VKILL] = '\25';
1054 ts.c_cc[VEOF] = '\4';
1055 ts.c_cc[VEOL] = vdis;
1056 ts.c_cc[VEOL2] = vdis;
1057 #ifdef VSWTCH
1058 ts.c_cc[VSWTCH] = vdis;
1059 #endif
1060 ts.c_cc[VSTART] = '\21';
1061 ts.c_cc[VSTOP] = '\23';
1062 ts.c_cc[VSUSP] = '\32';
1063 #ifdef VREPRINT
1064 ts.c_cc[VREPRINT] = '\22';
1065 #endif
1066 #ifdef VDISCARD
1067 ts.c_cc[VDISCARD] = '\17';
1068 #endif
1069 #ifdef VWERASE
1070 ts.c_cc[VWERASE] = '\27';
1071 #endif
1072 ts.c_cc[VLNEXT] = '\26';
1073 ts.c_cflag = CS8|CREAD;
1074 ts.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOKE|IEXTEN;
1075 ts.c_iflag = BRKINT|IGNPAR|ICRNL|IXON|IMAXBEL;
1076 #ifdef IUTF8
1077 if (MB_CUR_MAX > 1) {
1078 wchar_t wc;
1079 if (mbtowc(&wc, "\303\266", 2) == 2 && wc == 0xF6 &&
1080 mbtowc(&wc, "\342\202\254", 3) == 3 &&
1081 wc == 0x20AC)
1082 ts.c_iflag |= IUTF8;
1083 }
1084 #endif /* IUTF8 */
1085 ts.c_oflag = OPOST|ONLCR;
1086 cfsetispeed(&ts, ispeed);
1087 cfsetospeed(&ts, ospeed);
1088 }
1089
1090 #ifdef OFDEL
1091 static void
fill(int not)1092 fill(int not)
1093 {
1094 if (not)
1095 ts.c_oflag &= ~(tcflag_t)(OFILL|OFDEL);
1096 else {
1097 ts.c_oflag |= OFILL;
1098 ts.c_oflag &= ~(tcflag_t)OFDEL;
1099 }
1100 }
1101 #endif
1102
1103 #ifdef XCASE
1104 static void
lcase(int not)1105 lcase(int not)
1106 {
1107 if (not) {
1108 ts.c_lflag &= ~(tcflag_t)XCASE;
1109 ts.c_iflag &= ~(tcflag_t)IUCLC;
1110 ts.c_oflag &= ~(tcflag_t)OLCUC;
1111 } else {
1112 ts.c_lflag |= XCASE;
1113 ts.c_iflag |= IUCLC;
1114 ts.c_oflag |= OLCUC;
1115 }
1116 }
1117 #endif
1118
1119 static void
ek(int not)1120 ek(int not)
1121 {
1122 if (not)
1123 inval();
1124 ts.c_cc[VERASE] = '\10';
1125 ts.c_cc[VKILL] = '\25';
1126 }
1127
1128 #if 0
1129 static void
1130 tty33(int not)
1131 {
1132 if (not)
1133 inval();
1134 ts.c_oflag &= ~(tcflag_t)(NLDLY|CRDLY|TABDLY|BSDLY|FFDLY|VTDLY);
1135 ts.c_oflag |= CR1;
1136 }
1137
1138 static void
1139 tty37(int not)
1140 {
1141 if (not)
1142 inval();
1143 ts.c_oflag &= ~(tcflag_t)(NLDLY|CRDLY|TABDLY|BSDLY|FFDLY|VTDLY);
1144 ts.c_oflag |= NL1|CR2|TAB1|FF1|VT1;
1145 }
1146
1147 static void
1148 vt05(int not)
1149 {
1150 if (not)
1151 inval();
1152 ts.c_oflag &= ~(tcflag_t)(NLDLY|CRDLY|TABDLY|BSDLY|FFDLY|VTDLY);
1153 ts.c_oflag |= NL1;
1154 }
1155
1156 static void
1157 tn300(int not)
1158 {
1159 if (not)
1160 inval();
1161 ts.c_oflag &= ~(tcflag_t)(NLDLY|CRDLY|TABDLY|BSDLY|FFDLY|VTDLY);
1162 ts.c_oflag |= CR1;
1163 }
1164
1165 static void
1166 ti700(int not)
1167 {
1168 if (not)
1169 inval();
1170 ts.c_oflag &= ~(tcflag_t)(NLDLY|CRDLY|TABDLY|BSDLY|FFDLY|VTDLY);
1171 ts.c_oflag |= CR2;
1172 }
1173
1174 static void
1175 tek(int not)
1176 {
1177 if (not)
1178 inval();
1179 ts.c_oflag &= ~(tcflag_t)(NLDLY|CRDLY|TABDLY|BSDLY|FFDLY|VTDLY);
1180 ts.c_oflag |= FF1;
1181 }
1182 #endif
1183
1184 static void
rows(int not)1185 rows(int not)
1186 {
1187 if (not)
1188 inval();
1189 if (args[1] == NULL)
1190 return;
1191 wschange = 1;
1192 ws.ws_row = atoi(*++args);
1193 }
1194
1195 static void
columns(int not)1196 columns(int not)
1197 {
1198 if (not)
1199 inval();
1200 if (args[1] == NULL)
1201 return;
1202 wschange = 1;
1203 ws.ws_col = atoi(*++args);
1204 }
1205
1206 static void
ypixels(int not)1207 ypixels(int not)
1208 {
1209 if (not)
1210 inval();
1211 if (args[1] == NULL)
1212 return;
1213 wschange = 1;
1214 ws.ws_ypixel = atoi(*++args);
1215 }
1216
1217 static void
xpixels(int not)1218 xpixels(int not)
1219 {
1220 if (not)
1221 inval();
1222 if (args[1] == NULL)
1223 return;
1224 wschange = 1;
1225 ws.ws_xpixel = atoi(*++args);
1226 }
1227
1228 static void
vmin(int not)1229 vmin(int not)
1230 {
1231 if (not)
1232 inval();
1233 if (args[1] == NULL)
1234 return;
1235 ts.c_cc[VMIN] = atoi(*++args);
1236 }
1237
1238 static void
vtime(int not)1239 vtime(int not)
1240 {
1241 if (not)
1242 inval();
1243 if (args[1] == NULL)
1244 return;
1245 ts.c_cc[VTIME] = atoi(*++args);
1246 }
1247
1248
1249 static void
line(int not)1250 line(int not)
1251 {
1252 if (not)
1253 inval();
1254 if (args[1] == NULL)
1255 return;
1256 #ifdef __linux__
1257 ts.c_line = atoi(*++args);
1258 #endif
1259 }
1260
1261 static const char gfmt[] ="%lx:%lx:%lx:%lx:"
1262 "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x";
1263
1264 static void
glist(void)1265 glist(void)
1266 {
1267 printf(gfmt, (long)ts.c_iflag,
1268 (long)ts.c_oflag,
1269 (long)ts.c_cflag,
1270 (long)ts.c_lflag,
1271 (int)ts.c_cc[VINTR],
1272 (int)ts.c_cc[VQUIT],
1273 (int)ts.c_cc[VERASE],
1274 (int)ts.c_cc[VKILL],
1275 (int)ts.c_cc[VEOF],
1276 (int)ts.c_cc[VEOL],
1277 (int)ts.c_cc[VEOL2],
1278 #ifdef VSWTCH
1279 (int)ts.c_cc[VSWTCH],
1280 #else
1281 (int)vdis,
1282 #endif
1283 (int)ts.c_cc[VSTART],
1284 (int)ts.c_cc[VSTOP],
1285 (int)ts.c_cc[VSUSP],
1286 #ifdef VDSUSP
1287 (int)ts.c_cc[VDSUSP],
1288 #else
1289 (int)vdis,
1290 #endif
1291 #ifdef VREPRINT
1292 (int)ts.c_cc[VREPRINT],
1293 #else
1294 (int)vdis,
1295 #endif
1296 #ifdef VDISCARD
1297 (int)ts.c_cc[VDISCARD],
1298 #else
1299 (int)vdis,
1300 #endif
1301 #ifdef VWERASE
1302 (int)ts.c_cc[VWERASE],
1303 #else
1304 (int)vdis,
1305 #endif
1306 (int)ts.c_cc[VLNEXT],
1307 (int)ts.c_cc[VMIN],
1308 (int)ts.c_cc[VTIME]);
1309 putchar('\n');
1310 }
1311
1312 static void
gset(void)1313 gset(void)
1314 {
1315 long iflag, oflag, cflag, lflag;
1316 int vintr, vquit, verase, vkill,
1317 veof, veol, veol2, vswtch,
1318 vstart, vstop, vsusp, vdsusp,
1319 vrprnt, vflush, vwerase, vlnext,
1320 vmin, vtime;
1321
1322 if (sscanf(*args, gfmt,
1323 &iflag, &oflag, &cflag, &lflag,
1324 &vintr, &vquit, &verase, &vkill,
1325 &veof, &veol, &veol2, &vswtch,
1326 &vstart, &vstop, &vsusp, &vdsusp,
1327 &vrprnt, &vflush, &vwerase, &vlnext,
1328 &vmin, &vtime) != 22)
1329 inval();
1330 ts.c_iflag = iflag;
1331 ts.c_oflag = oflag;
1332 ts.c_cflag = cflag;
1333 ts.c_lflag = lflag;
1334 ts.c_cc[VINTR] = vintr;
1335 ts.c_cc[VQUIT] = vquit;
1336 ts.c_cc[VKILL] = vkill;
1337 ts.c_cc[VEOF] = veof;
1338 ts.c_cc[VEOL] = veol;
1339 ts.c_cc[VEOL2] = veol2;
1340 #ifdef VSWTCH
1341 ts.c_cc[VSWTCH] = vswtch;
1342 #endif
1343 ts.c_cc[VSTART] = vstart;
1344 ts.c_cc[VSTOP] = vstop;
1345 ts.c_cc[VSUSP] = vsusp;
1346 #ifdef VDSUSP
1347 ts.c_cc[VDSUSP] = vdsusp;
1348 #endif
1349 #ifdef VREPRINT
1350 ts.c_cc[VREPRINT] = vrprnt;
1351 #endif
1352 #ifdef VDISCARD
1353 ts.c_cc[VDISCARD] = vflush;
1354 #endif
1355 #ifdef VWERASE
1356 ts.c_cc[VWERASE] = vwerase;
1357 #endif
1358 ts.c_cc[VLNEXT] = vlnext;
1359 ts.c_cc[VMIN] = vmin;
1360 ts.c_cc[VTIME] = vtime;
1361 }
1362
1363 #ifdef UCB
1364 static void
hchar(int c,int c2,int spc)1365 hchar(int c, int c2, int spc)
1366 {
1367 int n = 0;
1368
1369 chr: if (c != vdis) {
1370 if (c & 0200) {
1371 c &= 0177;
1372 n += printf("M-");
1373 }
1374 if ((c&037) == c)
1375 n += printf("^%c", c | 0100);
1376 else if (c == '\177')
1377 n += printf("^?");
1378 else {
1379 putchar(c);
1380 n++;
1381 }
1382 }
1383 if (c2 != EOF) {
1384 putchar('/');
1385 n++;
1386 c = c2;
1387 c2 = EOF;
1388 goto chr;
1389 }
1390 if (spc)
1391 while (n++ < 7)
1392 putchar(' ');
1393 }
1394
1395 static void
hlist(int aflag)1396 hlist(int aflag)
1397 {
1398 list(aflag, 1);
1399 printf("erase kill werase rprnt flush lnext "
1400 "susp intr quit stop eof\n");
1401 hchar(ts.c_cc[VERASE]&0377, EOF, 1);
1402 hchar(ts.c_cc[VKILL]&0377, EOF, 1);
1403 #ifdef VWERASE
1404 hchar(ts.c_cc[VWERASE]&0377, EOF, 1);
1405 #else
1406 hchar(vdis, EOF, 1);
1407 #endif
1408 #ifdef VREPRINT
1409 hchar(ts.c_cc[VREPRINT]&0377, EOF, 1);
1410 #else
1411 hchar(vdis, EOF, 1);
1412 #endif
1413 #ifdef VDISCARD
1414 hchar(ts.c_cc[VDISCARD]&0377, EOF, 1);
1415 #else
1416 hchar(vdis, EOF, 1);
1417 #endif
1418 hchar(ts.c_cc[VLNEXT]&0377, EOF, 1);
1419 hchar(ts.c_cc[VSUSP]&0377, EOF, 1);
1420 hchar(ts.c_cc[VINTR]&0377, EOF, 1);
1421 hchar(ts.c_cc[VQUIT]&0377, EOF, 1);
1422 hchar(ts.c_cc[VSTOP]&0377, ts.c_cc[VSTART]&0377, 1);
1423 hchar(ts.c_cc[VEOF]&0377, EOF, 1);
1424 putchar('\n');
1425 }
1426
1427 static void
speed(void)1428 speed(void)
1429 {
1430 printf("%s\n", baudrate(cfgetospeed(&ts)));
1431 }
1432
1433 static void
size(void)1434 size(void)
1435 {
1436 printf("%d %d\n", (int)ws.ws_row, (int)ws.ws_col);
1437 }
1438
1439 static void
litout(int not)1440 litout(int not)
1441 {
1442 if (not) {
1443 ts.c_cflag |= PARENB;
1444 ts.c_iflag |= ISTRIP;
1445 ts.c_oflag |= OPOST;
1446 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS7;
1447 } else {
1448 ts.c_cflag &= ~(tcflag_t)PARENB;
1449 ts.c_iflag &= ~(tcflag_t)ISTRIP;
1450 ts.c_oflag &= ~(tcflag_t)OPOST;
1451 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS8;
1452 }
1453 }
1454
1455 static void
pass8(int not)1456 pass8(int not)
1457 {
1458 if (not) {
1459 ts.c_cflag |= PARENB;
1460 ts.c_iflag |= ISTRIP;
1461 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS7;
1462 } else {
1463 ts.c_cflag &= ~(tcflag_t)PARENB;
1464 ts.c_iflag &= ~(tcflag_t)ISTRIP;
1465 ts.c_cflag = ts.c_cflag&~(tcflag_t)CSIZE | CS8;
1466 }
1467 }
1468
1469 static void
crt(int not)1470 crt(int not)
1471 {
1472 if (not)
1473 inval();
1474 ts.c_lflag |= ECHOE|ECHOCTL;
1475 if (cfgetospeed(&ts) >= B1200)
1476 ts.c_lflag |= ECHOKE;
1477 }
1478
1479 static void
dec(int not)1480 dec(int not)
1481 {
1482 if (not)
1483 inval();
1484 ts.c_cc[VERASE] = '\177';
1485 ts.c_cc[VKILL] = '\25';
1486 ts.c_cc[VINTR] = '\3';
1487 ts.c_iflag &= ~(tcflag_t)IXANY;
1488 crt(not);
1489 }
1490 #endif /* UCB */
1491