1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2005, 2007-2012 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
58 #include "fd-reopen.h"
62 /* The official name of this program (e.g., no 'g' prefix). */
63 #define PROGRAM_NAME "stty"
65 #define AUTHORS proper_name ("David MacKenzie")
67 #ifndef _POSIX_VDISABLE
68 # define _POSIX_VDISABLE 0
71 #define Control(c) ((c) & 0x1f)
72 /* Canonical values for control characters. */
74 # define CINTR Control ('c')
83 # define CKILL Control ('u')
86 # define CEOF Control ('d')
89 # define CEOL _POSIX_VDISABLE
92 # define CSTART Control ('q')
95 # define CSTOP Control ('s')
98 # define CSUSP Control ('z')
100 #if defined VEOL2 && !defined CEOL2
101 # define CEOL2 _POSIX_VDISABLE
103 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
104 character is initialized by CSWTCH, if present. */
105 #if defined VSWTC && !defined VSWTCH
106 # define VSWTCH VSWTC
108 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
109 #if defined VSUSP && !defined VSWTCH
110 # define VSWTCH VSUSP
111 # if defined CSUSP && !defined CSWTCH
112 # define CSWTCH CSUSP
115 #if defined VSWTCH && !defined CSWTCH
116 # define CSWTCH _POSIX_VDISABLE
119 /* SunOS 5.3 loses (^Z doesn't work) if 'swtch' is the same as 'susp'.
120 So the default is to disable 'swtch.' */
121 #if defined __sparc__ && defined __svr4__
123 # define CSWTCH _POSIX_VDISABLE
126 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
127 # define VWERASE VWERSE
129 #if defined VDSUSP && !defined CDSUSP
130 # define CDSUSP Control ('y')
132 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
133 # define VREPRINT VRPRNT
135 #if defined VREPRINT && !defined CRPRNT
136 # define CRPRNT Control ('r')
138 #if defined CREPRINT && !defined CRPRNT
139 # define CRPRNT Control ('r')
141 #if defined VWERASE && !defined CWERASE
142 # define CWERASE Control ('w')
144 #if defined VLNEXT && !defined CLNEXT
145 # define CLNEXT Control ('v')
147 #if defined VDISCARD && !defined VFLUSHO
148 # define VFLUSHO VDISCARD
150 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
151 # define VFLUSHO VFLUSH
153 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
154 # define ECHOCTL CTLECH
156 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
157 # define ECHOCTL TCTLECH
159 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
160 # define ECHOKE CRTKIL
162 #if defined VFLUSHO && !defined CFLUSHO
163 # define CFLUSHO Control ('o')
165 #if defined VSTATUS && !defined CSTATUS
166 # define CSTATUS Control ('t')
169 /* Which speeds to set. */
172 input_speed
, output_speed
, both_speeds
175 /* What to output and how. */
178 changed
, all
, recoverable
/* Default, -a, -g. */
181 /* Which member(s) of 'struct termios' a mode uses. */
184 control
, input
, output
, local
, combination
187 /* Flags for 'struct mode_info'. */
188 #define SANE_SET 1 /* Set in 'sane' mode. */
189 #define SANE_UNSET 2 /* Unset in 'sane' mode. */
190 #define REV 4 /* Can be turned off by prepending '-'. */
191 #define OMIT 8 /* Don't display value. */
196 const char *name
; /* Name given on command line. */
197 enum mode_type type
; /* Which structure element to change. */
198 char flags
; /* Setting and display options. */
199 unsigned long bits
; /* Bits to set for this mode. */
200 unsigned long mask
; /* Other bits to turn off for this mode. */
203 static struct mode_info
const mode_info
[] =
205 {"parenb", control
, REV
, PARENB
, 0},
206 {"parodd", control
, REV
, PARODD
, 0},
207 {"cs5", control
, 0, CS5
, CSIZE
},
208 {"cs6", control
, 0, CS6
, CSIZE
},
209 {"cs7", control
, 0, CS7
, CSIZE
},
210 {"cs8", control
, 0, CS8
, CSIZE
},
211 {"hupcl", control
, REV
, HUPCL
, 0},
212 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
213 {"cstopb", control
, REV
, CSTOPB
, 0},
214 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
215 {"clocal", control
, REV
, CLOCAL
, 0},
217 {"crtscts", control
, REV
, CRTSCTS
, 0},
220 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
221 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
222 {"ignpar", input
, REV
, IGNPAR
, 0},
223 {"parmrk", input
, REV
, PARMRK
, 0},
224 {"inpck", input
, REV
, INPCK
, 0},
225 {"istrip", input
, REV
, ISTRIP
, 0},
226 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
227 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
228 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
229 {"ixon", input
, REV
, IXON
, 0},
230 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
231 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
233 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
236 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
239 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
242 {"iutf8", input
, SANE_UNSET
| REV
, IUTF8
, 0},
245 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
247 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
250 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
253 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
256 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
259 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
262 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
265 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
268 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
269 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
272 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
273 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
274 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
275 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
279 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
282 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
285 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
288 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
292 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
296 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
297 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
300 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
301 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
304 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
305 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
308 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
309 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
311 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
313 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
314 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
315 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
316 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
317 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
318 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
320 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
323 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
326 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
327 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
330 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
331 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
334 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
335 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
338 {"evenp", combination
, REV
| OMIT
, 0, 0},
339 {"parity", combination
, REV
| OMIT
, 0, 0},
340 {"oddp", combination
, REV
| OMIT
, 0, 0},
341 {"nl", combination
, REV
| OMIT
, 0, 0},
342 {"ek", combination
, OMIT
, 0, 0},
343 {"sane", combination
, OMIT
, 0, 0},
344 {"cooked", combination
, REV
| OMIT
, 0, 0},
345 {"raw", combination
, REV
| OMIT
, 0, 0},
346 {"pass8", combination
, REV
| OMIT
, 0, 0},
347 {"litout", combination
, REV
| OMIT
, 0, 0},
348 {"cbreak", combination
, REV
| OMIT
, 0, 0},
350 {"decctlq", combination
, REV
| OMIT
, 0, 0},
352 #if defined TABDLY || defined OXTABS
353 {"tabs", combination
, REV
| OMIT
, 0, 0},
355 #if defined XCASE && defined IUCLC && defined OLCUC
356 {"lcase", combination
, REV
| OMIT
, 0, 0},
357 {"LCASE", combination
, REV
| OMIT
, 0, 0},
359 {"crt", combination
, OMIT
, 0, 0},
360 {"dec", combination
, OMIT
, 0, 0},
362 {NULL
, control
, 0, 0, 0}
365 /* Control character settings. */
368 const char *name
; /* Name given on command line. */
369 cc_t saneval
; /* Value to set for 'stty sane'. */
370 size_t offset
; /* Offset in c_cc. */
373 /* Control characters. */
375 static struct control_info
const control_info
[] =
377 {"intr", CINTR
, VINTR
},
378 {"quit", CQUIT
, VQUIT
},
379 {"erase", CERASE
, VERASE
},
380 {"kill", CKILL
, VKILL
},
384 {"eol2", CEOL2
, VEOL2
},
387 {"swtch", CSWTCH
, VSWTCH
},
389 {"start", CSTART
, VSTART
},
390 {"stop", CSTOP
, VSTOP
},
391 {"susp", CSUSP
, VSUSP
},
393 {"dsusp", CDSUSP
, VDSUSP
},
396 {"rprnt", CRPRNT
, VREPRINT
},
398 # ifdef CREPRINT /* HPUX 10.20 needs this */
399 {"rprnt", CRPRNT
, CREPRINT
},
403 {"werase", CWERASE
, VWERASE
},
406 {"lnext", CLNEXT
, VLNEXT
},
409 {"flush", CFLUSHO
, VFLUSHO
},
412 {"status", CSTATUS
, VSTATUS
},
415 /* These must be last because of the display routines. */
421 static char const *visible (cc_t ch
);
422 static unsigned long int baud_to_value (speed_t speed
);
423 static bool recover_mode (char const *arg
, struct termios
*mode
);
424 static int screen_columns (void);
425 static bool set_mode (struct mode_info
const *info
, bool reversed
,
426 struct termios
*mode
);
427 static unsigned long int integer_arg (const char *s
, unsigned long int max
);
428 static speed_t
string_to_baud (const char *arg
);
429 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
430 static void display_all (struct termios
*mode
, char const *device_name
);
431 static void display_changed (struct termios
*mode
);
432 static void display_recoverable (struct termios
*mode
);
433 static void display_settings (enum output_type output_type
,
434 struct termios
*mode
,
435 const char *device_name
);
436 static void display_speed (struct termios
*mode
, bool fancy
);
437 static void display_window_size (bool fancy
, char const *device_name
);
438 static void sane_mode (struct termios
*mode
);
439 static void set_control_char (struct control_info
const *info
,
441 struct termios
*mode
);
442 static void set_speed (enum speed_setting type
, const char *arg
,
443 struct termios
*mode
);
444 static void set_window_size (int rows
, int cols
, char const *device_name
);
446 /* The width of the screen, for output wrapping. */
449 /* Current position, to know when to wrap. */
450 static int current_col
;
452 static struct option
const longopts
[] =
454 {"all", no_argument
, NULL
, 'a'},
455 {"save", no_argument
, NULL
, 'g'},
456 {"file", required_argument
, NULL
, 'F'},
457 {GETOPT_HELP_OPTION_DECL
},
458 {GETOPT_VERSION_OPTION_DECL
},
462 static void wrapf (const char *message
, ...)
463 __attribute__ ((__format__ (__printf__
, 1, 2)));
465 /* Print format string MESSAGE and optional args.
466 Wrap to next line first if it won't fit.
467 Print a space first unless MESSAGE will start a new line. */
470 wrapf (const char *message
,...)
476 va_start (args
, message
);
477 buflen
= vasprintf (&buf
, message
, args
);
485 if (max_col
- current_col
< buflen
)
499 current_col
+= buflen
;
505 if (status
!= EXIT_SUCCESS
)
510 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
511 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
512 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
514 program_name
, program_name
, program_name
);
516 Print or change terminal characteristics.\n\
518 -a, --all print all current settings in human-readable form\n\
519 -g, --save print all current settings in a stty-readable form\n\
520 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
522 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
523 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
526 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
527 settings. The underlying system defines which settings are available.\n\
531 Special characters:\n\
532 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
533 eof CHAR CHAR will send an end of file (terminate the input)\n\
534 eol CHAR CHAR will end the line\n\
537 * eol2 CHAR alternate CHAR for ending the line\n\
538 erase CHAR CHAR will erase the last character typed\n\
539 intr CHAR CHAR will send an interrupt signal\n\
540 kill CHAR CHAR will erase the current line\n\
543 * lnext CHAR CHAR will enter the next character quoted\n\
544 quit CHAR CHAR will send a quit signal\n\
545 * rprnt CHAR CHAR will redraw the current line\n\
546 start CHAR CHAR will restart the output after stopping it\n\
549 stop CHAR CHAR will stop the output\n\
550 susp CHAR CHAR will send a terminal stop signal\n\
551 * swtch CHAR CHAR will switch to a different shell layer\n\
552 * werase CHAR CHAR will erase the last word typed\n\
557 N set the input and output speeds to N bauds\n\
558 * cols N tell the kernel that the terminal has N columns\n\
559 * columns N same as cols N\n\
562 ispeed N set the input speed to N\n\
563 * line N use line discipline N\n\
564 min N with -icanon, set N characters minimum for a completed read\n\
565 ospeed N set the output speed to N\n\
568 * rows N tell the kernel that the terminal has N rows\n\
569 * size print the number of rows and columns according to the kernel\n\
570 speed print the terminal speed\n\
571 time N with -icanon, set read timeout of N tenths of a second\n\
576 [-]clocal disable modem control signals\n\
577 [-]cread allow input to be received\n\
578 * [-]crtscts enable RTS/CTS handshaking\n\
579 csN set character size to N bits, N in [5..8]\n\
582 [-]cstopb use two stop bits per character (one with '-')\n\
583 [-]hup send a hangup signal when the last process closes the tty\n\
584 [-]hupcl same as [-]hup\n\
585 [-]parenb generate parity bit in output and expect parity bit in input\n\
586 [-]parodd set odd parity (even with '-')\n\
591 [-]brkint breaks cause an interrupt signal\n\
592 [-]icrnl translate carriage return to newline\n\
593 [-]ignbrk ignore break characters\n\
594 [-]igncr ignore carriage return\n\
597 [-]ignpar ignore characters with parity errors\n\
598 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
599 [-]inlcr translate newline to carriage return\n\
600 [-]inpck enable input parity checking\n\
601 [-]istrip clear high (8th) bit of input characters\n\
604 * [-]iutf8 assume input characters are UTF-8 encoded\n\
607 * [-]iuclc translate uppercase characters to lowercase\n\
608 * [-]ixany let any character restart output, not only start character\n\
609 [-]ixoff enable sending of start/stop characters\n\
610 [-]ixon enable XON/XOFF flow control\n\
611 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
612 [-]tandem same as [-]ixoff\n\
617 * bsN backspace delay style, N in [0..1]\n\
618 * crN carriage return delay style, N in [0..3]\n\
619 * ffN form feed delay style, N in [0..1]\n\
620 * nlN newline delay style, N in [0..1]\n\
623 * [-]ocrnl translate carriage return to newline\n\
624 * [-]ofdel use delete characters for fill instead of null characters\n\
625 * [-]ofill use fill (padding) characters instead of timing for delays\n\
626 * [-]olcuc translate lowercase characters to uppercase\n\
627 * [-]onlcr translate newline to carriage return-newline\n\
628 * [-]onlret newline performs a carriage return\n\
631 * [-]onocr do not print carriage returns in the first column\n\
632 [-]opost postprocess output\n\
633 * tabN horizontal tab delay style, N in [0..3]\n\
634 * tabs same as tab0\n\
635 * -tabs same as tab3\n\
636 * vtN vertical tab delay style, N in [0..1]\n\
641 [-]crterase echo erase characters as backspace-space-backspace\n\
642 * crtkill kill all line by obeying the echoprt and echoe settings\n\
643 * -crtkill kill all line by obeying the echoctl and echok settings\n\
646 * [-]ctlecho echo control characters in hat notation ('^c')\n\
647 [-]echo echo input characters\n\
648 * [-]echoctl same as [-]ctlecho\n\
649 [-]echoe same as [-]crterase\n\
650 [-]echok echo a newline after a kill character\n\
653 * [-]echoke same as [-]crtkill\n\
654 [-]echonl echo newline even if not echoing other characters\n\
655 * [-]echoprt echo erased characters backward, between '\\' and '/'\n\
656 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
657 [-]iexten enable non-POSIX special characters\n\
660 [-]isig enable interrupt, quit, and suspend special characters\n\
661 [-]noflsh disable flushing after interrupt and quit special characters\n\
662 * [-]prterase same as [-]echoprt\n\
663 * [-]tostop stop background jobs that try to write to the terminal\n\
664 * [-]xcase with icanon, escape with '\\' for uppercase characters\n\
668 Combination settings:\n\
669 * [-]LCASE same as [-]lcase\n\
670 cbreak same as -icanon\n\
671 -cbreak same as icanon\n\
674 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
675 icanon, eof and eol characters to their default values\n\
676 -cooked same as raw\n\
677 crt same as echoe echoctl echoke\n\
680 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
682 * [-]decctlq same as [-]ixany\n\
683 ek erase and kill characters to their default values\n\
684 evenp same as parenb -parodd cs7\n\
687 -evenp same as -parenb cs8\n\
688 * [-]lcase same as xcase iuclc olcuc\n\
689 litout same as -parenb -istrip -opost cs8\n\
690 -litout same as parenb istrip opost cs7\n\
691 nl same as -icrnl -onlcr\n\
692 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
695 oddp same as parenb parodd cs7\n\
696 -oddp same as -parenb cs8\n\
697 [-]parity same as [-]evenp\n\
698 pass8 same as -parenb -istrip cs8\n\
699 -pass8 same as parenb istrip cs7\n\
702 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
703 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
704 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
705 -raw same as cooked\n\
708 sane same as cread -ignbrk brkint -inlcr -igncr icrnl -iutf8\n\
709 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
710 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
711 isig icanon iexten echo echoe echok -echonl -noflsh\n\
712 -xcase -tostop -echoprt echoctl echoke, all special\n\
713 characters to their default values\n\
717 Handle the tty line connected to standard input. Without arguments,\n\
718 prints baud rate, line discipline, and deviations from stty sane. In\n\
719 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
720 127; special values ^- or undef used to disable special characters.\n\
722 emit_ancillary_info ();
728 main (int argc
, char **argv
)
730 /* Initialize to all zeroes so there is no risk memcmp will report a
731 spurious difference in an uninitialized portion of the structure. */
732 struct termios mode
= { 0, };
734 enum output_type output_type
;
738 bool require_set_attr
;
741 bool recoverable_output
;
744 char *file_name
= NULL
;
745 const char *device_name
;
747 initialize_main (&argc
, &argv
);
748 set_program_name (argv
[0]);
749 setlocale (LC_ALL
, "");
750 bindtextdomain (PACKAGE
, LOCALEDIR
);
751 textdomain (PACKAGE
);
753 atexit (close_stdout
);
755 output_type
= changed
;
756 verbose_output
= false;
757 recoverable_output
= false;
759 /* Don't print error messages for unrecognized options. */
762 /* If any new options are ever added to stty, the short options MUST
763 NOT allow any ambiguity with the stty settings. For example, the
764 stty setting "-gagFork" would not be feasible, since it will be
765 parsed as "-g -a -g -F ork". If you change anything about how
766 stty parses options, be sure it still works with combinations of
767 short and long options, --, POSIXLY_CORRECT, etc. */
769 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
776 verbose_output
= true;
781 recoverable_output
= true;
782 output_type
= recoverable
;
787 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
791 case_GETOPT_HELP_CHAR
;
793 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
798 /* Skip the argument containing this unrecognized option;
799 the 2nd pass will analyze it. */
802 /* Restart getopt_long from the first unskipped argument. */
809 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
810 while (opti
< optind
)
811 argv
[argi
+ opti
++] = NULL
;
814 /* Specifying both -a and -g gets an error. */
815 if (verbose_output
&& recoverable_output
)
816 error (EXIT_FAILURE
, 0,
817 _("the options for verbose and stty-readable output styles are\n"
818 "mutually exclusive"));
820 /* Specifying any other arguments with -a or -g gets an error. */
821 if (!noargs
&& (verbose_output
|| recoverable_output
))
822 error (EXIT_FAILURE
, 0,
823 _("when specifying an output style, modes may not be set"));
825 /* FIXME: it'd be better not to open the file until we've verified
826 that all arguments are valid. Otherwise, we could end up doing
827 only some of the requested operations and then failing, probably
828 leaving things in an undesirable state. */
833 device_name
= file_name
;
834 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
835 error (EXIT_FAILURE
, errno
, "%s", device_name
);
836 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
837 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
838 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
842 device_name
= _("standard input");
844 if (tcgetattr (STDIN_FILENO
, &mode
))
845 error (EXIT_FAILURE
, errno
, "%s", device_name
);
847 if (verbose_output
|| recoverable_output
|| noargs
)
849 max_col
= screen_columns ();
851 display_settings (output_type
, &mode
, device_name
);
855 speed_was_set
= false;
856 require_set_attr
= false;
857 for (k
= 1; k
< argc
; k
++)
859 char const *arg
= argv
[k
];
860 bool match_found
= false;
861 bool reversed
= false;
872 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
874 if (STREQ (arg
, mode_info
[i
].name
))
876 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
877 require_set_attr
= true;
881 if (!match_found
&& reversed
)
883 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
884 usage (EXIT_FAILURE
);
888 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
890 if (STREQ (arg
, control_info
[i
].name
))
894 error (0, 0, _("missing argument to %s"), quote (arg
));
895 usage (EXIT_FAILURE
);
899 set_control_char (&control_info
[i
], argv
[k
], &mode
);
900 require_set_attr
= true;
907 if (STREQ (arg
, "ispeed"))
911 error (0, 0, _("missing argument to %s"), quote (arg
));
912 usage (EXIT_FAILURE
);
915 set_speed (input_speed
, argv
[k
], &mode
);
916 speed_was_set
= true;
917 require_set_attr
= true;
919 else if (STREQ (arg
, "ospeed"))
923 error (0, 0, _("missing argument to %s"), quote (arg
));
924 usage (EXIT_FAILURE
);
927 set_speed (output_speed
, argv
[k
], &mode
);
928 speed_was_set
= true;
929 require_set_attr
= true;
932 else if (STREQ (arg
, "rows"))
936 error (0, 0, _("missing argument to %s"), quote (arg
));
937 usage (EXIT_FAILURE
);
940 set_window_size (integer_arg (argv
[k
], INT_MAX
), -1,
943 else if (STREQ (arg
, "cols")
944 || STREQ (arg
, "columns"))
948 error (0, 0, _("missing argument to %s"), quote (arg
));
949 usage (EXIT_FAILURE
);
952 set_window_size (-1, integer_arg (argv
[k
], INT_MAX
),
955 else if (STREQ (arg
, "size"))
957 max_col
= screen_columns ();
959 display_window_size (false, device_name
);
963 else if (STREQ (arg
, "line"))
965 unsigned long int value
;
968 error (0, 0, _("missing argument to %s"), quote (arg
));
969 usage (EXIT_FAILURE
);
972 mode
.c_line
= value
= integer_arg (argv
[k
], ULONG_MAX
);
973 if (mode
.c_line
!= value
)
974 error (0, 0, _("invalid line discipline %s"), quote (argv
[k
]));
975 require_set_attr
= true;
978 else if (STREQ (arg
, "speed"))
980 max_col
= screen_columns ();
981 display_speed (&mode
, false);
983 else if (string_to_baud (arg
) != (speed_t
) -1)
985 set_speed (both_speeds
, arg
, &mode
);
986 speed_was_set
= true;
987 require_set_attr
= true;
991 if (! recover_mode (arg
, &mode
))
993 error (0, 0, _("invalid argument %s"), quote (arg
));
994 usage (EXIT_FAILURE
);
996 require_set_attr
= true;
1001 if (require_set_attr
)
1003 /* Initialize to all zeroes so there is no risk memcmp will report a
1004 spurious difference in an uninitialized portion of the structure. */
1005 struct termios new_mode
= { 0, };
1007 if (tcsetattr (STDIN_FILENO
, TCSADRAIN
, &mode
))
1008 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1010 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1011 it performs *any* of the requested operations. This means it
1012 can report 'success' when it has actually failed to perform
1013 some proper subset of the requested operations. To detect
1014 this partial failure, get the current terminal attributes and
1015 compare them to the requested ones. */
1017 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1018 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1020 /* Normally, one shouldn't use memcmp to compare structures that
1021 may have 'holes' containing uninitialized data, but we have been
1022 careful to initialize the storage of these two variables to all
1023 zeroes. One might think it more efficient simply to compare the
1024 modified fields, but that would require enumerating those fields --
1025 and not all systems have the same fields in this structure. */
1027 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1030 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1031 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1032 sometimes (m1 != m2). The only difference is in the four bits
1033 of the c_cflag field corresponding to the baud rate. To save
1034 Sun users a little confusion, don't report an error if this
1035 happens. But suppress the error only if we haven't tried to
1036 set the baud rate explicitly -- otherwise we'd never give an
1037 error for a true failure to set the baud rate. */
1039 new_mode
.c_cflag
&= (~CIBAUD
);
1040 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1043 error (EXIT_FAILURE
, 0,
1044 _("%s: unable to perform all requested operations"),
1049 printf ("new_mode: mode\n");
1050 for (i
= 0; i
< sizeof (new_mode
); i
++)
1051 printf ("0x%02x: 0x%02x\n",
1052 *(((unsigned char *) &new_mode
) + i
),
1053 *(((unsigned char *) &mode
) + i
));
1060 exit (EXIT_SUCCESS
);
1063 /* Return false if not applied because not reversible; otherwise
1067 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1071 if (reversed
&& (info
->flags
& REV
) == 0)
1074 bitsp
= mode_type_flag (info
->type
, mode
);
1078 /* Combination mode. */
1079 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1082 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1084 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1086 else if (STREQ (info
->name
, "oddp"))
1089 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1091 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1093 else if (STREQ (info
->name
, "nl"))
1097 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1098 mode
->c_oflag
= (mode
->c_oflag
1113 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1115 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1119 else if (STREQ (info
->name
, "ek"))
1121 mode
->c_cc
[VERASE
] = CERASE
;
1122 mode
->c_cc
[VKILL
] = CKILL
;
1124 else if (STREQ (info
->name
, "sane"))
1126 else if (STREQ (info
->name
, "cbreak"))
1129 mode
->c_lflag
|= ICANON
;
1131 mode
->c_lflag
&= ~ICANON
;
1133 else if (STREQ (info
->name
, "pass8"))
1137 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1138 mode
->c_iflag
|= ISTRIP
;
1142 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1143 mode
->c_iflag
&= ~ISTRIP
;
1146 else if (STREQ (info
->name
, "litout"))
1150 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1151 mode
->c_iflag
|= ISTRIP
;
1152 mode
->c_oflag
|= OPOST
;
1156 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1157 mode
->c_iflag
&= ~ISTRIP
;
1158 mode
->c_oflag
&= ~OPOST
;
1161 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1163 if ((info
->name
[0] == 'r' && reversed
)
1164 || (info
->name
[0] == 'c' && !reversed
))
1167 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1168 mode
->c_oflag
|= OPOST
;
1169 mode
->c_lflag
|= ISIG
| ICANON
;
1171 mode
->c_cc
[VEOF
] = CEOF
;
1174 mode
->c_cc
[VEOL
] = CEOL
;
1181 mode
->c_oflag
&= ~OPOST
;
1182 mode
->c_lflag
&= ~(ISIG
| ICANON
1187 mode
->c_cc
[VMIN
] = 1;
1188 mode
->c_cc
[VTIME
] = 0;
1192 else if (STREQ (info
->name
, "decctlq"))
1195 mode
->c_iflag
|= IXANY
;
1197 mode
->c_iflag
&= ~IXANY
;
1201 else if (STREQ (info
->name
, "tabs"))
1204 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1206 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1210 else if (STREQ (info
->name
, "tabs"))
1213 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1215 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1219 #if defined XCASE && defined IUCLC && defined OLCUC
1220 else if (STREQ (info
->name
, "lcase")
1221 || STREQ (info
->name
, "LCASE"))
1225 mode
->c_lflag
&= ~XCASE
;
1226 mode
->c_iflag
&= ~IUCLC
;
1227 mode
->c_oflag
&= ~OLCUC
;
1231 mode
->c_lflag
|= XCASE
;
1232 mode
->c_iflag
|= IUCLC
;
1233 mode
->c_oflag
|= OLCUC
;
1237 else if (STREQ (info
->name
, "crt"))
1238 mode
->c_lflag
|= ECHOE
1246 else if (STREQ (info
->name
, "dec"))
1248 mode
->c_cc
[VINTR
] = 3; /* ^C */
1249 mode
->c_cc
[VERASE
] = 127; /* DEL */
1250 mode
->c_cc
[VKILL
] = 21; /* ^U */
1251 mode
->c_lflag
|= ECHOE
1260 mode
->c_iflag
&= ~IXANY
;
1265 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1267 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1273 set_control_char (struct control_info
const *info
, const char *arg
,
1274 struct termios
*mode
)
1276 unsigned long int value
;
1278 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1279 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1280 else if (arg
[0] == '\0' || arg
[1] == '\0')
1281 value
= to_uchar (arg
[0]);
1282 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1283 value
= _POSIX_VDISABLE
;
1284 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1289 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1292 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1293 mode
->c_cc
[info
->offset
] = value
;
1297 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1301 baud
= string_to_baud (arg
);
1302 if (type
== input_speed
|| type
== both_speeds
)
1303 cfsetispeed (mode
, baud
);
1304 if (type
== output_speed
|| type
== both_speeds
)
1305 cfsetospeed (mode
, baud
);
1311 get_win_size (int fd
, struct winsize
*win
)
1313 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1318 set_window_size (int rows
, int cols
, char const *device_name
)
1322 if (get_win_size (STDIN_FILENO
, &win
))
1324 if (errno
!= EINVAL
)
1325 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1326 memset (&win
, 0, sizeof (win
));
1335 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1336 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1337 This comment from sys/ttold.h describes Sun's twisted logic - a better
1338 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1339 At any rate, the problem is gone in Solaris 2.x.
1341 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1342 but they can be disambiguated by checking whether a "struct ttysize"
1343 structure's "ts_lines" field is greater than 64K or not. If so,
1344 it's almost certainly a "struct winsize" instead.
1346 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1347 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1348 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1349 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1350 "stty cols 0 rows 0" would do the right thing. On a little-endian
1351 machine like the sun386i, the problem is the same, but for ws_col == 0.
1353 The workaround is to do the ioctl once with row and col = 1 to set the
1354 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1356 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1358 struct ttysize ttysz
;
1360 ttysz
.ts_lines
= win
.ws_row
;
1361 ttysz
.ts_cols
= win
.ws_col
;
1366 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1367 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1369 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1370 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1375 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1376 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1380 display_window_size (bool fancy
, char const *device_name
)
1384 if (get_win_size (STDIN_FILENO
, &win
))
1386 if (errno
!= EINVAL
)
1387 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1389 error (EXIT_FAILURE
, 0,
1390 _("%s: no size information for this device"), device_name
);
1394 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1395 win
.ws_row
, win
.ws_col
);
1403 screen_columns (void)
1408 /* With Solaris 2.[123], this ioctl fails and errno is set to
1409 EINVAL for telnet (but not rlogin) sessions.
1410 On ISC 3.0, it fails for the console and the serial port
1411 (but it works for ptys).
1412 It can also fail on any system when stdout isn't a tty.
1413 In case of any failure, just use the default. */
1414 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1418 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1419 char *col_string
= getenv ("COLUMNS");
1421 if (!(col_string
!= NULL
1422 && xstrtol (col_string
, NULL
, 0, &n_columns
, "") == LONGINT_OK
1424 && n_columns
<= INT_MAX
))
1430 static tcflag_t
* _GL_ATTRIBUTE_PURE
1431 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1436 return &mode
->c_cflag
;
1439 return &mode
->c_iflag
;
1442 return &mode
->c_oflag
;
1445 return &mode
->c_lflag
;
1456 display_settings (enum output_type output_type
, struct termios
*mode
,
1457 char const *device_name
)
1459 switch (output_type
)
1462 display_changed (mode
);
1466 display_all (mode
, device_name
);
1470 display_recoverable (mode
);
1476 display_changed (struct termios
*mode
)
1482 enum mode_type prev_type
= control
;
1484 display_speed (mode
, true);
1486 wrapf ("line = %d;", mode
->c_line
);
1492 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1494 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1496 /* If swtch is the same as susp, don't print both. */
1498 if (STREQ (control_info
[i
].name
, "swtch"))
1501 /* If eof uses the same slot as min, only print whichever applies. */
1503 if ((mode
->c_lflag
& ICANON
) == 0
1504 && (STREQ (control_info
[i
].name
, "eof")
1505 || STREQ (control_info
[i
].name
, "eol")))
1510 wrapf ("%s = %s;", control_info
[i
].name
,
1511 visible (mode
->c_cc
[control_info
[i
].offset
]));
1513 if ((mode
->c_lflag
& ICANON
) == 0)
1515 wrapf ("min = %lu; time = %lu;\n",
1516 (unsigned long int) mode
->c_cc
[VMIN
],
1517 (unsigned long int) mode
->c_cc
[VTIME
]);
1519 else if (!empty_line
)
1524 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1526 if (mode_info
[i
].flags
& OMIT
)
1528 if (mode_info
[i
].type
!= prev_type
)
1536 prev_type
= mode_info
[i
].type
;
1539 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1540 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1541 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1543 if (mode_info
[i
].flags
& SANE_UNSET
)
1545 wrapf ("%s", mode_info
[i
].name
);
1549 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1551 wrapf ("-%s", mode_info
[i
].name
);
1561 display_all (struct termios
*mode
, char const *device_name
)
1566 enum mode_type prev_type
= control
;
1568 display_speed (mode
, true);
1570 display_window_size (true, device_name
);
1573 wrapf ("line = %d;", mode
->c_line
);
1578 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
1580 /* If swtch is the same as susp, don't print both. */
1582 if (STREQ (control_info
[i
].name
, "swtch"))
1585 /* If eof uses the same slot as min, only print whichever applies. */
1587 if ((mode
->c_lflag
& ICANON
) == 0
1588 && (STREQ (control_info
[i
].name
, "eof")
1589 || STREQ (control_info
[i
].name
, "eol")))
1592 wrapf ("%s = %s;", control_info
[i
].name
,
1593 visible (mode
->c_cc
[control_info
[i
].offset
]));
1596 if ((mode
->c_lflag
& ICANON
) == 0)
1598 wrapf ("min = %lu; time = %lu;",
1599 (unsigned long int) mode
->c_cc
[VMIN
],
1600 (unsigned long int) mode
->c_cc
[VTIME
]);
1601 if (current_col
!= 0)
1605 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1607 if (mode_info
[i
].flags
& OMIT
)
1609 if (mode_info
[i
].type
!= prev_type
)
1613 prev_type
= mode_info
[i
].type
;
1616 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1617 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1618 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1619 wrapf ("%s", mode_info
[i
].name
);
1620 else if (mode_info
[i
].flags
& REV
)
1621 wrapf ("-%s", mode_info
[i
].name
);
1628 display_speed (struct termios
*mode
, bool fancy
)
1630 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1631 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1632 baud_to_value (cfgetospeed (mode
)));
1634 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1635 baud_to_value (cfgetispeed (mode
)),
1636 baud_to_value (cfgetospeed (mode
)));
1642 display_recoverable (struct termios
*mode
)
1646 printf ("%lx:%lx:%lx:%lx",
1647 (unsigned long int) mode
->c_iflag
,
1648 (unsigned long int) mode
->c_oflag
,
1649 (unsigned long int) mode
->c_cflag
,
1650 (unsigned long int) mode
->c_lflag
);
1651 for (i
= 0; i
< NCCS
; ++i
)
1652 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
1656 /* NOTE: identical to below, modulo use of tcflag_t */
1658 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
1663 ul
= strtoul (s
, p
, base
);
1664 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
1670 /* NOTE: identical to above, modulo use of cc_t */
1672 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
1676 ul
= strtoul (s
, p
, base
);
1677 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
1683 /* Parse the output of display_recoverable.
1684 Return false if any part of it is invalid. */
1686 recover_mode (char const *arg
, struct termios
*mode
)
1689 char const *s
= arg
;
1691 for (i
= 0; i
< 4; i
++)
1694 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
1698 mode
->c_iflag
= flag
[0];
1699 mode
->c_oflag
= flag
[1];
1700 mode
->c_cflag
= flag
[2];
1701 mode
->c_lflag
= flag
[3];
1703 for (i
= 0; i
< NCCS
; ++i
)
1706 char delim
= i
< NCCS
- 1 ? ':' : '\0';
1707 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
1717 const char *string
; /* ASCII representation. */
1718 speed_t speed
; /* Internal form. */
1719 unsigned long int value
; /* Numeric value. */
1722 static struct speed_map
const speeds
[] =
1729 {"134.5", B134
, 134},
1734 {"1200", B1200
, 1200},
1735 {"1800", B1800
, 1800},
1736 {"2400", B2400
, 2400},
1737 {"4800", B4800
, 4800},
1738 {"9600", B9600
, 9600},
1739 {"19200", B19200
, 19200},
1740 {"38400", B38400
, 38400},
1741 {"exta", B19200
, 19200},
1742 {"extb", B38400
, 38400},
1744 {"57600", B57600
, 57600},
1747 {"115200", B115200
, 115200},
1750 {"230400", B230400
, 230400},
1753 {"460800", B460800
, 460800},
1756 {"500000", B500000
, 500000},
1759 {"576000", B576000
, 576000},
1762 {"921600", B921600
, 921600},
1765 {"1000000", B1000000
, 1000000},
1768 {"1152000", B1152000
, 1152000},
1771 {"1500000", B1500000
, 1500000},
1774 {"2000000", B2000000
, 2000000},
1777 {"2500000", B2500000
, 2500000},
1780 {"3000000", B3000000
, 3000000},
1783 {"3500000", B3500000
, 3500000},
1786 {"4000000", B4000000
, 4000000},
1791 static speed_t _GL_ATTRIBUTE_PURE
1792 string_to_baud (const char *arg
)
1796 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1797 if (STREQ (arg
, speeds
[i
].string
))
1798 return speeds
[i
].speed
;
1799 return (speed_t
) -1;
1802 static unsigned long int _GL_ATTRIBUTE_PURE
1803 baud_to_value (speed_t speed
)
1807 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1808 if (speed
== speeds
[i
].speed
)
1809 return speeds
[i
].value
;
1814 sane_mode (struct termios
*mode
)
1819 for (i
= 0; control_info
[i
].name
; ++i
)
1822 if (STREQ (control_info
[i
].name
, "min"))
1825 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1828 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1830 if (mode_info
[i
].flags
& SANE_SET
)
1832 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1833 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1835 else if (mode_info
[i
].flags
& SANE_UNSET
)
1837 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1838 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1843 /* Return a string that is the printable representation of character CH. */
1844 /* Adapted from 'cat' by Torbjorn Granlund. */
1849 static char buf
[10];
1852 if (ch
== _POSIX_VDISABLE
)
1871 *bpout
++ = ch
- 128;
1881 *bpout
++ = ch
- 128 + 64;
1891 return (const char *) buf
;
1894 /* Parse string S as an integer, using decimal radix by default,
1895 but allowing octal and hex numbers as in C. Reject values
1896 larger than MAXVAL. */
1898 static unsigned long int
1899 integer_arg (const char *s
, unsigned long int maxval
)
1901 unsigned long int value
;
1902 if (xstrtoul (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
|| maxval
< value
)
1904 error (0, 0, _("invalid integer argument %s"), quote (s
));
1905 usage (EXIT_FAILURE
);