copy -> bcopy (more than vax and tahoe now)
[unix-history] / usr / src / bin / stty / stty.c
CommitLineData
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 8char 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 14static 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 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,
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
192struct {
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
216struct winsize win;
217int ldisc;
b24648a6
MT
218int debug = 0;
219int trace, dotrace;
b893a630 220int 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 225int ctl = CTL;
2ea9e68e
MT
226
227extern 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
234main(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);
428next:
429 argv++;
16b6b22b 430 }
2ea9e68e
MT
431setit:
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
440gfmtset(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
496prmode(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 */
661checkredirect() {
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))
666warning("stdout appears redirected, but stdin is the control descriptor");
667}
2ea9e68e 668
b24648a6 669char *
2ea9e68e
MT
670ccval(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
703mdput(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
724put(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
737warning(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
752errexit(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
768syserrexit(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}