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