merge with 1.8.1d
[coreutils.git] / src / stty.c
blob4f97981ae2c610f64e035d9a76dab12ed5e46971
1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Usage: stty [-ag] [--all] [--save] [setting...]
20 Options:
21 -a, --all Write all current settings to stdout in human-readable form.
22 -g, --save Write all current settings to stdout in stty-readable form.
24 If no args are given, write to stdout the baud rate and settings that
25 have been changed from their defaults. Mode reading and changes
26 are done on stdin.
28 David MacKenzie <djm@gnu.ai.mit.edu> */
30 #ifdef HAVE_CONFIG_H
31 #if defined (CONFIG_BROKETS)
32 /* We use <config.h> instead of "config.h" so that a compilation
33 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
34 (which it would do because it found this file in $srcdir). */
35 #include <config.h>
36 #else
37 #include "config.h"
38 #endif
39 #endif
41 #include <stdio.h>
42 #include <sys/types.h>
43 #include <termios.h>
44 #ifdef GWINSZ_IN_SYS_IOCTL
45 #include <sys/ioctl.h>
46 #endif
47 #ifdef WINSIZE_IN_PTEM
48 #include <sys/stream.h>
49 #include <sys/ptem.h>
50 #endif
51 #include <getopt.h>
52 #ifdef __STDC__
53 #include <stdarg.h>
54 #define VA_START(args, lastarg) va_start(args, lastarg)
55 #else
56 #include <varargs.h>
57 #define VA_START(args, lastarg) va_start(args)
58 #endif
60 #include "system.h"
61 #include "version.h"
63 #if defined(GWINSZ_BROKEN) /* Such as for SCO UNIX 3.2.2. */
64 #undef TIOCGWINSZ
65 #endif
67 #ifndef _POSIX_VDISABLE
68 #define _POSIX_VDISABLE ((unsigned char) 0)
69 #endif
71 #define Control(c) ((c) & 0x1f)
72 /* Canonical values for control characters. */
73 #ifndef CINTR
74 #define CINTR Control ('c')
75 #endif
76 #ifndef CQUIT
77 #define CQUIT 28
78 #endif
79 #ifndef CERASE
80 #define CERASE 127
81 #endif
82 #ifndef CKILL
83 #define CKILL Control ('u')
84 #endif
85 #ifndef CEOF
86 #define CEOF Control ('d')
87 #endif
88 #ifndef CEOL
89 #define CEOL _POSIX_VDISABLE
90 #endif
91 #ifndef CSTART
92 #define CSTART Control ('q')
93 #endif
94 #ifndef CSTOP
95 #define CSTOP Control ('s')
96 #endif
97 #ifndef CSUSP
98 #define CSUSP Control ('z')
99 #endif
100 #if defined(VEOL2) && !defined(CEOL2)
101 #define CEOL2 _POSIX_VDISABLE
102 #endif
103 #if defined(VSWTCH) && !defined(CSWTCH)
104 #define CSWTCH _POSIX_VDISABLE
105 #endif
106 #if defined(VDSUSP) && !defined (CDSUSP)
107 #define CDSUSP Control ('y')
108 #endif
109 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
110 #define VREPRINT VRPRNT
111 #endif
112 #if defined(VREPRINT) && !defined(CRPRNT)
113 #define CRPRNT Control ('r')
114 #endif
115 #if defined(VWERASE) && !defined(CWERASE)
116 #define CWERASE Control ('w')
117 #endif
118 #if defined(VLNEXT) && !defined(CLNEXT)
119 #define CLNEXT Control ('v')
120 #endif
121 #if defined(VFLUSHO) && !defined(CFLUSHO)
122 #define CFLUSHO Control ('o')
123 #endif
125 char *visible ();
126 unsigned long baud_to_value ();
127 int recover_mode ();
128 int screen_columns ();
129 int set_mode ();
130 long integer_arg ();
131 speed_t string_to_baud ();
132 tcflag_t *mode_type_flag ();
133 void display_all ();
134 void display_changed ();
135 void display_recoverable ();
136 void display_settings ();
137 void display_speed ();
138 void display_window_size ();
139 void error ();
140 void sane_mode ();
141 void set_control_char ();
142 void set_speed ();
143 void set_window_size ();
145 /* Which speeds to set. */
146 enum speed_setting
148 input_speed, output_speed, both_speeds
151 /* What to output and how. */
152 enum output_type
154 changed, all, recoverable /* Default, -a, -g. */
157 /* Which member(s) of `struct termios' a mode uses. */
158 enum mode_type
160 control, input, output, local, combination
163 /* Flags for `struct mode_info'. */
164 #define SANE_SET 1 /* Set in `sane' mode. */
165 #define SANE_UNSET 2 /* Unset in `sane' mode. */
166 #define REV 4 /* Can be turned off by prepending `-'. */
167 #define OMIT 8 /* Don't display value. */
169 /* Each mode. */
170 struct mode_info
172 char *name; /* Name given on command line. */
173 enum mode_type type; /* Which structure element to change. */
174 char flags; /* Setting and display options. */
175 unsigned long bits; /* Bits to set for this mode. */
176 unsigned long mask; /* Other bits to turn off for this mode. */
179 static struct mode_info mode_info[] =
181 {"parenb", control, REV, PARENB, 0},
182 {"parodd", control, REV, PARODD, 0},
183 {"cs5", control, 0, CS5, CSIZE},
184 {"cs6", control, 0, CS6, CSIZE},
185 {"cs7", control, 0, CS7, CSIZE},
186 {"cs8", control, 0, CS8, CSIZE},
187 {"hupcl", control, REV, HUPCL, 0},
188 {"hup", control, REV | OMIT, HUPCL, 0},
189 {"cstopb", control, REV, CSTOPB, 0},
190 {"cread", control, SANE_SET | REV, CREAD, 0},
191 {"clocal", control, REV, CLOCAL, 0},
192 #ifdef CRTSCTS
193 {"crtscts", control, REV, CRTSCTS, 0},
194 #endif
196 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
197 {"brkint", input, SANE_SET | REV, BRKINT, 0},
198 {"ignpar", input, REV, IGNPAR, 0},
199 {"parmrk", input, REV, PARMRK, 0},
200 {"inpck", input, REV, INPCK, 0},
201 {"istrip", input, REV, ISTRIP, 0},
202 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
203 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
204 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
205 {"ixon", input, REV, IXON, 0},
206 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
207 {"tandem", input, REV | OMIT, IXOFF, 0},
208 #ifdef IUCLC
209 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
210 #endif
211 #ifdef IXANY
212 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
213 #endif
214 #ifdef IMAXBEL
215 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
216 #endif
218 {"opost", output, SANE_SET | REV, OPOST, 0},
219 #ifdef OLCUC
220 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
221 #endif
222 #ifdef OCRNL
223 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
224 #endif
225 #ifdef ONLCR
226 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
227 #endif
228 #ifdef ONOCR
229 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
230 #endif
231 #ifdef ONLRET
232 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
233 #endif
234 #ifdef OFILL
235 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
236 #endif
237 #ifdef OFDEL
238 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
239 #endif
240 #ifdef NLDLY
241 {"nl1", output, SANE_UNSET, NL1, NLDLY},
242 {"nl0", output, SANE_SET, NL0, NLDLY},
243 #endif
244 #ifdef CRDLY
245 {"cr3", output, SANE_UNSET, CR3, CRDLY},
246 {"cr2", output, SANE_UNSET, CR2, CRDLY},
247 {"cr1", output, SANE_UNSET, CR1, CRDLY},
248 {"cr0", output, SANE_SET, CR0, CRDLY},
249 #endif
250 #ifdef TABDLY
251 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
252 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
253 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
254 {"tab0", output, SANE_SET, TAB0, TABDLY},
255 #endif
256 #ifdef BSDLY
257 {"bs1", output, SANE_UNSET, BS1, BSDLY},
258 {"bs0", output, SANE_SET, BS0, BSDLY},
259 #endif
260 #ifdef VTDLY
261 {"vt1", output, SANE_UNSET, VT1, VTDLY},
262 {"vt0", output, SANE_SET, VT0, VTDLY},
263 #endif
264 #ifdef FFDLY
265 {"ff1", output, SANE_UNSET, FF1, FFDLY},
266 {"ff0", output, SANE_SET, FF0, FFDLY},
267 #endif
269 {"isig", local, SANE_SET | REV, ISIG, 0},
270 {"icanon", local, SANE_SET | REV, ICANON, 0},
271 #ifdef IEXTEN
272 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
273 #endif
274 {"echo", local, SANE_SET | REV, ECHO, 0},
275 {"echoe", local, SANE_SET | REV, ECHOE, 0},
276 {"crterase", local, REV | OMIT, ECHOE, 0},
277 {"echok", local, SANE_SET | REV, ECHOK, 0},
278 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
279 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
280 #ifdef XCASE
281 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
282 #endif
283 #ifdef TOSTOP
284 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
285 #endif
286 #ifdef ECHOPRT
287 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
288 {"prterase", local, REV | OMIT, ECHOPRT, 0},
289 #endif
290 #ifdef ECHOCTL
291 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
292 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
293 #endif
294 #ifdef ECHOKE
295 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
296 {"crtkill", local, REV | OMIT, ECHOKE, 0},
297 #endif
299 {"evenp", combination, REV | OMIT, 0, 0},
300 {"parity", combination, REV | OMIT, 0, 0},
301 {"oddp", combination, REV | OMIT, 0, 0},
302 {"nl", combination, REV | OMIT, 0, 0},
303 {"ek", combination, OMIT, 0, 0},
304 {"sane", combination, OMIT, 0, 0},
305 {"cooked", combination, REV | OMIT, 0, 0},
306 {"raw", combination, REV | OMIT, 0, 0},
307 {"pass8", combination, REV | OMIT, 0, 0},
308 {"litout", combination, REV | OMIT, 0, 0},
309 {"cbreak", combination, REV | OMIT, 0, 0},
310 #ifdef IXANY
311 {"decctlq", combination, REV | OMIT, 0, 0},
312 #endif
313 #ifdef TABDLY
314 {"tabs", combination, REV | OMIT, 0, 0},
315 #endif
316 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
317 {"lcase", combination, REV | OMIT, 0, 0},
318 {"LCASE", combination, REV | OMIT, 0, 0},
319 #endif
320 {"crt", combination, OMIT, 0, 0},
321 {"dec", combination, OMIT, 0, 0},
323 {NULL, control, 0, 0, 0}
326 /* Control character settings. */
327 struct control_info
329 char *name; /* Name given on command line. */
330 unsigned char saneval; /* Value to set for `stty sane'. */
331 int offset; /* Offset in c_cc. */
334 /* Control characters. */
336 static struct control_info control_info[] =
338 {"intr", CINTR, VINTR},
339 {"quit", CQUIT, VQUIT},
340 {"erase", CERASE, VERASE},
341 {"kill", CKILL, VKILL},
342 {"eof", CEOF, VEOF},
343 {"eol", CEOL, VEOL},
344 #ifdef VEOL2
345 {"eol2", CEOL2, VEOL2},
346 #endif
347 #ifdef VSWTCH
348 {"swtch", CSWTCH, VSWTCH},
349 #endif
350 {"start", CSTART, VSTART},
351 {"stop", CSTOP, VSTOP},
352 {"susp", CSUSP, VSUSP},
353 #ifdef VDSUSP
354 {"dsusp", CDSUSP, VDSUSP},
355 #endif
356 #ifdef VREPRINT
357 {"rprnt", CRPRNT, VREPRINT},
358 #endif
359 #ifdef VWERASE
360 {"werase", CWERASE, VWERASE},
361 #endif
362 #ifdef VLNEXT
363 {"lnext", CLNEXT, VLNEXT},
364 #endif
365 #ifdef VFLUSHO
366 {"flush", CFLUSHO, VFLUSHO},
367 #endif
369 /* These must be last because of the display routines. */
370 {"min", 1, VMIN},
371 {"time", 0, VTIME},
372 {NULL, 0, 0}
375 /* The width of the screen, for output wrapping. */
376 static int max_col;
378 /* Current position, to know when to wrap. */
379 static int current_col;
381 /* If non-zero, display usage information and exit. */
382 static int show_help;
384 /* If non-zero, print the version on standard output and exit. */
385 static int show_version;
387 static struct option longopts[] =
389 {"all", no_argument, NULL, 'a'},
390 {"help", no_argument, &show_help, 1},
391 {"save", no_argument, NULL, 'g'},
392 {"version", no_argument, &show_version, 1},
393 {NULL, 0, NULL, 0}
396 /* The name this program was run with. */
397 char *program_name;
399 /* Print format string MESSAGE and optional args.
400 Wrap to next line first if it won't fit.
401 Print a space first unless MESSAGE will start a new line. */
403 /* VARARGS */
404 void
405 #ifdef __STDC__
406 wrapf (char *message, ...)
407 #else
408 wrapf (message, va_alist)
409 char *message;
410 va_dcl
411 #endif
413 va_list args;
414 char buf[1024]; /* Plenty long for our needs. */
415 int buflen;
417 VA_START (args, message);
418 vsprintf (buf, message, args);
419 va_end (args);
420 buflen = strlen (buf);
421 if (current_col + buflen >= max_col)
423 putchar ('\n');
424 current_col = 0;
426 if (current_col > 0)
428 putchar (' ');
429 current_col++;
431 fputs (buf, stdout);
432 current_col += buflen;
435 static void
436 usage ()
438 fprintf (stderr,
439 "Usage: %s [{--help,--version}] [-ag] [--all] [--save] [setting...]\n",
440 program_name);
441 exit (1);
444 void
445 main (argc, argv)
446 int argc;
447 char **argv;
449 struct termios mode;
450 enum output_type output_type = changed;
451 int optc;
453 program_name = argv[0];
454 opterr = 0;
456 while ((optc = getopt_long (argc, argv, "ag", longopts, (int *) 0)) != EOF)
458 switch (optc)
460 case 0:
461 break;
463 case 'a':
464 output_type = all;
465 break;
467 case 'g':
468 output_type = recoverable;
469 break;
471 default:
472 goto done;
476 done:;
478 if (show_version)
480 printf ("%s\n", version_string);
481 exit (0);
484 if (show_help)
485 usage ();
487 if (tcgetattr (0, &mode))
488 error (1, errno, "standard input");
490 max_col = screen_columns ();
491 current_col = 0;
493 if (optind == argc)
495 if (optc == '?')
496 error (1, 0, "invalid argument `%s'", argv[--optind]);
497 display_settings (output_type, &mode);
498 exit (0);
501 while (optind < argc)
503 int match_found = 0;
504 int reversed = 0;
505 int i;
507 if (argv[optind][0] == '-')
509 ++argv[optind];
510 reversed = 1;
512 for (i = 0; mode_info[i].name != NULL; ++i)
514 if (!strcmp (argv[optind], mode_info[i].name))
516 match_found = set_mode (&mode_info[i], reversed, &mode);
517 break;
520 if (match_found == 0 && reversed)
521 error (1, 0, "invalid argument `%s'", --argv[optind]);
522 if (match_found == 0)
524 for (i = 0; control_info[i].name != NULL; ++i)
526 if (!strcmp (argv[optind], control_info[i].name))
528 if (optind == argc - 1)
529 error (1, 0, "missing argument to `%s'", argv[optind]);
530 match_found = 1;
531 ++optind;
532 set_control_char (&control_info[i], argv[optind], &mode);
533 break;
537 if (match_found == 0)
539 if (!strcmp (argv[optind], "ispeed"))
541 if (optind == argc - 1)
542 error (1, 0, "missing argument to `%s'", argv[optind]);
543 ++optind;
544 set_speed (input_speed, argv[optind], &mode);
546 else if (!strcmp (argv[optind], "ospeed"))
548 if (optind == argc - 1)
549 error (1, 0, "missing argument to `%s'", argv[optind]);
550 ++optind;
551 set_speed (output_speed, argv[optind], &mode);
553 #ifdef TIOCGWINSZ
554 else if (!strcmp (argv[optind], "rows"))
556 if (optind == argc - 1)
557 error (1, 0, "missing argument to `%s'", argv[optind]);
558 ++optind;
559 set_window_size ((int) integer_arg (argv[optind]), -1);
561 else if (!strcmp (argv[optind], "cols")
562 || !strcmp (argv[optind], "columns"))
564 if (optind == argc - 1)
565 error (1, 0, "missing argument to `%s'", argv[optind]);
566 ++optind;
567 set_window_size (-1, (int) integer_arg (argv[optind]));
569 else if (!strcmp (argv[optind], "size"))
570 display_window_size (0);
571 #endif
572 #ifdef HAVE_C_LINE
573 else if (!strcmp (argv[optind], "line"))
575 if (optind == argc - 1)
576 error (1, 0, "missing argument to `%s'", argv[optind]);
577 ++optind;
578 mode.c_line = integer_arg (argv[optind]);
580 #endif
581 else if (!strcmp (argv[optind], "speed"))
582 display_speed (&mode, 0);
583 else if (string_to_baud (argv[optind]) != (speed_t) -1)
584 set_speed (both_speeds, argv[optind], &mode);
585 else if (recover_mode (argv[optind], &mode) == 0)
586 error (1, 0, "invalid argument `%s'", argv[optind]);
588 optind++;
591 if (tcsetattr (0, TCSADRAIN, &mode))
592 error (1, errno, "standard input");
594 exit (0);
597 /* Return 0 if not applied because not reversible; otherwise return 1. */
600 set_mode (info, reversed, mode)
601 struct mode_info *info;
602 int reversed;
603 struct termios *mode;
605 tcflag_t *bitsp;
607 if (reversed && (info->flags & REV) == 0)
608 return 0;
610 bitsp = mode_type_flag (info->type, mode);
612 if (bitsp == NULL)
614 /* Combination mode. */
615 if (!strcmp (info->name, "evenp") || !strcmp (info->name, "parity"))
617 if (reversed)
618 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
619 else
620 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
622 else if (!strcmp (info->name, "oddp"))
624 if (reversed)
625 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
626 else
627 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
629 else if (!strcmp (info->name, "nl"))
631 if (reversed)
633 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
634 mode->c_oflag = (mode->c_oflag
635 #ifdef ONLCR
636 | ONLCR
637 #endif
639 #ifdef OCRNL
640 & ~OCRNL
641 #endif
642 #ifdef ONLRET
643 & ~ONLRET
644 #endif
647 else
649 mode->c_iflag = mode->c_iflag & ~ICRNL;
650 #ifdef ONLCR
651 mode->c_oflag = mode->c_oflag & ~ONLCR;
652 #endif
655 else if (!strcmp (info->name, "ek"))
657 mode->c_cc[VERASE] = CERASE;
658 mode->c_cc[VKILL] = CKILL;
660 else if (!strcmp (info->name, "sane"))
661 sane_mode (mode);
662 else if (!strcmp (info->name, "cbreak"))
664 if (reversed)
665 mode->c_lflag |= ICANON;
666 else
667 mode->c_lflag &= ~ICANON;
669 else if (!strcmp (info->name, "pass8"))
671 if (reversed)
673 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
674 mode->c_iflag |= ISTRIP;
676 else
678 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
679 mode->c_iflag &= ~ISTRIP;
682 else if (!strcmp (info->name, "litout"))
684 if (reversed)
686 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
687 mode->c_iflag |= ISTRIP;
688 mode->c_oflag |= OPOST;
690 else
692 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
693 mode->c_iflag &= ~ISTRIP;
694 mode->c_oflag &= ~OPOST;
697 else if (!strcmp (info->name, "raw") || !strcmp (info->name, "cooked"))
699 if ((info->name[0] == 'r' && reversed)
700 || (info->name[0] == 'c' && !reversed))
702 /* Cooked mode. */
703 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
704 mode->c_oflag |= OPOST;
705 mode->c_lflag |= ISIG | ICANON;
706 #if VMIN == VEOF
707 mode->c_cc[VEOF] = CEOF;
708 #endif
709 #if VTIME == VEOL
710 mode->c_cc[VEOL] = CEOL;
711 #endif
713 else
715 /* Raw mode. */
716 mode->c_iflag = 0;
717 mode->c_oflag &= ~OPOST;
718 mode->c_lflag &= ~(ISIG | ICANON
719 #ifdef XCASE
720 | XCASE
721 #endif
723 mode->c_cc[VMIN] = 1;
724 mode->c_cc[VTIME] = 0;
727 #ifdef IXANY
728 else if (!strcmp (info->name, "decctlq"))
730 if (reversed)
731 mode->c_iflag |= IXANY;
732 else
733 mode->c_iflag &= ~IXANY;
735 #endif
736 #ifdef TABDLY
737 else if (!strcmp (info->name, "tabs"))
739 if (reversed)
740 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
741 else
742 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
744 #endif
745 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
746 else if (!strcmp (info->name, "lcase")
747 || !strcmp (info->name, "LCASE"))
749 if (reversed)
751 mode->c_lflag &= ~XCASE;
752 mode->c_iflag &= ~IUCLC;
753 mode->c_oflag &= ~OLCUC;
755 else
757 mode->c_lflag |= XCASE;
758 mode->c_iflag |= IUCLC;
759 mode->c_oflag |= OLCUC;
762 #endif
763 else if (!strcmp (info->name, "crt"))
764 mode->c_lflag |= ECHOE
765 #ifdef ECHOCTL
766 | ECHOCTL
767 #endif
768 #ifdef ECHOKE
769 | ECHOKE
770 #endif
772 else if (!strcmp (info->name, "dec"))
774 mode->c_cc[VINTR] = 3; /* ^C */
775 mode->c_cc[VERASE] = 127; /* DEL */
776 mode->c_cc[VKILL] = 21; /* ^U */
777 mode->c_lflag |= ECHOE
778 #ifdef ECHOCTL
779 | ECHOCTL
780 #endif
781 #ifdef ECHOKE
782 | ECHOKE
783 #endif
785 #ifdef IXANY
786 mode->c_iflag &= ~IXANY;
787 #endif
790 else if (reversed)
791 *bitsp = *bitsp & ~info->mask & ~info->bits;
792 else
793 *bitsp = (*bitsp & ~info->mask) | info->bits;
795 return 1;
798 void
799 set_control_char (info, arg, mode)
800 struct control_info *info;
801 char *arg;
802 struct termios *mode;
804 unsigned char value;
806 if (!strcmp (info->name, "min") || !strcmp (info->name, "time"))
807 value = integer_arg (arg);
808 else if (arg[0] == '\0' || arg[1] == '\0')
809 value = arg[0];
810 else if (!strcmp (arg, "^-") || !strcmp (arg, "undef"))
811 value = _POSIX_VDISABLE;
812 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
814 if (arg[1] == '?')
815 value = 127;
816 else
817 value = arg[1] & ~0140; /* Non-letters get weird results. */
819 else
820 value = integer_arg (arg);
821 mode->c_cc[info->offset] = value;
824 void
825 set_speed (type, arg, mode)
826 enum speed_setting type;
827 char *arg;
828 struct termios *mode;
830 speed_t baud;
832 baud = string_to_baud (arg);
833 if (type == input_speed || type == both_speeds)
834 cfsetispeed (mode, baud);
835 if (type == output_speed || type == both_speeds)
836 cfsetospeed (mode, baud);
839 #ifdef TIOCGWINSZ
840 void
841 set_window_size (rows, cols)
842 int rows, cols;
844 struct winsize win;
846 if (ioctl (0, TIOCGWINSZ, (char *) &win))
847 error (1, errno, "standard input");
848 if (rows >= 0)
849 win.ws_row = rows;
850 if (cols >= 0)
851 win.ws_col = cols;
852 if (ioctl (0, TIOCSWINSZ, (char *) &win))
853 error (1, errno, "standard input");
856 void
857 display_window_size (fancy)
858 int fancy;
860 struct winsize win;
862 if (ioctl (0, TIOCGWINSZ, (char *) &win))
863 error (1, errno, "standard input");
864 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n", win.ws_row, win.ws_col);
865 if (!fancy)
866 current_col = 0;
868 #endif
871 screen_columns ()
873 #ifdef TIOCGWINSZ
874 struct winsize win;
876 if (ioctl (0, TIOCGWINSZ, (char *) &win))
877 error (1, errno, "standard input");
878 if (win.ws_col > 0)
879 return win.ws_col;
880 #endif
881 if (getenv ("COLUMNS"))
882 return atoi (getenv ("COLUMNS"));
883 return 80;
886 tcflag_t *
887 mode_type_flag (type, mode)
888 enum mode_type type;
889 struct termios *mode;
891 switch (type)
893 case control:
894 return &mode->c_cflag;
896 case input:
897 return &mode->c_iflag;
899 case output:
900 return &mode->c_oflag;
902 case local:
903 return &mode->c_lflag;
905 case combination:
906 return NULL;
908 default:
909 abort ();
913 void
914 display_settings (output_type, mode)
915 enum output_type output_type;
916 struct termios *mode;
918 switch (output_type)
920 case changed:
921 display_changed (mode);
922 break;
924 case all:
925 display_all (mode);
926 break;
928 case recoverable:
929 display_recoverable (mode);
930 break;
934 void
935 display_changed (mode)
936 struct termios *mode;
938 int i;
939 int empty_line;
940 tcflag_t *bitsp;
941 unsigned long mask;
942 enum mode_type prev_type = control;
944 display_speed (mode, 1);
945 #ifdef HAVE_C_LINE
946 wrapf ("line = %d;", mode->c_line);
947 #endif
948 putchar ('\n');
949 current_col = 0;
951 empty_line = 1;
952 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
954 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
955 continue;
956 empty_line = 0;
957 wrapf ("%s = %s;", control_info[i].name,
958 visible (mode->c_cc[control_info[i].offset]));
960 if ((mode->c_lflag & ICANON) == 0)
962 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
963 (int) mode->c_cc[VTIME]);
965 else if (empty_line == 0)
966 putchar ('\n');
967 current_col = 0;
969 empty_line = 1;
970 for (i = 0; mode_info[i].name != NULL; ++i)
972 if (mode_info[i].flags & OMIT)
973 continue;
974 if (mode_info[i].type != prev_type)
976 if (empty_line == 0)
978 putchar ('\n');
979 current_col = 0;
980 empty_line = 1;
982 prev_type = mode_info[i].type;
985 bitsp = mode_type_flag (mode_info[i].type, mode);
986 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
987 if ((*bitsp & mask) == mode_info[i].bits)
989 if (mode_info[i].flags & SANE_UNSET)
991 wrapf ("%s", mode_info[i].name);
992 empty_line = 0;
995 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
997 wrapf ("-%s", mode_info[i].name);
998 empty_line = 0;
1001 if (empty_line == 0)
1002 putchar ('\n');
1003 current_col = 0;
1006 void
1007 display_all (mode)
1008 struct termios *mode;
1010 int i;
1011 tcflag_t *bitsp;
1012 unsigned long mask;
1013 enum mode_type prev_type = control;
1015 display_speed (mode, 1);
1016 #ifdef TIOCGWINSZ
1017 display_window_size (1);
1018 #endif
1019 #ifdef HAVE_C_LINE
1020 wrapf ("line = %d;", mode->c_line);
1021 #endif
1022 putchar ('\n');
1023 current_col = 0;
1025 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1027 wrapf ("%s = %s;", control_info[i].name,
1028 visible (mode->c_cc[control_info[i].offset]));
1030 wrapf ("min = %d; time = %d;\n", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1031 current_col = 0;
1033 for (i = 0; mode_info[i].name != NULL; ++i)
1035 if (mode_info[i].flags & OMIT)
1036 continue;
1037 if (mode_info[i].type != prev_type)
1039 putchar ('\n');
1040 current_col = 0;
1041 prev_type = mode_info[i].type;
1044 bitsp = mode_type_flag (mode_info[i].type, mode);
1045 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1046 if ((*bitsp & mask) == mode_info[i].bits)
1047 wrapf ("%s", mode_info[i].name);
1048 else if (mode_info[i].flags & REV)
1049 wrapf ("-%s", mode_info[i].name);
1051 putchar ('\n');
1052 current_col = 0;
1055 void
1056 display_speed (mode, fancy)
1057 struct termios *mode;
1058 int fancy;
1060 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1061 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1062 baud_to_value (cfgetospeed (mode)));
1063 else
1064 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1065 baud_to_value (cfgetispeed (mode)),
1066 baud_to_value (cfgetospeed (mode)));
1067 if (!fancy)
1068 current_col = 0;
1071 void
1072 display_recoverable (mode)
1073 struct termios *mode;
1075 int i;
1077 printf ("%lx:%lx:%lx:%lx",
1078 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1079 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1080 for (i = 0; i < NCCS; ++i)
1081 printf (":%x", (unsigned int) mode->c_cc[i]);
1082 putchar ('\n');
1086 recover_mode (arg, mode)
1087 char *arg;
1088 struct termios *mode;
1090 int i, n;
1091 unsigned int chr;
1092 unsigned long iflag, oflag, cflag, lflag;
1094 /* Scan into temporaries since it is too much trouble to figure out
1095 the right format for `tcflag_t'. */
1096 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1097 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1098 return 0;
1099 mode->c_iflag = iflag;
1100 mode->c_oflag = oflag;
1101 mode->c_cflag = cflag;
1102 mode->c_lflag = lflag;
1103 arg += n;
1104 for (i = 0; i < NCCS; ++i)
1106 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1107 return 0;
1108 mode->c_cc[i] = chr;
1109 arg += n;
1111 return 1;
1114 struct speed_map
1116 char *string; /* ASCII representation. */
1117 speed_t speed; /* Internal form. */
1118 unsigned long value; /* Numeric value. */
1121 struct speed_map speeds[] =
1123 {"0", B0, 0},
1124 {"50", B50, 50},
1125 {"75", B75, 75},
1126 {"110", B110, 110},
1127 {"134", B134, 134},
1128 {"134.5", B134, 134},
1129 {"150", B150, 150},
1130 {"200", B200, 200},
1131 {"300", B300, 300},
1132 {"600", B600, 600},
1133 {"1200", B1200, 1200},
1134 {"1800", B1800, 1800},
1135 {"2400", B2400, 2400},
1136 {"4800", B4800, 4800},
1137 {"9600", B9600, 9600},
1138 {"19200", B19200, 19200},
1139 {"38400", B38400, 38400},
1140 {"exta", B19200, 19200},
1141 {"extb", B38400, 38400},
1142 #ifdef B57600
1143 {"57600", B57600, 57600},
1144 #endif
1145 #ifdef B115200
1146 {"115200", B115200, 115200},
1147 #endif
1148 {NULL, 0, 0}
1151 speed_t
1152 string_to_baud (arg)
1153 char *arg;
1155 int i;
1157 for (i = 0; speeds[i].string != NULL; ++i)
1158 if (!strcmp (arg, speeds[i].string))
1159 return speeds[i].speed;
1160 return (speed_t) -1;
1163 unsigned long
1164 baud_to_value (speed)
1165 speed_t speed;
1167 int i;
1169 for (i = 0; speeds[i].string != NULL; ++i)
1170 if (speed == speeds[i].speed)
1171 return speeds[i].value;
1172 return 0;
1175 void
1176 sane_mode (mode)
1177 struct termios *mode;
1179 int i;
1180 tcflag_t *bitsp;
1182 for (i = 0; control_info[i].name; ++i)
1184 #if VMIN == VEOF
1185 if (!strcmp (control_info[i].name, "min"))
1186 break;
1187 #endif
1188 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1191 for (i = 0; mode_info[i].name != NULL; ++i)
1193 if (mode_info[i].flags & SANE_SET)
1195 bitsp = mode_type_flag (mode_info[i].type, mode);
1196 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1198 else if (mode_info[i].flags & SANE_UNSET)
1200 bitsp = mode_type_flag (mode_info[i].type, mode);
1201 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1206 /* Return a string that is the printable representation of character CH. */
1207 /* Adapted from `cat' by Torbjorn Granlund. */
1209 char *
1210 visible (ch)
1211 unsigned char ch;
1213 static char buf[10];
1214 char *bpout = buf;
1216 if (ch == _POSIX_VDISABLE)
1217 return "<undef>";
1219 if (ch >= 32)
1221 if (ch < 127)
1222 *bpout++ = ch;
1223 else if (ch == 127)
1225 *bpout++ = '^';
1226 *bpout++ = '?';
1228 else
1230 *bpout++ = 'M',
1231 *bpout++ = '-';
1232 if (ch >= 128 + 32)
1234 if (ch < 128 + 127)
1235 *bpout++ = ch - 128;
1236 else
1238 *bpout++ = '^';
1239 *bpout++ = '?';
1242 else
1244 *bpout++ = '^';
1245 *bpout++ = ch - 128 + 64;
1249 else
1251 *bpout++ = '^';
1252 *bpout++ = ch + 64;
1254 *bpout = '\0';
1255 return buf;
1258 /* Parse string S as an integer, using decimal radix by default,
1259 but allowing octal and hex numbers as in C. */
1260 /* From `od' by Richard Stallman. */
1262 long
1263 integer_arg (s)
1264 char *s;
1266 long value;
1267 int radix = 10;
1268 char *p = s;
1269 int c;
1271 if (*p != '0')
1272 radix = 10;
1273 else if (*++p == 'x')
1275 radix = 16;
1276 p++;
1278 else
1279 radix = 8;
1281 value = 0;
1282 while (((c = *p++) >= '0' && c <= '9')
1283 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
1285 value *= radix;
1286 if (c >= '0' && c <= '9')
1287 value += c - '0';
1288 else
1289 value += (c & ~40) - 'A';
1292 if (c == 'b')
1293 value *= 512;
1294 else if (c == 'B')
1295 value *= 1024;
1296 else
1297 p--;
1299 if (*p)
1300 error (1, 0, "invalid integer argument `%s'", s);
1301 return value;