put in cbreak and -cbreak (fudge)
[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
be51e567 14static 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 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, },
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
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 }
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);
416next:
417 argv++;
16b6b22b 418 }
2ea9e68e
MT
419setit:
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
428gfmtset(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
484prmode(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 */
646checkredirect() {
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))
651warning("stdout appears redirected, but stdin is the control descriptor");
652}
2ea9e68e 653
b24648a6 654char *
2ea9e68e
MT
655ccval(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
688mdput(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
709put(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
722warning(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
737errexit(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
753syserrexit(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}