1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-1999 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 Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Usage: stty [-ag] [--all] [--save] [-F device] [--file=device] [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.
23 -F, --file Open and use the specified device instead of stdin
25 If no args are given, write to stdout the baud rate and settings that
26 have been changed from their defaults. Mode reading and changes
27 are done on the specified device, or stdin if none was specified.
29 David MacKenzie <djm@gnu.ai.mit.edu> */
33 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
34 # define _XOPEN_SOURCE
38 #include <sys/types.h>
42 #ifdef GWINSZ_IN_SYS_IOCTL
43 # include <sys/ioctl.h>
45 #ifdef WINSIZE_IN_PTEM
46 # include <sys/stream.h>
47 # include <sys/ptem.h>
49 #ifdef GWINSZ_IN_SYS_PTY
50 # include <sys/ioctl.h>
57 # define VA_START(args, lastarg) va_start(args, lastarg)
60 # define VA_START(args, lastarg) va_start(args)
64 #include "long-options.h"
68 #ifndef _POSIX_VDISABLE
69 # define _POSIX_VDISABLE ((unsigned char) 0)
72 #define Control(c) ((c) & 0x1f)
73 /* Canonical values for control characters. */
75 # define CINTR Control ('c')
84 # define CKILL Control ('u')
87 # define CEOF Control ('d')
90 # define CEOL _POSIX_VDISABLE
93 # define CSTART Control ('q')
96 # define CSTOP Control ('s')
99 # define CSUSP Control ('z')
101 #if defined(VEOL2) && !defined(CEOL2)
102 # define CEOL2 _POSIX_VDISABLE
104 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
105 #if defined(VSUSP) && !defined(VSWTCH)
106 # define VSWTCH VSUSP
107 # define CSWTCH CSUSP
109 #if defined(VSWTCH) && !defined(CSWTCH)
110 # define CSWTCH _POSIX_VDISABLE
113 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
114 So the default is to disable `swtch.' */
115 #if defined (__sparc__) && defined (__svr4__)
117 # define CSWTCH _POSIX_VDISABLE
120 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
121 # define VWERASE VWERSE
123 #if defined(VDSUSP) && !defined (CDSUSP)
124 # define CDSUSP Control ('y')
126 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
127 # define VREPRINT VRPRNT
129 #if defined(VREPRINT) && !defined(CRPRNT)
130 # define CRPRNT Control ('r')
132 #if defined(VWERASE) && !defined(CWERASE)
133 # define CWERASE Control ('w')
135 #if defined(VLNEXT) && !defined(CLNEXT)
136 # define CLNEXT Control ('v')
138 #if defined(VDISCARD) && !defined(VFLUSHO)
139 # define VFLUSHO VDISCARD
141 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
142 # define VFLUSHO VFLUSH
144 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
145 # define ECHOCTL CTLECH
147 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
148 # define ECHOCTL TCTLECH
150 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
151 # define ECHOKE CRTKIL
153 #if defined(VFLUSHO) && !defined(CFLUSHO)
154 # define CFLUSHO Control ('o')
156 #if defined(VSTATUS) && !defined(CSTATUS)
157 # define CSTATUS Control ('t')
160 /* Which speeds to set. */
163 input_speed, output_speed, both_speeds
166 /* What to output and how. */
169 changed, all, recoverable /* Default, -a, -g. */
172 /* Which member(s) of `struct termios' a mode uses. */
175 control, input, output, local, combination
178 /* Flags for `struct mode_info'. */
179 #define SANE_SET 1 /* Set in `sane' mode. */
180 #define SANE_UNSET 2 /* Unset in `sane' mode. */
181 #define REV 4 /* Can be turned off by prepending `-'. */
182 #define OMIT 8 /* Don't display value. */
187 const char *name; /* Name given on command line. */
188 enum mode_type type; /* Which structure element to change. */
189 char flags; /* Setting and display options. */
190 unsigned long bits; /* Bits to set for this mode. */
191 unsigned long mask; /* Other bits to turn off for this mode. */
194 static struct mode_info mode_info[] =
196 {"parenb", control, REV, PARENB, 0},
197 {"parodd", control, REV, PARODD, 0},
198 {"cs5", control, 0, CS5, CSIZE},
199 {"cs6", control, 0, CS6, CSIZE},
200 {"cs7", control, 0, CS7, CSIZE},
201 {"cs8", control, 0, CS8, CSIZE},
202 {"hupcl", control, REV, HUPCL, 0},
203 {"hup", control, REV | OMIT, HUPCL, 0},
204 {"cstopb", control, REV, CSTOPB, 0},
205 {"cread", control, SANE_SET | REV, CREAD, 0},
206 {"clocal", control, REV, CLOCAL, 0},
208 {"crtscts", control, REV, CRTSCTS, 0},
211 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
212 {"brkint", input, SANE_SET | REV, BRKINT, 0},
213 {"ignpar", input, REV, IGNPAR, 0},
214 {"parmrk", input, REV, PARMRK, 0},
215 {"inpck", input, REV, INPCK, 0},
216 {"istrip", input, REV, ISTRIP, 0},
217 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
218 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
219 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
220 {"ixon", input, REV, IXON, 0},
221 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
222 {"tandem", input, REV | OMIT, IXOFF, 0},
224 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
227 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
230 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
233 {"opost", output, SANE_SET | REV, OPOST, 0},
235 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
238 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
241 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
244 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
247 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
250 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
253 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
256 {"nl1", output, SANE_UNSET, NL1, NLDLY},
257 {"nl0", output, SANE_SET, NL0, NLDLY},
260 {"cr3", output, SANE_UNSET, CR3, CRDLY},
261 {"cr2", output, SANE_UNSET, CR2, CRDLY},
262 {"cr1", output, SANE_UNSET, CR1, CRDLY},
263 {"cr0", output, SANE_SET, CR0, CRDLY},
266 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
267 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
268 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
269 {"tab0", output, SANE_SET, TAB0, TABDLY},
272 {"tab3", output, SANE_UNSET, OXTABS, 0},
276 {"bs1", output, SANE_UNSET, BS1, BSDLY},
277 {"bs0", output, SANE_SET, BS0, BSDLY},
280 {"vt1", output, SANE_UNSET, VT1, VTDLY},
281 {"vt0", output, SANE_SET, VT0, VTDLY},
284 {"ff1", output, SANE_UNSET, FF1, FFDLY},
285 {"ff0", output, SANE_SET, FF0, FFDLY},
288 {"isig", local, SANE_SET | REV, ISIG, 0},
289 {"icanon", local, SANE_SET | REV, ICANON, 0},
291 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
293 {"echo", local, SANE_SET | REV, ECHO, 0},
294 {"echoe", local, SANE_SET | REV, ECHOE, 0},
295 {"crterase", local, REV | OMIT, ECHOE, 0},
296 {"echok", local, SANE_SET | REV, ECHOK, 0},
297 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
298 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
300 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
303 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
306 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
307 {"prterase", local, REV | OMIT, ECHOPRT, 0},
310 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
311 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
314 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
315 {"crtkill", local, REV | OMIT, ECHOKE, 0},
318 {"evenp", combination, REV | OMIT, 0, 0},
319 {"parity", combination, REV | OMIT, 0, 0},
320 {"oddp", combination, REV | OMIT, 0, 0},
321 {"nl", combination, REV | OMIT, 0, 0},
322 {"ek", combination, OMIT, 0, 0},
323 {"sane", combination, OMIT, 0, 0},
324 {"cooked", combination, REV | OMIT, 0, 0},
325 {"raw", combination, REV | OMIT, 0, 0},
326 {"pass8", combination, REV | OMIT, 0, 0},
327 {"litout", combination, REV | OMIT, 0, 0},
328 {"cbreak", combination, REV | OMIT, 0, 0},
330 {"decctlq", combination, REV | OMIT, 0, 0},
332 #if defined (TABDLY) || defined (OXTABS)
333 {"tabs", combination, REV | OMIT, 0, 0},
335 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
336 {"lcase", combination, REV | OMIT, 0, 0},
337 {"LCASE", combination, REV | OMIT, 0, 0},
339 {"crt", combination, OMIT, 0, 0},
340 {"dec", combination, OMIT, 0, 0},
342 {NULL, control, 0, 0, 0}
345 /* Control character settings. */
348 const char *name; /* Name given on command line. */
349 unsigned char saneval; /* Value to set for `stty sane'. */
350 int offset; /* Offset in c_cc. */
353 /* Control characters. */
355 static struct control_info control_info[] =
357 {"intr", CINTR, VINTR},
358 {"quit", CQUIT, VQUIT},
359 {"erase", CERASE, VERASE},
360 {"kill", CKILL, VKILL},
364 {"eol2", CEOL2, VEOL2},
367 {"swtch", CSWTCH, VSWTCH},
369 {"start", CSTART, VSTART},
370 {"stop", CSTOP, VSTOP},
371 {"susp", CSUSP, VSUSP},
373 {"dsusp", CDSUSP, VDSUSP},
376 {"rprnt", CRPRNT, VREPRINT},
379 {"werase", CWERASE, VWERASE},
382 {"lnext", CLNEXT, VLNEXT},
385 {"flush", CFLUSHO, VFLUSHO},
388 {"status", CSTATUS, VSTATUS},
391 /* These must be last because of the display routines. */
397 static const char *visible PARAMS ((unsigned int ch));
398 static unsigned long baud_to_value PARAMS ((speed_t speed));
399 static int recover_mode PARAMS ((char *arg, struct termios *mode));
400 static int screen_columns PARAMS ((void));
401 static int set_mode PARAMS ((struct mode_info *info, int reversed,
402 struct termios *mode));
403 static long integer_arg PARAMS ((const char *s));
404 static speed_t string_to_baud PARAMS ((const char *arg));
405 static tcflag_t *mode_type_flag PARAMS ((enum mode_type type,
406 struct termios *mode));
407 static void display_all PARAMS ((struct termios *mode, int fd,
408 const char *device_name));
409 static void display_changed PARAMS ((struct termios *mode));
410 static void display_recoverable PARAMS ((struct termios *mode));
411 static void display_settings PARAMS ((enum output_type output_type,
412 struct termios *mode, int fd,
413 const char *device_name));
414 static void display_speed PARAMS ((struct termios *mode, int fancy));
415 static void display_window_size PARAMS ((int fancy, int fd,
416 const char *device_name));
417 static void sane_mode PARAMS ((struct termios *mode));
418 static void set_control_char PARAMS ((struct control_info *info,
420 struct termios *mode));
421 static void set_speed PARAMS ((enum speed_setting type, const char *arg,
422 struct termios *mode));
423 static void set_window_size PARAMS ((int rows, int cols, int fd,
424 const char *device_name));
426 /* The width of the screen, for output wrapping. */
429 /* Current position, to know when to wrap. */
430 static int current_col;
432 static struct option longopts[] =
434 {"all", no_argument, NULL, 'a'},
435 {"save", no_argument, NULL, 'g'},
436 {"file", required_argument, NULL, 'F'},
440 /* The name this program was run with. */
443 /* Print format string MESSAGE and optional args.
444 Wrap to next line first if it won't fit.
445 Print a space first unless MESSAGE will start a new line. */
450 wrapf (const char *message,...)
452 wrapf (message, va_alist)
458 char buf[1024]; /* Plenty long for our needs. */
461 VA_START (args, message);
462 vsprintf (buf, message, args);
464 buflen = strlen (buf);
465 if (current_col + (current_col > 0) + buflen >= max_col)
476 current_col += buflen;
483 fprintf (stderr, _("Try `%s --help' for more information.\n"),
488 Usage: %s [-F device] [--file=device] [SETTING]...\n\
489 or: %s [-F device] [--file=device] [-a|--all]\n\
490 or: %s [-F device] [--file=device] [-g|--save]\n\
492 program_name, program_name, program_name);
494 Print or change terminal characteristics.\n\
496 -a, --all print all current settings in human-readable form\n\
497 -g, --save print all current settings in a stty-readable form\n\
498 -F, --file open and use the specified device instead of stdin\n\
499 --help display this help and exit\n\
500 --version output version information and exit\n\
502 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
503 settings. The underlying system defines which settings are available.\n\
507 Special characters:\n\
508 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
509 eof CHAR CHAR will send an end of file (terminate the input)\n\
510 eol CHAR CHAR will end the line\n\
511 * eol2 CHAR alternate CHAR for ending the line\n\
512 erase CHAR CHAR will erase the last character typed\n\
513 intr CHAR CHAR will send an interrupt signal\n\
514 kill CHAR CHAR will erase the current line\n\
515 * lnext CHAR CHAR will enter the next character quoted\n\
516 quit CHAR CHAR will send a quit signal\n\
517 * rprnt CHAR CHAR will redraw the current line\n\
518 start CHAR CHAR will restart the output after stopping it\n\
519 stop CHAR CHAR will stop the output\n\
520 susp CHAR CHAR will send a terminal stop signal\n\
521 * swtch CHAR CHAR will switch to a different shell layer\n\
522 * werase CHAR CHAR will erase the last word typed\n\
527 N set the input and output speeds to N bauds\n\
528 * cols N tell the kernel that the terminal has N columns\n\
529 * columns N same as cols N\n\
530 ispeed N set the input speed to N\n\
531 * line N use line discipline N\n\
532 min N with -icanon, set N characters minimum for a completed read\n\
533 ospeed N set the output speed to N\n\
534 * rows N tell the kernel that the terminal has N rows\n\
535 * size print the number of rows and columns according to the kernel\n\
536 speed print the terminal speed\n\
537 time N with -icanon, set read timeout of N tenths of a second\n\
542 [-]clocal disable modem control signals\n\
543 [-]cread allow input to be received\n\
544 * [-]crtscts enable RTS/CTS handshaking\n\
545 csN set character size to N bits, N in [5..8]\n\
546 [-]cstopb use two stop bits per character (one with `-')\n\
547 [-]hup send a hangup signal when the last process closes the tty\n\
548 [-]hupcl same as [-]hup\n\
549 [-]parenb generate parity bit in output and expect parity bit in input\n\
550 [-]parodd set odd parity (even with `-')\n\
555 [-]brkint breaks cause an interrupt signal\n\
556 [-]icrnl translate carriage return to newline\n\
557 [-]ignbrk ignore break characters\n\
558 [-]igncr ignore carriage return\n\
559 [-]ignpar ignore characters with parity errors\n\
560 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
561 [-]inlcr translate newline to carriage return\n\
562 [-]inpck enable input parity checking\n\
563 [-]istrip clear high (8th) bit of input characters\n\
564 * [-]iuclc translate uppercase characters to lowercase\n\
565 * [-]ixany let any character restart output, not only start character\n\
566 [-]ixoff enable sending of start/stop characters\n\
567 [-]ixon enable XON/XOFF flow control\n\
568 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
569 [-]tandem same as [-]ixoff\n\
574 * bsN backspace delay style, N in [0..1]\n\
575 * crN carriage return delay style, N in [0..3]\n\
576 * ffN form feed delay style, N in [0..1]\n\
577 * nlN newline delay style, N in [0..1]\n\
578 * [-]ocrnl translate carriage return to newline\n\
579 * [-]ofdel use delete characters for fill instead of null characters\n\
580 * [-]ofill use fill (padding) characters instead of timing for delays\n\
581 * [-]olcuc translate lowercase characters to uppercase\n\
582 * [-]onlcr translate newline to carriage return-newline\n\
583 * [-]onlret newline performs a carriage return\n\
584 * [-]onocr do not print carriage returns in the first column\n\
585 [-]opost postprocess output\n\
586 * tabN horizontal tab delay style, N in [0..3]\n\
587 * tabs same as tab0\n\
588 * -tabs same as tab3\n\
589 * vtN vertical tab delay style, N in [0..1]\n\
594 [-]crterase echo erase characters as backspace-space-backspace\n\
595 * crtkill kill all line by obeying the echoprt and echoe settings\n\
596 * -crtkill kill all line by obeying the echoctl and echok settings\n\
597 * [-]ctlecho echo control characters in hat notation (`^c')\n\
598 [-]echo echo input characters\n\
599 * [-]echoctl same as [-]ctlecho\n\
600 [-]echoe same as [-]crterase\n\
601 [-]echok echo a newline after a kill character\n\
602 * [-]echoke same as [-]crtkill\n\
603 [-]echonl echo newline even if not echoing other characters\n\
604 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
605 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
606 [-]iexten enable non-POSIX special characters\n\
607 [-]isig enable interrupt, quit, and suspend special characters\n\
608 [-]noflsh disable flushing after interrupt and quit special characters\n\
609 * [-]prterase same as [-]echoprt\n\
610 * [-]tostop stop background jobs that try to write to the terminal\n\
611 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
615 Combination settings:\n\
616 * [-]LCASE same as [-]lcase\n\
617 cbreak same as -icanon\n\
618 -cbreak same as icanon\n\
619 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
620 icanon, eof and eol characters to their default values\n\
621 -cooked same as raw\n\
622 crt same as echoe echoctl echoke\n\
623 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
625 * [-]decctlq same as [-]ixany\n\
626 ek erase and kill characters to their default values\n\
627 evenp same as parenb -parodd cs7\n\
628 -evenp same as -parenb cs8\n\
629 * [-]lcase same as xcase iuclc olcuc\n\
630 litout same as -parenb -istrip -opost cs8\n\
631 -litout same as parenb istrip opost cs7\n\
632 nl same as -icrnl -onlcr\n\
633 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
634 oddp same as parenb parodd cs7\n\
635 -oddp same as -parenb cs8\n\
636 [-]parity same as [-]evenp\n\
637 pass8 same as -parenb -istrip cs8\n\
638 -pass8 same as parenb istrip cs7\n\
639 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
640 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
641 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
642 -raw same as cooked\n\
643 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
644 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
645 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
646 isig icanon iexten echo echoe echok -echonl -noflsh\n\
647 -xcase -tostop -echoprt echoctl echoke, all special\n\
648 characters to their default values.\n\
652 Handle the tty line connected to standard input. Without arguments,\n\
653 prints baud rate, line discipline, and deviations from stty sane. In\n\
654 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
655 127; special values ^- or undef used to disable special characters.\n\
657 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
662 /* Return 1 if the string contains only valid options. */
664 valid_options (char *opt, const char *valid_opts,
665 const char *valid_arg_opts)
675 if (strchr (valid_opts, ch))
677 if (strchr (valid_arg_opts, ch))
685 main (int argc, char **argv)
688 enum output_type output_type;
690 int require_set_attr;
693 int recoverable_output;
696 char *file_name = NULL;
698 const char *device_name;
699 const char *posixly_correct = getenv ("POSIXLY_CORRECT");
700 int invalid_long_option = 0;
702 program_name = argv[0];
703 setlocale (LC_ALL, "");
704 bindtextdomain (PACKAGE, LOCALEDIR);
705 textdomain (PACKAGE);
707 parse_long_options (argc, argv, "stty", GNU_PACKAGE, VERSION, usage);
709 output_type = changed;
711 recoverable_output = 0;
713 /* Don't print error messages for unrecognized options. */
716 while ((optc = getopt_long (argc, argv, "agF:", longopts, NULL)) != -1)
718 int unrecognized_option = 0;
727 recoverable_output = 1;
728 output_type = recoverable;
733 error (2, 0, _("only one device may be specified"));
738 unrecognized_option = 1;
742 if (unrecognized_option)
746 /* FIXME: what is this?!? */
747 if (invalid_long_option)
750 /* Clear out the options that have been parsed. This is really
751 gross, but it's needed because stty SETTINGS look like options to
752 getopt(), so we need to work around things in a really horrible
753 way. If any new options are ever added to stty, the short option
754 MUST NOT be a letter which is the first letter of one of the
755 possible stty settings. If you change anything about how stty
756 parses options, be sure it still works with combinations of
757 short and long options, --, POSIXLY_CORRECT, etc. */
758 for (k = 1; k < argc; k++)
766 /* Handle --, and reset noargs if there are arguments following it. */
767 if (STREQ (argv[k], "--"))
775 /* Handle "--file device" */
776 len = strlen (argv[k]);
777 if (len >= 3 && strstr ("--file", argv[k]))
784 /* Handle "--all" and "--save". */
786 && (strstr ("--all", argv[k])
787 || strstr ("--save", argv[k])))
793 /* Handle "--file=device". */
794 eq = strchr (argv[k], '=');
795 if (eq && eq - argv[k] >= 3)
798 if (strstr ("--file", argv[k]))
803 /* Put the equals sign back for the error message. */
807 /* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc. */
808 if (valid_options (argv[k], "ag", "F"))
810 /* FIXME: this loses when the device name ends in `F'.
811 e.g. `stty -F/dev/BARF nl' would clobber the `nl' argument. */
812 if (argv[k][strlen (argv[k]) - 1] == 'F')
816 /* Everything else must be a normal, non-option argument. */
825 /* Specifying both -a and -g gets an error. */
826 if (verbose_output && recoverable_output)
828 _("the options for verbose and stty-readable output styles are\n\
829 mutually exclusive"));
831 /* Specifying any other arguments with -a or -g gets an error. */
832 if (!noargs && (verbose_output || recoverable_output))
833 error (2, 0, _("when specifying an output style, modes may not be set"));
835 /* FIXME: it'd be better not to open the file until we've verified
836 that all arguments are valid. Otherwise, we could end up doing
837 only some of the requested operations and then failing, probably
838 leaving things in an undesirable state. */
843 device_name = file_name;
844 fd = open (device_name, O_RDONLY | O_NONBLOCK);
846 error (1, errno, "%s", device_name);
847 if ((fdflags = fcntl (fd, F_GETFL)) == -1
848 || fcntl (fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
849 error (1, errno, _("%s: couldn't reset non-blocking mode"),
855 device_name = _("standard input");
858 /* Initialize to all zeroes so there is no risk memcmp will report a
859 spurious difference in an uninitialized portion of the structure. */
860 memset (&mode, 0, sizeof (mode));
861 if (tcgetattr (fd, &mode))
862 error (1, errno, "%s", device_name);
864 if (verbose_output || recoverable_output || noargs)
866 max_col = screen_columns ();
868 display_settings (output_type, &mode, fd, device_name);
873 require_set_attr = 0;
887 if (argv[k][0] == '-')
892 for (i = 0; mode_info[i].name != NULL; ++i)
894 if (STREQ (argv[k], mode_info[i].name))
896 match_found = set_mode (&mode_info[i], reversed, &mode);
897 require_set_attr = 1;
901 if (match_found == 0 && reversed)
903 error (0, 0, _("invalid argument `%s'"), --argv[k]);
906 if (match_found == 0)
908 for (i = 0; control_info[i].name != NULL; ++i)
910 if (STREQ (argv[k], control_info[i].name))
914 error (0, 0, _("missing argument to `%s'"), argv[k]);
919 set_control_char (&control_info[i], argv[k], &mode);
920 require_set_attr = 1;
925 if (match_found == 0)
927 if (STREQ (argv[k], "ispeed"))
931 error (0, 0, _("missing argument to `%s'"), argv[k]);
935 set_speed (input_speed, argv[k], &mode);
937 require_set_attr = 1;
939 else if (STREQ (argv[k], "ospeed"))
943 error (0, 0, _("missing argument to `%s'"), argv[k]);
947 set_speed (output_speed, argv[k], &mode);
949 require_set_attr = 1;
952 else if (STREQ (argv[k], "rows"))
956 error (0, 0, _("missing argument to `%s'"), argv[k]);
960 set_window_size ((int) integer_arg (argv[k]), -1,
963 else if (STREQ (argv[k], "cols")
964 || STREQ (argv[k], "columns"))
968 error (0, 0, _("missing argument to `%s'"), argv[k]);
972 set_window_size (-1, (int) integer_arg (argv[k]),
975 else if (STREQ (argv[k], "size"))
977 max_col = screen_columns ();
979 display_window_size (0, fd, device_name);
983 else if (STREQ (argv[k], "line"))
987 error (0, 0, _("missing argument to `%s'"), argv[k]);
991 mode.c_line = integer_arg (argv[k]);
992 require_set_attr = 1;
995 else if (STREQ (argv[k], "speed"))
997 max_col = screen_columns ();
998 display_speed (&mode, 0);
1000 else if (string_to_baud (argv[k]) != (speed_t) -1)
1002 set_speed (both_speeds, argv[k], &mode);
1004 require_set_attr = 1;
1008 if (recover_mode (argv[k], &mode) == 0)
1010 error (0, 0, _("invalid argument `%s'"), argv[k]);
1013 require_set_attr = 1;
1019 if (require_set_attr)
1021 struct termios new_mode;
1023 if (tcsetattr (fd, TCSADRAIN, &mode))
1024 error (1, errno, "%s", device_name);
1026 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1027 it performs *any* of the requested operations. This means it
1028 can report `success' when it has actually failed to perform
1029 some proper subset of the requested operations. To detect
1030 this partial failure, get the current terminal attributes and
1031 compare them to the requested ones. */
1033 /* Initialize to all zeroes so there is no risk memcmp will report a
1034 spurious difference in an uninitialized portion of the structure. */
1035 memset (&new_mode, 0, sizeof (new_mode));
1036 if (tcgetattr (fd, &new_mode))
1037 error (1, errno, "%s", device_name);
1039 /* Normally, one shouldn't use memcmp to compare structures that
1040 may have `holes' containing uninitialized data, but we have been
1041 careful to initialize the storage of these two variables to all
1042 zeroes. One might think it more efficient simply to compare the
1043 modified fields, but that would require enumerating those fields --
1044 and not all systems have the same fields in this structure. */
1046 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1049 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1050 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1051 sometimes (m1 != m2). The only difference is in the four bits
1052 of the c_cflag field corresponding to the baud rate. To save
1053 Sun users a little confusion, don't report an error if this
1054 happens. But suppress the error only if we haven't tried to
1055 set the baud rate explicitly -- otherwise we'd never give an
1056 error for a true failure to set the baud rate. */
1058 new_mode.c_cflag &= (~CIBAUD);
1059 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1063 _("%s: unable to perform all requested operations"),
1068 printf (_("new_mode: mode\n"));
1069 for (i = 0; i < sizeof (new_mode); i++)
1070 printf ("0x%02x: 0x%02x\n",
1071 *(((unsigned char *) &new_mode) + i),
1072 *(((unsigned char *) &mode) + i));
1082 /* Return 0 if not applied because not reversible; otherwise return 1. */
1085 set_mode (struct mode_info *info, int reversed, struct termios *mode)
1089 if (reversed && (info->flags & REV) == 0)
1092 bitsp = mode_type_flag (info->type, mode);
1096 /* Combination mode. */
1097 if (STREQ (info->name, "evenp") || STREQ (info->name, "parity"))
1100 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1102 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
1104 else if (STREQ (info->name, "oddp"))
1107 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1109 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
1111 else if (STREQ (info->name, "nl"))
1115 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
1116 mode->c_oflag = (mode->c_oflag
1131 mode->c_iflag = mode->c_iflag & ~ICRNL;
1133 mode->c_oflag = mode->c_oflag & ~ONLCR;
1137 else if (STREQ (info->name, "ek"))
1139 mode->c_cc[VERASE] = CERASE;
1140 mode->c_cc[VKILL] = CKILL;
1142 else if (STREQ (info->name, "sane"))
1144 else if (STREQ (info->name, "cbreak"))
1147 mode->c_lflag |= ICANON;
1149 mode->c_lflag &= ~ICANON;
1151 else if (STREQ (info->name, "pass8"))
1155 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1156 mode->c_iflag |= ISTRIP;
1160 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1161 mode->c_iflag &= ~ISTRIP;
1164 else if (STREQ (info->name, "litout"))
1168 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1169 mode->c_iflag |= ISTRIP;
1170 mode->c_oflag |= OPOST;
1174 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1175 mode->c_iflag &= ~ISTRIP;
1176 mode->c_oflag &= ~OPOST;
1179 else if (STREQ (info->name, "raw") || STREQ (info->name, "cooked"))
1181 if ((info->name[0] == 'r' && reversed)
1182 || (info->name[0] == 'c' && !reversed))
1185 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1186 mode->c_oflag |= OPOST;
1187 mode->c_lflag |= ISIG | ICANON;
1189 mode->c_cc[VEOF] = CEOF;
1192 mode->c_cc[VEOL] = CEOL;
1199 mode->c_oflag &= ~OPOST;
1200 mode->c_lflag &= ~(ISIG | ICANON
1205 mode->c_cc[VMIN] = 1;
1206 mode->c_cc[VTIME] = 0;
1210 else if (STREQ (info->name, "decctlq"))
1213 mode->c_iflag |= IXANY;
1215 mode->c_iflag &= ~IXANY;
1219 else if (STREQ (info->name, "tabs"))
1222 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1224 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1228 else if (STREQ (info->name, "tabs"))
1231 mode->c_oflag = mode->c_oflag | OXTABS;
1233 mode->c_oflag = mode->c_oflag & ~OXTABS;
1237 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1238 else if (STREQ (info->name, "lcase")
1239 || STREQ (info->name, "LCASE"))
1243 mode->c_lflag &= ~XCASE;
1244 mode->c_iflag &= ~IUCLC;
1245 mode->c_oflag &= ~OLCUC;
1249 mode->c_lflag |= XCASE;
1250 mode->c_iflag |= IUCLC;
1251 mode->c_oflag |= OLCUC;
1255 else if (STREQ (info->name, "crt"))
1256 mode->c_lflag |= ECHOE
1264 else if (STREQ (info->name, "dec"))
1266 mode->c_cc[VINTR] = 3; /* ^C */
1267 mode->c_cc[VERASE] = 127; /* DEL */
1268 mode->c_cc[VKILL] = 21; /* ^U */
1269 mode->c_lflag |= ECHOE
1278 mode->c_iflag &= ~IXANY;
1283 *bitsp = *bitsp & ~info->mask & ~info->bits;
1285 *bitsp = (*bitsp & ~info->mask) | info->bits;
1291 set_control_char (struct control_info *info, const char *arg,
1292 struct termios *mode)
1294 unsigned char value;
1296 if (STREQ (info->name, "min") || STREQ (info->name, "time"))
1297 value = integer_arg (arg);
1298 else if (arg[0] == '\0' || arg[1] == '\0')
1300 else if (STREQ (arg, "^-") || STREQ (arg, "undef"))
1301 value = _POSIX_VDISABLE;
1302 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1307 value = arg[1] & ~0140; /* Non-letters get weird results. */
1310 value = integer_arg (arg);
1311 mode->c_cc[info->offset] = value;
1315 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1319 baud = string_to_baud (arg);
1320 if (type == input_speed || type == both_speeds)
1321 cfsetispeed (mode, baud);
1322 if (type == output_speed || type == both_speeds)
1323 cfsetospeed (mode, baud);
1329 get_win_size (int fd, struct winsize *win)
1331 int err = ioctl (fd, TIOCGWINSZ, (char *) win);
1336 set_window_size (int rows, int cols, int fd, const char *device_name)
1340 if (get_win_size (fd, &win))
1342 if (errno != EINVAL)
1343 error (1, errno, "%s", device_name);
1344 memset (&win, 0, sizeof (win));
1353 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1354 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1355 This comment from sys/ttold.h describes Sun's twisted logic - a better
1356 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1357 At any rate, the problem is gone in Solaris 2.x.
1359 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1360 but they can be disambiguated by checking whether a "struct ttysize"
1361 structure's "ts_lines" field is greater than 64K or not. If so,
1362 it's almost certainly a "struct winsize" instead.
1364 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1365 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1366 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1367 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1368 "stty cols 0 rows 0" would do the right thing. On a little-endian
1369 machine like the sun386i, the problem is the same, but for ws_col == 0.
1371 The workaround is to do the ioctl once with row and col = 1 to set the
1372 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1374 if (win.ws_row == 0 || win.ws_col == 0)
1376 struct ttysize ttysz;
1378 ttysz.ts_lines = win.ws_row;
1379 ttysz.ts_cols = win.ws_col;
1384 if (ioctl (fd, TIOCSWINSZ, (char *) &win))
1385 error (1, errno, "%s", device_name);
1387 if (ioctl (fd, TIOCSSIZE, (char *) &ttysz))
1388 error (1, errno, "%s", device_name);
1393 if (ioctl (fd, TIOCSWINSZ, (char *) &win))
1394 error (1, errno, "%s", device_name);
1398 display_window_size (int fancy, int fd, const char *device_name)
1402 if (get_win_size (fd, &win))
1404 if (errno != EINVAL)
1405 error (1, errno, "%s", device_name);
1407 error (1, 0, _("%s: no size information for this device"), device_name);
1411 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1412 win.ws_row, win.ws_col);
1420 screen_columns (void)
1425 /* With Solaris 2.[123], this ioctl fails and errno is set to
1426 EINVAL for telnet (but not rlogin) sessions.
1427 On ISC 3.0, it fails for the console and the serial port
1428 (but it works for ptys).
1429 It can also fail on any system when stdout isn't a tty.
1430 In case of any failure, just use the default. */
1431 if (get_win_size (STDOUT_FILENO, &win) == 0 && win.ws_col > 0)
1434 /* FIXME: use xstrtol */
1435 if (getenv ("COLUMNS"))
1436 return atoi (getenv ("COLUMNS"));
1441 mode_type_flag (enum mode_type type, struct termios *mode)
1446 return &mode->c_cflag;
1449 return &mode->c_iflag;
1452 return &mode->c_oflag;
1455 return &mode->c_lflag;
1466 display_settings (enum output_type output_type, struct termios *mode,
1467 int fd, const char *device_name)
1469 switch (output_type)
1472 display_changed (mode);
1476 display_all (mode, fd, device_name);
1480 display_recoverable (mode);
1486 display_changed (struct termios *mode)
1492 enum mode_type prev_type = control;
1494 display_speed (mode, 1);
1496 wrapf ("line = %d;", mode->c_line);
1502 for (i = 0; !STREQ (control_info[i].name, "min"); ++i)
1504 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1506 /* If swtch is the same as susp, don't print both. */
1508 if (STREQ (control_info[i].name, "swtch"))
1511 /* If eof uses the same slot as min, only print whichever applies. */
1513 if ((mode->c_lflag & ICANON) == 0
1514 && (STREQ (control_info[i].name, "eof")
1515 || STREQ (control_info[i].name, "eol")))
1520 wrapf ("%s = %s;", control_info[i].name,
1521 visible (mode->c_cc[control_info[i].offset]));
1523 if ((mode->c_lflag & ICANON) == 0)
1525 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1526 (int) mode->c_cc[VTIME]);
1528 else if (empty_line == 0)
1533 for (i = 0; mode_info[i].name != NULL; ++i)
1535 if (mode_info[i].flags & OMIT)
1537 if (mode_info[i].type != prev_type)
1539 if (empty_line == 0)
1545 prev_type = mode_info[i].type;
1548 bitsp = mode_type_flag (mode_info[i].type, mode);
1549 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1550 if ((*bitsp & mask) == mode_info[i].bits)
1552 if (mode_info[i].flags & SANE_UNSET)
1554 wrapf ("%s", mode_info[i].name);
1558 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1560 wrapf ("-%s", mode_info[i].name);
1564 if (empty_line == 0)
1570 display_all (struct termios *mode, int fd, const char *device_name)
1575 enum mode_type prev_type = control;
1577 display_speed (mode, 1);
1579 display_window_size (1, fd, device_name);
1582 wrapf ("line = %d;", mode->c_line);
1587 for (i = 0; ! STREQ (control_info[i].name, "min"); ++i)
1589 /* If swtch is the same as susp, don't print both. */
1591 if (STREQ (control_info[i].name, "swtch"))
1594 /* If eof uses the same slot as min, only print whichever applies. */
1596 if ((mode->c_lflag & ICANON) == 0
1597 && (STREQ (control_info[i].name, "eof")
1598 || STREQ (control_info[i].name, "eol")))
1601 wrapf ("%s = %s;", control_info[i].name,
1602 visible (mode->c_cc[control_info[i].offset]));
1605 if ((mode->c_lflag & ICANON) == 0)
1607 wrapf ("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1608 if (current_col != 0)
1612 for (i = 0; mode_info[i].name != NULL; ++i)
1614 if (mode_info[i].flags & OMIT)
1616 if (mode_info[i].type != prev_type)
1620 prev_type = mode_info[i].type;
1623 bitsp = mode_type_flag (mode_info[i].type, mode);
1624 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1625 if ((*bitsp & mask) == mode_info[i].bits)
1626 wrapf ("%s", mode_info[i].name);
1627 else if (mode_info[i].flags & REV)
1628 wrapf ("-%s", mode_info[i].name);
1635 display_speed (struct termios *mode, int fancy)
1637 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1638 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1639 baud_to_value (cfgetospeed (mode)));
1641 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1642 baud_to_value (cfgetispeed (mode)),
1643 baud_to_value (cfgetospeed (mode)));
1649 display_recoverable (struct termios *mode)
1653 printf ("%lx:%lx:%lx:%lx",
1654 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1655 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1656 for (i = 0; i < NCCS; ++i)
1657 printf (":%x", (unsigned int) mode->c_cc[i]);
1662 recover_mode (char *arg, struct termios *mode)
1666 unsigned long iflag, oflag, cflag, lflag;
1668 /* Scan into temporaries since it is too much trouble to figure out
1669 the right format for `tcflag_t'. */
1670 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1671 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1673 mode->c_iflag = iflag;
1674 mode->c_oflag = oflag;
1675 mode->c_cflag = cflag;
1676 mode->c_lflag = lflag;
1678 for (i = 0; i < NCCS; ++i)
1680 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1682 mode->c_cc[i] = chr;
1686 /* Fail if there are too many fields. */
1695 const char *string; /* ASCII representation. */
1696 speed_t speed; /* Internal form. */
1697 unsigned long value; /* Numeric value. */
1700 struct speed_map speeds[] =
1707 {"134.5", B134, 134},
1712 {"1200", B1200, 1200},
1713 {"1800", B1800, 1800},
1714 {"2400", B2400, 2400},
1715 {"4800", B4800, 4800},
1716 {"9600", B9600, 9600},
1717 {"19200", B19200, 19200},
1718 {"38400", B38400, 38400},
1719 {"exta", B19200, 19200},
1720 {"extb", B38400, 38400},
1722 {"57600", B57600, 57600},
1725 {"115200", B115200, 115200},
1728 {"230400", B230400, 230400},
1731 {"460800", B460800, 460800},
1737 string_to_baud (const char *arg)
1741 for (i = 0; speeds[i].string != NULL; ++i)
1742 if (STREQ (arg, speeds[i].string))
1743 return speeds[i].speed;
1744 return (speed_t) -1;
1747 static unsigned long
1748 baud_to_value (speed_t speed)
1752 for (i = 0; speeds[i].string != NULL; ++i)
1753 if (speed == speeds[i].speed)
1754 return speeds[i].value;
1759 sane_mode (struct termios *mode)
1764 for (i = 0; control_info[i].name; ++i)
1767 if (STREQ (control_info[i].name, "min"))
1770 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1773 for (i = 0; mode_info[i].name != NULL; ++i)
1775 if (mode_info[i].flags & SANE_SET)
1777 bitsp = mode_type_flag (mode_info[i].type, mode);
1778 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1780 else if (mode_info[i].flags & SANE_UNSET)
1782 bitsp = mode_type_flag (mode_info[i].type, mode);
1783 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1788 /* Return a string that is the printable representation of character CH. */
1789 /* Adapted from `cat' by Torbjorn Granlund. */
1792 visible (unsigned int ch)
1794 static char buf[10];
1797 if (ch == _POSIX_VDISABLE)
1798 return _("<undef>");
1816 *bpout++ = ch - 128;
1826 *bpout++ = ch - 128 + 64;
1836 return (const char *) buf;
1839 /* Parse string S as an integer, using decimal radix by default,
1840 but allowing octal and hex numbers as in C. */
1841 /* From `od' by Richard Stallman. */
1844 integer_arg (const char *s)
1847 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1849 error (0, 0, _("invalid integer argument `%s'"), s);