Commit | Line | Data |
---|---|---|
18949a0b | 1 | /* |
c086ab51 | 2 | * Copyright (c) 1980, 1989 Regents of the University of California. |
18949a0b DF |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
ba3dc8b4 | 7 | #ifndef lint |
18949a0b | 8 | char copyright[] = |
c086ab51 | 9 | "@(#) Copyright (c) 1980, 1989 Regents of the University of California.\n\ |
18949a0b DF |
10 | All rights reserved.\n"; |
11 | #endif not lint | |
12 | ||
13 | #ifndef lint | |
be51e567 | 14 | static char sccsid[] = "@(#)stty.c 5.17 (Berkeley) %G%"; |
18949a0b DF |
15 | #endif not lint |
16 | ||
16b6b22b BJ |
17 | /* |
18 | * set teletype modes | |
19 | */ | |
20 | ||
2ea9e68e MT |
21 | #include <sys/types.h> |
22 | #include <sys/stat.h> | |
4f05342b | 23 | #include <sys/ioctl.h> |
2ea9e68e MT |
24 | #include <sys/syslog.h> |
25 | #define KERNEL | |
26 | #include <sys/tty.h> | |
27 | #undef KERNEL | |
28 | #include <sys/termios.h> | |
29 | #include <sys/file.h> | |
30 | #include <errno.h> | |
31 | #include <ctype.h> | |
14fd0bf8 | 32 | #include <stdio.h> |
16b6b22b | 33 | |
b24648a6 | 34 | #define eq(s1, s2) (strcmp((s1), (s2)) == 0) |
2ea9e68e | 35 | #define WRAPCOL 65 |
2ea9e68e | 36 | |
b24648a6 | 37 | struct modes { |
2ea9e68e MT |
38 | char *name; |
39 | long set; | |
40 | long unset; | |
41 | }; | |
42 | ||
b24648a6 | 43 | struct modes imodes[] = { |
2ea9e68e MT |
44 | "ignbrk", IGNBRK, 0, |
45 | "-ignbrk", 0, IGNBRK, | |
46 | "brkint", BRKINT, 0, | |
47 | "-brkint", 0, BRKINT, | |
48 | "ignpar", IGNPAR, 0, | |
49 | "-ignpar", 0, IGNPAR, | |
50 | "parmrk", PARMRK, 0, | |
51 | "-parmrk", 0, PARMRK, | |
52 | "inpck", INPCK, 0, | |
53 | "-inpck", 0, INPCK, | |
54 | "istrip", ISTRIP, 0, | |
55 | "-istrip", 0, ISTRIP, | |
56 | "inlcr", INLCR, 0, | |
57 | "-inlcr", 0, INLCR, | |
58 | "igncr", IGNCR, 0, | |
59 | "-igncr", 0, IGNCR, | |
60 | "icrnl", ICRNL, 0, | |
61 | "-icrnl", 0, ICRNL, | |
62 | "ixon", IXON, 0, | |
63 | "-ixon", 0, IXON, | |
64 | "flow", IXON, 0, | |
65 | "-flow", 0, IXON, | |
66 | "ixoff", IXOFF, 0, | |
67 | "-ixoff", 0, IXOFF, | |
68 | "tandem", IXOFF, 0, | |
69 | "-tandem", 0, IXOFF, | |
70 | "ixany", IXANY, 0, | |
71 | "-ixany", 0, IXANY, | |
72 | "decctlq", 0, IXANY, | |
73 | "-decctlq", IXANY, 0, | |
74 | "imaxbel", IMAXBEL, 0, | |
75 | "-imaxbel", 0, IMAXBEL, | |
76 | 0 | |
77 | }; | |
78 | ||
b24648a6 | 79 | struct modes omodes[] = { |
2ea9e68e MT |
80 | "opost", OPOST, 0, |
81 | "-opost", 0, OPOST, | |
82 | "-litout", OPOST, 0, | |
83 | "litout", 0, OPOST, | |
84 | "onlcr", ONLCR, 0, | |
85 | "-onlcr", 0, ONLCR, | |
86 | "tabs", 0, OXTABS, /* "preserve" tabs */ | |
87 | "-tabs", OXTABS, 0, | |
6b85d402 MT |
88 | "xtabs", OXTABS, 0, |
89 | "-xtabs", 0, OXTABS, | |
2ea9e68e MT |
90 | "oxtabs", OXTABS, 0, |
91 | "-oxtabs", 0, OXTABS, | |
92 | 0 | |
16b6b22b BJ |
93 | }; |
94 | ||
b24648a6 | 95 | struct modes cmodes[] = { |
2ea9e68e MT |
96 | "cs5", CS5, CSIZE, |
97 | "cs6", CS6, CSIZE, | |
98 | "cs7", CS7, CSIZE, | |
99 | "cs8", CS8, CSIZE, | |
100 | "cstopb", CSTOPB, 0, | |
101 | "-cstopb", 0, CSTOPB, | |
102 | "cread", CREAD, 0, | |
103 | "-cread", 0, CREAD, | |
104 | "parenb", PARENB, 0, | |
105 | "-parenb", 0, PARENB, | |
106 | "parodd", PARODD, 0, | |
107 | "-parodd", 0, PARODD, | |
108 | "parity", PARENB | CS7, PARODD | CSIZE, | |
109 | "evenp", PARENB | CS7, PARODD | CSIZE, | |
110 | "oddp", PARENB | CS7 | PARODD, CSIZE, | |
111 | "-parity", CS8, PARODD | PARENB | CSIZE, | |
c086ab51 | 112 | "pass8", CS8, PARODD | PARENB | CSIZE, |
2ea9e68e MT |
113 | "-evenp", CS8, PARODD | PARENB | CSIZE, |
114 | "-oddp", CS8, PARODD | PARENB | CSIZE, | |
115 | "hupcl", HUPCL, 0, | |
116 | "-hupcl", 0, HUPCL, | |
117 | "hup", HUPCL, 0, | |
118 | "-hup", 0, HUPCL, | |
119 | "clocal", CLOCAL, 0, | |
120 | "-clocal", 0, CLOCAL, | |
121 | "crtscts", CRTSCTS, 0, | |
122 | "-crtscts", 0, CRTSCTS, | |
16b6b22b BJ |
123 | 0 |
124 | }; | |
16b6b22b | 125 | |
b24648a6 | 126 | struct modes lmodes[] = { |
2ea9e68e MT |
127 | "echo", ECHO, 0, |
128 | "-echo", 0, ECHO, | |
129 | "echoe", ECHOE, 0, | |
130 | "-echoe", 0, ECHOE, | |
131 | "crterase", ECHOE, 0, | |
132 | "-crterase", 0, ECHOE, | |
133 | "crtbs", ECHOE, 0, /* crtbs not supported, close enough */ | |
134 | "-crtbs", 0, ECHOE, | |
135 | "echok", ECHOK, 0, | |
136 | "-echok", 0, ECHOK, | |
137 | "echoke", ECHOKE, 0, | |
138 | "-echoke", 0, ECHOKE, | |
139 | "crtkill", ECHOKE, 0, | |
140 | "-crtkill", 0, ECHOKE, | |
141 | "altwerase", ALTWERASE, 0, | |
142 | "-altwerase", 0, ALTWERASE, | |
143 | "iexten", IEXTEN, 0, | |
144 | "-iexten", 0, IEXTEN, | |
145 | "echonl", ECHONL, 0, | |
146 | "-echonl", 0, ECHONL, | |
147 | "echoctl", ECHOCTL, 0, | |
148 | "-echoctl", 0, ECHOCTL, | |
149 | "ctlecho", ECHOCTL, 0, | |
150 | "-ctlecho", 0, ECHOCTL, | |
151 | "echoprt", ECHOPRT, 0, | |
152 | "-echoprt", 0, ECHOPRT, | |
153 | "prterase", ECHOPRT, 0, | |
154 | "-prterase", 0, ECHOPRT, | |
155 | "isig", ISIG, 0, | |
156 | "-isig", 0, ISIG, | |
157 | "icanon", ICANON, 0, | |
158 | "-icanon", 0, ICANON, | |
159 | "noflsh", NOFLSH, 0, | |
160 | "-noflsh", 0, NOFLSH, | |
161 | "tostop", TOSTOP, 0, | |
162 | "-tostop", 0, TOSTOP, | |
163 | "mdmbuf", MDMBUF, 0, | |
164 | "-mdmbuf", 0, MDMBUF, | |
2ea9e68e MT |
165 | "flusho", FLUSHO, 0, |
166 | "-flusho", 0, FLUSHO, | |
167 | "pendin", PENDIN, 0, | |
168 | "-pendin", 0, PENDIN, | |
169 | "crt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT, | |
170 | "-crt", ECHOK, ECHOE|ECHOKE|ECHOCTL, | |
171 | "newcrt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT, | |
172 | "-newcrt", ECHOK, ECHOE|ECHOKE|ECHOCTL, | |
173 | 0 | |
174 | }; | |
175 | ||
176 | /* | |
177 | * Special control characters. | |
178 | * | |
179 | * Each entry has a list of names. The first is the primary name | |
180 | * and is used when printing the control character in the "name = val;" | |
181 | * form. The second is an abbreviation which is guaranteed to be less | |
182 | * than or equal to four characters in length and is primarily used | |
183 | * when printing the values in columunar form (guarantees all will | |
184 | * fit within 80 cols). The rest are optional aliases. | |
185 | * All names are recognized on the command line. | |
186 | */ | |
b24648a6 MT |
187 | #define MAXNAMES 3 |
188 | struct { | |
6b85d402 | 189 | char *names[MAXNAMES+1]; |
2ea9e68e MT |
190 | int sub; |
191 | u_char def; | |
192 | } cchars[] = { | |
8d050676 KB |
193 | {{ "erase", "era" }, VERASE, CERASE, }, |
194 | {{ "werase", "wera" }, VWERASE, CWERASE, }, | |
195 | {{ "kill", "kill" }, VKILL, CKILL, }, | |
196 | {{ "intr", "int" }, VINTR, CINTR, }, | |
197 | {{ "quit", "quit" }, VQUIT, CQUIT, }, | |
198 | {{ "susp", "susp" }, VSUSP, CSUSP, }, | |
199 | {{ "dsusp", "dsus" }, VDSUSP, CDSUSP, }, | |
200 | {{ "eof", "eof" }, VEOF, CEOF, }, | |
201 | {{ "eol", "eol", "brk" }, VEOL, CEOL, }, | |
202 | {{ "eol2", "eol2" }, VEOL2, CEOL, }, | |
203 | {{ "stop", "stop", "xoff" }, VSTOP, CSTOP, }, | |
204 | {{ "start", "star", "xon" }, VSTART, CSTART, }, | |
205 | {{ "lnext", "lnxt" }, VLNEXT, CLNEXT, }, | |
5749b3a4 | 206 | {{ "discard", "disc", "flush" }, VDISCARD, CDISCARD, }, |
8d050676 | 207 | {{ "reprint", "rpnt", "rprnt" }, VREPRINT, CREPRINT, }, |
5749b3a4 | 208 | {{ "status", "stat" }, VSTATUS, CSTATUS, }, |
2ea9e68e MT |
209 | 0 |
210 | }; | |
8d050676 | 211 | |
b24648a6 MT |
212 | struct winsize win; |
213 | int ldisc; | |
214 | int dodisc; | |
215 | int debug = 0; | |
216 | int trace, dotrace; | |
2ea9e68e MT |
217 | |
218 | #define OUT stdout /* informational output stream */ | |
219 | #define ERR stderr /* error message stream */ | |
220 | #define CTL 0 /* default control descriptor */ | |
b24648a6 | 221 | int ctl = CTL; |
2ea9e68e MT |
222 | |
223 | extern errno; | |
2ea9e68e MT |
224 | |
225 | #define NORMAL 0 /* only print modes differing from defaults */ | |
226 | #define ALL 1 /* print all modes - POSIX standard format */ | |
227 | #define ALL_BSD 2 /* print all modes - using BSD shorthand for cc's */ | |
6d749894 | 228 | #define GFMT 3 /* print modes in form suitable to be re-input */ |
b24648a6 | 229 | |
2ea9e68e MT |
230 | main(argc, argv) |
231 | char *argv[]; | |
16b6b22b | 232 | { |
2ea9e68e MT |
233 | struct termios t; |
234 | int i, fmt = NORMAL; | |
235 | extern char *optarg; | |
236 | extern int optind; | |
237 | int ch; | |
238 | ||
239 | argc--, argv++; | |
240 | if (argc > 0 && eq(argv[0], "-a")) { | |
241 | fmt = ALL; | |
242 | argc--, argv++; | |
16b6b22b | 243 | } |
6d749894 MT |
244 | if (argc > 0 && eq(argv[0], "-g")) { |
245 | fmt = GFMT; | |
246 | argc--, argv++; | |
247 | } | |
2ea9e68e MT |
248 | if (argc > 0 && eq(argv[0], "-f")) { |
249 | argc--, argv++; | |
250 | if ((ctl = open(argv[0], O_RDONLY | O_NONBLOCK)) < 0) | |
251 | syserrexit(*argv); | |
252 | argc--, argv++; | |
16b6b22b | 253 | } |
2ea9e68e MT |
254 | if (ioctl(ctl, TIOCGETD, &ldisc) < 0) |
255 | syserrexit("TIOCGETD"); | |
256 | if (tcgetattr(ctl, &t) < 0) | |
257 | syserrexit("tcgetattr"); | |
258 | if (ioctl(ctl, TIOCGWINSZ, &win) < 0) | |
b24648a6 | 259 | warning("TIOCGWINSZ: %s", strerror(errno)); |
2ea9e68e | 260 | checkredirect(); /* conversion aid */ |
2ea9e68e MT |
261 | |
262 | if (argc == 0 || fmt) { | |
263 | prmode(&t, ldisc, fmt); | |
ba3dc8b4 SL |
264 | exit(0); |
265 | } | |
2ea9e68e MT |
266 | |
267 | while (*argv) { | |
268 | if (eq("everything", *argv)) { | |
269 | prmode(&t, ldisc, ALL_BSD); | |
270 | exit(0); | |
16b6b22b | 271 | } |
2ea9e68e MT |
272 | if (eq("all", *argv)) { |
273 | prmode(&t, ldisc, ALL); | |
274 | exit(0); | |
16b6b22b | 275 | } |
2ea9e68e MT |
276 | if (eq("old", *argv)) { |
277 | goto next; | |
16b6b22b | 278 | } |
2ea9e68e MT |
279 | if (eq("new", *argv)) { |
280 | goto next; | |
16b6b22b | 281 | } |
2ea9e68e MT |
282 | if (eq("nl", *argv)) { |
283 | t.c_iflag &= ~ICRNL; | |
284 | t.c_oflag &= ~ONLCR; | |
285 | goto next; | |
5e9810bc | 286 | } |
2ea9e68e MT |
287 | if (eq("-nl", *argv)) { |
288 | t.c_iflag |= ICRNL; | |
289 | t.c_oflag |= ONLCR; | |
290 | goto next; | |
16b6b22b | 291 | } |
2ea9e68e MT |
292 | if (eq("dec", *argv)){ |
293 | t.c_cc[VERASE] = (u_char)0177; | |
294 | t.c_cc[VKILL] = CTRL('u'); | |
295 | t.c_cc[VINTR] = CTRL('c'); | |
296 | t.c_lflag &= ~ECHOPRT; | |
297 | t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; | |
298 | t.c_iflag &= ~IXANY; | |
299 | goto next; | |
16b6b22b | 300 | } |
c086ab51 MK |
301 | if (eq("raw", *argv)) { |
302 | cfmakeraw(&t); | |
303 | t.c_cflag &= ~(CSIZE|PARENB); | |
304 | t.c_cflag |= CS8; | |
305 | goto next; | |
306 | } | |
be51e567 MT |
307 | if (eq("cbreak", *argv)) { |
308 | t.c_iflag | BRKINT|IXON|IMAXBEL; | |
309 | t.c_oflag |= OPOST; | |
310 | t.c_lflag |= ISIG|IEXTEN; | |
311 | t.c_lflag &= ~ICANON; | |
312 | } | |
c086ab51 | 313 | if (eq("cooked", *argv) || eq("-raw", *argv) || |
be51e567 | 314 | eq("sane", *argv) || eq("-cbreak", *argv)) { |
c086ab51 MK |
315 | t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL); |
316 | t.c_iflag = TTYDEF_IFLAG; | |
317 | t.c_iflag |= ICRNL; | |
318 | /* preserve user-preference flags in lflag */ | |
319 | #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) | |
320 | t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP); | |
321 | t.c_oflag = TTYDEF_OFLAG; | |
c086ab51 MK |
322 | goto next; |
323 | } | |
2ea9e68e MT |
324 | if (eq("rows", *argv)) { |
325 | if (*(argv+1) == 0) | |
326 | goto setit; | |
4f05342b | 327 | win.ws_row = atoi(*++argv); |
2ea9e68e MT |
328 | goto next; |
329 | } | |
330 | if (eq("ispeed", *argv)) { | |
331 | int code; | |
332 | if (*(argv+1) == 0) | |
333 | errexit("missing ispeed"); | |
334 | cfsetispeed(&t, atoi(*++argv)); | |
335 | goto next; | |
336 | } | |
337 | if (eq("ospeed", *argv)) { | |
2ea9e68e MT |
338 | if (*(argv+1) == 0) |
339 | errexit("missing ospeed"); | |
340 | cfsetospeed(&t, atoi(*++argv)); | |
341 | goto next; | |
4f05342b | 342 | } |
2ea9e68e MT |
343 | if (eq("cols", *argv) || eq("columns", *argv)) { |
344 | if (*(argv+1) == 0) | |
345 | goto setit; | |
4f05342b | 346 | win.ws_col = atoi(*++argv); |
2ea9e68e | 347 | goto next; |
4f05342b | 348 | } |
2ea9e68e MT |
349 | if (eq("size", *argv)) { |
350 | put("%d %d\n", win.ws_row, win.ws_col); | |
d6f0b7e6 MK |
351 | exit(0); |
352 | } | |
2ea9e68e MT |
353 | if (eq("speed", *argv)) { |
354 | put("%d\n", cfgetospeed(&t)); | |
355 | exit(0); | |
356 | } | |
357 | for (i=0; imodes[i].name; i++) | |
358 | if (eq(imodes[i].name, *argv)) { | |
359 | t.c_iflag &= ~imodes[i].unset; | |
360 | t.c_iflag |= imodes[i].set; | |
361 | goto next; | |
362 | } | |
363 | for (i=0; omodes[i].name; i++) | |
364 | if (eq(omodes[i].name, *argv)) { | |
365 | t.c_oflag &= ~omodes[i].unset; | |
366 | t.c_oflag |= omodes[i].set; | |
367 | goto next; | |
16b6b22b | 368 | } |
2ea9e68e MT |
369 | for (i=0; cmodes[i].name; i++) |
370 | if (eq(cmodes[i].name, *argv)) { | |
371 | t.c_cflag &= ~cmodes[i].unset; | |
372 | t.c_cflag |= cmodes[i].set; | |
373 | goto next; | |
374 | } | |
375 | for (i=0; lmodes[i].name; i++) | |
376 | if (eq(lmodes[i].name, *argv)) { | |
377 | t.c_lflag &= ~lmodes[i].unset; | |
378 | t.c_lflag |= lmodes[i].set; | |
379 | goto next; | |
380 | } | |
381 | for (i=0; *cchars[i].names; i++) { | |
382 | char **cp = cchars[i].names; | |
383 | while (*cp) { | |
384 | if (eq(*cp, *argv)) { | |
385 | if (*++argv == 0) | |
386 | goto setit; | |
387 | if (eq(*argv, "undef") || | |
388 | eq(*argv, "disable")) | |
389 | t.c_cc[cchars[i].sub] = | |
390 | _POSIX_VDISABLE; | |
391 | else if (**argv == '^') | |
392 | t.c_cc[cchars[i].sub] = | |
393 | ((*argv)[1] == '?') ? 0177 : | |
394 | ((*argv)[1] == '-') ? | |
395 | _POSIX_VDISABLE : | |
396 | (*argv)[1] & 037; | |
397 | else | |
398 | t.c_cc[cchars[i].sub] = **argv; | |
399 | goto next; | |
16b6b22b | 400 | } |
2ea9e68e | 401 | cp++; |
16b6b22b | 402 | } |
2ea9e68e MT |
403 | } |
404 | if (isdigit(**argv)) { | |
405 | cfsetospeed(&t, atoi(*argv)); | |
406 | cfsetispeed(&t, atoi(*argv)); | |
407 | goto next; | |
408 | } | |
6d749894 MT |
409 | if (strncmp(*argv, "-gfmt", sizeof ("-gfmt") - 1) == 0) { |
410 | gfmtset(&t, *argv); | |
411 | goto next; | |
412 | } | |
2ea9e68e MT |
413 | /* didn't match anything */ |
414 | errexit("unknown option: %s", *argv); | |
415 | exit(1); | |
416 | next: | |
417 | argv++; | |
16b6b22b | 418 | } |
2ea9e68e MT |
419 | setit: |
420 | if (tcsetattr(ctl, 0, &t) < 0) | |
421 | syserrexit("tcsetattr"); | |
422 | if (ioctl(ctl, TIOCSWINSZ, &win) < 0) | |
423 | warning("can't set window size"); | |
424 | ||
425 | exit(0); | |
16b6b22b BJ |
426 | } |
427 | ||
6d749894 MT |
428 | gfmtset(tp, s) |
429 | register struct termios *tp; | |
430 | char *s; | |
431 | { | |
432 | register int cnt; | |
433 | char sep; | |
434 | char *saves = s; | |
435 | int cval; | |
436 | #define advance(c) while (*(s) && *(s) != (c)) (s)++; if (*s) (s)++ ; \ | |
437 | else \ | |
438 | errexit("bad gfmt operand: %s", saves) | |
439 | #define chkeq(string) if (strncmp(s, (string), strlen(string))) \ | |
440 | errexit("bad gfmt operand: %s", saves) | |
441 | ||
442 | if (s == NULL) | |
443 | errexit("missing gfmt string"); | |
444 | advance(':'); | |
445 | chkeq("iflag="); | |
446 | advance('='); | |
447 | sscanf(s, "%x", &tp->c_iflag); | |
448 | ||
449 | advance(':'); | |
450 | chkeq("oflag"); | |
451 | advance('='); | |
452 | sscanf(s, "%x", &tp->c_oflag); | |
453 | ||
454 | advance(':'); | |
455 | chkeq("cflag"); | |
456 | advance('='); | |
457 | sscanf(s, "%x", &tp->c_cflag); | |
458 | ||
459 | advance(':'); | |
460 | chkeq("lflag"); | |
461 | advance('='); | |
462 | sscanf(s, "%x", &tp->c_lflag); | |
463 | ||
464 | advance(':'); | |
465 | chkeq("cc="); | |
466 | ||
467 | for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',') { | |
468 | advance(sep); | |
469 | sscanf(s, "%o", &cval); | |
470 | tp->c_cc[cnt] = cval; | |
471 | } | |
472 | ||
473 | advance(':'); | |
474 | chkeq("ispeed="); | |
475 | advance('='); | |
476 | sscanf(s, "%d", &tp->c_ispeed); | |
477 | ||
478 | advance(':'); | |
479 | chkeq("ospeed="); | |
480 | advance('='); | |
481 | sscanf(s, "%d", &tp->c_ospeed); | |
16b6b22b BJ |
482 | } |
483 | ||
2ea9e68e MT |
484 | prmode(tp, ldisc, fmt) |
485 | struct termios *tp; | |
16b6b22b | 486 | { |
2ea9e68e MT |
487 | long i = tp->c_iflag, |
488 | o = tp->c_oflag, | |
489 | c = tp->c_cflag, | |
490 | l = tp->c_lflag; | |
491 | u_char *cc = tp->c_cc; | |
492 | int ispeed = cfgetispeed(tp), | |
493 | ospeed = cfgetospeed(tp); | |
494 | char unknown[32], | |
495 | *ld; | |
496 | char *ccval(); | |
16b6b22b | 497 | |
6d749894 MT |
498 | if (fmt == GFMT) { |
499 | int cnt; | |
500 | char sep; | |
501 | ||
502 | printf("-gfmt:iflag=%x:oflag=%x:cflag=%x:lflag=%x:cc", | |
503 | i, o, c, l); | |
504 | for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',') | |
505 | printf("%c%o", sep, cc[cnt]); | |
506 | printf(":ispeed=%d:ospeed=%d:\n", ispeed, ospeed); | |
507 | return; | |
508 | } | |
509 | ||
2ea9e68e MT |
510 | /* |
511 | * line discipline | |
512 | */ | |
513 | if (ldisc != TTYDISC) { | |
514 | switch(ldisc) { | |
515 | case TABLDISC: | |
516 | ld = "tablet"; | |
517 | break; | |
518 | case SLIPDISC: | |
b24648a6 | 519 | ld = "slip"; |
16b6b22b | 520 | break; |
2ea9e68e MT |
521 | default: |
522 | sprintf(unknown, "#%d", ldisc); | |
523 | ld = unknown; | |
16b6b22b | 524 | } |
2ea9e68e MT |
525 | put("%s disc; ", ld); |
526 | } | |
527 | /* | |
528 | * line speed | |
529 | */ | |
530 | if (ispeed != ospeed) | |
531 | put("ispeed %d baud; ospeed %d baud;", | |
532 | ispeed, ospeed); | |
533 | else | |
534 | put("speed %d baud;", ispeed); | |
535 | if (fmt) | |
536 | put(" %d rows; %d columns;", win.ws_row, win.ws_col); | |
537 | put("\n"); | |
538 | ||
539 | #define lput(n, f, d) if (fmt || on(f) != d) mdput(n+on(f)) | |
540 | /* | |
541 | * "local" flags | |
542 | */ | |
543 | #define on(f) ((l&f) != 0) | |
544 | if (debug) mdput("LFLAG: "); | |
545 | lput("-icanon ",ICANON, 1); | |
546 | lput("-isig ", ISIG, 1); | |
547 | lput("-iexten ", IEXTEN, 1); | |
548 | lput("-echo ",ECHO, 1); | |
549 | lput("-echoe ",ECHOE, 0); | |
550 | lput("-echok ",ECHOK, 0); | |
551 | lput("-echoke ",ECHOKE, 0); | |
552 | lput("-echonl ",ECHONL, 0); | |
553 | lput("-echoctl ",ECHOCTL, 0); | |
554 | lput("-echoprt ",ECHOPRT, 0); | |
555 | lput("-altwerase ",ALTWERASE, 0); | |
556 | lput("-noflsh ",NOFLSH, 0); | |
557 | lput("-tostop ",TOSTOP, 0); | |
558 | lput("-mdmbuf ",MDMBUF, 0); | |
2ea9e68e MT |
559 | lput("-flusho ",FLUSHO, 0); |
560 | lput("-pendin ",PENDIN, 0); | |
561 | /* | |
562 | * input flags | |
563 | */ | |
564 | #undef on | |
565 | #define on(f) ((i&f) != 0) | |
566 | mdput(0); | |
567 | if (debug) mdput("IFLAG: "); | |
568 | lput("-istrip ", ISTRIP, 0); | |
569 | lput("-icrnl ", ICRNL, 1); | |
570 | lput("-inlcr ", INLCR, 0); | |
571 | lput("-igncr ", IGNCR, 0); | |
572 | lput("-ixon ", IXON, 1); | |
573 | lput("-ixoff ", IXOFF, 0); | |
574 | lput("-ixany ", IXANY, 1); | |
575 | lput("-imaxbel ", IMAXBEL, 1); | |
576 | lput("-ignbrk ", IGNBRK, 0); | |
577 | lput("-brkint ", BRKINT, 1); | |
578 | lput("-inpck ", INPCK, 0); | |
579 | lput("-ignpar ", IGNPAR, 0); | |
580 | lput("-parmrk ", PARMRK, 0); | |
581 | #undef on | |
582 | /* | |
583 | * output flags | |
584 | */ | |
585 | #define on(f) ((o&f) != 0) | |
586 | mdput(0); | |
587 | if (debug) mdput("OFLAG: "); | |
588 | lput("-opost ", OPOST, 1); | |
589 | lput("-onlcr ", ONLCR, 1); | |
590 | lput("-oxtabs ", OXTABS, 1); | |
591 | #undef on | |
592 | /* | |
593 | * control flags (hardware state) | |
594 | */ | |
595 | #define on(f) ((c&f) != 0) | |
596 | mdput(0); | |
597 | if (debug) mdput("CFLAG: "); | |
598 | lput("-cread ", CREAD, 1); | |
599 | switch(c&CSIZE) { | |
600 | case CS5: mdput("cs5 "); break; | |
601 | case CS6: mdput("cs6 "); break; | |
602 | case CS7: mdput("cs7 "); break; | |
603 | case CS8: mdput("cs8 "); break; | |
604 | } | |
605 | mdput("-parenb "+on(PARENB)); | |
606 | lput("-parodd ", PARODD, 0); | |
607 | lput("-hupcl ", HUPCL, 1); | |
608 | lput("-clocal ", CLOCAL, 0); | |
609 | lput("-cstopb ", CSTOPB, 0); | |
610 | lput("-crtscts ", CRTSCTS, 0); | |
611 | mdput(0); | |
612 | #undef on | |
613 | /* | |
614 | * special control characters | |
615 | */ | |
616 | if (debug) mdput("CCHARS: "); | |
617 | if (fmt != 2) { | |
618 | for (i=0; *cchars[i].names; i++) { | |
619 | char temp[64]; | |
620 | ||
621 | if (fmt || cc[cchars[i].sub] != cchars[i].def) { | |
622 | sprintf(temp, "%s = %s; ", *cchars[i].names, | |
623 | ccval(cc[cchars[i].sub]), fmt); | |
624 | mdput(temp); | |
625 | } | |
16b6b22b | 626 | } |
2ea9e68e MT |
627 | mdput(0); |
628 | } else { | |
629 | for (i=0; *cchars[i].names; i++) | |
630 | put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0), | |
631 | *(cchars[i].names+1)); | |
632 | printf("\n"); | |
633 | for (i=0; *cchars[i].names; i++) | |
634 | put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0), | |
635 | ccval(cc[cchars[i].sub], fmt)); | |
636 | printf("\n"); | |
16b6b22b BJ |
637 | } |
638 | } | |
639 | ||
2ea9e68e MT |
640 | /* |
641 | * gross, but since we're changing the control descriptor | |
642 | * from 1 to 0, most users will be probably be doing | |
643 | * "stty > /dev/sometty" by accident. If 1 and 2 are both ttys, | |
644 | * but not the same, assume that 1 was incorrectly redirected. | |
645 | */ | |
646 | checkredirect() { | |
647 | struct stat st1, st2; | |
648 | ||
649 | if (isatty(1) && isatty(2) && fstat(1, &st1) != -1 && | |
650 | fstat(2, &st2) != -1 && (st1.st_rdev != st2.st_rdev)) | |
651 | warning("stdout appears redirected, but stdin is the control descriptor"); | |
652 | } | |
2ea9e68e | 653 | |
b24648a6 | 654 | char * |
2ea9e68e MT |
655 | ccval(c, fmt) |
656 | unsigned char c; | |
16b6b22b | 657 | { |
2ea9e68e MT |
658 | static char buf[128]; |
659 | char *bp; | |
660 | ||
661 | *buf = 0, bp = buf; | |
662 | if (c == _POSIX_VDISABLE) | |
663 | if (fmt == 2) | |
664 | return("<u>"); | |
665 | else | |
666 | return("<undef>"); | |
667 | if (c & 0200) { | |
668 | strcat(buf, "M-"); | |
669 | *bp++ = 'M'; | |
670 | *bp++ = '-'; | |
671 | c &= 0177; | |
672 | } | |
673 | if (c == 0177) { | |
674 | *bp++ = '^'; | |
675 | *bp++ = '?'; | |
16b6b22b | 676 | } |
2ea9e68e MT |
677 | else if (c < 040) { |
678 | *bp++ = '^'; | |
679 | *bp++ = c + '@'; | |
16b6b22b | 680 | } |
2ea9e68e MT |
681 | else |
682 | *bp++ = c; | |
683 | *bp = 0; | |
684 | return(buf); | |
16b6b22b BJ |
685 | } |
686 | ||
b24648a6 | 687 | |
2ea9e68e MT |
688 | mdput(s) |
689 | char *s; | |
16b6b22b | 690 | { |
2ea9e68e | 691 | static int col = 0; |
16b6b22b | 692 | |
2ea9e68e MT |
693 | if (s == (char *)0) { |
694 | if (col) { | |
695 | put("\n"); | |
696 | col = 0; | |
697 | } | |
16b6b22b BJ |
698 | return; |
699 | } | |
2ea9e68e MT |
700 | if ((col += strlen(s)) > WRAPCOL) { |
701 | put("\n"); | |
702 | col = strlen(s); | |
16b6b22b | 703 | } |
2ea9e68e | 704 | put(s); |
16b6b22b BJ |
705 | } |
706 | ||
b24648a6 MT |
707 | #include <varargs.h> |
708 | ||
709 | put(va_alist) | |
710 | va_dcl | |
16b6b22b | 711 | { |
b24648a6 MT |
712 | char *fmt; |
713 | va_list ap; | |
714 | ||
715 | va_start(ap); | |
716 | fmt = va_arg(ap, char *); | |
717 | (void) vfprintf(OUT, fmt, ap); | |
718 | va_end(ap); | |
16b6b22b BJ |
719 | } |
720 | ||
b24648a6 MT |
721 | |
722 | warning(va_alist) | |
723 | va_dcl | |
2ea9e68e | 724 | { |
b24648a6 MT |
725 | char *fmt; |
726 | va_list ap; | |
727 | ||
2ea9e68e | 728 | fprintf(ERR, "stty: warning: "); |
b24648a6 MT |
729 | va_start(ap); |
730 | fmt = va_arg(ap, char *); | |
731 | (void) vfprintf(ERR, fmt, ap); | |
732 | va_end(ap); | |
2ea9e68e MT |
733 | fprintf(ERR, "\n"); |
734 | } | |
16b6b22b | 735 | |
b24648a6 MT |
736 | |
737 | errexit(va_alist) | |
738 | va_dcl | |
16b6b22b | 739 | { |
b24648a6 MT |
740 | char *fmt; |
741 | va_list ap; | |
742 | ||
2ea9e68e | 743 | fprintf(ERR, "stty: "); |
b24648a6 MT |
744 | va_start(ap); |
745 | fmt = va_arg(ap, char *); | |
746 | (void) vfprintf(ERR, fmt, ap); | |
747 | va_end(ap); | |
2ea9e68e MT |
748 | fprintf(ERR, "\n"); |
749 | exit(1); | |
750 | } | |
16b6b22b | 751 | |
b24648a6 MT |
752 | |
753 | syserrexit(va_alist) | |
754 | va_dcl | |
2ea9e68e | 755 | { |
b24648a6 MT |
756 | char *fmt; |
757 | va_list ap; | |
758 | ||
2ea9e68e | 759 | fprintf(ERR, "stty: "); |
b24648a6 MT |
760 | va_start(ap); |
761 | fmt = va_arg(ap, char *); | |
762 | (void) vfprintf(ERR, fmt, ap); | |
763 | va_end(ap); | |
764 | fprintf(ERR, ": %s\n", strerror(errno)); | |
2ea9e68e | 765 | exit(1); |
16b6b22b | 766 | } |