1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2024 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
58 #include "fd-reopen.h"
60 #include "xdectoint.h"
63 /* The official name of this program (e.g., no 'g' prefix). */
64 #define PROGRAM_NAME "stty"
66 #define AUTHORS proper_name ("David MacKenzie")
68 #ifndef _POSIX_VDISABLE
69 # define _POSIX_VDISABLE 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 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
105 character is initialized by CSWTCH, if present. */
106 #if defined VSWTC && !defined VSWTCH
107 # define VSWTCH VSWTC
109 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
110 #if defined VSUSP && !defined VSWTCH
111 # define VSWTCH VSUSP
112 # if defined CSUSP && !defined CSWTCH
113 # define CSWTCH CSUSP
116 #if defined VSWTCH && !defined CSWTCH
117 # define CSWTCH _POSIX_VDISABLE
120 /* SunOS >= 5.3 loses (^Z doesn't work) if 'swtch' is the same as 'susp'.
121 So the default is to disable 'swtch.' */
124 # define CSWTCH _POSIX_VDISABLE
127 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
128 # define VWERASE VWERSE
130 #if defined VDSUSP && !defined CDSUSP
131 # define CDSUSP Control ('y')
133 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
134 # define VREPRINT VRPRNT
136 #if defined VREPRINT && !defined CRPRNT
137 # define CRPRNT Control ('r')
139 #if defined CREPRINT && !defined CRPRNT
140 # define CRPRNT Control ('r')
142 #if defined VWERASE && !defined CWERASE
143 # define CWERASE Control ('w')
145 #if defined VLNEXT && !defined CLNEXT
146 # define CLNEXT Control ('v')
148 #if defined VDISCARD && !defined VFLUSHO
149 # define VFLUSHO VDISCARD
151 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
152 # define VFLUSHO VFLUSH
154 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
155 # define ECHOCTL CTLECH
157 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
158 # define ECHOCTL TCTLECH
160 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
161 # define ECHOKE CRTKIL
163 #if defined VFLUSHO && !defined CFLUSHO
164 # define CFLUSHO Control ('o')
166 #if defined VSTATUS && !defined CSTATUS
167 # define CSTATUS Control ('t')
170 /* Which speeds to set. */
173 input_speed
, output_speed
, both_speeds
176 /* What to output and how. */
179 changed
, all
, recoverable
/* Default, -a, -g. */
182 /* Which member(s) of 'struct termios' a mode uses. */
185 control
, input
, output
, local
, combination
188 /* Flags for 'struct mode_info'. */
189 #define SANE_SET 1 /* Set in 'sane' mode. */
190 #define SANE_UNSET 2 /* Unset in 'sane' mode. */
191 #define REV 4 /* Can be turned off by prepending '-'. */
192 #define OMIT 8 /* Don't display value. */
193 #define NO_SETATTR 16 /* tcsetattr not used to set mode bits. */
198 char const *name
; /* Name given on command line. */
199 enum mode_type type
; /* Which structure element to change. */
200 char flags
; /* Setting and display options. */
201 unsigned long bits
; /* Bits to set for this mode. */
202 unsigned long mask
; /* Other bits to turn off for this mode. */
205 static struct mode_info
const mode_info
[] =
207 {"parenb", control
, REV
, PARENB
, 0},
208 {"parodd", control
, REV
, PARODD
, 0},
210 {"cmspar", control
, REV
, CMSPAR
, 0},
212 {"cs5", control
, 0, CS5
, CSIZE
},
213 {"cs6", control
, 0, CS6
, CSIZE
},
214 {"cs7", control
, 0, CS7
, CSIZE
},
215 {"cs8", control
, 0, CS8
, CSIZE
},
216 {"hupcl", control
, REV
, HUPCL
, 0},
217 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
218 {"cstopb", control
, REV
, CSTOPB
, 0},
219 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
220 {"clocal", control
, REV
, CLOCAL
, 0},
222 {"crtscts", control
, REV
, CRTSCTS
, 0},
225 {"cdtrdsr", control
, REV
, CDTRDSR
, 0},
228 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
229 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
230 {"ignpar", input
, REV
, IGNPAR
, 0},
231 {"parmrk", input
, REV
, PARMRK
, 0},
232 {"inpck", input
, REV
, INPCK
, 0},
233 {"istrip", input
, REV
, ISTRIP
, 0},
234 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
235 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
236 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
237 {"ixon", input
, REV
, IXON
, 0},
238 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
239 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
241 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
244 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
247 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
250 {"iutf8", input
, SANE_UNSET
| REV
, IUTF8
, 0},
253 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
255 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
258 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
261 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
264 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
267 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
270 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
273 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
276 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
277 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
280 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
281 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
282 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
283 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
287 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
290 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
293 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
296 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
300 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
304 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
305 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
308 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
309 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
312 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
313 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
316 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
317 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
319 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
321 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
322 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
323 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
324 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
325 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
326 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
328 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
331 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
334 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
335 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
338 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
339 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
342 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
343 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
346 {"flusho", local
, SANE_UNSET
| REV
, FLUSHO
, 0},
349 {"extproc", local
, SANE_UNSET
| REV
| NO_SETATTR
, EXTPROC
, 0},
350 #elif defined EXTPROC
351 {"extproc", local
, SANE_UNSET
| REV
, EXTPROC
, 0},
354 {"evenp", combination
, REV
| OMIT
, 0, 0},
355 {"parity", combination
, REV
| OMIT
, 0, 0},
356 {"oddp", combination
, REV
| OMIT
, 0, 0},
357 {"nl", combination
, REV
| OMIT
, 0, 0},
358 {"ek", combination
, OMIT
, 0, 0},
359 {"sane", combination
, OMIT
, 0, 0},
360 {"cooked", combination
, REV
| OMIT
, 0, 0},
361 {"raw", combination
, REV
| OMIT
, 0, 0},
362 {"pass8", combination
, REV
| OMIT
, 0, 0},
363 {"litout", combination
, REV
| OMIT
, 0, 0},
364 {"cbreak", combination
, REV
| OMIT
, 0, 0},
366 {"decctlq", combination
, REV
| OMIT
, 0, 0},
368 #if defined TABDLY || defined OXTABS
369 {"tabs", combination
, REV
| OMIT
, 0, 0},
371 #if defined XCASE && defined IUCLC && defined OLCUC
372 {"lcase", combination
, REV
| OMIT
, 0, 0},
373 {"LCASE", combination
, REV
| OMIT
, 0, 0},
375 {"crt", combination
, OMIT
, 0, 0},
376 {"dec", combination
, OMIT
, 0, 0},
378 {nullptr, control
, 0, 0, 0}
381 /* Control character settings. */
384 char const *name
; /* Name given on command line. */
385 cc_t saneval
; /* Value to set for 'stty sane'. */
386 size_t offset
; /* Offset in c_cc. */
389 /* Control characters. */
391 static struct control_info
const control_info
[] =
393 {"intr", CINTR
, VINTR
},
394 {"quit", CQUIT
, VQUIT
},
395 {"erase", CERASE
, VERASE
},
396 {"kill", CKILL
, VKILL
},
400 {"eol2", CEOL2
, VEOL2
},
403 {"swtch", CSWTCH
, VSWTCH
},
405 {"start", CSTART
, VSTART
},
406 {"stop", CSTOP
, VSTOP
},
407 {"susp", CSUSP
, VSUSP
},
409 {"dsusp", CDSUSP
, VDSUSP
},
412 {"rprnt", CRPRNT
, VREPRINT
},
414 # ifdef CREPRINT /* HPUX 10.20 needs this */
415 {"rprnt", CRPRNT
, CREPRINT
},
419 {"werase", CWERASE
, VWERASE
},
422 {"lnext", CLNEXT
, VLNEXT
},
425 {"flush", CFLUSHO
, VFLUSHO
}, /* deprecated compat option. */
426 {"discard", CFLUSHO
, VFLUSHO
},
429 {"status", CSTATUS
, VSTATUS
},
432 /* These must be last because of the display routines. */
438 static char const *visible (cc_t ch
);
439 static unsigned long int baud_to_value (speed_t speed
);
440 static bool recover_mode (char const *arg
, struct termios
*mode
);
441 static int screen_columns (void);
442 static bool set_mode (struct mode_info
const *info
, bool reversed
,
443 struct termios
*mode
);
444 static bool eq_mode (struct termios
*mode1
, struct termios
*mode2
);
445 static uintmax_t integer_arg (char const *s
, uintmax_t max
);
446 static speed_t
string_to_baud (char const *arg
);
447 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
448 static void display_all (struct termios
*mode
, char const *device_name
);
449 static void display_changed (struct termios
*mode
);
450 static void display_recoverable (struct termios
*mode
);
451 static void display_settings (enum output_type output_type
,
452 struct termios
*mode
,
453 char const *device_name
);
454 static void check_speed (struct termios
*mode
);
455 static void display_speed (struct termios
*mode
, bool fancy
);
456 static void display_window_size (bool fancy
, char const *device_name
);
457 static void sane_mode (struct termios
*mode
);
458 static void set_control_char (struct control_info
const *info
,
460 struct termios
*mode
);
461 static void set_speed (enum speed_setting type
, char const *arg
,
462 struct termios
*mode
);
463 static void set_window_size (int rows
, int cols
, char const *device_name
);
465 /* The width of the screen, for output wrapping. */
468 /* Current position, to know when to wrap. */
469 static int current_col
;
471 /* Default "drain" mode for tcsetattr. */
472 static int tcsetattr_options
= TCSADRAIN
;
474 /* Extra info to aid stty development. */
475 static bool dev_debug
;
477 /* Record last speed set for correlation. */
478 static speed_t last_ibaud
= (speed_t
) -1;
479 static speed_t last_obaud
= (speed_t
) -1;
481 /* For long options that have no equivalent short option, use a
482 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
485 DEV_DEBUG_OPTION
= CHAR_MAX
+ 1,
488 static struct option
const longopts
[] =
490 {"all", no_argument
, nullptr, 'a'},
491 {"save", no_argument
, nullptr, 'g'},
492 {"file", required_argument
, nullptr, 'F'},
493 {"-debug", no_argument
, nullptr, DEV_DEBUG_OPTION
},
494 {GETOPT_HELP_OPTION_DECL
},
495 {GETOPT_VERSION_OPTION_DECL
},
496 {nullptr, 0, nullptr, 0}
499 /* Print format string MESSAGE and optional args.
500 Wrap to next line first if it won't fit.
501 Print a space first unless MESSAGE will start a new line. */
503 ATTRIBUTE_FORMAT ((printf
, 1, 2))
505 wrapf (char const *message
,...)
511 va_start (args
, message
);
512 buflen
= vasprintf (&buf
, message
, args
);
520 if (max_col
- current_col
<= buflen
)
534 current_col
+= buflen
;
540 if (status
!= EXIT_SUCCESS
)
545 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
546 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
547 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
549 program_name
, program_name
, program_name
);
551 Print or change terminal characteristics.\n\
554 emit_mandatory_arg_note ();
557 -a, --all print all current settings in human-readable form\n\
558 -g, --save print all current settings in a stty-readable form\n\
559 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
561 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
562 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
565 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
566 settings. The underlying system defines which settings are available.\n\
570 Special characters:\n"), stdout
);
573 * discard CHAR CHAR will toggle discarding of output\n\
578 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
582 eof CHAR CHAR will send an end of file (terminate the input)\n\
583 eol CHAR CHAR will end the line\n\
587 * eol2 CHAR alternate CHAR for ending the line\n\
591 erase CHAR CHAR will erase the last character typed\n\
592 intr CHAR CHAR will send an interrupt signal\n\
593 kill CHAR CHAR will erase the current line\n\
597 * lnext CHAR CHAR will enter the next character quoted\n\
602 * status CHAR CHAR will send an info signal\n\
606 quit CHAR CHAR will send a quit signal\n\
608 #if defined CREPRINT || defined VREPRINT
610 * rprnt CHAR CHAR will redraw the current line\n\
614 start CHAR CHAR will restart the output after stopping it\n\
615 stop CHAR CHAR will stop the output\n\
616 susp CHAR CHAR will send a terminal stop signal\n\
620 * swtch CHAR CHAR will switch to a different shell layer\n\
625 * werase CHAR CHAR will erase the last word typed\n\
631 N set the input and output speeds to N bauds\n\
635 * cols N tell the kernel that the terminal has N columns\n\
636 * columns N same as cols N\n\
640 * [-]drain wait for transmission before applying settings (%s by default)\
641 \n"), tcsetattr_options
== TCSADRAIN
? _("on") : _("off"));
643 ispeed N set the input speed to N\n\
647 * line N use line discipline N\n\
651 min N with -icanon, set N characters minimum for a completed read\n\
652 ospeed N set the output speed to N\n\
656 * rows N tell the kernel that the terminal has N rows\n\
657 * size print the number of rows and columns according to the kernel\n\
661 speed print the terminal speed\n\
662 time N with -icanon, set read timeout of N tenths of a second\n\
667 [-]clocal disable modem control signals\n\
668 [-]cread allow input to be received\n\
672 * [-]crtscts enable RTS/CTS handshaking\n\
677 * [-]cdtrdsr enable DTR/DSR handshaking\n\
681 csN set character size to N bits, N in [5..8]\n\
684 [-]cstopb use two stop bits per character (one with '-')\n\
685 [-]hup send a hangup signal when the last process closes the tty\n\
686 [-]hupcl same as [-]hup\n\
687 [-]parenb generate parity bit in output and expect parity bit in input\n\
688 [-]parodd set odd parity (or even parity with '-')\n\
692 * [-]cmspar use \"stick\" (mark/space) parity\n\
698 [-]brkint breaks cause an interrupt signal\n\
699 [-]icrnl translate carriage return to newline\n\
700 [-]ignbrk ignore break characters\n\
701 [-]igncr ignore carriage return\n\
702 [-]ignpar ignore characters with parity errors\n\
706 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
710 [-]inlcr translate newline to carriage return\n\
711 [-]inpck enable input parity checking\n\
712 [-]istrip clear high (8th) bit of input characters\n\
716 * [-]iutf8 assume input characters are UTF-8 encoded\n\
721 * [-]iuclc translate uppercase characters to lowercase\n\
726 * [-]ixany let any character restart output, not only start character\n\
730 [-]ixoff enable sending of start/stop characters\n\
731 [-]ixon enable XON/XOFF flow control\n\
732 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
733 [-]tandem same as [-]ixoff\n\
741 * bsN backspace delay style, N in [0..1]\n\
746 * crN carriage return delay style, N in [0..3]\n\
751 * ffN form feed delay style, N in [0..1]\n\
756 * nlN newline delay style, N in [0..1]\n\
761 * [-]ocrnl translate carriage return to newline\n\
766 * [-]ofdel use delete characters for fill instead of NUL characters\n\
771 * [-]ofill use fill (padding) characters instead of timing for delays\n\
776 * [-]olcuc translate lowercase characters to uppercase\n\
781 * [-]onlcr translate newline to carriage return-newline\n\
786 * [-]onlret newline performs a carriage return\n\
791 * [-]onocr do not print carriage returns in the first column\n\
795 [-]opost postprocess output\n\
797 #if defined TABDLY || defined OXTABS
799 * tabN horizontal tab delay style, N in [0..3]\n\
800 * tabs same as tab0\n\
801 * -tabs same as tab3\n\
806 * vtN vertical tab delay style, N in [0..1]\n\
812 [-]crterase echo erase characters as backspace-space-backspace\n\
816 * crtkill kill all line by obeying the echoprt and echoe settings\n\
817 * -crtkill kill all line by obeying the echoctl and echok settings\n\
822 * [-]ctlecho echo control characters in hat notation ('^c')\n\
826 [-]echo echo input characters\n\
830 * [-]echoctl same as [-]ctlecho\n\
834 [-]echoe same as [-]crterase\n\
835 [-]echok echo a newline after a kill character\n\
839 * [-]echoke same as [-]crtkill\n\
843 [-]echonl echo newline even if not echoing other characters\n\
847 * [-]echoprt echo erased characters backward, between '\\' and '/'\n\
850 #if defined EXTPROC || defined TIOCEXT
852 * [-]extproc enable \"LINEMODE\"; useful with high latency links\n\
857 * [-]flusho discard output\n\
861 [-]icanon enable special characters: %s\n\
862 [-]iexten enable non-POSIX special characters\n\
867 #if defined CREPRINT || defined VREPRINT
872 [-]isig enable interrupt, quit, and suspend special characters\n\
873 [-]noflsh disable flushing after interrupt and quit special characters\n\
877 * [-]prterase same as [-]echoprt\n\
882 * [-]tostop stop background jobs that try to write to the terminal\n\
887 * [-]xcase with icanon, escape with '\\' for uppercase characters\n\
892 Combination settings:\n\
894 #if defined XCASE && defined IUCLC && defined OLCUC
896 * [-]LCASE same as [-]lcase\n\
900 cbreak same as -icanon\n\
901 -cbreak same as icanon\n\
904 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
905 icanon, eof and eol characters to their default values\n\
906 -cooked same as raw\n\
919 dec same as %s intr ^c erase 0177\n\
934 * [-]decctlq same as [-]ixany\n\
938 ek erase and kill characters to their default values\n\
939 evenp same as parenb -parodd cs7\n\
940 -evenp same as -parenb cs8\n\
942 #if defined XCASE && defined IUCLC && defined OLCUC
944 * [-]lcase same as xcase iuclc olcuc\n\
948 litout same as -parenb -istrip -opost cs8\n\
949 -litout same as parenb istrip opost cs7\n\
958 , "icrnl -inlcr -igncr"
970 oddp same as parenb parodd cs7\n\
971 -oddp same as -parenb cs8\n\
972 [-]parity same as [-]evenp\n\
973 pass8 same as -parenb -istrip cs8\n\
974 -pass8 same as parenb istrip cs7\n\
977 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
978 -inlcr -igncr -icrnl -ixon -ixoff -icanon -opost\n\
979 -isig%s min 1 time 0\n\
980 -raw same as cooked\n\
996 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
997 icanon iexten echo echoe echok -echonl -noflsh\n\
1001 all special characters to their default values\n\
1083 Handle the tty line connected to standard input. Without arguments,\n\
1084 prints baud rate, line discipline, and deviations from stty sane. In\n\
1085 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
1086 127; special values ^- or undef used to disable special characters.\n\
1088 emit_ancillary_info (PROGRAM_NAME
);
1094 /* Apply specified settings to MODE and REQUIRE_SET_ATTR as required.
1095 If CHECKING is true, this function doesn't interact
1096 with a device, and only validates specified settings. */
1099 apply_settings (bool checking
, char const *device_name
,
1100 char * const *settings
, int n_settings
,
1101 struct termios
*mode
, bool *require_set_attr
)
1103 #define check_argument(arg) \
1106 if (k == n_settings - 1 || ! settings[k + 1]) \
1108 error (0, 0, _("missing argument to %s"), quote (arg)); \
1109 usage (EXIT_FAILURE); \
1114 for (int k
= 1; k
< n_settings
; k
++)
1116 char const *arg
= settings
[k
];
1117 bool match_found
= false;
1118 bool not_set_attr
= false;
1119 bool reversed
= false;
1130 if (STREQ (arg
, "drain"))
1132 tcsetattr_options
= reversed
? TCSANOW
: TCSADRAIN
;
1135 for (i
= 0; mode_info
[i
].name
!= nullptr; ++i
)
1137 if (STREQ (arg
, mode_info
[i
].name
))
1139 if ((mode_info
[i
].flags
& NO_SETATTR
) == 0)
1141 match_found
= set_mode (&mode_info
[i
], reversed
, mode
);
1142 *require_set_attr
= true;
1145 match_found
= not_set_attr
= true;
1149 if (!match_found
&& reversed
)
1151 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
1152 usage (EXIT_FAILURE
);
1156 for (i
= 0; control_info
[i
].name
!= nullptr; ++i
)
1158 if (STREQ (arg
, control_info
[i
].name
))
1160 check_argument (arg
);
1163 set_control_char (&control_info
[i
], settings
[k
], mode
);
1164 *require_set_attr
= true;
1169 if (!match_found
|| not_set_attr
)
1171 if (STREQ (arg
, "ispeed"))
1173 check_argument (arg
);
1175 if (string_to_baud (settings
[k
]) == (speed_t
) -1)
1177 error (0, 0, _("invalid ispeed %s"), quote (settings
[k
]));
1178 usage (EXIT_FAILURE
);
1180 set_speed (input_speed
, settings
[k
], mode
);
1183 *require_set_attr
= true;
1185 else if (STREQ (arg
, "ospeed"))
1187 check_argument (arg
);
1189 if (string_to_baud (settings
[k
]) == (speed_t
) -1)
1191 error (0, 0, _("invalid ospeed %s"), quote (settings
[k
]));
1192 usage (EXIT_FAILURE
);
1194 set_speed (output_speed
, settings
[k
], mode
);
1197 *require_set_attr
= true;
1200 /* This is the BSD interface to "extproc".
1201 Even though it's an lflag, an ioctl is used to set it. */
1202 else if (STREQ (arg
, "extproc"))
1204 int val
= ! reversed
;
1209 if (ioctl (STDIN_FILENO
, TIOCEXT
, &val
) != 0)
1210 error (EXIT_FAILURE
, errno
, _("%s: error setting %s"),
1211 quotef_n (0, device_name
), quote_n (1, arg
));
1215 else if (STREQ (arg
, "rows"))
1217 check_argument (arg
);
1221 set_window_size (integer_arg (settings
[k
], INT_MAX
), -1,
1224 else if (STREQ (arg
, "cols")
1225 || STREQ (arg
, "columns"))
1227 check_argument (arg
);
1231 set_window_size (-1, integer_arg (settings
[k
], INT_MAX
),
1234 else if (STREQ (arg
, "size"))
1238 max_col
= screen_columns ();
1240 display_window_size (false, device_name
);
1244 else if (STREQ (arg
, "line"))
1246 check_argument (arg
);
1248 uintmax_t value
= integer_arg (settings
[k
], UINTMAX_MAX
);
1249 if (ckd_add (&mode
->c_line
, value
, 0))
1250 error (0, EOVERFLOW
, _("invalid line discipline %s"),
1251 quote (settings
[k
]));
1252 *require_set_attr
= true;
1255 else if (STREQ (arg
, "speed"))
1259 max_col
= screen_columns ();
1260 display_speed (mode
, false);
1262 else if (string_to_baud (arg
) != (speed_t
) -1)
1264 set_speed (both_speeds
, arg
, mode
);
1267 *require_set_attr
= true;
1271 if (! recover_mode (arg
, mode
))
1273 error (0, 0, _("invalid argument %s"), quote (arg
));
1274 usage (EXIT_FAILURE
);
1276 *require_set_attr
= true;
1286 main (int argc
, char **argv
)
1288 /* Initialize to all zeroes so there is no risk memcmp will report a
1289 spurious difference in an uninitialized portion of the structure. */
1290 static struct termios mode
;
1292 enum output_type output_type
;
1296 bool require_set_attr
;
1297 bool verbose_output
;
1298 bool recoverable_output
;
1300 char *file_name
= nullptr;
1301 char const *device_name
;
1303 initialize_main (&argc
, &argv
);
1304 set_program_name (argv
[0]);
1305 setlocale (LC_ALL
, "");
1306 bindtextdomain (PACKAGE
, LOCALEDIR
);
1307 textdomain (PACKAGE
);
1309 atexit (close_stdout
);
1311 output_type
= changed
;
1312 verbose_output
= false;
1313 recoverable_output
= false;
1315 /* Don't print error messages for unrecognized options. */
1318 /* If any new options are ever added to stty, the short options MUST
1319 NOT allow any ambiguity with the stty settings. For example, the
1320 stty setting "-gagFork" would not be feasible, since it will be
1321 parsed as "-g -a -g -F ork". If you change anything about how
1322 stty parses options, be sure it still works with combinations of
1323 short and long options, --, POSIXLY_CORRECT, etc. */
1325 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
1332 verbose_output
= true;
1337 recoverable_output
= true;
1338 output_type
= recoverable
;
1343 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
1347 case DEV_DEBUG_OPTION
:
1351 case_GETOPT_HELP_CHAR
;
1353 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1356 /* Consider "drain" as an option rather than a setting,
1357 to support: alias stty='stty -drain' etc. */
1358 if (! STREQ (argv
[argi
+ opti
], "-drain")
1359 && ! STREQ (argv
[argi
+ opti
], "drain"))
1362 /* Skip the argument containing this unrecognized option;
1363 the 2nd pass will analyze it. */
1366 /* Restart getopt_long from the first unskipped argument. */
1373 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
1374 while (opti
< optind
)
1375 argv
[argi
+ opti
++] = nullptr;
1378 /* Specifying both -a and -g gets an error. */
1379 if (verbose_output
&& recoverable_output
)
1380 error (EXIT_FAILURE
, 0,
1381 _("the options for verbose and stty-readable output styles are\n"
1382 "mutually exclusive"));
1384 /* Specifying any other arguments with -a or -g gets an error. */
1385 if (!noargs
&& (verbose_output
|| recoverable_output
))
1386 error (EXIT_FAILURE
, 0,
1387 _("when specifying an output style, modes may not be set"));
1389 device_name
= file_name
? file_name
: _("standard input");
1391 if (!noargs
&& !verbose_output
&& !recoverable_output
)
1393 static struct termios check_mode
;
1394 apply_settings (/* checking= */ true, device_name
, argv
, argc
,
1395 &check_mode
, &require_set_attr
);
1401 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
1402 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1403 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
1404 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
1405 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
1406 quotef (device_name
));
1409 if (tcgetattr (STDIN_FILENO
, &mode
))
1410 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1412 if (verbose_output
|| recoverable_output
|| noargs
)
1414 max_col
= screen_columns ();
1416 display_settings (output_type
, &mode
, device_name
);
1417 return EXIT_SUCCESS
;
1420 require_set_attr
= false;
1421 apply_settings (/* checking= */ false, device_name
, argv
, argc
,
1422 &mode
, &require_set_attr
);
1424 if (require_set_attr
)
1426 /* Initialize to all zeroes so there is no risk memcmp will report a
1427 spurious difference in an uninitialized portion of the structure. */
1428 static struct termios new_mode
;
1430 if (tcsetattr (STDIN_FILENO
, tcsetattr_options
, &mode
))
1431 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1433 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1434 it performs *any* of the requested operations. This means it
1435 can report 'success' when it has actually failed to perform
1436 some proper subset of the requested operations. To detect
1437 this partial failure, get the current terminal attributes and
1438 compare them to the requested ones. */
1440 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1441 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1443 if (! eq_mode (&mode
, &new_mode
))
1447 error (0, 0, _("indx: mode: actual mode"));
1448 for (unsigned int i
= 0; i
< sizeof (new_mode
); i
++)
1450 unsigned int newc
= *(((unsigned char *) &new_mode
) + i
);
1451 unsigned int oldc
= *(((unsigned char *) &mode
) + i
);
1452 error (0, 0, "0x%02x, 0x%02x: 0x%02x%s", i
, oldc
, newc
,
1453 newc
== oldc
? "" : " *");
1457 error (EXIT_FAILURE
, 0,
1458 _("%s: unable to perform all requested operations"),
1459 quotef (device_name
));
1463 return EXIT_SUCCESS
;
1466 /* Return true if modes are equivalent. */
1469 eq_mode (struct termios
*mode1
, struct termios
*mode2
)
1471 return mode1
->c_iflag
== mode2
->c_iflag
1472 && mode1
->c_oflag
== mode2
->c_oflag
1473 && mode1
->c_cflag
== mode2
->c_cflag
1474 && mode1
->c_lflag
== mode2
->c_lflag
1476 && mode1
->c_line
== mode2
->c_line
1478 && memcmp (mode1
->c_cc
, mode2
->c_cc
, sizeof (mode1
->c_cc
)) == 0
1479 && cfgetispeed (mode1
) == cfgetispeed (mode2
)
1480 && cfgetospeed (mode1
) == cfgetospeed (mode2
);
1483 /* Return false if not applied because not reversible; otherwise
1487 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1491 if (reversed
&& (info
->flags
& REV
) == 0)
1494 bitsp
= mode_type_flag (info
->type
, mode
);
1496 if (bitsp
== nullptr)
1498 /* Combination mode. */
1499 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1502 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1504 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1506 else if (STREQ (info
->name
, "oddp"))
1509 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1511 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1513 else if (STREQ (info
->name
, "nl"))
1517 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1518 mode
->c_oflag
= (mode
->c_oflag
1533 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1535 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1539 else if (STREQ (info
->name
, "ek"))
1541 mode
->c_cc
[VERASE
] = CERASE
;
1542 mode
->c_cc
[VKILL
] = CKILL
;
1544 else if (STREQ (info
->name
, "sane"))
1546 else if (STREQ (info
->name
, "cbreak"))
1549 mode
->c_lflag
|= ICANON
;
1551 mode
->c_lflag
&= ~ICANON
;
1553 else if (STREQ (info
->name
, "pass8"))
1557 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1558 mode
->c_iflag
|= ISTRIP
;
1562 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1563 mode
->c_iflag
&= ~ISTRIP
;
1566 else if (STREQ (info
->name
, "litout"))
1570 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1571 mode
->c_iflag
|= ISTRIP
;
1572 mode
->c_oflag
|= OPOST
;
1576 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1577 mode
->c_iflag
&= ~ISTRIP
;
1578 mode
->c_oflag
&= ~OPOST
;
1581 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1583 if ((info
->name
[0] == 'r' && reversed
)
1584 || (info
->name
[0] == 'c' && !reversed
))
1587 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1588 mode
->c_oflag
|= OPOST
;
1589 mode
->c_lflag
|= ISIG
| ICANON
;
1591 mode
->c_cc
[VEOF
] = CEOF
;
1594 mode
->c_cc
[VEOL
] = CEOL
;
1601 mode
->c_oflag
&= ~OPOST
;
1602 mode
->c_lflag
&= ~(ISIG
| ICANON
1607 mode
->c_cc
[VMIN
] = 1;
1608 mode
->c_cc
[VTIME
] = 0;
1612 else if (STREQ (info
->name
, "decctlq"))
1615 mode
->c_iflag
|= IXANY
;
1617 mode
->c_iflag
&= ~IXANY
;
1621 else if (STREQ (info
->name
, "tabs"))
1624 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1626 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1630 else if (STREQ (info
->name
, "tabs"))
1633 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1635 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1639 #if defined XCASE && defined IUCLC && defined OLCUC
1640 else if (STREQ (info
->name
, "lcase")
1641 || STREQ (info
->name
, "LCASE"))
1645 mode
->c_lflag
&= ~XCASE
;
1646 mode
->c_iflag
&= ~IUCLC
;
1647 mode
->c_oflag
&= ~OLCUC
;
1651 mode
->c_lflag
|= XCASE
;
1652 mode
->c_iflag
|= IUCLC
;
1653 mode
->c_oflag
|= OLCUC
;
1657 else if (STREQ (info
->name
, "crt"))
1658 mode
->c_lflag
|= ECHOE
1666 else if (STREQ (info
->name
, "dec"))
1668 mode
->c_cc
[VINTR
] = 3; /* ^C */
1669 mode
->c_cc
[VERASE
] = 127; /* DEL */
1670 mode
->c_cc
[VKILL
] = 21; /* ^U */
1671 mode
->c_lflag
|= ECHOE
1680 mode
->c_iflag
&= ~IXANY
;
1685 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1687 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1693 set_control_char (struct control_info
const *info
, char const *arg
,
1694 struct termios
*mode
)
1696 unsigned long int value
;
1698 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1699 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1700 else if (arg
[0] == '\0' || arg
[1] == '\0')
1701 value
= to_uchar (arg
[0]);
1702 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1703 value
= _POSIX_VDISABLE
;
1704 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1709 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1712 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1713 mode
->c_cc
[info
->offset
] = value
;
1717 set_speed (enum speed_setting type
, char const *arg
, struct termios
*mode
)
1719 /* Note cfset[io]speed(), do not check with the device,
1720 and only check whether the system logic supports the specified speed.
1721 Therefore we don't report the device name in any errors. */
1723 speed_t baud
= string_to_baud (arg
);
1724 affirm (baud
!= (speed_t
) -1);
1726 if (type
== input_speed
|| type
== both_speeds
)
1729 if (cfsetispeed (mode
, baud
))
1730 error (EXIT_FAILURE
, 0, _("unsupported ispeed %s"), quoteaf (arg
));
1732 if (type
== output_speed
|| type
== both_speeds
)
1735 if (cfsetospeed (mode
, baud
))
1736 error (EXIT_FAILURE
, 0, _("unsupported ospeed %s"), quoteaf (arg
));
1743 get_win_size (int fd
, struct winsize
*win
)
1745 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1750 set_window_size (int rows
, int cols
, char const *device_name
)
1754 if (get_win_size (STDIN_FILENO
, &win
))
1756 if (errno
!= EINVAL
)
1757 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1758 memset (&win
, 0, sizeof (win
));
1767 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1768 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1769 This comment from sys/ttold.h describes Sun's twisted logic - a better
1770 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1771 At any rate, the problem is gone in Solaris 2.x.
1773 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1774 but they can be disambiguated by checking whether a "struct ttysize"
1775 structure's "ts_lines" field is greater than 64K or not. If so,
1776 it's almost certainly a "struct winsize" instead.
1778 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1779 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16)
1780 + ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1781 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1782 "stty cols 0 rows 0" would do the right thing. On a little-endian
1783 machine like the sun386i, the problem is the same, but for ws_col == 0.
1785 The workaround is to do the ioctl once with row and col = 1 to set the
1786 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1788 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1790 struct ttysize ttysz
;
1792 ttysz
.ts_lines
= win
.ws_row
;
1793 ttysz
.ts_cols
= win
.ws_col
;
1798 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1799 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1801 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1802 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1807 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1808 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1812 display_window_size (bool fancy
, char const *device_name
)
1816 if (get_win_size (STDIN_FILENO
, &win
))
1818 if (errno
!= EINVAL
)
1819 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1821 error (EXIT_FAILURE
, 0,
1822 _("%s: no size information for this device"),
1823 quotef (device_name
));
1827 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1828 win
.ws_row
, win
.ws_col
);
1836 screen_columns (void)
1841 /* With Solaris 2.[123], this ioctl fails and errno is set to
1842 EINVAL for telnet (but not rlogin) sessions.
1843 On ISC 3.0, it fails for the console and the serial port
1844 (but it works for ptys).
1845 It can also fail on any system when stdout isn't a tty.
1846 In case of any failure, just use the default. */
1847 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1851 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1852 char *col_string
= getenv ("COLUMNS");
1854 if (!(col_string
!= nullptr
1855 && xstrtol (col_string
, nullptr, 0, &n_columns
, "") == LONGINT_OK
1857 && n_columns
<= INT_MAX
))
1865 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1870 return &mode
->c_cflag
;
1873 return &mode
->c_iflag
;
1876 return &mode
->c_oflag
;
1879 return &mode
->c_lflag
;
1890 display_settings (enum output_type output_type
, struct termios
*mode
,
1891 char const *device_name
)
1893 switch (output_type
)
1896 display_changed (mode
);
1900 display_all (mode
, device_name
);
1904 display_recoverable (mode
);
1910 display_changed (struct termios
*mode
)
1916 enum mode_type prev_type
= control
;
1918 display_speed (mode
, true);
1920 wrapf ("line = %d;", mode
->c_line
);
1926 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1928 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1932 /* 'flush' is the deprecated equivalent of 'discard'. */
1933 if (STREQ (control_info
[i
].name
, "flush"))
1936 /* If swtch is the same as susp, don't print both. */
1938 if (STREQ (control_info
[i
].name
, "swtch"))
1941 /* If eof uses the same slot as min, only print whichever applies. */
1943 if ((mode
->c_lflag
& ICANON
) == 0
1944 && (STREQ (control_info
[i
].name
, "eof")
1945 || STREQ (control_info
[i
].name
, "eol")))
1950 wrapf ("%s = %s;", control_info
[i
].name
,
1951 visible (mode
->c_cc
[control_info
[i
].offset
]));
1953 if ((mode
->c_lflag
& ICANON
) == 0)
1955 wrapf ("min = %lu; time = %lu;\n",
1956 (unsigned long int) mode
->c_cc
[VMIN
],
1957 (unsigned long int) mode
->c_cc
[VTIME
]);
1959 else if (!empty_line
)
1964 for (i
= 0; mode_info
[i
].name
!= nullptr; ++i
)
1966 if (mode_info
[i
].flags
& OMIT
)
1968 if (mode_info
[i
].type
!= prev_type
)
1976 prev_type
= mode_info
[i
].type
;
1979 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1980 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1981 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1983 if (mode_info
[i
].flags
& SANE_UNSET
)
1985 wrapf ("%s", mode_info
[i
].name
);
1989 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1991 wrapf ("-%s", mode_info
[i
].name
);
2001 display_all (struct termios
*mode
, char const *device_name
)
2006 enum mode_type prev_type
= control
;
2008 display_speed (mode
, true);
2010 display_window_size (true, device_name
);
2013 wrapf ("line = %d;", mode
->c_line
);
2018 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
2021 /* 'flush' is the deprecated equivalent of 'discard'. */
2022 if (STREQ (control_info
[i
].name
, "flush"))
2025 /* If swtch is the same as susp, don't print both. */
2027 if (STREQ (control_info
[i
].name
, "swtch"))
2030 /* If eof uses the same slot as min, only print whichever applies. */
2032 if ((mode
->c_lflag
& ICANON
) == 0
2033 && (STREQ (control_info
[i
].name
, "eof")
2034 || STREQ (control_info
[i
].name
, "eol")))
2037 wrapf ("%s = %s;", control_info
[i
].name
,
2038 visible (mode
->c_cc
[control_info
[i
].offset
]));
2041 if ((mode
->c_lflag
& ICANON
) == 0)
2043 wrapf ("min = %lu; time = %lu;",
2044 (unsigned long int) mode
->c_cc
[VMIN
],
2045 (unsigned long int) mode
->c_cc
[VTIME
]);
2046 if (current_col
!= 0)
2050 for (i
= 0; mode_info
[i
].name
!= nullptr; ++i
)
2052 if (mode_info
[i
].flags
& OMIT
)
2054 if (mode_info
[i
].type
!= prev_type
)
2058 prev_type
= mode_info
[i
].type
;
2061 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2062 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
2063 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
2064 wrapf ("%s", mode_info
[i
].name
);
2065 else if (mode_info
[i
].flags
& REV
)
2066 wrapf ("-%s", mode_info
[i
].name
);
2072 /* Verify requested asymmetric speeds are supported.
2073 Note we don't flag the case where only ispeed or
2074 ospeed is set, when that would set both. */
2077 check_speed (struct termios
*mode
)
2079 if (last_ibaud
!= -1 && last_obaud
!= -1)
2081 if (cfgetispeed (mode
) != last_ibaud
2082 || cfgetospeed (mode
) != last_obaud
)
2083 error (EXIT_FAILURE
, 0,
2084 _("asymmetric input (%lu), output (%lu) speeds not supported"),
2085 baud_to_value (last_ibaud
), baud_to_value (last_obaud
));
2090 display_speed (struct termios
*mode
, bool fancy
)
2092 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
2093 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
2094 baud_to_value (cfgetospeed (mode
)));
2096 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
2097 baud_to_value (cfgetispeed (mode
)),
2098 baud_to_value (cfgetospeed (mode
)));
2104 display_recoverable (struct termios
*mode
)
2106 printf ("%lx:%lx:%lx:%lx",
2107 (unsigned long int) mode
->c_iflag
,
2108 (unsigned long int) mode
->c_oflag
,
2109 (unsigned long int) mode
->c_cflag
,
2110 (unsigned long int) mode
->c_lflag
);
2111 for (size_t i
= 0; i
< NCCS
; ++i
)
2112 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
2116 /* NOTE: identical to below, modulo use of tcflag_t */
2118 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
2123 ul
= strtoul (s
, p
, base
);
2124 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
2130 /* NOTE: identical to above, modulo use of cc_t */
2132 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
2136 ul
= strtoul (s
, p
, base
);
2137 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
2143 /* Parse the output of display_recoverable.
2144 Return false if any part of it is invalid. */
2146 recover_mode (char const *arg
, struct termios
*mode
)
2149 char const *s
= arg
;
2151 for (i
= 0; i
< 4; i
++)
2154 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
2158 mode
->c_iflag
= flag
[0];
2159 mode
->c_oflag
= flag
[1];
2160 mode
->c_cflag
= flag
[2];
2161 mode
->c_lflag
= flag
[3];
2163 for (i
= 0; i
< NCCS
; ++i
)
2166 char delim
= i
< NCCS
- 1 ? ':' : '\0';
2167 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
2177 char const *string
; /* ASCII representation. */
2178 speed_t speed
; /* Internal form. */
2179 unsigned long int value
; /* Numeric value. */
2182 static struct speed_map
const speeds
[] =
2189 {"134.5", B134
, 134},
2194 {"1200", B1200
, 1200},
2195 {"1800", B1800
, 1800},
2196 {"2400", B2400
, 2400},
2197 {"4800", B4800
, 4800},
2198 {"9600", B9600
, 9600},
2199 {"19200", B19200
, 19200},
2200 {"38400", B38400
, 38400},
2201 {"exta", B19200
, 19200},
2202 {"extb", B38400
, 38400},
2204 {"57600", B57600
, 57600},
2207 {"115200", B115200
, 115200},
2210 {"230400", B230400
, 230400},
2213 {"460800", B460800
, 460800},
2216 {"500000", B500000
, 500000},
2219 {"576000", B576000
, 576000},
2222 {"921600", B921600
, 921600},
2225 {"1000000", B1000000
, 1000000},
2228 {"1152000", B1152000
, 1152000},
2231 {"1500000", B1500000
, 1500000},
2234 {"2000000", B2000000
, 2000000},
2237 {"2500000", B2500000
, 2500000},
2240 {"3000000", B3000000
, 3000000},
2243 {"3500000", B3500000
, 3500000},
2246 {"4000000", B4000000
, 4000000},
2253 string_to_baud (char const *arg
)
2255 for (int i
= 0; speeds
[i
].string
!= nullptr; ++i
)
2256 if (STREQ (arg
, speeds
[i
].string
))
2257 return speeds
[i
].speed
;
2258 return (speed_t
) -1;
2262 static unsigned long int
2263 baud_to_value (speed_t speed
)
2265 for (int i
= 0; speeds
[i
].string
!= nullptr; ++i
)
2266 if (speed
== speeds
[i
].speed
)
2267 return speeds
[i
].value
;
2272 sane_mode (struct termios
*mode
)
2277 for (i
= 0; control_info
[i
].name
; ++i
)
2280 if (STREQ (control_info
[i
].name
, "min"))
2283 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
2286 for (i
= 0; mode_info
[i
].name
!= nullptr; ++i
)
2288 if (mode_info
[i
].flags
& NO_SETATTR
)
2291 if (mode_info
[i
].flags
& SANE_SET
)
2293 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2294 assume (bitsp
); /* combination modes will not have SANE_SET. */
2295 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
2297 else if (mode_info
[i
].flags
& SANE_UNSET
)
2299 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2300 assume (bitsp
); /* combination modes will not have SANE_UNSET. */
2301 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
2306 /* Return a string that is the printable representation of character CH. */
2307 /* Adapted from 'cat' by Torbjörn Granlund. */
2312 static char buf
[10];
2315 if (ch
== _POSIX_VDISABLE
)
2334 *bpout
++ = ch
- 128;
2344 *bpout
++ = ch
- 128 + 64;
2354 return (char const *) buf
;
2357 /* Parse string S as an integer, using decimal radix by default,
2358 but allowing octal and hex numbers as in C. Reject values
2359 larger than MAXVAL. */
2362 integer_arg (char const *s
, uintmax_t maxval
)
2364 return xnumtoumax (s
, 0, 0, maxval
, "bB", _("invalid integer argument"),