cleanup, make documentation match program, move config files into /etc
[unix-history] / usr / src / bin / stty / stty.c
CommitLineData
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 8char 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
6d749894 14static char sccsid[] = "@(#)stty.c 5.14 (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 37struct modes {
2ea9e68e
MT
38 char *name;
39 long set;
40 long unset;
41};
42
b24648a6 43struct 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 79struct 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 95struct 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 126struct 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
188struct {
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, },
380b8072 206 {{ "discard", "disc", }, VDISCARD, CDISCARD, },
8d050676
KB
207 {{ "reprint", "rpnt", "rprnt" }, VREPRINT, CREPRINT, },
208 {{ "info", "info" }, VINFO, CINFO, },
2ea9e68e
MT
209 0
210};
8d050676 211
b24648a6
MT
212struct winsize win;
213int ldisc;
214int dodisc;
215int debug = 0;
216int 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 221int ctl = CTL;
2ea9e68e
MT
222
223extern 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
230main(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 }
307 if (eq("cooked", *argv) || eq("-raw", *argv) ||
308 eq("sane", *argv)) {
309 t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL);
310 t.c_iflag = TTYDEF_IFLAG;
311 t.c_iflag |= ICRNL;
312 /* preserve user-preference flags in lflag */
313#define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH)
314 t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP);
315 t.c_oflag = TTYDEF_OFLAG;
c086ab51
MK
316 goto next;
317 }
2ea9e68e
MT
318 if (eq("rows", *argv)) {
319 if (*(argv+1) == 0)
320 goto setit;
4f05342b 321 win.ws_row = atoi(*++argv);
2ea9e68e
MT
322 goto next;
323 }
324 if (eq("ispeed", *argv)) {
325 int code;
326 if (*(argv+1) == 0)
327 errexit("missing ispeed");
328 cfsetispeed(&t, atoi(*++argv));
329 goto next;
330 }
331 if (eq("ospeed", *argv)) {
2ea9e68e
MT
332 if (*(argv+1) == 0)
333 errexit("missing ospeed");
334 cfsetospeed(&t, atoi(*++argv));
335 goto next;
4f05342b 336 }
2ea9e68e
MT
337 if (eq("cols", *argv) || eq("columns", *argv)) {
338 if (*(argv+1) == 0)
339 goto setit;
4f05342b 340 win.ws_col = atoi(*++argv);
2ea9e68e 341 goto next;
4f05342b 342 }
2ea9e68e
MT
343 if (eq("size", *argv)) {
344 put("%d %d\n", win.ws_row, win.ws_col);
d6f0b7e6
MK
345 exit(0);
346 }
2ea9e68e
MT
347 if (eq("speed", *argv)) {
348 put("%d\n", cfgetospeed(&t));
349 exit(0);
350 }
351 for (i=0; imodes[i].name; i++)
352 if (eq(imodes[i].name, *argv)) {
353 t.c_iflag &= ~imodes[i].unset;
354 t.c_iflag |= imodes[i].set;
355 goto next;
356 }
357 for (i=0; omodes[i].name; i++)
358 if (eq(omodes[i].name, *argv)) {
359 t.c_oflag &= ~omodes[i].unset;
360 t.c_oflag |= omodes[i].set;
361 goto next;
16b6b22b 362 }
2ea9e68e
MT
363 for (i=0; cmodes[i].name; i++)
364 if (eq(cmodes[i].name, *argv)) {
365 t.c_cflag &= ~cmodes[i].unset;
366 t.c_cflag |= cmodes[i].set;
367 goto next;
368 }
369 for (i=0; lmodes[i].name; i++)
370 if (eq(lmodes[i].name, *argv)) {
371 t.c_lflag &= ~lmodes[i].unset;
372 t.c_lflag |= lmodes[i].set;
373 goto next;
374 }
375 for (i=0; *cchars[i].names; i++) {
376 char **cp = cchars[i].names;
377 while (*cp) {
378 if (eq(*cp, *argv)) {
379 if (*++argv == 0)
380 goto setit;
381 if (eq(*argv, "undef") ||
382 eq(*argv, "disable"))
383 t.c_cc[cchars[i].sub] =
384 _POSIX_VDISABLE;
385 else if (**argv == '^')
386 t.c_cc[cchars[i].sub] =
387 ((*argv)[1] == '?') ? 0177 :
388 ((*argv)[1] == '-') ?
389 _POSIX_VDISABLE :
390 (*argv)[1] & 037;
391 else
392 t.c_cc[cchars[i].sub] = **argv;
393 goto next;
16b6b22b 394 }
2ea9e68e 395 cp++;
16b6b22b 396 }
2ea9e68e
MT
397 }
398 if (isdigit(**argv)) {
399 cfsetospeed(&t, atoi(*argv));
400 cfsetispeed(&t, atoi(*argv));
401 goto next;
402 }
6d749894
MT
403 if (strncmp(*argv, "-gfmt", sizeof ("-gfmt") - 1) == 0) {
404 gfmtset(&t, *argv);
405 goto next;
406 }
2ea9e68e
MT
407 /* didn't match anything */
408 errexit("unknown option: %s", *argv);
409 exit(1);
410next:
411 argv++;
16b6b22b 412 }
2ea9e68e
MT
413setit:
414 if (tcsetattr(ctl, 0, &t) < 0)
415 syserrexit("tcsetattr");
416 if (ioctl(ctl, TIOCSWINSZ, &win) < 0)
417 warning("can't set window size");
418
419 exit(0);
16b6b22b
BJ
420}
421
6d749894
MT
422gfmtset(tp, s)
423 register struct termios *tp;
424 char *s;
425{
426 register int cnt;
427 char sep;
428 char *saves = s;
429 int cval;
430#define advance(c) while (*(s) && *(s) != (c)) (s)++; if (*s) (s)++ ; \
431 else \
432 errexit("bad gfmt operand: %s", saves)
433#define chkeq(string) if (strncmp(s, (string), strlen(string))) \
434 errexit("bad gfmt operand: %s", saves)
435
436 if (s == NULL)
437 errexit("missing gfmt string");
438 advance(':');
439 chkeq("iflag=");
440 advance('=');
441 sscanf(s, "%x", &tp->c_iflag);
442
443 advance(':');
444 chkeq("oflag");
445 advance('=');
446 sscanf(s, "%x", &tp->c_oflag);
447
448 advance(':');
449 chkeq("cflag");
450 advance('=');
451 sscanf(s, "%x", &tp->c_cflag);
452
453 advance(':');
454 chkeq("lflag");
455 advance('=');
456 sscanf(s, "%x", &tp->c_lflag);
457
458 advance(':');
459 chkeq("cc=");
460
461 for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',') {
462 advance(sep);
463 sscanf(s, "%o", &cval);
464 tp->c_cc[cnt] = cval;
465 }
466
467 advance(':');
468 chkeq("ispeed=");
469 advance('=');
470 sscanf(s, "%d", &tp->c_ispeed);
471
472 advance(':');
473 chkeq("ospeed=");
474 advance('=');
475 sscanf(s, "%d", &tp->c_ospeed);
16b6b22b
BJ
476}
477
2ea9e68e
MT
478prmode(tp, ldisc, fmt)
479 struct termios *tp;
16b6b22b 480{
2ea9e68e
MT
481 long i = tp->c_iflag,
482 o = tp->c_oflag,
483 c = tp->c_cflag,
484 l = tp->c_lflag;
485 u_char *cc = tp->c_cc;
486 int ispeed = cfgetispeed(tp),
487 ospeed = cfgetospeed(tp);
488 char unknown[32],
489 *ld;
490 char *ccval();
16b6b22b 491
6d749894
MT
492 if (fmt == GFMT) {
493 int cnt;
494 char sep;
495
496 printf("-gfmt:iflag=%x:oflag=%x:cflag=%x:lflag=%x:cc",
497 i, o, c, l);
498 for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',')
499 printf("%c%o", sep, cc[cnt]);
500 printf(":ispeed=%d:ospeed=%d:\n", ispeed, ospeed);
501 return;
502 }
503
2ea9e68e
MT
504 /*
505 * line discipline
506 */
507 if (ldisc != TTYDISC) {
508 switch(ldisc) {
509 case TABLDISC:
510 ld = "tablet";
511 break;
512 case SLIPDISC:
b24648a6 513 ld = "slip";
16b6b22b 514 break;
2ea9e68e
MT
515 default:
516 sprintf(unknown, "#%d", ldisc);
517 ld = unknown;
16b6b22b 518 }
2ea9e68e
MT
519 put("%s disc; ", ld);
520 }
521 /*
522 * line speed
523 */
524 if (ispeed != ospeed)
525 put("ispeed %d baud; ospeed %d baud;",
526 ispeed, ospeed);
527 else
528 put("speed %d baud;", ispeed);
529 if (fmt)
530 put(" %d rows; %d columns;", win.ws_row, win.ws_col);
531 put("\n");
532
533#define lput(n, f, d) if (fmt || on(f) != d) mdput(n+on(f))
534 /*
535 * "local" flags
536 */
537#define on(f) ((l&f) != 0)
538 if (debug) mdput("LFLAG: ");
539 lput("-icanon ",ICANON, 1);
540 lput("-isig ", ISIG, 1);
541 lput("-iexten ", IEXTEN, 1);
542 lput("-echo ",ECHO, 1);
543 lput("-echoe ",ECHOE, 0);
544 lput("-echok ",ECHOK, 0);
545 lput("-echoke ",ECHOKE, 0);
546 lput("-echonl ",ECHONL, 0);
547 lput("-echoctl ",ECHOCTL, 0);
548 lput("-echoprt ",ECHOPRT, 0);
549 lput("-altwerase ",ALTWERASE, 0);
550 lput("-noflsh ",NOFLSH, 0);
551 lput("-tostop ",TOSTOP, 0);
552 lput("-mdmbuf ",MDMBUF, 0);
2ea9e68e
MT
553 lput("-flusho ",FLUSHO, 0);
554 lput("-pendin ",PENDIN, 0);
555 /*
556 * input flags
557 */
558#undef on
559#define on(f) ((i&f) != 0)
560 mdput(0);
561 if (debug) mdput("IFLAG: ");
562 lput("-istrip ", ISTRIP, 0);
563 lput("-icrnl ", ICRNL, 1);
564 lput("-inlcr ", INLCR, 0);
565 lput("-igncr ", IGNCR, 0);
566 lput("-ixon ", IXON, 1);
567 lput("-ixoff ", IXOFF, 0);
568 lput("-ixany ", IXANY, 1);
569 lput("-imaxbel ", IMAXBEL, 1);
570 lput("-ignbrk ", IGNBRK, 0);
571 lput("-brkint ", BRKINT, 1);
572 lput("-inpck ", INPCK, 0);
573 lput("-ignpar ", IGNPAR, 0);
574 lput("-parmrk ", PARMRK, 0);
575#undef on
576 /*
577 * output flags
578 */
579#define on(f) ((o&f) != 0)
580 mdput(0);
581 if (debug) mdput("OFLAG: ");
582 lput("-opost ", OPOST, 1);
583 lput("-onlcr ", ONLCR, 1);
584 lput("-oxtabs ", OXTABS, 1);
585#undef on
586 /*
587 * control flags (hardware state)
588 */
589#define on(f) ((c&f) != 0)
590 mdput(0);
591 if (debug) mdput("CFLAG: ");
592 lput("-cread ", CREAD, 1);
593 switch(c&CSIZE) {
594 case CS5: mdput("cs5 "); break;
595 case CS6: mdput("cs6 "); break;
596 case CS7: mdput("cs7 "); break;
597 case CS8: mdput("cs8 "); break;
598 }
599 mdput("-parenb "+on(PARENB));
600 lput("-parodd ", PARODD, 0);
601 lput("-hupcl ", HUPCL, 1);
602 lput("-clocal ", CLOCAL, 0);
603 lput("-cstopb ", CSTOPB, 0);
604 lput("-crtscts ", CRTSCTS, 0);
605 mdput(0);
606#undef on
607 /*
608 * special control characters
609 */
610 if (debug) mdput("CCHARS: ");
611 if (fmt != 2) {
612 for (i=0; *cchars[i].names; i++) {
613 char temp[64];
614
615 if (fmt || cc[cchars[i].sub] != cchars[i].def) {
616 sprintf(temp, "%s = %s; ", *cchars[i].names,
617 ccval(cc[cchars[i].sub]), fmt);
618 mdput(temp);
619 }
16b6b22b 620 }
2ea9e68e
MT
621 mdput(0);
622 } else {
623 for (i=0; *cchars[i].names; i++)
624 put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0),
625 *(cchars[i].names+1));
626 printf("\n");
627 for (i=0; *cchars[i].names; i++)
628 put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0),
629 ccval(cc[cchars[i].sub], fmt));
630 printf("\n");
16b6b22b
BJ
631 }
632}
633
2ea9e68e
MT
634/*
635 * gross, but since we're changing the control descriptor
636 * from 1 to 0, most users will be probably be doing
637 * "stty > /dev/sometty" by accident. If 1 and 2 are both ttys,
638 * but not the same, assume that 1 was incorrectly redirected.
639 */
640checkredirect() {
641 struct stat st1, st2;
642
643 if (isatty(1) && isatty(2) && fstat(1, &st1) != -1 &&
644 fstat(2, &st2) != -1 && (st1.st_rdev != st2.st_rdev))
645warning("stdout appears redirected, but stdin is the control descriptor");
646}
2ea9e68e 647
b24648a6 648char *
2ea9e68e
MT
649ccval(c, fmt)
650 unsigned char c;
16b6b22b 651{
2ea9e68e
MT
652 static char buf[128];
653 char *bp;
654
655 *buf = 0, bp = buf;
656 if (c == _POSIX_VDISABLE)
657 if (fmt == 2)
658 return("<u>");
659 else
660 return("<undef>");
661 if (c & 0200) {
662 strcat(buf, "M-");
663 *bp++ = 'M';
664 *bp++ = '-';
665 c &= 0177;
666 }
667 if (c == 0177) {
668 *bp++ = '^';
669 *bp++ = '?';
16b6b22b 670 }
2ea9e68e
MT
671 else if (c < 040) {
672 *bp++ = '^';
673 *bp++ = c + '@';
16b6b22b 674 }
2ea9e68e
MT
675 else
676 *bp++ = c;
677 *bp = 0;
678 return(buf);
16b6b22b
BJ
679}
680
b24648a6 681
2ea9e68e
MT
682mdput(s)
683 char *s;
16b6b22b 684{
2ea9e68e 685 static int col = 0;
16b6b22b 686
2ea9e68e
MT
687 if (s == (char *)0) {
688 if (col) {
689 put("\n");
690 col = 0;
691 }
16b6b22b
BJ
692 return;
693 }
2ea9e68e
MT
694 if ((col += strlen(s)) > WRAPCOL) {
695 put("\n");
696 col = strlen(s);
16b6b22b 697 }
2ea9e68e 698 put(s);
16b6b22b
BJ
699}
700
b24648a6
MT
701#include <varargs.h>
702
703put(va_alist)
704 va_dcl
16b6b22b 705{
b24648a6
MT
706 char *fmt;
707 va_list ap;
708
709 va_start(ap);
710 fmt = va_arg(ap, char *);
711 (void) vfprintf(OUT, fmt, ap);
712 va_end(ap);
16b6b22b
BJ
713}
714
b24648a6
MT
715
716warning(va_alist)
717 va_dcl
2ea9e68e 718{
b24648a6
MT
719 char *fmt;
720 va_list ap;
721
2ea9e68e 722 fprintf(ERR, "stty: warning: ");
b24648a6
MT
723 va_start(ap);
724 fmt = va_arg(ap, char *);
725 (void) vfprintf(ERR, fmt, ap);
726 va_end(ap);
2ea9e68e
MT
727 fprintf(ERR, "\n");
728}
16b6b22b 729
b24648a6
MT
730
731errexit(va_alist)
732 va_dcl
16b6b22b 733{
b24648a6
MT
734 char *fmt;
735 va_list ap;
736
2ea9e68e 737 fprintf(ERR, "stty: ");
b24648a6
MT
738 va_start(ap);
739 fmt = va_arg(ap, char *);
740 (void) vfprintf(ERR, fmt, ap);
741 va_end(ap);
2ea9e68e
MT
742 fprintf(ERR, "\n");
743 exit(1);
744}
16b6b22b 745
b24648a6
MT
746
747syserrexit(va_alist)
748 va_dcl
2ea9e68e 749{
b24648a6
MT
750 char *fmt;
751 va_list ap;
752
2ea9e68e 753 fprintf(ERR, "stty: ");
b24648a6
MT
754 va_start(ap);
755 fmt = va_arg(ap, char *);
756 (void) vfprintf(ERR, fmt, ap);
757 va_end(ap);
758 fprintf(ERR, ": %s\n", strerror(errno));
2ea9e68e 759 exit(1);
16b6b22b 760}