1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2005, 2007-2010 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>
45 #include <sys/ioctl.h>
47 #ifdef WINSIZE_IN_PTEM
48 # include <sys/stream.h>
49 # include <sys/ptem.h>
51 #ifdef GWINSZ_IN_SYS_PTY
60 #include "fd-reopen.h"
64 /* The official name of this program (e.g., no `g' prefix). */
65 #define PROGRAM_NAME "stty"
67 #define AUTHORS proper_name ("David MacKenzie")
69 #ifndef _POSIX_VDISABLE
70 # define _POSIX_VDISABLE 0
73 #define Control(c) ((c) & 0x1f)
74 /* Canonical values for control characters. */
76 # define CINTR Control ('c')
85 # define CKILL Control ('u')
88 # define CEOF Control ('d')
91 # define CEOL _POSIX_VDISABLE
94 # define CSTART Control ('q')
97 # define CSTOP Control ('s')
100 # define CSUSP Control ('z')
102 #if defined VEOL2 && !defined CEOL2
103 # define CEOL2 _POSIX_VDISABLE
105 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
106 character is initialized by CSWTCH, if present. */
107 #if defined VSWTC && !defined VSWTCH
108 # define VSWTCH VSWTC
110 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
111 #if defined VSUSP && !defined VSWTCH
112 # define VSWTCH VSUSP
113 # if defined CSUSP && !defined CSWTCH
114 # define CSWTCH CSUSP
117 #if defined VSWTCH && !defined CSWTCH
118 # define CSWTCH _POSIX_VDISABLE
121 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
122 So the default is to disable `swtch.' */
123 #if defined __sparc__ && defined __svr4__
125 # define CSWTCH _POSIX_VDISABLE
128 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
129 # define VWERASE VWERSE
131 #if defined VDSUSP && !defined CDSUSP
132 # define CDSUSP Control ('y')
134 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
135 # define VREPRINT VRPRNT
137 #if defined VREPRINT && !defined CRPRNT
138 # define CRPRNT Control ('r')
140 #if defined CREPRINT && !defined CRPRNT
141 # define CRPRNT Control ('r')
143 #if defined VWERASE && !defined CWERASE
144 # define CWERASE Control ('w')
146 #if defined VLNEXT && !defined CLNEXT
147 # define CLNEXT Control ('v')
149 #if defined VDISCARD && !defined VFLUSHO
150 # define VFLUSHO VDISCARD
152 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
153 # define VFLUSHO VFLUSH
155 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
156 # define ECHOCTL CTLECH
158 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
159 # define ECHOCTL TCTLECH
161 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
162 # define ECHOKE CRTKIL
164 #if defined VFLUSHO && !defined CFLUSHO
165 # define CFLUSHO Control ('o')
167 #if defined VSTATUS && !defined CSTATUS
168 # define CSTATUS Control ('t')
171 /* Which speeds to set. */
174 input_speed
, output_speed
, both_speeds
177 /* What to output and how. */
180 changed
, all
, recoverable
/* Default, -a, -g. */
183 /* Which member(s) of `struct termios' a mode uses. */
186 control
, input
, output
, local
, combination
189 /* Flags for `struct mode_info'. */
190 #define SANE_SET 1 /* Set in `sane' mode. */
191 #define SANE_UNSET 2 /* Unset in `sane' mode. */
192 #define REV 4 /* Can be turned off by prepending `-'. */
193 #define OMIT 8 /* Don't display value. */
198 const char *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},
209 {"cs5", control
, 0, CS5
, CSIZE
},
210 {"cs6", control
, 0, CS6
, CSIZE
},
211 {"cs7", control
, 0, CS7
, CSIZE
},
212 {"cs8", control
, 0, CS8
, CSIZE
},
213 {"hupcl", control
, REV
, HUPCL
, 0},
214 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
215 {"cstopb", control
, REV
, CSTOPB
, 0},
216 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
217 {"clocal", control
, REV
, CLOCAL
, 0},
219 {"crtscts", control
, REV
, CRTSCTS
, 0},
222 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
223 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
224 {"ignpar", input
, REV
, IGNPAR
, 0},
225 {"parmrk", input
, REV
, PARMRK
, 0},
226 {"inpck", input
, REV
, INPCK
, 0},
227 {"istrip", input
, REV
, ISTRIP
, 0},
228 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
229 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
230 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
231 {"ixon", input
, REV
, IXON
, 0},
232 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
233 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
235 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
238 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
241 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
244 {"iutf8", input
, SANE_UNSET
| REV
, IUTF8
, 0},
247 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
249 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
252 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
255 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
258 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
261 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
264 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
267 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
270 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
271 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
274 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
275 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
276 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
277 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
281 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
284 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
287 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
290 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
294 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
298 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
299 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
302 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
303 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
306 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
307 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
310 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
311 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
313 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
315 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
316 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
317 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
318 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
319 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
320 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
322 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
325 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
328 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
329 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
332 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
333 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
336 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
337 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
340 {"evenp", combination
, REV
| OMIT
, 0, 0},
341 {"parity", combination
, REV
| OMIT
, 0, 0},
342 {"oddp", combination
, REV
| OMIT
, 0, 0},
343 {"nl", combination
, REV
| OMIT
, 0, 0},
344 {"ek", combination
, OMIT
, 0, 0},
345 {"sane", combination
, OMIT
, 0, 0},
346 {"cooked", combination
, REV
| OMIT
, 0, 0},
347 {"raw", combination
, REV
| OMIT
, 0, 0},
348 {"pass8", combination
, REV
| OMIT
, 0, 0},
349 {"litout", combination
, REV
| OMIT
, 0, 0},
350 {"cbreak", combination
, REV
| OMIT
, 0, 0},
352 {"decctlq", combination
, REV
| OMIT
, 0, 0},
354 #if defined TABDLY || defined OXTABS
355 {"tabs", combination
, REV
| OMIT
, 0, 0},
357 #if defined XCASE && defined IUCLC && defined OLCUC
358 {"lcase", combination
, REV
| OMIT
, 0, 0},
359 {"LCASE", combination
, REV
| OMIT
, 0, 0},
361 {"crt", combination
, OMIT
, 0, 0},
362 {"dec", combination
, OMIT
, 0, 0},
364 {NULL
, control
, 0, 0, 0}
367 /* Control character settings. */
370 const char *name
; /* Name given on command line. */
371 cc_t saneval
; /* Value to set for `stty sane'. */
372 size_t offset
; /* Offset in c_cc. */
375 /* Control characters. */
377 static struct control_info
const control_info
[] =
379 {"intr", CINTR
, VINTR
},
380 {"quit", CQUIT
, VQUIT
},
381 {"erase", CERASE
, VERASE
},
382 {"kill", CKILL
, VKILL
},
386 {"eol2", CEOL2
, VEOL2
},
389 {"swtch", CSWTCH
, VSWTCH
},
391 {"start", CSTART
, VSTART
},
392 {"stop", CSTOP
, VSTOP
},
393 {"susp", CSUSP
, VSUSP
},
395 {"dsusp", CDSUSP
, VDSUSP
},
398 {"rprnt", CRPRNT
, VREPRINT
},
400 # ifdef CREPRINT /* HPUX 10.20 needs this */
401 {"rprnt", CRPRNT
, CREPRINT
},
405 {"werase", CWERASE
, VWERASE
},
408 {"lnext", CLNEXT
, VLNEXT
},
411 {"flush", CFLUSHO
, VFLUSHO
},
414 {"status", CSTATUS
, VSTATUS
},
417 /* These must be last because of the display routines. */
423 static char const *visible (cc_t ch
);
424 static unsigned long int baud_to_value (speed_t speed
);
425 static bool recover_mode (char const *arg
, struct termios
*mode
);
426 static int screen_columns (void);
427 static bool set_mode (struct mode_info
const *info
, bool reversed
,
428 struct termios
*mode
);
429 static unsigned long int integer_arg (const char *s
, unsigned long int max
);
430 static speed_t
string_to_baud (const char *arg
);
431 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
432 static void display_all (struct termios
*mode
, char const *device_name
);
433 static void display_changed (struct termios
*mode
);
434 static void display_recoverable (struct termios
*mode
);
435 static void display_settings (enum output_type output_type
,
436 struct termios
*mode
,
437 const char *device_name
);
438 static void display_speed (struct termios
*mode
, bool fancy
);
439 static void display_window_size (bool fancy
, char const *device_name
);
440 static void sane_mode (struct termios
*mode
);
441 static void set_control_char (struct control_info
const *info
,
443 struct termios
*mode
);
444 static void set_speed (enum speed_setting type
, const char *arg
,
445 struct termios
*mode
);
446 static void set_window_size (int rows
, int cols
, char const *device_name
);
448 /* The width of the screen, for output wrapping. */
451 /* Current position, to know when to wrap. */
452 static int current_col
;
454 static struct option
const longopts
[] =
456 {"all", no_argument
, NULL
, 'a'},
457 {"save", no_argument
, NULL
, 'g'},
458 {"file", required_argument
, NULL
, 'F'},
459 {GETOPT_HELP_OPTION_DECL
},
460 {GETOPT_VERSION_OPTION_DECL
},
464 static void wrapf (const char *message
, ...)
465 __attribute__ ((__format__ (__printf__
, 1, 2)));
467 /* Print format string MESSAGE and optional args.
468 Wrap to next line first if it won't fit.
469 Print a space first unless MESSAGE will start a new line. */
472 wrapf (const char *message
,...)
478 va_start (args
, message
);
479 buflen
= vasprintf (&buf
, message
, args
);
487 if (max_col
- current_col
< buflen
)
501 current_col
+= buflen
;
507 if (status
!= EXIT_SUCCESS
)
508 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
513 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
514 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
515 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
517 program_name
, program_name
, program_name
);
519 Print or change terminal characteristics.\n\
521 -a, --all print all current settings in human-readable form\n\
522 -g, --save print all current settings in a stty-readable form\n\
523 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
525 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
526 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
529 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
530 settings. The underlying system defines which settings are available.\n\
534 Special characters:\n\
535 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
536 eof CHAR CHAR will send an end of file (terminate the input)\n\
537 eol CHAR CHAR will end the line\n\
540 * eol2 CHAR alternate CHAR for ending the line\n\
541 erase CHAR CHAR will erase the last character typed\n\
542 intr CHAR CHAR will send an interrupt signal\n\
543 kill CHAR CHAR will erase the current line\n\
546 * lnext CHAR CHAR will enter the next character quoted\n\
547 quit CHAR CHAR will send a quit signal\n\
548 * rprnt CHAR CHAR will redraw the current line\n\
549 start CHAR CHAR will restart the output after stopping it\n\
552 stop CHAR CHAR will stop the output\n\
553 susp CHAR CHAR will send a terminal stop signal\n\
554 * swtch CHAR CHAR will switch to a different shell layer\n\
555 * werase CHAR CHAR will erase the last word typed\n\
560 N set the input and output speeds to N bauds\n\
561 * cols N tell the kernel that the terminal has N columns\n\
562 * columns N same as cols N\n\
565 ispeed N set the input speed to N\n\
566 * line N use line discipline N\n\
567 min N with -icanon, set N characters minimum for a completed read\n\
568 ospeed N set the output speed to N\n\
571 * rows N tell the kernel that the terminal has N rows\n\
572 * size print the number of rows and columns according to the kernel\n\
573 speed print the terminal speed\n\
574 time N with -icanon, set read timeout of N tenths of a second\n\
579 [-]clocal disable modem control signals\n\
580 [-]cread allow input to be received\n\
581 * [-]crtscts enable RTS/CTS handshaking\n\
582 csN set character size to N bits, N in [5..8]\n\
585 [-]cstopb use two stop bits per character (one with `-')\n\
586 [-]hup send a hangup signal when the last process closes the tty\n\
587 [-]hupcl same as [-]hup\n\
588 [-]parenb generate parity bit in output and expect parity bit in input\n\
589 [-]parodd set odd parity (even with `-')\n\
594 [-]brkint breaks cause an interrupt signal\n\
595 [-]icrnl translate carriage return to newline\n\
596 [-]ignbrk ignore break characters\n\
597 [-]igncr ignore carriage return\n\
600 [-]ignpar ignore characters with parity errors\n\
601 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
602 [-]inlcr translate newline to carriage return\n\
603 [-]inpck enable input parity checking\n\
604 [-]istrip clear high (8th) bit of input characters\n\
607 * [-]iutf8 assume input characters are UTF-8 encoded\n\
610 * [-]iuclc translate uppercase characters to lowercase\n\
611 * [-]ixany let any character restart output, not only start character\n\
612 [-]ixoff enable sending of start/stop characters\n\
613 [-]ixon enable XON/XOFF flow control\n\
614 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
615 [-]tandem same as [-]ixoff\n\
620 * bsN backspace delay style, N in [0..1]\n\
621 * crN carriage return delay style, N in [0..3]\n\
622 * ffN form feed delay style, N in [0..1]\n\
623 * nlN newline delay style, N in [0..1]\n\
626 * [-]ocrnl translate carriage return to newline\n\
627 * [-]ofdel use delete characters for fill instead of null characters\n\
628 * [-]ofill use fill (padding) characters instead of timing for delays\n\
629 * [-]olcuc translate lowercase characters to uppercase\n\
630 * [-]onlcr translate newline to carriage return-newline\n\
631 * [-]onlret newline performs a carriage return\n\
634 * [-]onocr do not print carriage returns in the first column\n\
635 [-]opost postprocess output\n\
636 * tabN horizontal tab delay style, N in [0..3]\n\
637 * tabs same as tab0\n\
638 * -tabs same as tab3\n\
639 * vtN vertical tab delay style, N in [0..1]\n\
644 [-]crterase echo erase characters as backspace-space-backspace\n\
645 * crtkill kill all line by obeying the echoprt and echoe settings\n\
646 * -crtkill kill all line by obeying the echoctl and echok settings\n\
649 * [-]ctlecho echo control characters in hat notation (`^c')\n\
650 [-]echo echo input characters\n\
651 * [-]echoctl same as [-]ctlecho\n\
652 [-]echoe same as [-]crterase\n\
653 [-]echok echo a newline after a kill character\n\
656 * [-]echoke same as [-]crtkill\n\
657 [-]echonl echo newline even if not echoing other characters\n\
658 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
659 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
660 [-]iexten enable non-POSIX special characters\n\
663 [-]isig enable interrupt, quit, and suspend special characters\n\
664 [-]noflsh disable flushing after interrupt and quit special characters\n\
665 * [-]prterase same as [-]echoprt\n\
666 * [-]tostop stop background jobs that try to write to the terminal\n\
667 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
671 Combination settings:\n\
672 * [-]LCASE same as [-]lcase\n\
673 cbreak same as -icanon\n\
674 -cbreak same as icanon\n\
677 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
678 icanon, eof and eol characters to their default values\n\
679 -cooked same as raw\n\
680 crt same as echoe echoctl echoke\n\
683 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
685 * [-]decctlq same as [-]ixany\n\
686 ek erase and kill characters to their default values\n\
687 evenp same as parenb -parodd cs7\n\
690 -evenp same as -parenb cs8\n\
691 * [-]lcase same as xcase iuclc olcuc\n\
692 litout same as -parenb -istrip -opost cs8\n\
693 -litout same as parenb istrip opost cs7\n\
694 nl same as -icrnl -onlcr\n\
695 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
698 oddp same as parenb parodd cs7\n\
699 -oddp same as -parenb cs8\n\
700 [-]parity same as [-]evenp\n\
701 pass8 same as -parenb -istrip cs8\n\
702 -pass8 same as parenb istrip cs7\n\
705 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
706 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
707 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
708 -raw same as cooked\n\
711 sane same as cread -ignbrk brkint -inlcr -igncr icrnl -iutf8\n\
712 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
713 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
714 isig icanon iexten echo echoe echok -echonl -noflsh\n\
715 -xcase -tostop -echoprt echoctl echoke, all special\n\
716 characters to their default values\n\
720 Handle the tty line connected to standard input. Without arguments,\n\
721 prints baud rate, line discipline, and deviations from stty sane. In\n\
722 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
723 127; special values ^- or undef used to disable special characters.\n\
725 emit_ancillary_info ();
731 main (int argc
, char **argv
)
733 /* Initialize to all zeroes so there is no risk memcmp will report a
734 spurious difference in an uninitialized portion of the structure. */
735 DECLARE_ZEROED_AGGREGATE (struct termios
, mode
);
737 enum output_type output_type
;
741 bool require_set_attr
;
744 bool recoverable_output
;
747 char *file_name
= NULL
;
748 const char *device_name
;
750 initialize_main (&argc
, &argv
);
751 set_program_name (argv
[0]);
752 setlocale (LC_ALL
, "");
753 bindtextdomain (PACKAGE
, LOCALEDIR
);
754 textdomain (PACKAGE
);
756 atexit (close_stdout
);
758 output_type
= changed
;
759 verbose_output
= false;
760 recoverable_output
= false;
762 /* Don't print error messages for unrecognized options. */
765 /* If any new options are ever added to stty, the short options MUST
766 NOT allow any ambiguity with the stty settings. For example, the
767 stty setting "-gagFork" would not be feasible, since it will be
768 parsed as "-g -a -g -F ork". If you change anything about how
769 stty parses options, be sure it still works with combinations of
770 short and long options, --, POSIXLY_CORRECT, etc. */
772 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
779 verbose_output
= true;
784 recoverable_output
= true;
785 output_type
= recoverable
;
790 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
794 case_GETOPT_HELP_CHAR
;
796 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
801 /* Skip the argument containing this unrecognized option;
802 the 2nd pass will analyze it. */
805 /* Restart getopt_long from the first unskipped argument. */
812 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
813 while (opti
< optind
)
814 argv
[argi
+ opti
++] = NULL
;
817 /* Specifying both -a and -g gets an error. */
818 if (verbose_output
&& recoverable_output
)
819 error (EXIT_FAILURE
, 0,
820 _("the options for verbose and stty-readable output styles are\n"
821 "mutually exclusive"));
823 /* Specifying any other arguments with -a or -g gets an error. */
824 if (!noargs
&& (verbose_output
|| recoverable_output
))
825 error (EXIT_FAILURE
, 0,
826 _("when specifying an output style, modes may not be set"));
828 /* FIXME: it'd be better not to open the file until we've verified
829 that all arguments are valid. Otherwise, we could end up doing
830 only some of the requested operations and then failing, probably
831 leaving things in an undesirable state. */
836 device_name
= file_name
;
837 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
838 error (EXIT_FAILURE
, errno
, "%s", device_name
);
839 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
840 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
841 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
845 device_name
= _("standard input");
847 if (tcgetattr (STDIN_FILENO
, &mode
))
848 error (EXIT_FAILURE
, errno
, "%s", device_name
);
850 if (verbose_output
|| recoverable_output
|| noargs
)
852 max_col
= screen_columns ();
854 display_settings (output_type
, &mode
, device_name
);
858 speed_was_set
= false;
859 require_set_attr
= false;
860 for (k
= 1; k
< argc
; k
++)
862 char const *arg
= argv
[k
];
863 bool match_found
= false;
864 bool reversed
= false;
875 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
877 if (STREQ (arg
, mode_info
[i
].name
))
879 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
880 require_set_attr
= true;
884 if (!match_found
&& reversed
)
886 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
887 usage (EXIT_FAILURE
);
891 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
893 if (STREQ (arg
, control_info
[i
].name
))
897 error (0, 0, _("missing argument to %s"), quote (arg
));
898 usage (EXIT_FAILURE
);
902 set_control_char (&control_info
[i
], argv
[k
], &mode
);
903 require_set_attr
= true;
910 if (STREQ (arg
, "ispeed"))
914 error (0, 0, _("missing argument to %s"), quote (arg
));
915 usage (EXIT_FAILURE
);
918 set_speed (input_speed
, argv
[k
], &mode
);
919 speed_was_set
= true;
920 require_set_attr
= true;
922 else if (STREQ (arg
, "ospeed"))
926 error (0, 0, _("missing argument to %s"), quote (arg
));
927 usage (EXIT_FAILURE
);
930 set_speed (output_speed
, argv
[k
], &mode
);
931 speed_was_set
= true;
932 require_set_attr
= true;
935 else if (STREQ (arg
, "rows"))
939 error (0, 0, _("missing argument to %s"), quote (arg
));
940 usage (EXIT_FAILURE
);
943 set_window_size (integer_arg (argv
[k
], INT_MAX
), -1,
946 else if (STREQ (arg
, "cols")
947 || STREQ (arg
, "columns"))
951 error (0, 0, _("missing argument to %s"), quote (arg
));
952 usage (EXIT_FAILURE
);
955 set_window_size (-1, integer_arg (argv
[k
], INT_MAX
),
958 else if (STREQ (arg
, "size"))
960 max_col
= screen_columns ();
962 display_window_size (false, device_name
);
966 else if (STREQ (arg
, "line"))
968 unsigned long int value
;
971 error (0, 0, _("missing argument to %s"), quote (arg
));
972 usage (EXIT_FAILURE
);
975 mode
.c_line
= value
= integer_arg (argv
[k
], ULONG_MAX
);
976 if (mode
.c_line
!= value
)
977 error (0, 0, _("invalid line discipline %s"), quote (argv
[k
]));
978 require_set_attr
= true;
981 else if (STREQ (arg
, "speed"))
983 max_col
= screen_columns ();
984 display_speed (&mode
, false);
986 else if (string_to_baud (arg
) != (speed_t
) -1)
988 set_speed (both_speeds
, arg
, &mode
);
989 speed_was_set
= true;
990 require_set_attr
= true;
994 if (! recover_mode (arg
, &mode
))
996 error (0, 0, _("invalid argument %s"), quote (arg
));
997 usage (EXIT_FAILURE
);
999 require_set_attr
= true;
1004 if (require_set_attr
)
1006 /* Initialize to all zeroes so there is no risk memcmp will report a
1007 spurious difference in an uninitialized portion of the structure. */
1008 DECLARE_ZEROED_AGGREGATE (struct termios
, new_mode
);
1010 if (tcsetattr (STDIN_FILENO
, TCSADRAIN
, &mode
))
1011 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1013 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1014 it performs *any* of the requested operations. This means it
1015 can report `success' when it has actually failed to perform
1016 some proper subset of the requested operations. To detect
1017 this partial failure, get the current terminal attributes and
1018 compare them to the requested ones. */
1020 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1021 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1023 /* Normally, one shouldn't use memcmp to compare structures that
1024 may have `holes' containing uninitialized data, but we have been
1025 careful to initialize the storage of these two variables to all
1026 zeroes. One might think it more efficient simply to compare the
1027 modified fields, but that would require enumerating those fields --
1028 and not all systems have the same fields in this structure. */
1030 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1033 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1034 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1035 sometimes (m1 != m2). The only difference is in the four bits
1036 of the c_cflag field corresponding to the baud rate. To save
1037 Sun users a little confusion, don't report an error if this
1038 happens. But suppress the error only if we haven't tried to
1039 set the baud rate explicitly -- otherwise we'd never give an
1040 error for a true failure to set the baud rate. */
1042 new_mode
.c_cflag
&= (~CIBAUD
);
1043 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1046 error (EXIT_FAILURE
, 0,
1047 _("%s: unable to perform all requested operations"),
1052 printf ("new_mode: mode\n");
1053 for (i
= 0; i
< sizeof (new_mode
); i
++)
1054 printf ("0x%02x: 0x%02x\n",
1055 *(((unsigned char *) &new_mode
) + i
),
1056 *(((unsigned char *) &mode
) + i
));
1063 exit (EXIT_SUCCESS
);
1066 /* Return false if not applied because not reversible; otherwise
1070 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1074 if (reversed
&& (info
->flags
& REV
) == 0)
1077 bitsp
= mode_type_flag (info
->type
, mode
);
1081 /* Combination mode. */
1082 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1085 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1087 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1089 else if (STREQ (info
->name
, "oddp"))
1092 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1094 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1096 else if (STREQ (info
->name
, "nl"))
1100 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1101 mode
->c_oflag
= (mode
->c_oflag
1116 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1118 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1122 else if (STREQ (info
->name
, "ek"))
1124 mode
->c_cc
[VERASE
] = CERASE
;
1125 mode
->c_cc
[VKILL
] = CKILL
;
1127 else if (STREQ (info
->name
, "sane"))
1129 else if (STREQ (info
->name
, "cbreak"))
1132 mode
->c_lflag
|= ICANON
;
1134 mode
->c_lflag
&= ~ICANON
;
1136 else if (STREQ (info
->name
, "pass8"))
1140 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1141 mode
->c_iflag
|= ISTRIP
;
1145 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1146 mode
->c_iflag
&= ~ISTRIP
;
1149 else if (STREQ (info
->name
, "litout"))
1153 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1154 mode
->c_iflag
|= ISTRIP
;
1155 mode
->c_oflag
|= OPOST
;
1159 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1160 mode
->c_iflag
&= ~ISTRIP
;
1161 mode
->c_oflag
&= ~OPOST
;
1164 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1166 if ((info
->name
[0] == 'r' && reversed
)
1167 || (info
->name
[0] == 'c' && !reversed
))
1170 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1171 mode
->c_oflag
|= OPOST
;
1172 mode
->c_lflag
|= ISIG
| ICANON
;
1174 mode
->c_cc
[VEOF
] = CEOF
;
1177 mode
->c_cc
[VEOL
] = CEOL
;
1184 mode
->c_oflag
&= ~OPOST
;
1185 mode
->c_lflag
&= ~(ISIG
| ICANON
1190 mode
->c_cc
[VMIN
] = 1;
1191 mode
->c_cc
[VTIME
] = 0;
1195 else if (STREQ (info
->name
, "decctlq"))
1198 mode
->c_iflag
|= IXANY
;
1200 mode
->c_iflag
&= ~IXANY
;
1204 else if (STREQ (info
->name
, "tabs"))
1207 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1209 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1213 else if (STREQ (info
->name
, "tabs"))
1216 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1218 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1222 #if defined XCASE && defined IUCLC && defined OLCUC
1223 else if (STREQ (info
->name
, "lcase")
1224 || STREQ (info
->name
, "LCASE"))
1228 mode
->c_lflag
&= ~XCASE
;
1229 mode
->c_iflag
&= ~IUCLC
;
1230 mode
->c_oflag
&= ~OLCUC
;
1234 mode
->c_lflag
|= XCASE
;
1235 mode
->c_iflag
|= IUCLC
;
1236 mode
->c_oflag
|= OLCUC
;
1240 else if (STREQ (info
->name
, "crt"))
1241 mode
->c_lflag
|= ECHOE
1249 else if (STREQ (info
->name
, "dec"))
1251 mode
->c_cc
[VINTR
] = 3; /* ^C */
1252 mode
->c_cc
[VERASE
] = 127; /* DEL */
1253 mode
->c_cc
[VKILL
] = 21; /* ^U */
1254 mode
->c_lflag
|= ECHOE
1263 mode
->c_iflag
&= ~IXANY
;
1268 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1270 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1276 set_control_char (struct control_info
const *info
, const char *arg
,
1277 struct termios
*mode
)
1279 unsigned long int value
;
1281 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1282 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1283 else if (arg
[0] == '\0' || arg
[1] == '\0')
1284 value
= to_uchar (arg
[0]);
1285 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1286 value
= _POSIX_VDISABLE
;
1287 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1292 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1295 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1296 mode
->c_cc
[info
->offset
] = value
;
1300 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1304 baud
= string_to_baud (arg
);
1305 if (type
== input_speed
|| type
== both_speeds
)
1306 cfsetispeed (mode
, baud
);
1307 if (type
== output_speed
|| type
== both_speeds
)
1308 cfsetospeed (mode
, baud
);
1314 get_win_size (int fd
, struct winsize
*win
)
1316 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1321 set_window_size (int rows
, int cols
, char const *device_name
)
1325 if (get_win_size (STDIN_FILENO
, &win
))
1327 if (errno
!= EINVAL
)
1328 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1329 memset (&win
, 0, sizeof (win
));
1338 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1339 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1340 This comment from sys/ttold.h describes Sun's twisted logic - a better
1341 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1342 At any rate, the problem is gone in Solaris 2.x.
1344 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1345 but they can be disambiguated by checking whether a "struct ttysize"
1346 structure's "ts_lines" field is greater than 64K or not. If so,
1347 it's almost certainly a "struct winsize" instead.
1349 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1350 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1351 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1352 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1353 "stty cols 0 rows 0" would do the right thing. On a little-endian
1354 machine like the sun386i, the problem is the same, but for ws_col == 0.
1356 The workaround is to do the ioctl once with row and col = 1 to set the
1357 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1359 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1361 struct ttysize ttysz
;
1363 ttysz
.ts_lines
= win
.ws_row
;
1364 ttysz
.ts_cols
= win
.ws_col
;
1369 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1370 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1372 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1373 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1378 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1379 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1383 display_window_size (bool fancy
, char const *device_name
)
1387 if (get_win_size (STDIN_FILENO
, &win
))
1389 if (errno
!= EINVAL
)
1390 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1392 error (EXIT_FAILURE
, 0,
1393 _("%s: no size information for this device"), device_name
);
1397 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1398 win
.ws_row
, win
.ws_col
);
1406 screen_columns (void)
1411 /* With Solaris 2.[123], this ioctl fails and errno is set to
1412 EINVAL for telnet (but not rlogin) sessions.
1413 On ISC 3.0, it fails for the console and the serial port
1414 (but it works for ptys).
1415 It can also fail on any system when stdout isn't a tty.
1416 In case of any failure, just use the default. */
1417 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1421 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1422 char *col_string
= getenv ("COLUMNS");
1424 if (!(col_string
!= NULL
1425 && xstrtol (col_string
, NULL
, 0, &n_columns
, "") == LONGINT_OK
1427 && n_columns
<= INT_MAX
))
1434 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1439 return &mode
->c_cflag
;
1442 return &mode
->c_iflag
;
1445 return &mode
->c_oflag
;
1448 return &mode
->c_lflag
;
1459 display_settings (enum output_type output_type
, struct termios
*mode
,
1460 char const *device_name
)
1462 switch (output_type
)
1465 display_changed (mode
);
1469 display_all (mode
, device_name
);
1473 display_recoverable (mode
);
1479 display_changed (struct termios
*mode
)
1485 enum mode_type prev_type
= control
;
1487 display_speed (mode
, true);
1489 wrapf ("line = %d;", mode
->c_line
);
1495 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1497 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1499 /* If swtch is the same as susp, don't print both. */
1501 if (STREQ (control_info
[i
].name
, "swtch"))
1504 /* If eof uses the same slot as min, only print whichever applies. */
1506 if ((mode
->c_lflag
& ICANON
) == 0
1507 && (STREQ (control_info
[i
].name
, "eof")
1508 || STREQ (control_info
[i
].name
, "eol")))
1513 wrapf ("%s = %s;", control_info
[i
].name
,
1514 visible (mode
->c_cc
[control_info
[i
].offset
]));
1516 if ((mode
->c_lflag
& ICANON
) == 0)
1518 wrapf ("min = %lu; time = %lu;\n",
1519 (unsigned long int) mode
->c_cc
[VMIN
],
1520 (unsigned long int) mode
->c_cc
[VTIME
]);
1522 else if (!empty_line
)
1527 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1529 if (mode_info
[i
].flags
& OMIT
)
1531 if (mode_info
[i
].type
!= prev_type
)
1539 prev_type
= mode_info
[i
].type
;
1542 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1543 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1544 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1546 if (mode_info
[i
].flags
& SANE_UNSET
)
1548 wrapf ("%s", mode_info
[i
].name
);
1552 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1554 wrapf ("-%s", mode_info
[i
].name
);
1564 display_all (struct termios
*mode
, char const *device_name
)
1569 enum mode_type prev_type
= control
;
1571 display_speed (mode
, true);
1573 display_window_size (true, device_name
);
1576 wrapf ("line = %d;", mode
->c_line
);
1581 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
1583 /* If swtch is the same as susp, don't print both. */
1585 if (STREQ (control_info
[i
].name
, "swtch"))
1588 /* If eof uses the same slot as min, only print whichever applies. */
1590 if ((mode
->c_lflag
& ICANON
) == 0
1591 && (STREQ (control_info
[i
].name
, "eof")
1592 || STREQ (control_info
[i
].name
, "eol")))
1595 wrapf ("%s = %s;", control_info
[i
].name
,
1596 visible (mode
->c_cc
[control_info
[i
].offset
]));
1599 if ((mode
->c_lflag
& ICANON
) == 0)
1601 wrapf ("min = %lu; time = %lu;",
1602 (unsigned long int) mode
->c_cc
[VMIN
],
1603 (unsigned long int) mode
->c_cc
[VTIME
]);
1604 if (current_col
!= 0)
1608 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1610 if (mode_info
[i
].flags
& OMIT
)
1612 if (mode_info
[i
].type
!= prev_type
)
1616 prev_type
= mode_info
[i
].type
;
1619 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1620 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1621 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1622 wrapf ("%s", mode_info
[i
].name
);
1623 else if (mode_info
[i
].flags
& REV
)
1624 wrapf ("-%s", mode_info
[i
].name
);
1631 display_speed (struct termios
*mode
, bool fancy
)
1633 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1634 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1635 baud_to_value (cfgetospeed (mode
)));
1637 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1638 baud_to_value (cfgetispeed (mode
)),
1639 baud_to_value (cfgetospeed (mode
)));
1645 display_recoverable (struct termios
*mode
)
1649 printf ("%lx:%lx:%lx:%lx",
1650 (unsigned long int) mode
->c_iflag
,
1651 (unsigned long int) mode
->c_oflag
,
1652 (unsigned long int) mode
->c_cflag
,
1653 (unsigned long int) mode
->c_lflag
);
1654 for (i
= 0; i
< NCCS
; ++i
)
1655 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
1659 /* NOTE: identical to below, modulo use of tcflag_t */
1661 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
1666 ul
= strtoul (s
, p
, base
);
1667 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
1673 /* NOTE: identical to above, modulo use of cc_t */
1675 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
1679 ul
= strtoul (s
, p
, base
);
1680 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
1686 /* Parse the output of display_recoverable.
1687 Return false if any part of it is invalid. */
1689 recover_mode (char const *arg
, struct termios
*mode
)
1692 char const *s
= arg
;
1694 for (i
= 0; i
< 4; i
++)
1697 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
1701 mode
->c_iflag
= flag
[0];
1702 mode
->c_oflag
= flag
[1];
1703 mode
->c_cflag
= flag
[2];
1704 mode
->c_lflag
= flag
[3];
1706 for (i
= 0; i
< NCCS
; ++i
)
1709 char delim
= i
< NCCS
- 1 ? ':' : '\0';
1710 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
1720 const char *string
; /* ASCII representation. */
1721 speed_t speed
; /* Internal form. */
1722 unsigned long int value
; /* Numeric value. */
1725 static struct speed_map
const speeds
[] =
1732 {"134.5", B134
, 134},
1737 {"1200", B1200
, 1200},
1738 {"1800", B1800
, 1800},
1739 {"2400", B2400
, 2400},
1740 {"4800", B4800
, 4800},
1741 {"9600", B9600
, 9600},
1742 {"19200", B19200
, 19200},
1743 {"38400", B38400
, 38400},
1744 {"exta", B19200
, 19200},
1745 {"extb", B38400
, 38400},
1747 {"57600", B57600
, 57600},
1750 {"115200", B115200
, 115200},
1753 {"230400", B230400
, 230400},
1756 {"460800", B460800
, 460800},
1759 {"500000", B500000
, 500000},
1762 {"576000", B576000
, 576000},
1765 {"921600", B921600
, 921600},
1768 {"1000000", B1000000
, 1000000},
1771 {"1152000", B1152000
, 1152000},
1774 {"1500000", B1500000
, 1500000},
1777 {"2000000", B2000000
, 2000000},
1780 {"2500000", B2500000
, 2500000},
1783 {"3000000", B3000000
, 3000000},
1786 {"3500000", B3500000
, 3500000},
1789 {"4000000", B4000000
, 4000000},
1795 string_to_baud (const char *arg
)
1799 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1800 if (STREQ (arg
, speeds
[i
].string
))
1801 return speeds
[i
].speed
;
1802 return (speed_t
) -1;
1805 static unsigned long int
1806 baud_to_value (speed_t speed
)
1810 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1811 if (speed
== speeds
[i
].speed
)
1812 return speeds
[i
].value
;
1817 sane_mode (struct termios
*mode
)
1822 for (i
= 0; control_info
[i
].name
; ++i
)
1825 if (STREQ (control_info
[i
].name
, "min"))
1828 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1831 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1833 if (mode_info
[i
].flags
& SANE_SET
)
1835 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1836 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1838 else if (mode_info
[i
].flags
& SANE_UNSET
)
1840 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1841 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1846 /* Return a string that is the printable representation of character CH. */
1847 /* Adapted from `cat' by Torbjorn Granlund. */
1852 static char buf
[10];
1855 if (ch
== _POSIX_VDISABLE
)
1874 *bpout
++ = ch
- 128;
1884 *bpout
++ = ch
- 128 + 64;
1894 return (const char *) buf
;
1897 /* Parse string S as an integer, using decimal radix by default,
1898 but allowing octal and hex numbers as in C. Reject values
1899 larger than MAXVAL. */
1901 static unsigned long int
1902 integer_arg (const char *s
, unsigned long int maxval
)
1904 unsigned long int value
;
1905 if (xstrtoul (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
|| maxval
< value
)
1907 error (0, 0, _("invalid integer argument %s"), quote (s
));
1908 usage (EXIT_FAILURE
);