1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2023 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 3 of the License, or
7 (at your option) 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, see <https://www.gnu.org/licenses/>. */
17 /* Usage: stty [-ag] [--all] [--save] [-F device] [--file=device] [setting...]
20 -a, --all Write all current settings to stdout in human-readable form.
21 -g, --save Write all current settings to stdout in stty-readable form.
22 -F, --file Open and use the specified device instead of stdin
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 the specified device, or stdin if none was specified.
28 David MacKenzie <djm@gnu.ai.mit.edu> */
32 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
33 # define _XOPEN_SOURCE
37 #include <sys/types.h>
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
60 #include "fd-reopen.h"
62 #include "xdectoint.h"
65 /* The official name of this program (e.g., no 'g' prefix). */
66 #define PROGRAM_NAME "stty"
68 #define AUTHORS proper_name ("David MacKenzie")
70 #ifndef _POSIX_VDISABLE
71 # define _POSIX_VDISABLE 0
74 #define Control(c) ((c) & 0x1f)
75 /* Canonical values for control characters. */
77 # define CINTR Control ('c')
86 # define CKILL Control ('u')
89 # define CEOF Control ('d')
92 # define CEOL _POSIX_VDISABLE
95 # define CSTART Control ('q')
98 # define CSTOP Control ('s')
101 # define CSUSP Control ('z')
103 #if defined VEOL2 && !defined CEOL2
104 # define CEOL2 _POSIX_VDISABLE
106 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
107 character is initialized by CSWTCH, if present. */
108 #if defined VSWTC && !defined VSWTCH
109 # define VSWTCH VSWTC
111 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
112 #if defined VSUSP && !defined VSWTCH
113 # define VSWTCH VSUSP
114 # if defined CSUSP && !defined CSWTCH
115 # define CSWTCH CSUSP
118 #if defined VSWTCH && !defined CSWTCH
119 # define CSWTCH _POSIX_VDISABLE
122 /* SunOS >= 5.3 loses (^Z doesn't work) if 'swtch' is the same as 'susp'.
123 So the default is to disable 'swtch.' */
126 # define CSWTCH _POSIX_VDISABLE
129 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
130 # define VWERASE VWERSE
132 #if defined VDSUSP && !defined CDSUSP
133 # define CDSUSP Control ('y')
135 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
136 # define VREPRINT VRPRNT
138 #if defined VREPRINT && !defined CRPRNT
139 # define CRPRNT Control ('r')
141 #if defined CREPRINT && !defined CRPRNT
142 # define CRPRNT Control ('r')
144 #if defined VWERASE && !defined CWERASE
145 # define CWERASE Control ('w')
147 #if defined VLNEXT && !defined CLNEXT
148 # define CLNEXT Control ('v')
150 #if defined VDISCARD && !defined VFLUSHO
151 # define VFLUSHO VDISCARD
153 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
154 # define VFLUSHO VFLUSH
156 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
157 # define ECHOCTL CTLECH
159 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
160 # define ECHOCTL TCTLECH
162 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
163 # define ECHOKE CRTKIL
165 #if defined VFLUSHO && !defined CFLUSHO
166 # define CFLUSHO Control ('o')
168 #if defined VSTATUS && !defined CSTATUS
169 # define CSTATUS Control ('t')
172 /* Which speeds to set. */
175 input_speed
, output_speed
, both_speeds
178 /* What to output and how. */
181 changed
, all
, recoverable
/* Default, -a, -g. */
184 /* Which member(s) of 'struct termios' a mode uses. */
187 control
, input
, output
, local
, combination
190 /* Flags for 'struct mode_info'. */
191 #define SANE_SET 1 /* Set in 'sane' mode. */
192 #define SANE_UNSET 2 /* Unset in 'sane' mode. */
193 #define REV 4 /* Can be turned off by prepending '-'. */
194 #define OMIT 8 /* Don't display value. */
195 #define NO_SETATTR 16 /* tcsetattr not used to set mode bits. */
200 char const *name
; /* Name given on command line. */
201 enum mode_type type
; /* Which structure element to change. */
202 char flags
; /* Setting and display options. */
203 unsigned long bits
; /* Bits to set for this mode. */
204 unsigned long mask
; /* Other bits to turn off for this mode. */
207 static struct mode_info
const mode_info
[] =
209 {"parenb", control
, REV
, PARENB
, 0},
210 {"parodd", control
, REV
, PARODD
, 0},
212 {"cmspar", control
, REV
, CMSPAR
, 0},
214 {"cs5", control
, 0, CS5
, CSIZE
},
215 {"cs6", control
, 0, CS6
, CSIZE
},
216 {"cs7", control
, 0, CS7
, CSIZE
},
217 {"cs8", control
, 0, CS8
, CSIZE
},
218 {"hupcl", control
, REV
, HUPCL
, 0},
219 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
220 {"cstopb", control
, REV
, CSTOPB
, 0},
221 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
222 {"clocal", control
, REV
, CLOCAL
, 0},
224 {"crtscts", control
, REV
, CRTSCTS
, 0},
227 {"cdtrdsr", control
, REV
, CDTRDSR
, 0},
230 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
231 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
232 {"ignpar", input
, REV
, IGNPAR
, 0},
233 {"parmrk", input
, REV
, PARMRK
, 0},
234 {"inpck", input
, REV
, INPCK
, 0},
235 {"istrip", input
, REV
, ISTRIP
, 0},
236 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
237 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
238 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
239 {"ixon", input
, REV
, IXON
, 0},
240 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
241 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
243 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
246 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
249 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
252 {"iutf8", input
, SANE_UNSET
| REV
, IUTF8
, 0},
255 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
257 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
260 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
263 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
266 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
269 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
272 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
275 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
278 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
279 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
282 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
283 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
284 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
285 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
289 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
292 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
295 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
298 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
302 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
306 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
307 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
310 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
311 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
314 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
315 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
318 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
319 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
321 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
323 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
324 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
325 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
326 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
327 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
328 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
330 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
333 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
336 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
337 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
340 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
341 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
344 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
345 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
348 {"flusho", local
, SANE_UNSET
| REV
, FLUSHO
, 0},
351 {"extproc", local
, SANE_UNSET
| REV
| NO_SETATTR
, EXTPROC
, 0},
352 #elif defined EXTPROC
353 {"extproc", local
, SANE_UNSET
| REV
, EXTPROC
, 0},
356 {"evenp", combination
, REV
| OMIT
, 0, 0},
357 {"parity", combination
, REV
| OMIT
, 0, 0},
358 {"oddp", combination
, REV
| OMIT
, 0, 0},
359 {"nl", combination
, REV
| OMIT
, 0, 0},
360 {"ek", combination
, OMIT
, 0, 0},
361 {"sane", combination
, OMIT
, 0, 0},
362 {"cooked", combination
, REV
| OMIT
, 0, 0},
363 {"raw", combination
, REV
| OMIT
, 0, 0},
364 {"pass8", combination
, REV
| OMIT
, 0, 0},
365 {"litout", combination
, REV
| OMIT
, 0, 0},
366 {"cbreak", combination
, REV
| OMIT
, 0, 0},
368 {"decctlq", combination
, REV
| OMIT
, 0, 0},
370 #if defined TABDLY || defined OXTABS
371 {"tabs", combination
, REV
| OMIT
, 0, 0},
373 #if defined XCASE && defined IUCLC && defined OLCUC
374 {"lcase", combination
, REV
| OMIT
, 0, 0},
375 {"LCASE", combination
, REV
| OMIT
, 0, 0},
377 {"crt", combination
, OMIT
, 0, 0},
378 {"dec", combination
, OMIT
, 0, 0},
380 {NULL
, control
, 0, 0, 0}
383 /* Control character settings. */
386 char const *name
; /* Name given on command line. */
387 cc_t saneval
; /* Value to set for 'stty sane'. */
388 size_t offset
; /* Offset in c_cc. */
391 /* Control characters. */
393 static struct control_info
const control_info
[] =
395 {"intr", CINTR
, VINTR
},
396 {"quit", CQUIT
, VQUIT
},
397 {"erase", CERASE
, VERASE
},
398 {"kill", CKILL
, VKILL
},
402 {"eol2", CEOL2
, VEOL2
},
405 {"swtch", CSWTCH
, VSWTCH
},
407 {"start", CSTART
, VSTART
},
408 {"stop", CSTOP
, VSTOP
},
409 {"susp", CSUSP
, VSUSP
},
411 {"dsusp", CDSUSP
, VDSUSP
},
414 {"rprnt", CRPRNT
, VREPRINT
},
416 # ifdef CREPRINT /* HPUX 10.20 needs this */
417 {"rprnt", CRPRNT
, CREPRINT
},
421 {"werase", CWERASE
, VWERASE
},
424 {"lnext", CLNEXT
, VLNEXT
},
427 {"flush", CFLUSHO
, VFLUSHO
}, /* deprecated compat option. */
428 {"discard", CFLUSHO
, VFLUSHO
},
431 {"status", CSTATUS
, VSTATUS
},
434 /* These must be last because of the display routines. */
440 static char const *visible (cc_t ch
);
441 static unsigned long int baud_to_value (speed_t speed
);
442 static bool recover_mode (char const *arg
, struct termios
*mode
);
443 static int screen_columns (void);
444 static bool set_mode (struct mode_info
const *info
, bool reversed
,
445 struct termios
*mode
);
446 static bool eq_mode (struct termios
*mode1
, struct termios
*mode2
);
447 static unsigned long int integer_arg (char const *s
, unsigned long int max
);
448 static speed_t
string_to_baud (char const *arg
);
449 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
450 static void display_all (struct termios
*mode
, char const *device_name
);
451 static void display_changed (struct termios
*mode
);
452 static void display_recoverable (struct termios
*mode
);
453 static void display_settings (enum output_type output_type
,
454 struct termios
*mode
,
455 char const *device_name
);
456 static void check_speed (struct termios
*mode
);
457 static void display_speed (struct termios
*mode
, bool fancy
);
458 static void display_window_size (bool fancy
, char const *device_name
);
459 static void sane_mode (struct termios
*mode
);
460 static void set_control_char (struct control_info
const *info
,
462 struct termios
*mode
);
463 static void set_speed (enum speed_setting type
, char const *arg
,
464 struct termios
*mode
);
465 static void set_window_size (int rows
, int cols
, char const *device_name
);
467 /* The width of the screen, for output wrapping. */
470 /* Current position, to know when to wrap. */
471 static int current_col
;
473 /* Default "drain" mode for tcsetattr. */
474 static int tcsetattr_options
= TCSADRAIN
;
476 /* Extra info to aid stty development. */
477 static bool dev_debug
;
479 /* Record last speed set for correlation. */
480 static speed_t last_ibaud
= (speed_t
) -1;
481 static speed_t last_obaud
= (speed_t
) -1;
483 /* For long options that have no equivalent short option, use a
484 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
487 DEV_DEBUG_OPTION
= CHAR_MAX
+ 1,
490 static struct option
const longopts
[] =
492 {"all", no_argument
, NULL
, 'a'},
493 {"save", no_argument
, NULL
, 'g'},
494 {"file", required_argument
, NULL
, 'F'},
495 {"-debug", no_argument
, NULL
, DEV_DEBUG_OPTION
},
496 {GETOPT_HELP_OPTION_DECL
},
497 {GETOPT_VERSION_OPTION_DECL
},
501 /* Print format string MESSAGE and optional args.
502 Wrap to next line first if it won't fit.
503 Print a space first unless MESSAGE will start a new line. */
505 ATTRIBUTE_FORMAT ((printf
, 1, 2))
507 wrapf (char const *message
,...)
513 va_start (args
, message
);
514 buflen
= vasprintf (&buf
, message
, args
);
522 if (max_col
- current_col
<= buflen
)
536 current_col
+= buflen
;
542 if (status
!= EXIT_SUCCESS
)
547 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
548 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
549 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
551 program_name
, program_name
, program_name
);
553 Print or change terminal characteristics.\n\
556 emit_mandatory_arg_note ();
559 -a, --all print all current settings in human-readable form\n\
560 -g, --save print all current settings in a stty-readable form\n\
561 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
563 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
564 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
567 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
568 settings. The underlying system defines which settings are available.\n\
572 Special characters:\n"), stdout
);
575 * discard CHAR CHAR will toggle discarding of output\n\
580 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
584 eof CHAR CHAR will send an end of file (terminate the input)\n\
585 eol CHAR CHAR will end the line\n\
589 * eol2 CHAR alternate CHAR for ending the line\n\
593 erase CHAR CHAR will erase the last character typed\n\
594 intr CHAR CHAR will send an interrupt signal\n\
595 kill CHAR CHAR will erase the current line\n\
599 * lnext CHAR CHAR will enter the next character quoted\n\
604 * status CHAR CHAR will send an info signal\n\
608 quit CHAR CHAR will send a quit signal\n\
610 #if defined CREPRINT || defined VREPRINT
612 * rprnt CHAR CHAR will redraw the current line\n\
616 start CHAR CHAR will restart the output after stopping it\n\
617 stop CHAR CHAR will stop the output\n\
618 susp CHAR CHAR will send a terminal stop signal\n\
622 * swtch CHAR CHAR will switch to a different shell layer\n\
627 * werase CHAR CHAR will erase the last word typed\n\
633 N set the input and output speeds to N bauds\n\
637 * cols N tell the kernel that the terminal has N columns\n\
638 * columns N same as cols N\n\
642 * [-]drain wait for transmission before applying settings (%s by default)\
643 \n"), tcsetattr_options
== TCSADRAIN
? _("on") : _("off"));
645 ispeed N set the input speed to N\n\
649 * line N use line discipline N\n\
653 min N with -icanon, set N characters minimum for a completed read\n\
654 ospeed N set the output speed to N\n\
658 * rows N tell the kernel that the terminal has N rows\n\
659 * size print the number of rows and columns according to the kernel\n\
663 speed print the terminal speed\n\
664 time N with -icanon, set read timeout of N tenths of a second\n\
669 [-]clocal disable modem control signals\n\
670 [-]cread allow input to be received\n\
674 * [-]crtscts enable RTS/CTS handshaking\n\
679 * [-]cdtrdsr enable DTR/DSR handshaking\n\
683 csN set character size to N bits, N in [5..8]\n\
686 [-]cstopb use two stop bits per character (one with '-')\n\
687 [-]hup send a hangup signal when the last process closes the tty\n\
688 [-]hupcl same as [-]hup\n\
689 [-]parenb generate parity bit in output and expect parity bit in input\n\
690 [-]parodd set odd parity (or even parity with '-')\n\
694 * [-]cmspar use \"stick\" (mark/space) parity\n\
700 [-]brkint breaks cause an interrupt signal\n\
701 [-]icrnl translate carriage return to newline\n\
702 [-]ignbrk ignore break characters\n\
703 [-]igncr ignore carriage return\n\
704 [-]ignpar ignore characters with parity errors\n\
708 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
712 [-]inlcr translate newline to carriage return\n\
713 [-]inpck enable input parity checking\n\
714 [-]istrip clear high (8th) bit of input characters\n\
718 * [-]iutf8 assume input characters are UTF-8 encoded\n\
723 * [-]iuclc translate uppercase characters to lowercase\n\
728 * [-]ixany let any character restart output, not only start character\n\
732 [-]ixoff enable sending of start/stop characters\n\
733 [-]ixon enable XON/XOFF flow control\n\
734 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
735 [-]tandem same as [-]ixoff\n\
743 * bsN backspace delay style, N in [0..1]\n\
748 * crN carriage return delay style, N in [0..3]\n\
753 * ffN form feed delay style, N in [0..1]\n\
758 * nlN newline delay style, N in [0..1]\n\
763 * [-]ocrnl translate carriage return to newline\n\
768 * [-]ofdel use delete characters for fill instead of NUL characters\n\
773 * [-]ofill use fill (padding) characters instead of timing for delays\n\
778 * [-]olcuc translate lowercase characters to uppercase\n\
783 * [-]onlcr translate newline to carriage return-newline\n\
788 * [-]onlret newline performs a carriage return\n\
793 * [-]onocr do not print carriage returns in the first column\n\
797 [-]opost postprocess output\n\
799 #if defined TABDLY || defined OXTABS
801 * tabN horizontal tab delay style, N in [0..3]\n\
802 * tabs same as tab0\n\
803 * -tabs same as tab3\n\
808 * vtN vertical tab delay style, N in [0..1]\n\
814 [-]crterase echo erase characters as backspace-space-backspace\n\
818 * crtkill kill all line by obeying the echoprt and echoe settings\n\
819 * -crtkill kill all line by obeying the echoctl and echok settings\n\
824 * [-]ctlecho echo control characters in hat notation ('^c')\n\
828 [-]echo echo input characters\n\
832 * [-]echoctl same as [-]ctlecho\n\
836 [-]echoe same as [-]crterase\n\
837 [-]echok echo a newline after a kill character\n\
841 * [-]echoke same as [-]crtkill\n\
845 [-]echonl echo newline even if not echoing other characters\n\
849 * [-]echoprt echo erased characters backward, between '\\' and '/'\n\
852 #if defined EXTPROC || defined TIOCEXT
854 * [-]extproc enable \"LINEMODE\"; useful with high latency links\n\
859 * [-]flusho discard output\n\
863 [-]icanon enable special characters: %s\n\
864 [-]iexten enable non-POSIX special characters\n\
869 #if defined CREPRINT || defined VREPRINT
874 [-]isig enable interrupt, quit, and suspend special characters\n\
875 [-]noflsh disable flushing after interrupt and quit special characters\n\
879 * [-]prterase same as [-]echoprt\n\
884 * [-]tostop stop background jobs that try to write to the terminal\n\
889 * [-]xcase with icanon, escape with '\\' for uppercase characters\n\
894 Combination settings:\n\
896 #if defined XCASE && defined IUCLC && defined OLCUC
898 * [-]LCASE same as [-]lcase\n\
902 cbreak same as -icanon\n\
903 -cbreak same as icanon\n\
906 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
907 icanon, eof and eol characters to their default values\n\
908 -cooked same as raw\n\
921 dec same as %s intr ^c erase 0177\n\
936 * [-]decctlq same as [-]ixany\n\
940 ek erase and kill characters to their default values\n\
941 evenp same as parenb -parodd cs7\n\
942 -evenp same as -parenb cs8\n\
944 #if defined XCASE && defined IUCLC && defined OLCUC
946 * [-]lcase same as xcase iuclc olcuc\n\
950 litout same as -parenb -istrip -opost cs8\n\
951 -litout same as parenb istrip opost cs7\n\
960 , "icrnl -inlcr -igncr"
972 oddp same as parenb parodd cs7\n\
973 -oddp same as -parenb cs8\n\
974 [-]parity same as [-]evenp\n\
975 pass8 same as -parenb -istrip cs8\n\
976 -pass8 same as parenb istrip cs7\n\
979 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
980 -inlcr -igncr -icrnl -ixon -ixoff -icanon -opost\n\
981 -isig%s min 1 time 0\n\
982 -raw same as cooked\n\
998 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
999 icanon iexten echo echoe echok -echonl -noflsh\n\
1003 all special characters to their default values\n\
1085 Handle the tty line connected to standard input. Without arguments,\n\
1086 prints baud rate, line discipline, and deviations from stty sane. In\n\
1087 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
1088 127; special values ^- or undef used to disable special characters.\n\
1090 emit_ancillary_info (PROGRAM_NAME
);
1096 /* Apply specified settings to MODE and REQUIRE_SET_ATTR as required.
1097 If CHECKING is true, this function doesn't interact
1098 with a device, and only validates specified settings. */
1101 apply_settings (bool checking
, char const *device_name
,
1102 char * const *settings
, int n_settings
,
1103 struct termios
*mode
, bool *require_set_attr
)
1105 #define check_argument(arg) \
1108 if (k == n_settings - 1 || ! settings[k + 1]) \
1110 error (0, 0, _("missing argument to %s"), quote (arg)); \
1111 usage (EXIT_FAILURE); \
1116 for (int k
= 1; k
< n_settings
; k
++)
1118 char const *arg
= settings
[k
];
1119 bool match_found
= false;
1120 bool not_set_attr
= false;
1121 bool reversed
= false;
1132 if (STREQ (arg
, "drain"))
1134 tcsetattr_options
= reversed
? TCSANOW
: TCSADRAIN
;
1137 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1139 if (STREQ (arg
, mode_info
[i
].name
))
1141 if ((mode_info
[i
].flags
& NO_SETATTR
) == 0)
1143 match_found
= set_mode (&mode_info
[i
], reversed
, mode
);
1144 *require_set_attr
= true;
1147 match_found
= not_set_attr
= true;
1151 if (!match_found
&& reversed
)
1153 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
1154 usage (EXIT_FAILURE
);
1158 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
1160 if (STREQ (arg
, control_info
[i
].name
))
1162 check_argument (arg
);
1165 set_control_char (&control_info
[i
], settings
[k
], mode
);
1166 *require_set_attr
= true;
1171 if (!match_found
|| not_set_attr
)
1173 if (STREQ (arg
, "ispeed"))
1175 check_argument (arg
);
1177 if (string_to_baud (settings
[k
]) == (speed_t
) -1)
1179 error (0, 0, _("invalid ispeed %s"), quote (settings
[k
]));
1180 usage (EXIT_FAILURE
);
1182 set_speed (input_speed
, settings
[k
], mode
);
1185 *require_set_attr
= true;
1187 else if (STREQ (arg
, "ospeed"))
1189 check_argument (arg
);
1191 if (string_to_baud (settings
[k
]) == (speed_t
) -1)
1193 error (0, 0, _("invalid ospeed %s"), quote (settings
[k
]));
1194 usage (EXIT_FAILURE
);
1196 set_speed (output_speed
, settings
[k
], mode
);
1199 *require_set_attr
= true;
1202 /* This is the BSD interface to "extproc".
1203 Even though it's an lflag, an ioctl is used to set it. */
1204 else if (STREQ (arg
, "extproc"))
1206 int val
= ! reversed
;
1211 if (ioctl (STDIN_FILENO
, TIOCEXT
, &val
) != 0)
1213 die (EXIT_FAILURE
, errno
, _("%s: error setting %s"),
1214 quotef_n (0, device_name
), quote_n (1, arg
));
1219 else if (STREQ (arg
, "rows"))
1221 check_argument (arg
);
1225 set_window_size (integer_arg (settings
[k
], INT_MAX
), -1,
1228 else if (STREQ (arg
, "cols")
1229 || STREQ (arg
, "columns"))
1231 check_argument (arg
);
1235 set_window_size (-1, integer_arg (settings
[k
], INT_MAX
),
1238 else if (STREQ (arg
, "size"))
1242 max_col
= screen_columns ();
1244 display_window_size (false, device_name
);
1248 else if (STREQ (arg
, "line"))
1250 unsigned long int value
;
1251 check_argument (arg
);
1253 mode
->c_line
= value
= integer_arg (settings
[k
], ULONG_MAX
);
1254 if (mode
->c_line
!= value
)
1255 error (0, 0, _("invalid line discipline %s"),
1256 quote (settings
[k
]));
1257 *require_set_attr
= true;
1260 else if (STREQ (arg
, "speed"))
1264 max_col
= screen_columns ();
1265 display_speed (mode
, false);
1267 else if (string_to_baud (arg
) != (speed_t
) -1)
1269 set_speed (both_speeds
, arg
, mode
);
1272 *require_set_attr
= true;
1276 if (! recover_mode (arg
, mode
))
1278 error (0, 0, _("invalid argument %s"), quote (arg
));
1279 usage (EXIT_FAILURE
);
1281 *require_set_attr
= true;
1291 main (int argc
, char **argv
)
1293 struct termios mode
;
1295 enum output_type output_type
;
1299 bool require_set_attr
;
1300 bool verbose_output
;
1301 bool recoverable_output
;
1303 char *file_name
= NULL
;
1304 char const *device_name
;
1306 initialize_main (&argc
, &argv
);
1307 set_program_name (argv
[0]);
1308 setlocale (LC_ALL
, "");
1309 bindtextdomain (PACKAGE
, LOCALEDIR
);
1310 textdomain (PACKAGE
);
1312 atexit (close_stdout
);
1314 output_type
= changed
;
1315 verbose_output
= false;
1316 recoverable_output
= false;
1318 /* Don't print error messages for unrecognized options. */
1321 /* If any new options are ever added to stty, the short options MUST
1322 NOT allow any ambiguity with the stty settings. For example, the
1323 stty setting "-gagFork" would not be feasible, since it will be
1324 parsed as "-g -a -g -F ork". If you change anything about how
1325 stty parses options, be sure it still works with combinations of
1326 short and long options, --, POSIXLY_CORRECT, etc. */
1328 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
1335 verbose_output
= true;
1340 recoverable_output
= true;
1341 output_type
= recoverable
;
1346 die (EXIT_FAILURE
, 0, _("only one device may be specified"));
1350 case DEV_DEBUG_OPTION
:
1354 case_GETOPT_HELP_CHAR
;
1356 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1359 /* Consider "drain" as an option rather than a setting,
1360 to support: alias stty='stty -drain' etc. */
1361 if (! STREQ (argv
[argi
+ opti
], "-drain")
1362 && ! STREQ (argv
[argi
+ opti
], "drain"))
1365 /* Skip the argument containing this unrecognized option;
1366 the 2nd pass will analyze it. */
1369 /* Restart getopt_long from the first unskipped argument. */
1376 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
1377 while (opti
< optind
)
1378 argv
[argi
+ opti
++] = NULL
;
1381 /* Specifying both -a and -g gets an error. */
1382 if (verbose_output
&& recoverable_output
)
1383 die (EXIT_FAILURE
, 0,
1384 _("the options for verbose and stty-readable output styles are\n"
1385 "mutually exclusive"));
1387 /* Specifying any other arguments with -a or -g gets an error. */
1388 if (!noargs
&& (verbose_output
|| recoverable_output
))
1389 die (EXIT_FAILURE
, 0,
1390 _("when specifying an output style, modes may not be set"));
1392 device_name
= file_name
? file_name
: _("standard input");
1394 if (!noargs
&& !verbose_output
&& !recoverable_output
)
1396 static struct termios check_mode
;
1397 apply_settings (/* checking= */ true, device_name
, argv
, argc
,
1398 &check_mode
, &require_set_attr
);
1404 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
1405 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1406 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
1407 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
1408 die (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
1409 quotef (device_name
));
1412 if (tcgetattr (STDIN_FILENO
, &mode
))
1413 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1415 if (verbose_output
|| recoverable_output
|| noargs
)
1417 max_col
= screen_columns ();
1419 display_settings (output_type
, &mode
, device_name
);
1420 return EXIT_SUCCESS
;
1423 require_set_attr
= false;
1424 apply_settings (/* checking= */ false, device_name
, argv
, argc
,
1425 &mode
, &require_set_attr
);
1427 if (require_set_attr
)
1429 struct termios new_mode
;
1431 if (tcsetattr (STDIN_FILENO
, tcsetattr_options
, &mode
))
1432 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1434 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1435 it performs *any* of the requested operations. This means it
1436 can report 'success' when it has actually failed to perform
1437 some proper subset of the requested operations. To detect
1438 this partial failure, get the current terminal attributes and
1439 compare them to the requested ones. */
1441 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1442 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1444 if (! eq_mode (&mode
, &new_mode
))
1448 error (0, 0, _("indx: mode: actual mode"));
1449 for (unsigned int i
= 0; i
< sizeof (new_mode
); i
++)
1451 unsigned int newc
= *(((unsigned char *) &new_mode
) + i
);
1452 unsigned int oldc
= *(((unsigned char *) &mode
) + i
);
1453 error (0, 0, "0x%02x, 0x%02x: 0x%02x%s", i
, oldc
, newc
,
1454 newc
== oldc
? "" : " *");
1458 die (EXIT_FAILURE
, 0,
1459 _("%s: unable to perform all requested operations"),
1460 quotef (device_name
));
1464 return EXIT_SUCCESS
;
1467 /* Return true if modes are equivalent. */
1470 eq_mode (struct termios
*mode1
, struct termios
*mode2
)
1472 return mode1
->c_iflag
== mode2
->c_iflag
1473 && mode1
->c_oflag
== mode2
->c_oflag
1474 && mode1
->c_cflag
== mode2
->c_cflag
1475 && mode1
->c_lflag
== mode2
->c_lflag
1477 && mode1
->c_line
== mode2
->c_line
1479 && memcmp (mode1
->c_cc
, mode2
->c_cc
, sizeof (mode1
->c_cc
)) == 0
1480 && cfgetispeed (mode1
) == cfgetispeed (mode2
)
1481 && cfgetospeed (mode1
) == cfgetospeed (mode2
);
1484 /* Return false if not applied because not reversible; otherwise
1488 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1492 if (reversed
&& (info
->flags
& REV
) == 0)
1495 bitsp
= mode_type_flag (info
->type
, mode
);
1499 /* Combination mode. */
1500 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1503 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1505 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1507 else if (STREQ (info
->name
, "oddp"))
1510 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1512 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1514 else if (STREQ (info
->name
, "nl"))
1518 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1519 mode
->c_oflag
= (mode
->c_oflag
1534 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1536 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1540 else if (STREQ (info
->name
, "ek"))
1542 mode
->c_cc
[VERASE
] = CERASE
;
1543 mode
->c_cc
[VKILL
] = CKILL
;
1545 else if (STREQ (info
->name
, "sane"))
1547 else if (STREQ (info
->name
, "cbreak"))
1550 mode
->c_lflag
|= ICANON
;
1552 mode
->c_lflag
&= ~ICANON
;
1554 else if (STREQ (info
->name
, "pass8"))
1558 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1559 mode
->c_iflag
|= ISTRIP
;
1563 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1564 mode
->c_iflag
&= ~ISTRIP
;
1567 else if (STREQ (info
->name
, "litout"))
1571 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1572 mode
->c_iflag
|= ISTRIP
;
1573 mode
->c_oflag
|= OPOST
;
1577 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1578 mode
->c_iflag
&= ~ISTRIP
;
1579 mode
->c_oflag
&= ~OPOST
;
1582 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1584 if ((info
->name
[0] == 'r' && reversed
)
1585 || (info
->name
[0] == 'c' && !reversed
))
1588 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1589 mode
->c_oflag
|= OPOST
;
1590 mode
->c_lflag
|= ISIG
| ICANON
;
1592 mode
->c_cc
[VEOF
] = CEOF
;
1595 mode
->c_cc
[VEOL
] = CEOL
;
1602 mode
->c_oflag
&= ~OPOST
;
1603 mode
->c_lflag
&= ~(ISIG
| ICANON
1608 mode
->c_cc
[VMIN
] = 1;
1609 mode
->c_cc
[VTIME
] = 0;
1613 else if (STREQ (info
->name
, "decctlq"))
1616 mode
->c_iflag
|= IXANY
;
1618 mode
->c_iflag
&= ~IXANY
;
1622 else if (STREQ (info
->name
, "tabs"))
1625 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1627 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1631 else if (STREQ (info
->name
, "tabs"))
1634 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1636 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1640 #if defined XCASE && defined IUCLC && defined OLCUC
1641 else if (STREQ (info
->name
, "lcase")
1642 || STREQ (info
->name
, "LCASE"))
1646 mode
->c_lflag
&= ~XCASE
;
1647 mode
->c_iflag
&= ~IUCLC
;
1648 mode
->c_oflag
&= ~OLCUC
;
1652 mode
->c_lflag
|= XCASE
;
1653 mode
->c_iflag
|= IUCLC
;
1654 mode
->c_oflag
|= OLCUC
;
1658 else if (STREQ (info
->name
, "crt"))
1659 mode
->c_lflag
|= ECHOE
1667 else if (STREQ (info
->name
, "dec"))
1669 mode
->c_cc
[VINTR
] = 3; /* ^C */
1670 mode
->c_cc
[VERASE
] = 127; /* DEL */
1671 mode
->c_cc
[VKILL
] = 21; /* ^U */
1672 mode
->c_lflag
|= ECHOE
1681 mode
->c_iflag
&= ~IXANY
;
1686 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1688 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1694 set_control_char (struct control_info
const *info
, char const *arg
,
1695 struct termios
*mode
)
1697 unsigned long int value
;
1699 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1700 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1701 else if (arg
[0] == '\0' || arg
[1] == '\0')
1702 value
= to_uchar (arg
[0]);
1703 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1704 value
= _POSIX_VDISABLE
;
1705 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1710 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1713 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1714 mode
->c_cc
[info
->offset
] = value
;
1718 set_speed (enum speed_setting type
, char const *arg
, struct termios
*mode
)
1720 /* Note cfset[io]speed(), do not check with the device,
1721 and only check whether the system logic supports the specified speed.
1722 Therefore we don't report the device name in any errors. */
1724 speed_t baud
= string_to_baud (arg
);
1725 assert (baud
!= (speed_t
) -1);
1727 if (type
== input_speed
|| type
== both_speeds
)
1730 if (cfsetispeed (mode
, baud
))
1731 die (EXIT_FAILURE
, 0, "unsupported ispeed %s", quotef (arg
));
1733 if (type
== output_speed
|| type
== both_speeds
)
1736 if (cfsetospeed (mode
, baud
))
1737 die (EXIT_FAILURE
, 0, "unsupported ospeed %s", quotef (arg
));
1744 get_win_size (int fd
, struct winsize
*win
)
1746 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1751 set_window_size (int rows
, int cols
, char const *device_name
)
1755 if (get_win_size (STDIN_FILENO
, &win
))
1757 if (errno
!= EINVAL
)
1758 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1759 memset (&win
, 0, sizeof (win
));
1768 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1769 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1770 This comment from sys/ttold.h describes Sun's twisted logic - a better
1771 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1772 At any rate, the problem is gone in Solaris 2.x.
1774 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1775 but they can be disambiguated by checking whether a "struct ttysize"
1776 structure's "ts_lines" field is greater than 64K or not. If so,
1777 it's almost certainly a "struct winsize" instead.
1779 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1780 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16)
1781 + ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1782 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1783 "stty cols 0 rows 0" would do the right thing. On a little-endian
1784 machine like the sun386i, the problem is the same, but for ws_col == 0.
1786 The workaround is to do the ioctl once with row and col = 1 to set the
1787 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1789 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1791 struct ttysize ttysz
;
1793 ttysz
.ts_lines
= win
.ws_row
;
1794 ttysz
.ts_cols
= win
.ws_col
;
1799 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1800 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1802 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1803 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1808 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1809 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1813 display_window_size (bool fancy
, char const *device_name
)
1817 if (get_win_size (STDIN_FILENO
, &win
))
1819 if (errno
!= EINVAL
)
1820 die (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1822 die (EXIT_FAILURE
, 0,
1823 _("%s: no size information for this device"),
1824 quotef (device_name
));
1828 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1829 win
.ws_row
, win
.ws_col
);
1837 screen_columns (void)
1842 /* With Solaris 2.[123], this ioctl fails and errno is set to
1843 EINVAL for telnet (but not rlogin) sessions.
1844 On ISC 3.0, it fails for the console and the serial port
1845 (but it works for ptys).
1846 It can also fail on any system when stdout isn't a tty.
1847 In case of any failure, just use the default. */
1848 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1852 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1853 char *col_string
= getenv ("COLUMNS");
1855 if (!(col_string
!= NULL
1856 && xstrtol (col_string
, NULL
, 0, &n_columns
, "") == LONGINT_OK
1858 && n_columns
<= INT_MAX
))
1866 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1871 return &mode
->c_cflag
;
1874 return &mode
->c_iflag
;
1877 return &mode
->c_oflag
;
1880 return &mode
->c_lflag
;
1891 display_settings (enum output_type output_type
, struct termios
*mode
,
1892 char const *device_name
)
1894 switch (output_type
)
1897 display_changed (mode
);
1901 display_all (mode
, device_name
);
1905 display_recoverable (mode
);
1911 display_changed (struct termios
*mode
)
1917 enum mode_type prev_type
= control
;
1919 display_speed (mode
, true);
1921 wrapf ("line = %d;", mode
->c_line
);
1927 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1929 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1933 /* 'flush' is the deprecated equivalent of 'discard'. */
1934 if (STREQ (control_info
[i
].name
, "flush"))
1937 /* If swtch is the same as susp, don't print both. */
1939 if (STREQ (control_info
[i
].name
, "swtch"))
1942 /* If eof uses the same slot as min, only print whichever applies. */
1944 if ((mode
->c_lflag
& ICANON
) == 0
1945 && (STREQ (control_info
[i
].name
, "eof")
1946 || STREQ (control_info
[i
].name
, "eol")))
1951 wrapf ("%s = %s;", control_info
[i
].name
,
1952 visible (mode
->c_cc
[control_info
[i
].offset
]));
1954 if ((mode
->c_lflag
& ICANON
) == 0)
1956 wrapf ("min = %lu; time = %lu;\n",
1957 (unsigned long int) mode
->c_cc
[VMIN
],
1958 (unsigned long int) mode
->c_cc
[VTIME
]);
1960 else if (!empty_line
)
1965 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1967 if (mode_info
[i
].flags
& OMIT
)
1969 if (mode_info
[i
].type
!= prev_type
)
1977 prev_type
= mode_info
[i
].type
;
1980 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1981 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1983 /* bitsp would be NULL only for "combination" modes, yet those
1984 are filtered out above via the OMIT flag. Tell static analysis
1985 tools that it's ok to dereference bitsp here. */
1988 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1990 if (mode_info
[i
].flags
& SANE_UNSET
)
1992 wrapf ("%s", mode_info
[i
].name
);
1996 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1998 wrapf ("-%s", mode_info
[i
].name
);
2008 display_all (struct termios
*mode
, char const *device_name
)
2013 enum mode_type prev_type
= control
;
2015 display_speed (mode
, true);
2017 display_window_size (true, device_name
);
2020 wrapf ("line = %d;", mode
->c_line
);
2025 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
2028 /* 'flush' is the deprecated equivalent of 'discard'. */
2029 if (STREQ (control_info
[i
].name
, "flush"))
2032 /* If swtch is the same as susp, don't print both. */
2034 if (STREQ (control_info
[i
].name
, "swtch"))
2037 /* If eof uses the same slot as min, only print whichever applies. */
2039 if ((mode
->c_lflag
& ICANON
) == 0
2040 && (STREQ (control_info
[i
].name
, "eof")
2041 || STREQ (control_info
[i
].name
, "eol")))
2044 wrapf ("%s = %s;", control_info
[i
].name
,
2045 visible (mode
->c_cc
[control_info
[i
].offset
]));
2048 if ((mode
->c_lflag
& ICANON
) == 0)
2050 wrapf ("min = %lu; time = %lu;",
2051 (unsigned long int) mode
->c_cc
[VMIN
],
2052 (unsigned long int) mode
->c_cc
[VTIME
]);
2053 if (current_col
!= 0)
2057 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
2059 if (mode_info
[i
].flags
& OMIT
)
2061 if (mode_info
[i
].type
!= prev_type
)
2065 prev_type
= mode_info
[i
].type
;
2068 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2069 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
2070 assert (bitsp
); /* See the identical assertion and comment above. */
2071 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
2072 wrapf ("%s", mode_info
[i
].name
);
2073 else if (mode_info
[i
].flags
& REV
)
2074 wrapf ("-%s", mode_info
[i
].name
);
2080 /* Verify requested asymmetric speeds are supported.
2081 Note we don't flag the case where only ispeed or
2082 ospeed is set, when that would set both. */
2085 check_speed (struct termios
*mode
)
2087 if (last_ibaud
!= -1 && last_obaud
!= -1)
2089 if (cfgetispeed (mode
) != last_ibaud
2090 || cfgetospeed (mode
) != last_obaud
)
2091 die (EXIT_FAILURE
, 0,
2092 _("asymmetric input (%lu), output (%lu) speeds not supported"),
2093 baud_to_value (last_ibaud
), baud_to_value (last_obaud
));
2098 display_speed (struct termios
*mode
, bool fancy
)
2100 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
2101 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
2102 baud_to_value (cfgetospeed (mode
)));
2104 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
2105 baud_to_value (cfgetispeed (mode
)),
2106 baud_to_value (cfgetospeed (mode
)));
2112 display_recoverable (struct termios
*mode
)
2114 printf ("%lx:%lx:%lx:%lx",
2115 (unsigned long int) mode
->c_iflag
,
2116 (unsigned long int) mode
->c_oflag
,
2117 (unsigned long int) mode
->c_cflag
,
2118 (unsigned long int) mode
->c_lflag
);
2119 for (size_t i
= 0; i
< NCCS
; ++i
)
2120 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
2124 /* NOTE: identical to below, modulo use of tcflag_t */
2126 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
2131 ul
= strtoul (s
, p
, base
);
2132 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
2138 /* NOTE: identical to above, modulo use of cc_t */
2140 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
2144 ul
= strtoul (s
, p
, base
);
2145 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
2151 /* Parse the output of display_recoverable.
2152 Return false if any part of it is invalid. */
2154 recover_mode (char const *arg
, struct termios
*mode
)
2157 char const *s
= arg
;
2159 for (i
= 0; i
< 4; i
++)
2162 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
2166 mode
->c_iflag
= flag
[0];
2167 mode
->c_oflag
= flag
[1];
2168 mode
->c_cflag
= flag
[2];
2169 mode
->c_lflag
= flag
[3];
2171 for (i
= 0; i
< NCCS
; ++i
)
2174 char delim
= i
< NCCS
- 1 ? ':' : '\0';
2175 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
2185 char const *string
; /* ASCII representation. */
2186 speed_t speed
; /* Internal form. */
2187 unsigned long int value
; /* Numeric value. */
2190 static struct speed_map
const speeds
[] =
2197 {"134.5", B134
, 134},
2202 {"1200", B1200
, 1200},
2203 {"1800", B1800
, 1800},
2204 {"2400", B2400
, 2400},
2205 {"4800", B4800
, 4800},
2206 {"9600", B9600
, 9600},
2207 {"19200", B19200
, 19200},
2208 {"38400", B38400
, 38400},
2209 {"exta", B19200
, 19200},
2210 {"extb", B38400
, 38400},
2212 {"57600", B57600
, 57600},
2215 {"115200", B115200
, 115200},
2218 {"230400", B230400
, 230400},
2221 {"460800", B460800
, 460800},
2224 {"500000", B500000
, 500000},
2227 {"576000", B576000
, 576000},
2230 {"921600", B921600
, 921600},
2233 {"1000000", B1000000
, 1000000},
2236 {"1152000", B1152000
, 1152000},
2239 {"1500000", B1500000
, 1500000},
2242 {"2000000", B2000000
, 2000000},
2245 {"2500000", B2500000
, 2500000},
2248 {"3000000", B3000000
, 3000000},
2251 {"3500000", B3500000
, 3500000},
2254 {"4000000", B4000000
, 4000000},
2261 string_to_baud (char const *arg
)
2263 for (int i
= 0; speeds
[i
].string
!= NULL
; ++i
)
2264 if (STREQ (arg
, speeds
[i
].string
))
2265 return speeds
[i
].speed
;
2266 return (speed_t
) -1;
2270 static unsigned long int
2271 baud_to_value (speed_t speed
)
2273 for (int i
= 0; speeds
[i
].string
!= NULL
; ++i
)
2274 if (speed
== speeds
[i
].speed
)
2275 return speeds
[i
].value
;
2280 sane_mode (struct termios
*mode
)
2285 for (i
= 0; control_info
[i
].name
; ++i
)
2288 if (STREQ (control_info
[i
].name
, "min"))
2291 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
2294 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
2296 if (mode_info
[i
].flags
& NO_SETATTR
)
2299 if (mode_info
[i
].flags
& SANE_SET
)
2301 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2302 assert (bitsp
); /* combination modes will not have SANE_SET. */
2303 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
2305 else if (mode_info
[i
].flags
& SANE_UNSET
)
2307 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2308 assert (bitsp
); /* combination modes will not have SANE_UNSET. */
2309 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
2314 /* Return a string that is the printable representation of character CH. */
2315 /* Adapted from 'cat' by Torbjorn Granlund. */
2320 static char buf
[10];
2323 if (ch
== _POSIX_VDISABLE
)
2342 *bpout
++ = ch
- 128;
2352 *bpout
++ = ch
- 128 + 64;
2362 return (char const *) buf
;
2365 /* Parse string S as an integer, using decimal radix by default,
2366 but allowing octal and hex numbers as in C. Reject values
2367 larger than MAXVAL. */
2369 static unsigned long int
2370 integer_arg (char const *s
, unsigned long int maxval
)
2372 return xnumtoumax (s
, 0, 0, maxval
, "bB", _("invalid integer argument"), 0);