1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2013 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 <http://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
59 #include "fd-reopen.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.' */
122 #if defined __sparc__ && defined __svr4__
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. */
197 const char *name
; /* Name given on command line. */
198 enum mode_type type
; /* Which structure element to change. */
199 char flags
; /* Setting and display options. */
200 unsigned long bits
; /* Bits to set for this mode. */
201 unsigned long mask
; /* Other bits to turn off for this mode. */
204 static struct mode_info
const mode_info
[] =
206 {"parenb", control
, REV
, PARENB
, 0},
207 {"parodd", control
, REV
, PARODD
, 0},
208 {"cs5", control
, 0, CS5
, CSIZE
},
209 {"cs6", control
, 0, CS6
, CSIZE
},
210 {"cs7", control
, 0, CS7
, CSIZE
},
211 {"cs8", control
, 0, CS8
, CSIZE
},
212 {"hupcl", control
, REV
, HUPCL
, 0},
213 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
214 {"cstopb", control
, REV
, CSTOPB
, 0},
215 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
216 {"clocal", control
, REV
, CLOCAL
, 0},
218 {"crtscts", control
, REV
, CRTSCTS
, 0},
221 {"cdtrdsr", control
, REV
, CDTRDSR
, 0},
224 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
225 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
226 {"ignpar", input
, REV
, IGNPAR
, 0},
227 {"parmrk", input
, REV
, PARMRK
, 0},
228 {"inpck", input
, REV
, INPCK
, 0},
229 {"istrip", input
, REV
, ISTRIP
, 0},
230 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
231 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
232 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
233 {"ixon", input
, REV
, IXON
, 0},
234 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
235 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
237 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
240 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
243 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
246 {"iutf8", input
, SANE_UNSET
| REV
, IUTF8
, 0},
249 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
251 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
254 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
257 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
260 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
263 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
266 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
269 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
272 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
273 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
276 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
277 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
278 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
279 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
283 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
286 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
289 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
292 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
296 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
300 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
301 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
304 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
305 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
308 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
309 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
312 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
313 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
315 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
317 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
318 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
319 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
320 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
321 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
322 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
324 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
327 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
330 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
331 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
334 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
335 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
338 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
339 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
342 {"evenp", combination
, REV
| OMIT
, 0, 0},
343 {"parity", combination
, REV
| OMIT
, 0, 0},
344 {"oddp", combination
, REV
| OMIT
, 0, 0},
345 {"nl", combination
, REV
| OMIT
, 0, 0},
346 {"ek", combination
, OMIT
, 0, 0},
347 {"sane", combination
, OMIT
, 0, 0},
348 {"cooked", combination
, REV
| OMIT
, 0, 0},
349 {"raw", combination
, REV
| OMIT
, 0, 0},
350 {"pass8", combination
, REV
| OMIT
, 0, 0},
351 {"litout", combination
, REV
| OMIT
, 0, 0},
352 {"cbreak", combination
, REV
| OMIT
, 0, 0},
354 {"decctlq", combination
, REV
| OMIT
, 0, 0},
356 #if defined TABDLY || defined OXTABS
357 {"tabs", combination
, REV
| OMIT
, 0, 0},
359 #if defined XCASE && defined IUCLC && defined OLCUC
360 {"lcase", combination
, REV
| OMIT
, 0, 0},
361 {"LCASE", combination
, REV
| OMIT
, 0, 0},
363 {"crt", combination
, OMIT
, 0, 0},
364 {"dec", combination
, OMIT
, 0, 0},
366 {NULL
, control
, 0, 0, 0}
369 /* Control character settings. */
372 const char *name
; /* Name given on command line. */
373 cc_t saneval
; /* Value to set for 'stty sane'. */
374 size_t offset
; /* Offset in c_cc. */
377 /* Control characters. */
379 static struct control_info
const control_info
[] =
381 {"intr", CINTR
, VINTR
},
382 {"quit", CQUIT
, VQUIT
},
383 {"erase", CERASE
, VERASE
},
384 {"kill", CKILL
, VKILL
},
388 {"eol2", CEOL2
, VEOL2
},
391 {"swtch", CSWTCH
, VSWTCH
},
393 {"start", CSTART
, VSTART
},
394 {"stop", CSTOP
, VSTOP
},
395 {"susp", CSUSP
, VSUSP
},
397 {"dsusp", CDSUSP
, VDSUSP
},
400 {"rprnt", CRPRNT
, VREPRINT
},
402 # ifdef CREPRINT /* HPUX 10.20 needs this */
403 {"rprnt", CRPRNT
, CREPRINT
},
407 {"werase", CWERASE
, VWERASE
},
410 {"lnext", CLNEXT
, VLNEXT
},
413 {"flush", CFLUSHO
, VFLUSHO
},
416 {"status", CSTATUS
, VSTATUS
},
419 /* These must be last because of the display routines. */
425 static char const *visible (cc_t ch
);
426 static unsigned long int baud_to_value (speed_t speed
);
427 static bool recover_mode (char const *arg
, struct termios
*mode
);
428 static int screen_columns (void);
429 static bool set_mode (struct mode_info
const *info
, bool reversed
,
430 struct termios
*mode
);
431 static unsigned long int integer_arg (const char *s
, unsigned long int max
);
432 static speed_t
string_to_baud (const char *arg
);
433 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
434 static void display_all (struct termios
*mode
, char const *device_name
);
435 static void display_changed (struct termios
*mode
);
436 static void display_recoverable (struct termios
*mode
);
437 static void display_settings (enum output_type output_type
,
438 struct termios
*mode
,
439 const char *device_name
);
440 static void display_speed (struct termios
*mode
, bool fancy
);
441 static void display_window_size (bool fancy
, char const *device_name
);
442 static void sane_mode (struct termios
*mode
);
443 static void set_control_char (struct control_info
const *info
,
445 struct termios
*mode
);
446 static void set_speed (enum speed_setting type
, const char *arg
,
447 struct termios
*mode
);
448 static void set_window_size (int rows
, int cols
, char const *device_name
);
450 /* The width of the screen, for output wrapping. */
453 /* Current position, to know when to wrap. */
454 static int current_col
;
456 static struct option
const longopts
[] =
458 {"all", no_argument
, NULL
, 'a'},
459 {"save", no_argument
, NULL
, 'g'},
460 {"file", required_argument
, NULL
, 'F'},
461 {GETOPT_HELP_OPTION_DECL
},
462 {GETOPT_VERSION_OPTION_DECL
},
466 static void wrapf (const char *message
, ...)
467 __attribute__ ((__format__ (__printf__
, 1, 2)));
469 /* Print format string MESSAGE and optional args.
470 Wrap to next line first if it won't fit.
471 Print a space first unless MESSAGE will start a new line. */
474 wrapf (const char *message
,...)
480 va_start (args
, message
);
481 buflen
= vasprintf (&buf
, message
, args
);
489 if (max_col
- current_col
< buflen
)
503 current_col
+= buflen
;
509 if (status
!= EXIT_SUCCESS
)
514 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
515 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
516 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
518 program_name
, program_name
, program_name
);
520 Print or change terminal characteristics.\n\
523 emit_mandatory_arg_note ();
526 -a, --all print all current settings in human-readable form\n\
527 -g, --save print all current settings in a stty-readable form\n\
528 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
530 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
531 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
534 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
535 settings. The underlying system defines which settings are available.\n\
539 Special characters:\n\
540 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
541 eof CHAR CHAR will send an end of file (terminate the input)\n\
542 eol CHAR CHAR will end the line\n\
545 * eol2 CHAR alternate CHAR for ending the line\n\
546 erase CHAR CHAR will erase the last character typed\n\
547 intr CHAR CHAR will send an interrupt signal\n\
548 kill CHAR CHAR will erase the current line\n\
551 * lnext CHAR CHAR will enter the next character quoted\n\
552 quit CHAR CHAR will send a quit signal\n\
553 * rprnt CHAR CHAR will redraw the current line\n\
554 start CHAR CHAR will restart the output after stopping it\n\
557 stop CHAR CHAR will stop the output\n\
558 susp CHAR CHAR will send a terminal stop signal\n\
559 * swtch CHAR CHAR will switch to a different shell layer\n\
560 * werase CHAR CHAR will erase the last word typed\n\
565 N set the input and output speeds to N bauds\n\
566 * cols N tell the kernel that the terminal has N columns\n\
567 * columns N same as cols N\n\
570 ispeed N set the input speed to N\n\
571 * line N use line discipline N\n\
572 min N with -icanon, set N characters minimum for a completed read\n\
573 ospeed N set the output speed to N\n\
576 * rows N tell the kernel that the terminal has N rows\n\
577 * size print the number of rows and columns according to the kernel\n\
578 speed print the terminal speed\n\
579 time N with -icanon, set read timeout of N tenths of a second\n\
584 [-]clocal disable modem control signals\n\
585 [-]cread allow input to be received\n\
586 * [-]crtscts enable RTS/CTS handshaking\n\
587 * [-]cdtrdsr enable DTR/DSR handshaking\n\
588 csN set character size to N bits, N in [5..8]\n\
591 [-]cstopb use two stop bits per character (one with '-')\n\
592 [-]hup send a hangup signal when the last process closes the tty\n\
593 [-]hupcl same as [-]hup\n\
594 [-]parenb generate parity bit in output and expect parity bit in input\n\
595 [-]parodd set odd parity (or even parity with '-')\n\
600 [-]brkint breaks cause an interrupt signal\n\
601 [-]icrnl translate carriage return to newline\n\
602 [-]ignbrk ignore break characters\n\
603 [-]igncr ignore carriage return\n\
606 [-]ignpar ignore characters with parity errors\n\
607 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
608 [-]inlcr translate newline to carriage return\n\
609 [-]inpck enable input parity checking\n\
610 [-]istrip clear high (8th) bit of input characters\n\
613 * [-]iutf8 assume input characters are UTF-8 encoded\n\
616 * [-]iuclc translate uppercase characters to lowercase\n\
617 * [-]ixany let any character restart output, not only start character\n\
618 [-]ixoff enable sending of start/stop characters\n\
619 [-]ixon enable XON/XOFF flow control\n\
620 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
621 [-]tandem same as [-]ixoff\n\
626 * bsN backspace delay style, N in [0..1]\n\
627 * crN carriage return delay style, N in [0..3]\n\
628 * ffN form feed delay style, N in [0..1]\n\
629 * nlN newline delay style, N in [0..1]\n\
632 * [-]ocrnl translate carriage return to newline\n\
633 * [-]ofdel use delete characters for fill instead of null characters\n\
634 * [-]ofill use fill (padding) characters instead of timing for delays\n\
635 * [-]olcuc translate lowercase characters to uppercase\n\
636 * [-]onlcr translate newline to carriage return-newline\n\
637 * [-]onlret newline performs a carriage return\n\
640 * [-]onocr do not print carriage returns in the first column\n\
641 [-]opost postprocess output\n\
642 * tabN horizontal tab delay style, N in [0..3]\n\
643 * tabs same as tab0\n\
644 * -tabs same as tab3\n\
645 * vtN vertical tab delay style, N in [0..1]\n\
650 [-]crterase echo erase characters as backspace-space-backspace\n\
651 * crtkill kill all line by obeying the echoprt and echoe settings\n\
652 * -crtkill kill all line by obeying the echoctl and echok settings\n\
655 * [-]ctlecho echo control characters in hat notation ('^c')\n\
656 [-]echo echo input characters\n\
657 * [-]echoctl same as [-]ctlecho\n\
658 [-]echoe same as [-]crterase\n\
659 [-]echok echo a newline after a kill character\n\
662 * [-]echoke same as [-]crtkill\n\
663 [-]echonl echo newline even if not echoing other characters\n\
664 * [-]echoprt echo erased characters backward, between '\\' and '/'\n\
665 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
666 [-]iexten enable non-POSIX special characters\n\
669 [-]isig enable interrupt, quit, and suspend special characters\n\
670 [-]noflsh disable flushing after interrupt and quit special characters\n\
671 * [-]prterase same as [-]echoprt\n\
672 * [-]tostop stop background jobs that try to write to the terminal\n\
673 * [-]xcase with icanon, escape with '\\' for uppercase characters\n\
677 Combination settings:\n\
678 * [-]LCASE same as [-]lcase\n\
679 cbreak same as -icanon\n\
680 -cbreak same as icanon\n\
683 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
684 icanon, eof and eol characters to their default values\n\
685 -cooked same as raw\n\
686 crt same as echoe echoctl echoke\n\
689 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
691 * [-]decctlq same as [-]ixany\n\
692 ek erase and kill characters to their default values\n\
693 evenp same as parenb -parodd cs7\n\
696 -evenp same as -parenb cs8\n\
697 * [-]lcase same as xcase iuclc olcuc\n\
698 litout same as -parenb -istrip -opost cs8\n\
699 -litout same as parenb istrip opost cs7\n\
700 nl same as -icrnl -onlcr\n\
701 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
704 oddp same as parenb parodd cs7\n\
705 -oddp same as -parenb cs8\n\
706 [-]parity same as [-]evenp\n\
707 pass8 same as -parenb -istrip cs8\n\
708 -pass8 same as parenb istrip cs7\n\
711 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
712 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
713 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
714 -raw same as cooked\n\
717 sane same as cread -ignbrk brkint -inlcr -igncr icrnl -iutf8\n\
718 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
719 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
720 isig icanon iexten echo echoe echok -echonl -noflsh\n\
721 -xcase -tostop -echoprt echoctl echoke, all special\n\
722 characters to their default values\n\
726 Handle the tty line connected to standard input. Without arguments,\n\
727 prints baud rate, line discipline, and deviations from stty sane. In\n\
728 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
729 127; special values ^- or undef used to disable special characters.\n\
731 emit_ancillary_info ();
737 main (int argc
, char **argv
)
739 /* Initialize to all zeroes so there is no risk memcmp will report a
740 spurious difference in an uninitialized portion of the structure. */
741 static struct termios mode
;
743 enum output_type output_type
;
747 bool require_set_attr
;
748 bool speed_was_set ATTRIBUTE_UNUSED
;
750 bool recoverable_output
;
753 char *file_name
= NULL
;
754 const char *device_name
;
756 initialize_main (&argc
, &argv
);
757 set_program_name (argv
[0]);
758 setlocale (LC_ALL
, "");
759 bindtextdomain (PACKAGE
, LOCALEDIR
);
760 textdomain (PACKAGE
);
762 atexit (close_stdout
);
764 output_type
= changed
;
765 verbose_output
= false;
766 recoverable_output
= false;
768 /* Don't print error messages for unrecognized options. */
771 /* If any new options are ever added to stty, the short options MUST
772 NOT allow any ambiguity with the stty settings. For example, the
773 stty setting "-gagFork" would not be feasible, since it will be
774 parsed as "-g -a -g -F ork". If you change anything about how
775 stty parses options, be sure it still works with combinations of
776 short and long options, --, POSIXLY_CORRECT, etc. */
778 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
785 verbose_output
= true;
790 recoverable_output
= true;
791 output_type
= recoverable
;
796 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
800 case_GETOPT_HELP_CHAR
;
802 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
807 /* Skip the argument containing this unrecognized option;
808 the 2nd pass will analyze it. */
811 /* Restart getopt_long from the first unskipped argument. */
818 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
819 while (opti
< optind
)
820 argv
[argi
+ opti
++] = NULL
;
823 /* Specifying both -a and -g gets an error. */
824 if (verbose_output
&& recoverable_output
)
825 error (EXIT_FAILURE
, 0,
826 _("the options for verbose and stty-readable output styles are\n"
827 "mutually exclusive"));
829 /* Specifying any other arguments with -a or -g gets an error. */
830 if (!noargs
&& (verbose_output
|| recoverable_output
))
831 error (EXIT_FAILURE
, 0,
832 _("when specifying an output style, modes may not be set"));
834 /* FIXME: it'd be better not to open the file until we've verified
835 that all arguments are valid. Otherwise, we could end up doing
836 only some of the requested operations and then failing, probably
837 leaving things in an undesirable state. */
842 device_name
= file_name
;
843 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
844 error (EXIT_FAILURE
, errno
, "%s", device_name
);
845 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
846 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
847 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
851 device_name
= _("standard input");
853 if (tcgetattr (STDIN_FILENO
, &mode
))
854 error (EXIT_FAILURE
, errno
, "%s", device_name
);
856 if (verbose_output
|| recoverable_output
|| noargs
)
858 max_col
= screen_columns ();
860 display_settings (output_type
, &mode
, device_name
);
864 speed_was_set
= false;
865 require_set_attr
= false;
866 for (k
= 1; k
< argc
; k
++)
868 char const *arg
= argv
[k
];
869 bool match_found
= false;
870 bool reversed
= false;
881 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
883 if (STREQ (arg
, mode_info
[i
].name
))
885 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
886 require_set_attr
= true;
890 if (!match_found
&& reversed
)
892 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
893 usage (EXIT_FAILURE
);
897 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
899 if (STREQ (arg
, control_info
[i
].name
))
903 error (0, 0, _("missing argument to %s"), quote (arg
));
904 usage (EXIT_FAILURE
);
908 set_control_char (&control_info
[i
], argv
[k
], &mode
);
909 require_set_attr
= true;
916 if (STREQ (arg
, "ispeed"))
920 error (0, 0, _("missing argument to %s"), quote (arg
));
921 usage (EXIT_FAILURE
);
924 set_speed (input_speed
, argv
[k
], &mode
);
925 speed_was_set
= true;
926 require_set_attr
= true;
928 else if (STREQ (arg
, "ospeed"))
932 error (0, 0, _("missing argument to %s"), quote (arg
));
933 usage (EXIT_FAILURE
);
936 set_speed (output_speed
, argv
[k
], &mode
);
937 speed_was_set
= true;
938 require_set_attr
= true;
941 else if (STREQ (arg
, "rows"))
945 error (0, 0, _("missing argument to %s"), quote (arg
));
946 usage (EXIT_FAILURE
);
949 set_window_size (integer_arg (argv
[k
], INT_MAX
), -1,
952 else if (STREQ (arg
, "cols")
953 || STREQ (arg
, "columns"))
957 error (0, 0, _("missing argument to %s"), quote (arg
));
958 usage (EXIT_FAILURE
);
961 set_window_size (-1, integer_arg (argv
[k
], INT_MAX
),
964 else if (STREQ (arg
, "size"))
966 max_col
= screen_columns ();
968 display_window_size (false, device_name
);
972 else if (STREQ (arg
, "line"))
974 unsigned long int value
;
977 error (0, 0, _("missing argument to %s"), quote (arg
));
978 usage (EXIT_FAILURE
);
981 mode
.c_line
= value
= integer_arg (argv
[k
], ULONG_MAX
);
982 if (mode
.c_line
!= value
)
983 error (0, 0, _("invalid line discipline %s"), quote (argv
[k
]));
984 require_set_attr
= true;
987 else if (STREQ (arg
, "speed"))
989 max_col
= screen_columns ();
990 display_speed (&mode
, false);
992 else if (string_to_baud (arg
) != (speed_t
) -1)
994 set_speed (both_speeds
, arg
, &mode
);
995 speed_was_set
= true;
996 require_set_attr
= true;
1000 if (! recover_mode (arg
, &mode
))
1002 error (0, 0, _("invalid argument %s"), quote (arg
));
1003 usage (EXIT_FAILURE
);
1005 require_set_attr
= true;
1010 if (require_set_attr
)
1012 /* Initialize to all zeroes so there is no risk memcmp will report a
1013 spurious difference in an uninitialized portion of the structure. */
1014 static struct termios new_mode
;
1016 if (tcsetattr (STDIN_FILENO
, TCSADRAIN
, &mode
))
1017 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1019 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1020 it performs *any* of the requested operations. This means it
1021 can report 'success' when it has actually failed to perform
1022 some proper subset of the requested operations. To detect
1023 this partial failure, get the current terminal attributes and
1024 compare them to the requested ones. */
1026 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1027 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1029 /* Normally, one shouldn't use memcmp to compare structures that
1030 may have 'holes' containing uninitialized data, but we have been
1031 careful to initialize the storage of these two variables to all
1032 zeroes. One might think it more efficient simply to compare the
1033 modified fields, but that would require enumerating those fields --
1034 and not all systems have the same fields in this structure. */
1036 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1039 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1040 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1041 sometimes (m1 != m2). The only difference is in the four bits
1042 of the c_cflag field corresponding to the baud rate. To save
1043 Sun users a little confusion, don't report an error if this
1044 happens. But suppress the error only if we haven't tried to
1045 set the baud rate explicitly -- otherwise we'd never give an
1046 error for a true failure to set the baud rate. */
1048 new_mode
.c_cflag
&= (~CIBAUD
);
1049 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1052 error (EXIT_FAILURE
, 0,
1053 _("%s: unable to perform all requested operations"),
1058 printf ("new_mode: mode\n");
1059 for (i
= 0; i
< sizeof (new_mode
); i
++)
1060 printf ("0x%02x: 0x%02x\n",
1061 *(((unsigned char *) &new_mode
) + i
),
1062 *(((unsigned char *) &mode
) + i
));
1069 exit (EXIT_SUCCESS
);
1072 /* Return false if not applied because not reversible; otherwise
1076 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1080 if (reversed
&& (info
->flags
& REV
) == 0)
1083 bitsp
= mode_type_flag (info
->type
, mode
);
1087 /* Combination mode. */
1088 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1091 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1093 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1095 else if (STREQ (info
->name
, "oddp"))
1098 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1100 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1102 else if (STREQ (info
->name
, "nl"))
1106 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1107 mode
->c_oflag
= (mode
->c_oflag
1122 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1124 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1128 else if (STREQ (info
->name
, "ek"))
1130 mode
->c_cc
[VERASE
] = CERASE
;
1131 mode
->c_cc
[VKILL
] = CKILL
;
1133 else if (STREQ (info
->name
, "sane"))
1135 else if (STREQ (info
->name
, "cbreak"))
1138 mode
->c_lflag
|= ICANON
;
1140 mode
->c_lflag
&= ~ICANON
;
1142 else if (STREQ (info
->name
, "pass8"))
1146 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1147 mode
->c_iflag
|= ISTRIP
;
1151 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1152 mode
->c_iflag
&= ~ISTRIP
;
1155 else if (STREQ (info
->name
, "litout"))
1159 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1160 mode
->c_iflag
|= ISTRIP
;
1161 mode
->c_oflag
|= OPOST
;
1165 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1166 mode
->c_iflag
&= ~ISTRIP
;
1167 mode
->c_oflag
&= ~OPOST
;
1170 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1172 if ((info
->name
[0] == 'r' && reversed
)
1173 || (info
->name
[0] == 'c' && !reversed
))
1176 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1177 mode
->c_oflag
|= OPOST
;
1178 mode
->c_lflag
|= ISIG
| ICANON
;
1180 mode
->c_cc
[VEOF
] = CEOF
;
1183 mode
->c_cc
[VEOL
] = CEOL
;
1190 mode
->c_oflag
&= ~OPOST
;
1191 mode
->c_lflag
&= ~(ISIG
| ICANON
1196 mode
->c_cc
[VMIN
] = 1;
1197 mode
->c_cc
[VTIME
] = 0;
1201 else if (STREQ (info
->name
, "decctlq"))
1204 mode
->c_iflag
|= IXANY
;
1206 mode
->c_iflag
&= ~IXANY
;
1210 else if (STREQ (info
->name
, "tabs"))
1213 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1215 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1219 else if (STREQ (info
->name
, "tabs"))
1222 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1224 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1228 #if defined XCASE && defined IUCLC && defined OLCUC
1229 else if (STREQ (info
->name
, "lcase")
1230 || STREQ (info
->name
, "LCASE"))
1234 mode
->c_lflag
&= ~XCASE
;
1235 mode
->c_iflag
&= ~IUCLC
;
1236 mode
->c_oflag
&= ~OLCUC
;
1240 mode
->c_lflag
|= XCASE
;
1241 mode
->c_iflag
|= IUCLC
;
1242 mode
->c_oflag
|= OLCUC
;
1246 else if (STREQ (info
->name
, "crt"))
1247 mode
->c_lflag
|= ECHOE
1255 else if (STREQ (info
->name
, "dec"))
1257 mode
->c_cc
[VINTR
] = 3; /* ^C */
1258 mode
->c_cc
[VERASE
] = 127; /* DEL */
1259 mode
->c_cc
[VKILL
] = 21; /* ^U */
1260 mode
->c_lflag
|= ECHOE
1269 mode
->c_iflag
&= ~IXANY
;
1274 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1276 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1282 set_control_char (struct control_info
const *info
, const char *arg
,
1283 struct termios
*mode
)
1285 unsigned long int value
;
1287 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1288 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1289 else if (arg
[0] == '\0' || arg
[1] == '\0')
1290 value
= to_uchar (arg
[0]);
1291 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1292 value
= _POSIX_VDISABLE
;
1293 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1298 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1301 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1302 mode
->c_cc
[info
->offset
] = value
;
1306 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1310 baud
= string_to_baud (arg
);
1311 if (type
== input_speed
|| type
== both_speeds
)
1312 cfsetispeed (mode
, baud
);
1313 if (type
== output_speed
|| type
== both_speeds
)
1314 cfsetospeed (mode
, baud
);
1320 get_win_size (int fd
, struct winsize
*win
)
1322 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1327 set_window_size (int rows
, int cols
, char const *device_name
)
1331 if (get_win_size (STDIN_FILENO
, &win
))
1333 if (errno
!= EINVAL
)
1334 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1335 memset (&win
, 0, sizeof (win
));
1344 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1345 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1346 This comment from sys/ttold.h describes Sun's twisted logic - a better
1347 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1348 At any rate, the problem is gone in Solaris 2.x.
1350 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1351 but they can be disambiguated by checking whether a "struct ttysize"
1352 structure's "ts_lines" field is greater than 64K or not. If so,
1353 it's almost certainly a "struct winsize" instead.
1355 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1356 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16)
1357 + ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1358 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1359 "stty cols 0 rows 0" would do the right thing. On a little-endian
1360 machine like the sun386i, the problem is the same, but for ws_col == 0.
1362 The workaround is to do the ioctl once with row and col = 1 to set the
1363 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1365 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1367 struct ttysize ttysz
;
1369 ttysz
.ts_lines
= win
.ws_row
;
1370 ttysz
.ts_cols
= win
.ws_col
;
1375 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1376 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1378 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1379 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1384 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1385 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1389 display_window_size (bool fancy
, char const *device_name
)
1393 if (get_win_size (STDIN_FILENO
, &win
))
1395 if (errno
!= EINVAL
)
1396 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1398 error (EXIT_FAILURE
, 0,
1399 _("%s: no size information for this device"), device_name
);
1403 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1404 win
.ws_row
, win
.ws_col
);
1412 screen_columns (void)
1417 /* With Solaris 2.[123], this ioctl fails and errno is set to
1418 EINVAL for telnet (but not rlogin) sessions.
1419 On ISC 3.0, it fails for the console and the serial port
1420 (but it works for ptys).
1421 It can also fail on any system when stdout isn't a tty.
1422 In case of any failure, just use the default. */
1423 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1427 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1428 char *col_string
= getenv ("COLUMNS");
1430 if (!(col_string
!= NULL
1431 && xstrtol (col_string
, NULL
, 0, &n_columns
, "") == LONGINT_OK
1433 && n_columns
<= INT_MAX
))
1439 static tcflag_t
* _GL_ATTRIBUTE_PURE
1440 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1445 return &mode
->c_cflag
;
1448 return &mode
->c_iflag
;
1451 return &mode
->c_oflag
;
1454 return &mode
->c_lflag
;
1465 display_settings (enum output_type output_type
, struct termios
*mode
,
1466 char const *device_name
)
1468 switch (output_type
)
1471 display_changed (mode
);
1475 display_all (mode
, device_name
);
1479 display_recoverable (mode
);
1485 display_changed (struct termios
*mode
)
1491 enum mode_type prev_type
= control
;
1493 display_speed (mode
, true);
1495 wrapf ("line = %d;", mode
->c_line
);
1501 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1503 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1505 /* If swtch is the same as susp, don't print both. */
1507 if (STREQ (control_info
[i
].name
, "swtch"))
1510 /* If eof uses the same slot as min, only print whichever applies. */
1512 if ((mode
->c_lflag
& ICANON
) == 0
1513 && (STREQ (control_info
[i
].name
, "eof")
1514 || STREQ (control_info
[i
].name
, "eol")))
1519 wrapf ("%s = %s;", control_info
[i
].name
,
1520 visible (mode
->c_cc
[control_info
[i
].offset
]));
1522 if ((mode
->c_lflag
& ICANON
) == 0)
1524 wrapf ("min = %lu; time = %lu;\n",
1525 (unsigned long int) mode
->c_cc
[VMIN
],
1526 (unsigned long int) mode
->c_cc
[VTIME
]);
1528 else if (!empty_line
)
1533 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1535 if (mode_info
[i
].flags
& OMIT
)
1537 if (mode_info
[i
].type
!= prev_type
)
1545 prev_type
= mode_info
[i
].type
;
1548 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1549 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1551 /* bitsp would be NULL only for "combination" modes, yet those
1552 are filtered out above via the OMIT flag. Tell static analysis
1553 tools that it's ok to dereference bitsp here. */
1556 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1558 if (mode_info
[i
].flags
& SANE_UNSET
)
1560 wrapf ("%s", mode_info
[i
].name
);
1564 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1566 wrapf ("-%s", mode_info
[i
].name
);
1576 display_all (struct termios
*mode
, char const *device_name
)
1581 enum mode_type prev_type
= control
;
1583 display_speed (mode
, true);
1585 display_window_size (true, device_name
);
1588 wrapf ("line = %d;", mode
->c_line
);
1593 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
1595 /* If swtch is the same as susp, don't print both. */
1597 if (STREQ (control_info
[i
].name
, "swtch"))
1600 /* If eof uses the same slot as min, only print whichever applies. */
1602 if ((mode
->c_lflag
& ICANON
) == 0
1603 && (STREQ (control_info
[i
].name
, "eof")
1604 || STREQ (control_info
[i
].name
, "eol")))
1607 wrapf ("%s = %s;", control_info
[i
].name
,
1608 visible (mode
->c_cc
[control_info
[i
].offset
]));
1611 if ((mode
->c_lflag
& ICANON
) == 0)
1613 wrapf ("min = %lu; time = %lu;",
1614 (unsigned long int) mode
->c_cc
[VMIN
],
1615 (unsigned long int) mode
->c_cc
[VTIME
]);
1616 if (current_col
!= 0)
1620 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1622 if (mode_info
[i
].flags
& OMIT
)
1624 if (mode_info
[i
].type
!= prev_type
)
1628 prev_type
= mode_info
[i
].type
;
1631 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1632 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1633 assert (bitsp
); /* See the identical assertion and comment above. */
1634 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1635 wrapf ("%s", mode_info
[i
].name
);
1636 else if (mode_info
[i
].flags
& REV
)
1637 wrapf ("-%s", mode_info
[i
].name
);
1644 display_speed (struct termios
*mode
, bool fancy
)
1646 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1647 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1648 baud_to_value (cfgetospeed (mode
)));
1650 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1651 baud_to_value (cfgetispeed (mode
)),
1652 baud_to_value (cfgetospeed (mode
)));
1658 display_recoverable (struct termios
*mode
)
1662 printf ("%lx:%lx:%lx:%lx",
1663 (unsigned long int) mode
->c_iflag
,
1664 (unsigned long int) mode
->c_oflag
,
1665 (unsigned long int) mode
->c_cflag
,
1666 (unsigned long int) mode
->c_lflag
);
1667 for (i
= 0; i
< NCCS
; ++i
)
1668 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
1672 /* NOTE: identical to below, modulo use of tcflag_t */
1674 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
1679 ul
= strtoul (s
, p
, base
);
1680 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
1686 /* NOTE: identical to above, modulo use of cc_t */
1688 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
1692 ul
= strtoul (s
, p
, base
);
1693 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
1699 /* Parse the output of display_recoverable.
1700 Return false if any part of it is invalid. */
1702 recover_mode (char const *arg
, struct termios
*mode
)
1705 char const *s
= arg
;
1707 for (i
= 0; i
< 4; i
++)
1710 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
1714 mode
->c_iflag
= flag
[0];
1715 mode
->c_oflag
= flag
[1];
1716 mode
->c_cflag
= flag
[2];
1717 mode
->c_lflag
= flag
[3];
1719 for (i
= 0; i
< NCCS
; ++i
)
1722 char delim
= i
< NCCS
- 1 ? ':' : '\0';
1723 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
1733 const char *string
; /* ASCII representation. */
1734 speed_t speed
; /* Internal form. */
1735 unsigned long int value
; /* Numeric value. */
1738 static struct speed_map
const speeds
[] =
1745 {"134.5", B134
, 134},
1750 {"1200", B1200
, 1200},
1751 {"1800", B1800
, 1800},
1752 {"2400", B2400
, 2400},
1753 {"4800", B4800
, 4800},
1754 {"9600", B9600
, 9600},
1755 {"19200", B19200
, 19200},
1756 {"38400", B38400
, 38400},
1757 {"exta", B19200
, 19200},
1758 {"extb", B38400
, 38400},
1760 {"57600", B57600
, 57600},
1763 {"115200", B115200
, 115200},
1766 {"230400", B230400
, 230400},
1769 {"460800", B460800
, 460800},
1772 {"500000", B500000
, 500000},
1775 {"576000", B576000
, 576000},
1778 {"921600", B921600
, 921600},
1781 {"1000000", B1000000
, 1000000},
1784 {"1152000", B1152000
, 1152000},
1787 {"1500000", B1500000
, 1500000},
1790 {"2000000", B2000000
, 2000000},
1793 {"2500000", B2500000
, 2500000},
1796 {"3000000", B3000000
, 3000000},
1799 {"3500000", B3500000
, 3500000},
1802 {"4000000", B4000000
, 4000000},
1807 static speed_t _GL_ATTRIBUTE_PURE
1808 string_to_baud (const char *arg
)
1812 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1813 if (STREQ (arg
, speeds
[i
].string
))
1814 return speeds
[i
].speed
;
1815 return (speed_t
) -1;
1818 static unsigned long int _GL_ATTRIBUTE_PURE
1819 baud_to_value (speed_t speed
)
1823 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1824 if (speed
== speeds
[i
].speed
)
1825 return speeds
[i
].value
;
1830 sane_mode (struct termios
*mode
)
1835 for (i
= 0; control_info
[i
].name
; ++i
)
1838 if (STREQ (control_info
[i
].name
, "min"))
1841 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1844 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1846 if (mode_info
[i
].flags
& SANE_SET
)
1848 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1849 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1851 else if (mode_info
[i
].flags
& SANE_UNSET
)
1853 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1854 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1859 /* Return a string that is the printable representation of character CH. */
1860 /* Adapted from 'cat' by Torbjorn Granlund. */
1865 static char buf
[10];
1868 if (ch
== _POSIX_VDISABLE
)
1887 *bpout
++ = ch
- 128;
1897 *bpout
++ = ch
- 128 + 64;
1907 return (const char *) buf
;
1910 /* Parse string S as an integer, using decimal radix by default,
1911 but allowing octal and hex numbers as in C. Reject values
1912 larger than MAXVAL. */
1914 static unsigned long int
1915 integer_arg (const char *s
, unsigned long int maxval
)
1917 unsigned long int value
;
1918 if (xstrtoul (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
|| maxval
< value
)
1920 error (0, 0, _("invalid integer argument %s"), quote (s
));
1921 usage (EXIT_FAILURE
);