1 /* stty -- change and print terminal line settings
2 Copyright (C) 90, 91, 92, 93, 94, 1995 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)
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...]
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
28 David MacKenzie <djm@gnu.ai.mit.edu> */
32 #include <sys/types.h>
34 #ifdef GWINSZ_IN_SYS_IOCTL
35 #include <sys/ioctl.h>
37 #ifdef WINSIZE_IN_PTEM
38 #include <sys/stream.h>
44 #define VA_START(args, lastarg) va_start(args, lastarg)
47 #define VA_START(args, lastarg) va_start(args)
52 #include "long-options.h"
55 #if defined(GWINSZ_BROKEN) /* Such as for SCO UNIX 3.2.2. */
59 #ifndef _POSIX_VDISABLE
60 #define _POSIX_VDISABLE ((unsigned char) 0)
63 #define Control(c) ((c) & 0x1f)
64 /* Canonical values for control characters. */
66 #define CINTR Control ('c')
75 #define CKILL Control ('u')
78 #define CEOF Control ('d')
81 #define CEOL _POSIX_VDISABLE
84 #define CSTART Control ('q')
87 #define CSTOP Control ('s')
90 #define CSUSP Control ('z')
92 #if defined(VEOL2) && !defined(CEOL2)
93 #define CEOL2 _POSIX_VDISABLE
95 #if defined(VSWTCH) && !defined(CSWTCH)
96 #define CSWTCH _POSIX_VDISABLE
99 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
100 So the default is to disable `swtch.' */
101 #if defined (__sparc__) && defined (__svr4__)
103 #define CSWTCH _POSIX_VDISABLE
106 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
107 #define VWERASE VWERSE
109 #if defined(VDSUSP) && !defined (CDSUSP)
110 #define CDSUSP Control ('y')
112 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
113 #define VREPRINT VRPRNT
115 #if defined(VREPRINT) && !defined(CRPRNT)
116 #define CRPRNT Control ('r')
118 #if defined(VWERASE) && !defined(CWERASE)
119 #define CWERASE Control ('w')
121 #if defined(VLNEXT) && !defined(CLNEXT)
122 #define CLNEXT Control ('v')
124 #if defined(VDISCARD) && !defined(VFLUSHO)
125 #define VFLUSHO VDISCARD
127 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
128 #define VFLUSHO VFLUSH
130 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
131 #define ECHOCTL CTLECH
133 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
134 #define ECHOCTL TCTLECH
136 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
137 #define ECHOKE CRTKIL
139 #if defined(VFLUSHO) && !defined(CFLUSHO)
140 #define CFLUSHO Control ('o')
142 #if defined(VSTATUS) && !defined(CSTATUS)
143 #define CSTATUS Control ('t')
146 static const char *visible ();
147 static unsigned long baud_to_value ();
148 static int recover_mode ();
149 static int screen_columns ();
150 static int set_mode ();
151 static long integer_arg ();
152 static speed_t string_to_baud ();
153 static tcflag_t *mode_type_flag ();
154 static void display_all ();
155 static void display_changed ();
156 static void display_recoverable ();
157 static void display_settings ();
158 static void display_speed ();
159 static void display_window_size ();
160 static void sane_mode ();
161 static void set_control_char ();
162 static void set_speed ();
163 static void set_window_size ();
165 /* Which speeds to set. */
168 input_speed, output_speed, both_speeds
171 /* What to output and how. */
174 changed, all, recoverable /* Default, -a, -g. */
177 /* Which member(s) of `struct termios' a mode uses. */
180 control, input, output, local, combination
183 /* Flags for `struct mode_info'. */
184 #define SANE_SET 1 /* Set in `sane' mode. */
185 #define SANE_UNSET 2 /* Unset in `sane' mode. */
186 #define REV 4 /* Can be turned off by prepending `-'. */
187 #define OMIT 8 /* Don't display value. */
192 const char *name; /* Name given on command line. */
193 enum mode_type type; /* Which structure element to change. */
194 char flags; /* Setting and display options. */
195 unsigned long bits; /* Bits to set for this mode. */
196 unsigned long mask; /* Other bits to turn off for this mode. */
199 static struct mode_info mode_info[] =
201 {"parenb", control, REV, PARENB, 0},
202 {"parodd", control, REV, PARODD, 0},
203 {"cs5", control, 0, CS5, CSIZE},
204 {"cs6", control, 0, CS6, CSIZE},
205 {"cs7", control, 0, CS7, CSIZE},
206 {"cs8", control, 0, CS8, CSIZE},
207 {"hupcl", control, REV, HUPCL, 0},
208 {"hup", control, REV | OMIT, HUPCL, 0},
209 {"cstopb", control, REV, CSTOPB, 0},
210 {"cread", control, SANE_SET | REV, CREAD, 0},
211 {"clocal", control, REV, CLOCAL, 0},
213 {"crtscts", control, REV, CRTSCTS, 0},
216 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
217 {"brkint", input, SANE_SET | REV, BRKINT, 0},
218 {"ignpar", input, REV, IGNPAR, 0},
219 {"parmrk", input, REV, PARMRK, 0},
220 {"inpck", input, REV, INPCK, 0},
221 {"istrip", input, REV, ISTRIP, 0},
222 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
223 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
224 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
225 {"ixon", input, REV, IXON, 0},
226 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
227 {"tandem", input, REV | OMIT, IXOFF, 0},
229 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
232 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
235 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
238 {"opost", output, SANE_SET | REV, OPOST, 0},
240 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
243 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
246 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
249 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
252 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
255 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
258 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
261 {"nl1", output, SANE_UNSET, NL1, NLDLY},
262 {"nl0", output, SANE_SET, NL0, NLDLY},
265 {"cr3", output, SANE_UNSET, CR3, CRDLY},
266 {"cr2", output, SANE_UNSET, CR2, CRDLY},
267 {"cr1", output, SANE_UNSET, CR1, CRDLY},
268 {"cr0", output, SANE_SET, CR0, CRDLY},
271 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
272 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
273 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
274 {"tab0", output, SANE_SET, TAB0, TABDLY},
277 {"tab3", output, SANE_UNSET, OXTABS, 0},
281 {"bs1", output, SANE_UNSET, BS1, BSDLY},
282 {"bs0", output, SANE_SET, BS0, BSDLY},
285 {"vt1", output, SANE_UNSET, VT1, VTDLY},
286 {"vt0", output, SANE_SET, VT0, VTDLY},
289 {"ff1", output, SANE_UNSET, FF1, FFDLY},
290 {"ff0", output, SANE_SET, FF0, FFDLY},
293 {"isig", local, SANE_SET | REV, ISIG, 0},
294 {"icanon", local, SANE_SET | REV, ICANON, 0},
296 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
298 {"echo", local, SANE_SET | REV, ECHO, 0},
299 {"echoe", local, SANE_SET | REV, ECHOE, 0},
300 {"crterase", local, REV | OMIT, ECHOE, 0},
301 {"echok", local, SANE_SET | REV, ECHOK, 0},
302 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
303 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
305 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
308 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
311 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
312 {"prterase", local, REV | OMIT, ECHOPRT, 0},
315 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
316 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
319 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
320 {"crtkill", local, REV | OMIT, ECHOKE, 0},
323 {"evenp", combination, REV | OMIT, 0, 0},
324 {"parity", combination, REV | OMIT, 0, 0},
325 {"oddp", combination, REV | OMIT, 0, 0},
326 {"nl", combination, REV | OMIT, 0, 0},
327 {"ek", combination, OMIT, 0, 0},
328 {"sane", combination, OMIT, 0, 0},
329 {"cooked", combination, REV | OMIT, 0, 0},
330 {"raw", combination, REV | OMIT, 0, 0},
331 {"pass8", combination, REV | OMIT, 0, 0},
332 {"litout", combination, REV | OMIT, 0, 0},
333 {"cbreak", combination, REV | OMIT, 0, 0},
335 {"decctlq", combination, REV | OMIT, 0, 0},
337 #if defined (TABDLY) || defined (OXTABS)
338 {"tabs", combination, REV | OMIT, 0, 0},
340 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
341 {"lcase", combination, REV | OMIT, 0, 0},
342 {"LCASE", combination, REV | OMIT, 0, 0},
344 {"crt", combination, OMIT, 0, 0},
345 {"dec", combination, OMIT, 0, 0},
347 {NULL, control, 0, 0, 0}
350 /* Control character settings. */
353 const char *name; /* Name given on command line. */
354 unsigned char saneval; /* Value to set for `stty sane'. */
355 int offset; /* Offset in c_cc. */
358 /* Control characters. */
360 static struct control_info control_info[] =
362 {"intr", CINTR, VINTR},
363 {"quit", CQUIT, VQUIT},
364 {"erase", CERASE, VERASE},
365 {"kill", CKILL, VKILL},
369 {"eol2", CEOL2, VEOL2},
372 {"swtch", CSWTCH, VSWTCH},
374 {"start", CSTART, VSTART},
375 {"stop", CSTOP, VSTOP},
376 {"susp", CSUSP, VSUSP},
378 {"dsusp", CDSUSP, VDSUSP},
381 {"rprnt", CRPRNT, VREPRINT},
384 {"werase", CWERASE, VWERASE},
387 {"lnext", CLNEXT, VLNEXT},
390 {"flush", CFLUSHO, VFLUSHO},
393 {"status", CSTATUS, VSTATUS},
396 /* These must be last because of the display routines. */
402 /* The width of the screen, for output wrapping. */
405 /* Current position, to know when to wrap. */
406 static int current_col;
408 static struct option longopts[] =
410 {"all", no_argument, NULL, 'a'},
411 {"save", no_argument, NULL, 'g'},
415 /* The name this program was run with. */
418 /* Print format string MESSAGE and optional args.
419 Wrap to next line first if it won't fit.
420 Print a space first unless MESSAGE will start a new line. */
425 wrapf (const char *message,...)
427 wrapf (message, va_alist)
433 char buf[1024]; /* Plenty long for our needs. */
436 VA_START (args, message);
437 vsprintf (buf, message, args);
439 buflen = strlen (buf);
440 if (current_col + (current_col > 0) + buflen >= max_col)
451 current_col += buflen;
459 fprintf (stderr, "Try `%s --help' for more information.\n",
464 Usage: %s [SETTING]...\n\
467 program_name, program_name);
470 -a, --all print all current settings in human-readable form\n\
471 -g, --save print all current settings in a stty-readable form\n\
472 --help display this help and exit\n\
473 --version output version information and exit\n\
475 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
476 settings. The underlying system defines which settings are available.\n\
480 Special characters:\n\
481 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
482 eof CHAR CHAR will send an end of file (terminate the input)\n\
483 eol CHAR CHAR will end the line\n\
484 * eol2 CHAR alternate CHAR for ending the line\n\
485 erase CHAR CHAR will erase the last character typed\n\
486 intr CHAR CHAR will send an interrupt signal\n\
487 kill CHAR CHAR will erase the current line\n\
488 * lnext CHAR CHAR will enter the next character quoted\n\
489 quit CHAR CHAR will send a quit signal\n\
490 * rprnt CHAR CHAR will redraw the current line\n\
491 start CHAR CHAR will restart the output after stopping it\n\
492 stop CHAR CHAR will stop the output\n\
493 susp CHAR CHAR will send a terminal stop signal\n\
494 * swtch CHAR CHAR will switch to a different shell layer\n\
495 * werase CHAR CHAR will erase the last word typed\n\
500 N set the input and output speeds to N bauds\n\
501 * cols N tell the kernel that the terminal has N columns\n\
502 * columns N same as cols N\n\
503 ispeed N set the input speed to N\n\
504 * line N use line discipline N\n\
505 min N with -icanon, set N characters minimum for a completed read\n\
506 ospeed N set the output speed to N\n\
507 * rows N tell the kernel that the terminal has N rows\n\
508 * size print the number of rows and columns according to the kernel\n\
509 speed print the terminal speed\n\
510 time N with -icanon, set read timeout of N tenths of a second\n\
515 [-]clocal disable modem control signals\n\
516 [-]cread allow input to be received\n\
517 * [-]crtscts enable RTS/CTS handshaking\n\
518 csN set character size to N bits, N in [5..8]\n\
519 [-]cstopb use two stop bits per character (one with `-')\n\
520 [-]hup send a hangup signal when the last process closes the tty\n\
521 [-]hupcl same as [-]hup\n\
522 [-]parenb generate parity bit in output and expect parity bit in input\n\
523 [-]parodd set odd parity (even with `-')\n\
528 [-]brkint breaks cause an interrupt signal\n\
529 [-]icrnl translate carriage return to newline\n\
530 [-]ignbrk ignore breaks\n\
531 [-]igncr ignore carriage return\n\
532 [-]ignpar ignore parity errors\n\
533 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
534 [-]inlcr translate newline to carriage return\n\
535 [-]inpck enable input parity checking\n\
536 [-]istrip clear high (8th) bit of input characters\n\
537 * [-]iuclc translate uppercase characters to lowercase\n\
538 * [-]ixany let any character restart output, not only start character\n\
539 [-]ixoff enable sending of start/stop characters\n\
540 [-]ixon enable XON/XOFF flow control\n\
541 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
542 [-]tandem same as [-]ixoff\n\
547 * bsN backspace delay style, N in [0..1]\n\
548 * crN carriage return delay style, N in [0..3]\n\
549 * ffN form feed delay style, N in [0..1]\n\
550 * nlN newline delay style, N in [0..1]\n\
551 * [-]ocrnl translate carriage return to newline\n\
552 * [-]ofdel use delete characters for fill instead of null characters\n\
553 * [-]ofill use fill (padding) characters instead of timing for delays\n\
554 * [-]olcuc translate lowercase characters to uppercase\n\
555 * [-]onlcr translate newline to carriage return-newline\n\
556 * [-]onlret newline performs a carriage return\n\
557 * [-]onocr do not print carriage returns in the first column\n\
558 [-]opost postprocess output\n\
559 * tabN horizontal tab delay style, N in [0..3]\n\
560 * tabs same as tab0\n\
561 * -tabs same as tab3\n\
562 * vtN vertical tab delay style, N in [0..1]\n\
567 [-]crterase echo erase characters as backspace-space-backspace\n\
568 * crtkill kill all line by obeying the echoprt and echoe settings\n\
569 * -crtkill kill all line by obeying the echoctl and echok settings\n\
570 * [-]ctlecho echo control characters in hat notation (`^c')\n\
571 [-]echo echo input characters\n\
572 * [-]echoctl same as [-]ctlecho\n\
573 [-]echoe same as [-]crterase\n\
574 [-]echok echo a newline after a kill character\n\
575 * [-]echoke same as [-]crtkill\n\
576 [-]echonl echo newline even if not echoing other characters\n\
577 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
578 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
579 [-]iexten enable non-POSIX special characters\n\
580 [-]isig enable interrupt, quit, and suspend special characters\n\
581 [-]noflsh disable flushing after interrupt and quit special characters\n\
582 * [-]prterase same as [-]echoprt\n\
583 * [-]tostop stop background jobs that try to write to the terminal\n\
584 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
588 Combination settings:\n\
589 * [-]LCASE same as [-]lcase\n\
590 cbreak same as -icanon\n\
591 -cbreak same as icanon\n\
592 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
593 icanon, eof and eol characters to their default values\n\
594 -cooked same as raw\n\
595 crt same as echoe echoctl echoke\n\
596 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
598 * [-]decctlq same as [-]ixany\n\
599 ek erase and kill characters to their default values\n\
600 evenp same as parenb -parodd cs7\n\
601 -evenp same as -parenb cs8\n\
602 * [-]lcase same as xcase iuclc olcuc\n\
603 litout same as -parenb -istrip -opost cs8\n\
604 -litout same as parenb istrip opost cs7\n\
605 nl same as -icrnl -onlcr\n\
606 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
607 oddp same as parenb parodd cs7\n\
608 -oddp same as -parenb cs8\n\
609 [-]parity same as [-]evenp\n\
610 pass8 same as -parenb -istrip cs8\n\
611 -pass8 same as parenb istrip cs7\n\
612 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
613 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
614 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
615 -raw same as cooked\n\
616 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
617 -ixoff -iucl -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
618 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
619 isig icanon iexten echo echoe echok -echonl -noflsh\n\
620 -xcase -tostop -echoprt echoctl echoke, all special\n\
621 characters to their default values.\n\
625 Handle the tty line connected to standard input. Without arguments,\n\
626 prints baud rate, line discipline, and deviations from stty sane. In\n\
627 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
628 127; special values ^- or undef used to disable special characters.\n\
640 enum output_type output_type;
642 int require_set_attr;
645 int recoverable_output;
648 program_name = argv[0];
650 parse_long_options (argc, argv, "stty", version_string, usage);
652 output_type = changed;
654 recoverable_output = 0;
656 /* Recognize the long options only. */
658 while ((optc = getopt_long_only (argc, argv, "ag", longopts, (int *) 0))
669 recoverable_output = 1;
670 output_type = recoverable;
678 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
679 They need not precede non-options. We cannot use GNU getopt because
680 it would treat -tabs and -ixany as uses of the -a option. */
681 for (k = optind; k < argc; k++)
683 if (argv[k][0] == '-')
685 if (argv[k][1] == 'a'
686 && argv[k][2] == '\0')
691 else if (argv[k][1] == 'g'
692 && argv[k][2] == '\0')
695 recoverable_output = 1;
697 else if ((argv[k][1] == 'g'
699 && argv[k][3] == '\0')
700 || (argv[k][1] == 'a'
702 && argv[k][3] == '\0'))
706 recoverable_output = 1;
711 /* Specifying both -a and -g gets an error. */
712 if (verbose_output && recoverable_output)
714 "the options for verbose and stty-readable output styles are\n\
715 \tmutually exclusive");
717 /* Specifying any other arguments with -a or -g gets an error. */
718 if (argc - optind > 0 && (verbose_output || recoverable_output))
719 error (2, 0, "when specifying an output style, modes may not be set");
721 /* Initialize to all zeroes so there is no risk memcmp will report a
722 spurious difference in an uninitialized portion of the structure. */
723 memset (&mode, 0, sizeof (mode));
724 if (tcgetattr (0, &mode))
725 error (1, errno, "standard input");
727 if (verbose_output || recoverable_output || argc == 1)
729 max_col = screen_columns ();
731 display_settings (output_type, &mode);
736 require_set_attr = 0;
744 if (argv[k][0] == '-')
749 for (i = 0; mode_info[i].name != NULL; ++i)
751 if (!strcmp (argv[k], mode_info[i].name))
753 match_found = set_mode (&mode_info[i], reversed, &mode);
754 require_set_attr = 1;
758 if (match_found == 0 && reversed)
760 error (0, 0, "invalid argument `%s'", --argv[k]);
763 if (match_found == 0)
765 for (i = 0; control_info[i].name != NULL; ++i)
767 if (!strcmp (argv[k], control_info[i].name))
771 error (0, 0, "missing argument to `%s'", argv[k]);
776 set_control_char (&control_info[i], argv[k], &mode);
777 require_set_attr = 1;
782 if (match_found == 0)
784 if (!strcmp (argv[k], "ispeed"))
788 error (0, 0, "missing argument to `%s'", argv[k]);
792 set_speed (input_speed, argv[k], &mode);
794 require_set_attr = 1;
796 else if (!strcmp (argv[k], "ospeed"))
800 error (0, 0, "missing argument to `%s'", argv[k]);
804 set_speed (output_speed, argv[k], &mode);
806 require_set_attr = 1;
809 else if (!strcmp (argv[k], "rows"))
813 error (0, 0, "missing argument to `%s'", argv[k]);
817 set_window_size ((int) integer_arg (argv[k]), -1);
819 else if (!strcmp (argv[k], "cols")
820 || !strcmp (argv[k], "columns"))
824 error (0, 0, "missing argument to `%s'", argv[k]);
828 set_window_size (-1, (int) integer_arg (argv[k]));
830 else if (!strcmp (argv[k], "size"))
832 max_col = screen_columns ();
834 display_window_size (0);
838 else if (!strcmp (argv[k], "line"))
842 error (0, 0, "missing argument to `%s'", argv[k]);
846 mode.c_line = integer_arg (argv[k]);
847 require_set_attr = 1;
850 else if (!strcmp (argv[k], "speed"))
852 max_col = screen_columns ();
853 display_speed (&mode, 0);
855 else if (string_to_baud (argv[k]) != (speed_t) -1)
857 set_speed (both_speeds, argv[k], &mode);
859 require_set_attr = 1;
863 if (recover_mode (argv[k], &mode) == 0)
865 error (0, 0, "invalid argument `%s'", argv[k]);
868 require_set_attr = 1;
874 if (require_set_attr)
876 struct termios new_mode;
878 if (tcsetattr (0, TCSADRAIN, &mode))
879 error (1, errno, "standard input");
881 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
882 it performs *any* of the requested operations. This means it
883 can report `success' when it has actually failed to perform
884 some proper subset of the requested operations. To detect
885 this partial failure, get the current terminal attributes and
886 compare them to the requested ones. */
888 /* Initialize to all zeroes so there is no risk memcmp will report a
889 spurious difference in an uninitialized portion of the structure. */
890 memset (&new_mode, 0, sizeof (new_mode));
891 if (tcgetattr (0, &new_mode))
892 error (1, errno, "standard input");
894 /* Normally, one shouldn't use memcmp to compare structures that
895 may have `holes' containing uninitialized data, but we have been
896 careful to initialize the storage of these two variables to all
897 zeroes. One might think it more efficient simply to compare the
898 modified fields, but that would require enumerating those fields --
899 and not all systems have the same fields in this structure. */
901 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
904 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
905 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
906 sometimes (m1 != m2). The only difference is in the four bits
907 of the c_cflag field corresponding to the baud rate. To save
908 Sun users a little confusion, don't report an error if this
909 happens. But suppress the error only if we haven't tried to
910 set the baud rate explicitly -- otherwise we'd never give an
911 error for a true failure to set the baud rate. */
913 new_mode.c_cflag &= (~CIBAUD);
914 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
919 "standard input: unable to perform all requested operations");
920 printf ("new_mode: mode\n");
921 for (i=0; i<sizeof(new_mode); i++)
922 printf ("0x%02x: 0x%02x\n",
923 *(((unsigned char *) &new_mode) + i),
924 *(((unsigned char *) &mode) + i));
932 /* Return 0 if not applied because not reversible; otherwise return 1. */
935 set_mode (info, reversed, mode)
936 struct mode_info *info;
938 struct termios *mode;
942 if (reversed && (info->flags & REV) == 0)
945 bitsp = mode_type_flag (info->type, mode);
949 /* Combination mode. */
950 if (!strcmp (info->name, "evenp") || !strcmp (info->name, "parity"))
953 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
955 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
957 else if (!strcmp (info->name, "oddp"))
960 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
962 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
964 else if (!strcmp (info->name, "nl"))
968 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
969 mode->c_oflag = (mode->c_oflag
984 mode->c_iflag = mode->c_iflag & ~ICRNL;
986 mode->c_oflag = mode->c_oflag & ~ONLCR;
990 else if (!strcmp (info->name, "ek"))
992 mode->c_cc[VERASE] = CERASE;
993 mode->c_cc[VKILL] = CKILL;
995 else if (!strcmp (info->name, "sane"))
997 else if (!strcmp (info->name, "cbreak"))
1000 mode->c_lflag |= ICANON;
1002 mode->c_lflag &= ~ICANON;
1004 else if (!strcmp (info->name, "pass8"))
1008 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1009 mode->c_iflag |= ISTRIP;
1013 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1014 mode->c_iflag &= ~ISTRIP;
1017 else if (!strcmp (info->name, "litout"))
1021 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1022 mode->c_iflag |= ISTRIP;
1023 mode->c_oflag |= OPOST;
1027 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1028 mode->c_iflag &= ~ISTRIP;
1029 mode->c_oflag &= ~OPOST;
1032 else if (!strcmp (info->name, "raw") || !strcmp (info->name, "cooked"))
1034 if ((info->name[0] == 'r' && reversed)
1035 || (info->name[0] == 'c' && !reversed))
1038 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1039 mode->c_oflag |= OPOST;
1040 mode->c_lflag |= ISIG | ICANON;
1042 mode->c_cc[VEOF] = CEOF;
1045 mode->c_cc[VEOL] = CEOL;
1052 mode->c_oflag &= ~OPOST;
1053 mode->c_lflag &= ~(ISIG | ICANON
1058 mode->c_cc[VMIN] = 1;
1059 mode->c_cc[VTIME] = 0;
1063 else if (!strcmp (info->name, "decctlq"))
1066 mode->c_iflag |= IXANY;
1068 mode->c_iflag &= ~IXANY;
1072 else if (!strcmp (info->name, "tabs"))
1075 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1077 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1081 else if (!strcmp (info->name, "tabs"))
1084 mode->c_oflag = mode->c_oflag | OXTABS;
1086 mode->c_oflag = mode->c_oflag & ~OXTABS;
1090 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1091 else if (!strcmp (info->name, "lcase")
1092 || !strcmp (info->name, "LCASE"))
1096 mode->c_lflag &= ~XCASE;
1097 mode->c_iflag &= ~IUCLC;
1098 mode->c_oflag &= ~OLCUC;
1102 mode->c_lflag |= XCASE;
1103 mode->c_iflag |= IUCLC;
1104 mode->c_oflag |= OLCUC;
1108 else if (!strcmp (info->name, "crt"))
1109 mode->c_lflag |= ECHOE
1117 else if (!strcmp (info->name, "dec"))
1119 mode->c_cc[VINTR] = 3; /* ^C */
1120 mode->c_cc[VERASE] = 127; /* DEL */
1121 mode->c_cc[VKILL] = 21; /* ^U */
1122 mode->c_lflag |= ECHOE
1131 mode->c_iflag &= ~IXANY;
1136 *bitsp = *bitsp & ~info->mask & ~info->bits;
1138 *bitsp = (*bitsp & ~info->mask) | info->bits;
1144 set_control_char (info, arg, mode)
1145 struct control_info *info;
1147 struct termios *mode;
1149 unsigned char value;
1151 if (!strcmp (info->name, "min") || !strcmp (info->name, "time"))
1152 value = integer_arg (arg);
1153 else if (arg[0] == '\0' || arg[1] == '\0')
1155 else if (!strcmp (arg, "^-") || !strcmp (arg, "undef"))
1156 value = _POSIX_VDISABLE;
1157 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1162 value = arg[1] & ~0140; /* Non-letters get weird results. */
1165 value = integer_arg (arg);
1166 mode->c_cc[info->offset] = value;
1170 set_speed (type, arg, mode)
1171 enum speed_setting type;
1173 struct termios *mode;
1177 baud = string_to_baud (arg);
1178 if (type == input_speed || type == both_speeds)
1179 cfsetispeed (mode, baud);
1180 if (type == output_speed || type == both_speeds)
1181 cfsetospeed (mode, baud);
1186 /* Get window size information. First try getting the information
1187 associated with standard output and if that fails, try standard input.
1188 Return zero for success, non-zero if both ioctl's failed. */
1192 struct winsize *win;
1196 err = ioctl (1, TIOCGWINSZ, (char *) win);
1198 err = ioctl (0, TIOCGWINSZ, (char *) win);
1203 set_window_size (rows, cols)
1208 if (get_win_size (&win))
1210 if (errno != EINVAL)
1211 error (1, errno, "standard input");
1212 memset (&win, 0, sizeof (win));
1221 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1222 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1223 This comment from sys/ttold.h describes Sun's twisted logic - a better
1224 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1225 At any rate, the problem is gone in Solaris 2.x.
1227 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1228 but they can be disambiguated by checking whether a "struct ttysize"
1229 structure's "ts_lines" field is greater than 64K or not. If so,
1230 it's almost certainly a "struct winsize" instead.
1232 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1233 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1234 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1235 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1236 "stty cols 0 rows 0" would do the right thing. On a little-endian
1237 machine like the sun386i, the problem is the same, but for ws_col == 0.
1239 The workaround is to do the ioctl once with row and col = 1 to set the
1240 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1242 if (win.ws_row == 0 || win.ws_col == 0)
1244 struct ttysize ttysz;
1246 ttysz.ts_lines = win.ws_row;
1247 ttysz.ts_cols = win.ws_col;
1252 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1253 error (1, errno, "standard input");
1255 if (ioctl (0, TIOCSSIZE, (char *) &ttysz))
1256 error (1, errno, "standard input");
1261 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1262 error (1, errno, "standard input");
1266 display_window_size (fancy)
1271 if (get_win_size (&win))
1273 if (errno != EINVAL)
1274 error (1, errno, "standard input");
1278 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1279 win.ws_row, win.ws_col);
1292 if (get_win_size (&win))
1294 /* With Solaris 2.[123], this ioctl fails and errno is set to
1295 EINVAL for telnet (but not rlogin) sessions. */
1296 if (errno != EINVAL)
1297 error (1, errno, "standard input");
1299 else if (win.ws_col > 0)
1302 if (getenv ("COLUMNS"))
1303 return atoi (getenv ("COLUMNS"));
1308 mode_type_flag (type, mode)
1309 enum mode_type type;
1310 struct termios *mode;
1315 return &mode->c_cflag;
1318 return &mode->c_iflag;
1321 return &mode->c_oflag;
1324 return &mode->c_lflag;
1335 display_settings (output_type, mode)
1336 enum output_type output_type;
1337 struct termios *mode;
1339 switch (output_type)
1342 display_changed (mode);
1350 display_recoverable (mode);
1356 display_changed (mode)
1357 struct termios *mode;
1363 enum mode_type prev_type = control;
1365 display_speed (mode, 1);
1367 wrapf ("line = %d;", mode->c_line);
1373 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1375 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1378 wrapf ("%s = %s;", control_info[i].name,
1379 visible (mode->c_cc[control_info[i].offset]));
1381 if ((mode->c_lflag & ICANON) == 0)
1383 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1384 (int) mode->c_cc[VTIME]);
1386 else if (empty_line == 0)
1391 for (i = 0; mode_info[i].name != NULL; ++i)
1393 if (mode_info[i].flags & OMIT)
1395 if (mode_info[i].type != prev_type)
1397 if (empty_line == 0)
1403 prev_type = mode_info[i].type;
1406 bitsp = mode_type_flag (mode_info[i].type, mode);
1407 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1408 if ((*bitsp & mask) == mode_info[i].bits)
1410 if (mode_info[i].flags & SANE_UNSET)
1412 wrapf ("%s", mode_info[i].name);
1416 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1418 wrapf ("-%s", mode_info[i].name);
1422 if (empty_line == 0)
1429 struct termios *mode;
1434 enum mode_type prev_type = control;
1436 display_speed (mode, 1);
1438 display_window_size (1);
1441 wrapf ("line = %d;", mode->c_line);
1446 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1448 wrapf ("%s = %s;", control_info[i].name,
1449 visible (mode->c_cc[control_info[i].offset]));
1451 wrapf ("min = %d; time = %d;\n", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1454 for (i = 0; mode_info[i].name != NULL; ++i)
1456 if (mode_info[i].flags & OMIT)
1458 if (mode_info[i].type != prev_type)
1462 prev_type = mode_info[i].type;
1465 bitsp = mode_type_flag (mode_info[i].type, mode);
1466 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1467 if ((*bitsp & mask) == mode_info[i].bits)
1468 wrapf ("%s", mode_info[i].name);
1469 else if (mode_info[i].flags & REV)
1470 wrapf ("-%s", mode_info[i].name);
1477 display_speed (mode, fancy)
1478 struct termios *mode;
1481 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1482 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1483 baud_to_value (cfgetospeed (mode)));
1485 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1486 baud_to_value (cfgetispeed (mode)),
1487 baud_to_value (cfgetospeed (mode)));
1493 display_recoverable (mode)
1494 struct termios *mode;
1498 printf ("%lx:%lx:%lx:%lx",
1499 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1500 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1501 for (i = 0; i < NCCS; ++i)
1502 printf (":%x", (unsigned int) mode->c_cc[i]);
1507 recover_mode (arg, mode)
1509 struct termios *mode;
1513 unsigned long iflag, oflag, cflag, lflag;
1515 /* Scan into temporaries since it is too much trouble to figure out
1516 the right format for `tcflag_t'. */
1517 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1518 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1520 mode->c_iflag = iflag;
1521 mode->c_oflag = oflag;
1522 mode->c_cflag = cflag;
1523 mode->c_lflag = lflag;
1525 for (i = 0; i < NCCS; ++i)
1527 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1529 mode->c_cc[i] = chr;
1537 const char *string; /* ASCII representation. */
1538 speed_t speed; /* Internal form. */
1539 unsigned long value; /* Numeric value. */
1542 struct speed_map speeds[] =
1549 {"134.5", B134, 134},
1554 {"1200", B1200, 1200},
1555 {"1800", B1800, 1800},
1556 {"2400", B2400, 2400},
1557 {"4800", B4800, 4800},
1558 {"9600", B9600, 9600},
1559 {"19200", B19200, 19200},
1560 {"38400", B38400, 38400},
1561 {"exta", B19200, 19200},
1562 {"extb", B38400, 38400},
1564 {"57600", B57600, 57600},
1567 {"115200", B115200, 115200},
1573 string_to_baud (arg)
1578 for (i = 0; speeds[i].string != NULL; ++i)
1579 if (!strcmp (arg, speeds[i].string))
1580 return speeds[i].speed;
1581 return (speed_t) -1;
1584 static unsigned long
1585 baud_to_value (speed)
1590 for (i = 0; speeds[i].string != NULL; ++i)
1591 if (speed == speeds[i].speed)
1592 return speeds[i].value;
1598 struct termios *mode;
1603 for (i = 0; control_info[i].name; ++i)
1606 if (!strcmp (control_info[i].name, "min"))
1609 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1612 for (i = 0; mode_info[i].name != NULL; ++i)
1614 if (mode_info[i].flags & SANE_SET)
1616 bitsp = mode_type_flag (mode_info[i].type, mode);
1617 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1619 else if (mode_info[i].flags & SANE_UNSET)
1621 bitsp = mode_type_flag (mode_info[i].type, mode);
1622 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1627 /* Return a string that is the printable representation of character CH. */
1628 /* Adapted from `cat' by Torbjorn Granlund. */
1634 static char buf[10];
1637 if (ch == _POSIX_VDISABLE)
1656 *bpout++ = ch - 128;
1666 *bpout++ = ch - 128 + 64;
1676 return (const char *) buf;
1679 /* Parse string S as an integer, using decimal radix by default,
1680 but allowing octal and hex numbers as in C. */
1681 /* From `od' by Richard Stallman. */
1694 else if (*++p == 'x')
1703 while (((c = *p++) >= '0' && c <= '9')
1704 || (radix == 16 && (c & ~40) >= 'A' && (c & ~40) <= 'Z'))
1707 if (c >= '0' && c <= '9')
1710 value += (c & ~40) - 'A';
1722 error (0, 0, "invalid integer argument `%s'", s);