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 unsigned long int integer_arg (char const *s
, unsigned long int 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 unsigned long int value
;
1247 check_argument (arg
);
1249 mode
->c_line
= value
= integer_arg (settings
[k
], ULONG_MAX
);
1250 if (mode
->c_line
!= value
)
1251 error (0, 0, _("invalid line discipline %s"),
1252 quote (settings
[k
]));
1253 *require_set_attr
= true;
1256 else if (STREQ (arg
, "speed"))
1260 max_col
= screen_columns ();
1261 display_speed (mode
, false);
1263 else if (string_to_baud (arg
) != (speed_t
) -1)
1265 set_speed (both_speeds
, arg
, mode
);
1268 *require_set_attr
= true;
1272 if (! recover_mode (arg
, mode
))
1274 error (0, 0, _("invalid argument %s"), quote (arg
));
1275 usage (EXIT_FAILURE
);
1277 *require_set_attr
= true;
1287 main (int argc
, char **argv
)
1289 /* Initialize to all zeroes so there is no risk memcmp will report a
1290 spurious difference in an uninitialized portion of the structure. */
1291 static struct termios mode
;
1293 enum output_type output_type
;
1297 bool require_set_attr
;
1298 bool verbose_output
;
1299 bool recoverable_output
;
1301 char *file_name
= nullptr;
1302 char const *device_name
;
1304 initialize_main (&argc
, &argv
);
1305 set_program_name (argv
[0]);
1306 setlocale (LC_ALL
, "");
1307 bindtextdomain (PACKAGE
, LOCALEDIR
);
1308 textdomain (PACKAGE
);
1310 atexit (close_stdout
);
1312 output_type
= changed
;
1313 verbose_output
= false;
1314 recoverable_output
= false;
1316 /* Don't print error messages for unrecognized options. */
1319 /* If any new options are ever added to stty, the short options MUST
1320 NOT allow any ambiguity with the stty settings. For example, the
1321 stty setting "-gagFork" would not be feasible, since it will be
1322 parsed as "-g -a -g -F ork". If you change anything about how
1323 stty parses options, be sure it still works with combinations of
1324 short and long options, --, POSIXLY_CORRECT, etc. */
1326 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
1333 verbose_output
= true;
1338 recoverable_output
= true;
1339 output_type
= recoverable
;
1344 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
1348 case DEV_DEBUG_OPTION
:
1352 case_GETOPT_HELP_CHAR
;
1354 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1357 /* Consider "drain" as an option rather than a setting,
1358 to support: alias stty='stty -drain' etc. */
1359 if (! STREQ (argv
[argi
+ opti
], "-drain")
1360 && ! STREQ (argv
[argi
+ opti
], "drain"))
1363 /* Skip the argument containing this unrecognized option;
1364 the 2nd pass will analyze it. */
1367 /* Restart getopt_long from the first unskipped argument. */
1374 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
1375 while (opti
< optind
)
1376 argv
[argi
+ opti
++] = nullptr;
1379 /* Specifying both -a and -g gets an error. */
1380 if (verbose_output
&& recoverable_output
)
1381 error (EXIT_FAILURE
, 0,
1382 _("the options for verbose and stty-readable output styles are\n"
1383 "mutually exclusive"));
1385 /* Specifying any other arguments with -a or -g gets an error. */
1386 if (!noargs
&& (verbose_output
|| recoverable_output
))
1387 error (EXIT_FAILURE
, 0,
1388 _("when specifying an output style, modes may not be set"));
1390 device_name
= file_name
? file_name
: _("standard input");
1392 if (!noargs
&& !verbose_output
&& !recoverable_output
)
1394 static struct termios check_mode
;
1395 apply_settings (/* checking= */ true, device_name
, argv
, argc
,
1396 &check_mode
, &require_set_attr
);
1402 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
1403 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1404 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
1405 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
1406 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
1407 quotef (device_name
));
1410 if (tcgetattr (STDIN_FILENO
, &mode
))
1411 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1413 if (verbose_output
|| recoverable_output
|| noargs
)
1415 max_col
= screen_columns ();
1417 display_settings (output_type
, &mode
, device_name
);
1418 return EXIT_SUCCESS
;
1421 require_set_attr
= false;
1422 apply_settings (/* checking= */ false, device_name
, argv
, argc
,
1423 &mode
, &require_set_attr
);
1425 if (require_set_attr
)
1427 /* Initialize to all zeroes so there is no risk memcmp will report a
1428 spurious difference in an uninitialized portion of the structure. */
1429 static struct termios new_mode
;
1431 if (tcsetattr (STDIN_FILENO
, tcsetattr_options
, &mode
))
1432 error (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 error (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 error (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
);
1497 if (bitsp
== nullptr)
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 affirm (baud
!= (speed_t
) -1);
1727 if (type
== input_speed
|| type
== both_speeds
)
1730 if (cfsetispeed (mode
, baud
))
1731 error (EXIT_FAILURE
, 0, _("unsupported ispeed %s"), quoteaf (arg
));
1733 if (type
== output_speed
|| type
== both_speeds
)
1736 if (cfsetospeed (mode
, baud
))
1737 error (EXIT_FAILURE
, 0, _("unsupported ospeed %s"), quoteaf (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 error (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 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1802 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1803 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1808 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1809 error (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 error (EXIT_FAILURE
, errno
, "%s", quotef (device_name
));
1822 error (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
!= nullptr
1856 && xstrtol (col_string
, nullptr, 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
!= nullptr; ++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
;
1982 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1984 if (mode_info
[i
].flags
& SANE_UNSET
)
1986 wrapf ("%s", mode_info
[i
].name
);
1990 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1992 wrapf ("-%s", mode_info
[i
].name
);
2002 display_all (struct termios
*mode
, char const *device_name
)
2007 enum mode_type prev_type
= control
;
2009 display_speed (mode
, true);
2011 display_window_size (true, device_name
);
2014 wrapf ("line = %d;", mode
->c_line
);
2019 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
2022 /* 'flush' is the deprecated equivalent of 'discard'. */
2023 if (STREQ (control_info
[i
].name
, "flush"))
2026 /* If swtch is the same as susp, don't print both. */
2028 if (STREQ (control_info
[i
].name
, "swtch"))
2031 /* If eof uses the same slot as min, only print whichever applies. */
2033 if ((mode
->c_lflag
& ICANON
) == 0
2034 && (STREQ (control_info
[i
].name
, "eof")
2035 || STREQ (control_info
[i
].name
, "eol")))
2038 wrapf ("%s = %s;", control_info
[i
].name
,
2039 visible (mode
->c_cc
[control_info
[i
].offset
]));
2042 if ((mode
->c_lflag
& ICANON
) == 0)
2044 wrapf ("min = %lu; time = %lu;",
2045 (unsigned long int) mode
->c_cc
[VMIN
],
2046 (unsigned long int) mode
->c_cc
[VTIME
]);
2047 if (current_col
!= 0)
2051 for (i
= 0; mode_info
[i
].name
!= nullptr; ++i
)
2053 if (mode_info
[i
].flags
& OMIT
)
2055 if (mode_info
[i
].type
!= prev_type
)
2059 prev_type
= mode_info
[i
].type
;
2062 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2063 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
2064 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
2065 wrapf ("%s", mode_info
[i
].name
);
2066 else if (mode_info
[i
].flags
& REV
)
2067 wrapf ("-%s", mode_info
[i
].name
);
2073 /* Verify requested asymmetric speeds are supported.
2074 Note we don't flag the case where only ispeed or
2075 ospeed is set, when that would set both. */
2078 check_speed (struct termios
*mode
)
2080 if (last_ibaud
!= -1 && last_obaud
!= -1)
2082 if (cfgetispeed (mode
) != last_ibaud
2083 || cfgetospeed (mode
) != last_obaud
)
2084 error (EXIT_FAILURE
, 0,
2085 _("asymmetric input (%lu), output (%lu) speeds not supported"),
2086 baud_to_value (last_ibaud
), baud_to_value (last_obaud
));
2091 display_speed (struct termios
*mode
, bool fancy
)
2093 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
2094 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
2095 baud_to_value (cfgetospeed (mode
)));
2097 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
2098 baud_to_value (cfgetispeed (mode
)),
2099 baud_to_value (cfgetospeed (mode
)));
2105 display_recoverable (struct termios
*mode
)
2107 printf ("%lx:%lx:%lx:%lx",
2108 (unsigned long int) mode
->c_iflag
,
2109 (unsigned long int) mode
->c_oflag
,
2110 (unsigned long int) mode
->c_cflag
,
2111 (unsigned long int) mode
->c_lflag
);
2112 for (size_t i
= 0; i
< NCCS
; ++i
)
2113 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
2117 /* NOTE: identical to below, modulo use of tcflag_t */
2119 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
2124 ul
= strtoul (s
, p
, base
);
2125 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
2131 /* NOTE: identical to above, modulo use of cc_t */
2133 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
2137 ul
= strtoul (s
, p
, base
);
2138 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
2144 /* Parse the output of display_recoverable.
2145 Return false if any part of it is invalid. */
2147 recover_mode (char const *arg
, struct termios
*mode
)
2150 char const *s
= arg
;
2152 for (i
= 0; i
< 4; i
++)
2155 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
2159 mode
->c_iflag
= flag
[0];
2160 mode
->c_oflag
= flag
[1];
2161 mode
->c_cflag
= flag
[2];
2162 mode
->c_lflag
= flag
[3];
2164 for (i
= 0; i
< NCCS
; ++i
)
2167 char delim
= i
< NCCS
- 1 ? ':' : '\0';
2168 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
2178 char const *string
; /* ASCII representation. */
2179 speed_t speed
; /* Internal form. */
2180 unsigned long int value
; /* Numeric value. */
2183 static struct speed_map
const speeds
[] =
2190 {"134.5", B134
, 134},
2195 {"1200", B1200
, 1200},
2196 {"1800", B1800
, 1800},
2197 {"2400", B2400
, 2400},
2198 {"4800", B4800
, 4800},
2199 {"9600", B9600
, 9600},
2200 {"19200", B19200
, 19200},
2201 {"38400", B38400
, 38400},
2202 {"exta", B19200
, 19200},
2203 {"extb", B38400
, 38400},
2205 {"57600", B57600
, 57600},
2208 {"115200", B115200
, 115200},
2211 {"230400", B230400
, 230400},
2214 {"460800", B460800
, 460800},
2217 {"500000", B500000
, 500000},
2220 {"576000", B576000
, 576000},
2223 {"921600", B921600
, 921600},
2226 {"1000000", B1000000
, 1000000},
2229 {"1152000", B1152000
, 1152000},
2232 {"1500000", B1500000
, 1500000},
2235 {"2000000", B2000000
, 2000000},
2238 {"2500000", B2500000
, 2500000},
2241 {"3000000", B3000000
, 3000000},
2244 {"3500000", B3500000
, 3500000},
2247 {"4000000", B4000000
, 4000000},
2254 string_to_baud (char const *arg
)
2256 for (int i
= 0; speeds
[i
].string
!= nullptr; ++i
)
2257 if (STREQ (arg
, speeds
[i
].string
))
2258 return speeds
[i
].speed
;
2259 return (speed_t
) -1;
2263 static unsigned long int
2264 baud_to_value (speed_t speed
)
2266 for (int i
= 0; speeds
[i
].string
!= nullptr; ++i
)
2267 if (speed
== speeds
[i
].speed
)
2268 return speeds
[i
].value
;
2273 sane_mode (struct termios
*mode
)
2278 for (i
= 0; control_info
[i
].name
; ++i
)
2281 if (STREQ (control_info
[i
].name
, "min"))
2284 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
2287 for (i
= 0; mode_info
[i
].name
!= nullptr; ++i
)
2289 if (mode_info
[i
].flags
& NO_SETATTR
)
2292 if (mode_info
[i
].flags
& SANE_SET
)
2294 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2295 assume (bitsp
); /* combination modes will not have SANE_SET. */
2296 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
2298 else if (mode_info
[i
].flags
& SANE_UNSET
)
2300 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
2301 assume (bitsp
); /* combination modes will not have SANE_UNSET. */
2302 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
2307 /* Return a string that is the printable representation of character CH. */
2308 /* Adapted from 'cat' by Torbjörn Granlund. */
2313 static char buf
[10];
2316 if (ch
== _POSIX_VDISABLE
)
2335 *bpout
++ = ch
- 128;
2345 *bpout
++ = ch
- 128 + 64;
2355 return (char const *) buf
;
2358 /* Parse string S as an integer, using decimal radix by default,
2359 but allowing octal and hex numbers as in C. Reject values
2360 larger than MAXVAL. */
2362 static unsigned long int
2363 integer_arg (char const *s
, unsigned long int maxval
)
2365 return xnumtoumax (s
, 0, 0, maxval
, "bB", _("invalid integer argument"), 0);