1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2005, 2007-2009 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 #ifdef HAVE_SYS_IOCTL_H
46 # include <sys/ioctl.h>
49 #ifdef WINSIZE_IN_PTEM
50 # include <sys/stream.h>
51 # include <sys/ptem.h>
53 #ifdef GWINSZ_IN_SYS_PTY
62 #include "fd-reopen.h"
66 /* The official name of this program (e.g., no `g' prefix). */
67 #define PROGRAM_NAME "stty"
69 #define AUTHORS proper_name ("David MacKenzie")
71 #ifndef _POSIX_VDISABLE
72 # define _POSIX_VDISABLE 0
75 #define Control(c) ((c) & 0x1f)
76 /* Canonical values for control characters. */
78 # define CINTR Control ('c')
87 # define CKILL Control ('u')
90 # define CEOF Control ('d')
93 # define CEOL _POSIX_VDISABLE
96 # define CSTART Control ('q')
99 # define CSTOP Control ('s')
102 # define CSUSP Control ('z')
104 #if defined VEOL2 && !defined CEOL2
105 # define CEOL2 _POSIX_VDISABLE
107 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
108 character is initialized by CSWTCH, if present. */
109 #if defined VSWTC && !defined VSWTCH
110 # define VSWTCH VSWTC
112 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
113 #if defined VSUSP && !defined VSWTCH
114 # define VSWTCH VSUSP
115 # if defined CSUSP && !defined CSWTCH
116 # define CSWTCH CSUSP
119 #if defined VSWTCH && !defined CSWTCH
120 # define CSWTCH _POSIX_VDISABLE
123 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
124 So the default is to disable `swtch.' */
125 #if defined __sparc__ && defined __svr4__
127 # define CSWTCH _POSIX_VDISABLE
130 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
131 # define VWERASE VWERSE
133 #if defined VDSUSP && !defined CDSUSP
134 # define CDSUSP Control ('y')
136 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
137 # define VREPRINT VRPRNT
139 #if defined VREPRINT && !defined CRPRNT
140 # define CRPRNT Control ('r')
142 #if defined CREPRINT && !defined CRPRNT
143 # define CRPRNT Control ('r')
145 #if defined VWERASE && !defined CWERASE
146 # define CWERASE Control ('w')
148 #if defined VLNEXT && !defined CLNEXT
149 # define CLNEXT Control ('v')
151 #if defined VDISCARD && !defined VFLUSHO
152 # define VFLUSHO VDISCARD
154 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
155 # define VFLUSHO VFLUSH
157 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
158 # define ECHOCTL CTLECH
160 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
161 # define ECHOCTL TCTLECH
163 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
164 # define ECHOKE CRTKIL
166 #if defined VFLUSHO && !defined CFLUSHO
167 # define CFLUSHO Control ('o')
169 #if defined VSTATUS && !defined CSTATUS
170 # define CSTATUS Control ('t')
173 /* Which speeds to set. */
176 input_speed
, output_speed
, both_speeds
179 /* What to output and how. */
182 changed
, all
, recoverable
/* Default, -a, -g. */
185 /* Which member(s) of `struct termios' a mode uses. */
188 control
, input
, output
, local
, combination
191 /* Flags for `struct mode_info'. */
192 #define SANE_SET 1 /* Set in `sane' mode. */
193 #define SANE_UNSET 2 /* Unset in `sane' mode. */
194 #define REV 4 /* Can be turned off by prepending `-'. */
195 #define OMIT 8 /* Don't display value. */
200 const char *name
; /* Name given on command line. */
201 enum mode_type type
; /* Which structure element to change. */
202 char flags
; /* Setting and display options. */
203 unsigned long bits
; /* Bits to set for this mode. */
204 unsigned long mask
; /* Other bits to turn off for this mode. */
207 static struct mode_info
const mode_info
[] =
209 {"parenb", control
, REV
, PARENB
, 0},
210 {"parodd", control
, REV
, PARODD
, 0},
211 {"cs5", control
, 0, CS5
, CSIZE
},
212 {"cs6", control
, 0, CS6
, CSIZE
},
213 {"cs7", control
, 0, CS7
, CSIZE
},
214 {"cs8", control
, 0, CS8
, CSIZE
},
215 {"hupcl", control
, REV
, HUPCL
, 0},
216 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
217 {"cstopb", control
, REV
, CSTOPB
, 0},
218 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
219 {"clocal", control
, REV
, CLOCAL
, 0},
221 {"crtscts", control
, REV
, CRTSCTS
, 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
},
282 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
283 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
284 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
285 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
288 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
292 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
293 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
296 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
297 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
300 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
301 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
304 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
305 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
307 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
309 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
310 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
311 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
312 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
313 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
314 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
316 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
319 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
322 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
323 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
326 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
327 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
330 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
331 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
334 {"evenp", combination
, REV
| OMIT
, 0, 0},
335 {"parity", combination
, REV
| OMIT
, 0, 0},
336 {"oddp", combination
, REV
| OMIT
, 0, 0},
337 {"nl", combination
, REV
| OMIT
, 0, 0},
338 {"ek", combination
, OMIT
, 0, 0},
339 {"sane", combination
, OMIT
, 0, 0},
340 {"cooked", combination
, REV
| OMIT
, 0, 0},
341 {"raw", combination
, REV
| OMIT
, 0, 0},
342 {"pass8", combination
, REV
| OMIT
, 0, 0},
343 {"litout", combination
, REV
| OMIT
, 0, 0},
344 {"cbreak", combination
, REV
| OMIT
, 0, 0},
346 {"decctlq", combination
, REV
| OMIT
, 0, 0},
348 #if defined TABDLY || defined OXTABS
349 {"tabs", combination
, REV
| OMIT
, 0, 0},
351 #if defined XCASE && defined IUCLC && defined OLCUC
352 {"lcase", combination
, REV
| OMIT
, 0, 0},
353 {"LCASE", combination
, REV
| OMIT
, 0, 0},
355 {"crt", combination
, OMIT
, 0, 0},
356 {"dec", combination
, OMIT
, 0, 0},
358 {NULL
, control
, 0, 0, 0}
361 /* Control character settings. */
364 const char *name
; /* Name given on command line. */
365 cc_t saneval
; /* Value to set for `stty sane'. */
366 size_t offset
; /* Offset in c_cc. */
369 /* Control characters. */
371 static struct control_info
const control_info
[] =
373 {"intr", CINTR
, VINTR
},
374 {"quit", CQUIT
, VQUIT
},
375 {"erase", CERASE
, VERASE
},
376 {"kill", CKILL
, VKILL
},
380 {"eol2", CEOL2
, VEOL2
},
383 {"swtch", CSWTCH
, VSWTCH
},
385 {"start", CSTART
, VSTART
},
386 {"stop", CSTOP
, VSTOP
},
387 {"susp", CSUSP
, VSUSP
},
389 {"dsusp", CDSUSP
, VDSUSP
},
392 {"rprnt", CRPRNT
, VREPRINT
},
394 # ifdef CREPRINT /* HPUX 10.20 needs this */
395 {"rprnt", CRPRNT
, CREPRINT
},
399 {"werase", CWERASE
, VWERASE
},
402 {"lnext", CLNEXT
, VLNEXT
},
405 {"flush", CFLUSHO
, VFLUSHO
},
408 {"status", CSTATUS
, VSTATUS
},
411 /* These must be last because of the display routines. */
417 static char const *visible (cc_t ch
);
418 static unsigned long int baud_to_value (speed_t speed
);
419 static bool recover_mode (char const *arg
, struct termios
*mode
);
420 static int screen_columns (void);
421 static bool set_mode (struct mode_info
const *info
, bool reversed
,
422 struct termios
*mode
);
423 static unsigned long int integer_arg (const char *s
, unsigned long int max
);
424 static speed_t
string_to_baud (const char *arg
);
425 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
426 static void display_all (struct termios
*mode
, char const *device_name
);
427 static void display_changed (struct termios
*mode
);
428 static void display_recoverable (struct termios
*mode
);
429 static void display_settings (enum output_type output_type
,
430 struct termios
*mode
,
431 const char *device_name
);
432 static void display_speed (struct termios
*mode
, bool fancy
);
433 static void display_window_size (bool fancy
, char const *device_name
);
434 static void sane_mode (struct termios
*mode
);
435 static void set_control_char (struct control_info
const *info
,
437 struct termios
*mode
);
438 static void set_speed (enum speed_setting type
, const char *arg
,
439 struct termios
*mode
);
440 static void set_window_size (int rows
, int cols
, char const *device_name
);
442 /* The width of the screen, for output wrapping. */
445 /* Current position, to know when to wrap. */
446 static int current_col
;
448 static struct option
const longopts
[] =
450 {"all", no_argument
, NULL
, 'a'},
451 {"save", no_argument
, NULL
, 'g'},
452 {"file", required_argument
, NULL
, 'F'},
453 {GETOPT_HELP_OPTION_DECL
},
454 {GETOPT_VERSION_OPTION_DECL
},
458 static void wrapf (const char *message
, ...)
459 __attribute__ ((__format__ (__printf__
, 1, 2)));
461 /* Print format string MESSAGE and optional args.
462 Wrap to next line first if it won't fit.
463 Print a space first unless MESSAGE will start a new line. */
466 wrapf (const char *message
,...)
472 va_start (args
, message
);
473 buflen
= vasprintf (&buf
, message
, args
);
481 if (max_col
- current_col
< buflen
)
495 current_col
+= buflen
;
501 if (status
!= EXIT_SUCCESS
)
502 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
507 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
508 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
509 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
511 program_name
, program_name
, program_name
);
513 Print or change terminal characteristics.\n\
515 -a, --all print all current settings in human-readable form\n\
516 -g, --save print all current settings in a stty-readable form\n\
517 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
519 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
520 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
523 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
524 settings. The underlying system defines which settings are available.\n\
528 Special characters:\n\
529 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
530 eof CHAR CHAR will send an end of file (terminate the input)\n\
531 eol CHAR CHAR will end the line\n\
534 * eol2 CHAR alternate CHAR for ending the line\n\
535 erase CHAR CHAR will erase the last character typed\n\
536 intr CHAR CHAR will send an interrupt signal\n\
537 kill CHAR CHAR will erase the current line\n\
540 * lnext CHAR CHAR will enter the next character quoted\n\
541 quit CHAR CHAR will send a quit signal\n\
542 * rprnt CHAR CHAR will redraw the current line\n\
543 start CHAR CHAR will restart the output after stopping it\n\
546 stop CHAR CHAR will stop the output\n\
547 susp CHAR CHAR will send a terminal stop signal\n\
548 * swtch CHAR CHAR will switch to a different shell layer\n\
549 * werase CHAR CHAR will erase the last word typed\n\
554 N set the input and output speeds to N bauds\n\
555 * cols N tell the kernel that the terminal has N columns\n\
556 * columns N same as cols N\n\
559 ispeed N set the input speed to N\n\
560 * line N use line discipline N\n\
561 min N with -icanon, set N characters minimum for a completed read\n\
562 ospeed N set the output speed to N\n\
565 * rows N tell the kernel that the terminal has N rows\n\
566 * size print the number of rows and columns according to the kernel\n\
567 speed print the terminal speed\n\
568 time N with -icanon, set read timeout of N tenths of a second\n\
573 [-]clocal disable modem control signals\n\
574 [-]cread allow input to be received\n\
575 * [-]crtscts enable RTS/CTS handshaking\n\
576 csN set character size to N bits, N in [5..8]\n\
579 [-]cstopb use two stop bits per character (one with `-')\n\
580 [-]hup send a hangup signal when the last process closes the tty\n\
581 [-]hupcl same as [-]hup\n\
582 [-]parenb generate parity bit in output and expect parity bit in input\n\
583 [-]parodd set odd parity (even with `-')\n\
588 [-]brkint breaks cause an interrupt signal\n\
589 [-]icrnl translate carriage return to newline\n\
590 [-]ignbrk ignore break characters\n\
591 [-]igncr ignore carriage return\n\
594 [-]ignpar ignore characters with parity errors\n\
595 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
596 [-]inlcr translate newline to carriage return\n\
597 [-]inpck enable input parity checking\n\
598 [-]istrip clear high (8th) bit of input characters\n\
601 * [-]iutf8 assume input characters are UTF-8 encoded\n\
604 * [-]iuclc translate uppercase characters to lowercase\n\
605 * [-]ixany let any character restart output, not only start character\n\
606 [-]ixoff enable sending of start/stop characters\n\
607 [-]ixon enable XON/XOFF flow control\n\
608 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
609 [-]tandem same as [-]ixoff\n\
614 * bsN backspace delay style, N in [0..1]\n\
615 * crN carriage return delay style, N in [0..3]\n\
616 * ffN form feed delay style, N in [0..1]\n\
617 * nlN newline delay style, N in [0..1]\n\
620 * [-]ocrnl translate carriage return to newline\n\
621 * [-]ofdel use delete characters for fill instead of null characters\n\
622 * [-]ofill use fill (padding) characters instead of timing for delays\n\
623 * [-]olcuc translate lowercase characters to uppercase\n\
624 * [-]onlcr translate newline to carriage return-newline\n\
625 * [-]onlret newline performs a carriage return\n\
628 * [-]onocr do not print carriage returns in the first column\n\
629 [-]opost postprocess output\n\
630 * tabN horizontal tab delay style, N in [0..3]\n\
631 * tabs same as tab0\n\
632 * -tabs same as tab3\n\
633 * vtN vertical tab delay style, N in [0..1]\n\
638 [-]crterase echo erase characters as backspace-space-backspace\n\
639 * crtkill kill all line by obeying the echoprt and echoe settings\n\
640 * -crtkill kill all line by obeying the echoctl and echok settings\n\
643 * [-]ctlecho echo control characters in hat notation (`^c')\n\
644 [-]echo echo input characters\n\
645 * [-]echoctl same as [-]ctlecho\n\
646 [-]echoe same as [-]crterase\n\
647 [-]echok echo a newline after a kill character\n\
650 * [-]echoke same as [-]crtkill\n\
651 [-]echonl echo newline even if not echoing other characters\n\
652 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
653 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
654 [-]iexten enable non-POSIX special characters\n\
657 [-]isig enable interrupt, quit, and suspend special characters\n\
658 [-]noflsh disable flushing after interrupt and quit special characters\n\
659 * [-]prterase same as [-]echoprt\n\
660 * [-]tostop stop background jobs that try to write to the terminal\n\
661 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
665 Combination settings:\n\
666 * [-]LCASE same as [-]lcase\n\
667 cbreak same as -icanon\n\
668 -cbreak same as icanon\n\
671 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
672 icanon, eof and eol characters to their default values\n\
673 -cooked same as raw\n\
674 crt same as echoe echoctl echoke\n\
677 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
679 * [-]decctlq same as [-]ixany\n\
680 ek erase and kill characters to their default values\n\
681 evenp same as parenb -parodd cs7\n\
684 -evenp same as -parenb cs8\n\
685 * [-]lcase same as xcase iuclc olcuc\n\
686 litout same as -parenb -istrip -opost cs8\n\
687 -litout same as parenb istrip opost cs7\n\
688 nl same as -icrnl -onlcr\n\
689 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
692 oddp same as parenb parodd cs7\n\
693 -oddp same as -parenb cs8\n\
694 [-]parity same as [-]evenp\n\
695 pass8 same as -parenb -istrip cs8\n\
696 -pass8 same as parenb istrip cs7\n\
699 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
700 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
701 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
702 -raw same as cooked\n\
705 sane same as cread -ignbrk brkint -inlcr -igncr icrnl -iutf8\n\
706 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
707 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
708 isig icanon iexten echo echoe echok -echonl -noflsh\n\
709 -xcase -tostop -echoprt echoctl echoke, all special\n\
710 characters to their default values\n\
714 Handle the tty line connected to standard input. Without arguments,\n\
715 prints baud rate, line discipline, and deviations from stty sane. In\n\
716 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
717 127; special values ^- or undef used to disable special characters.\n\
719 emit_bug_reporting_address ();
725 main (int argc
, char **argv
)
727 /* Initialize to all zeroes so there is no risk memcmp will report a
728 spurious difference in an uninitialized portion of the structure. */
729 DECLARE_ZEROED_AGGREGATE (struct termios
, mode
);
731 enum output_type output_type
;
735 bool require_set_attr
;
738 bool recoverable_output
;
741 char *file_name
= NULL
;
742 const char *device_name
;
744 initialize_main (&argc
, &argv
);
745 set_program_name (argv
[0]);
746 setlocale (LC_ALL
, "");
747 bindtextdomain (PACKAGE
, LOCALEDIR
);
748 textdomain (PACKAGE
);
750 atexit (close_stdout
);
752 output_type
= changed
;
753 verbose_output
= false;
754 recoverable_output
= false;
756 /* Don't print error messages for unrecognized options. */
759 /* If any new options are ever added to stty, the short options MUST
760 NOT allow any ambiguity with the stty settings. For example, the
761 stty setting "-gagFork" would not be feasible, since it will be
762 parsed as "-g -a -g -F ork". If you change anything about how
763 stty parses options, be sure it still works with combinations of
764 short and long options, --, POSIXLY_CORRECT, etc. */
766 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
773 verbose_output
= true;
778 recoverable_output
= true;
779 output_type
= recoverable
;
784 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
788 case_GETOPT_HELP_CHAR
;
790 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
795 /* Skip the argument containing this unrecognized option;
796 the 2nd pass will analyze it. */
799 /* Restart getopt_long from the first unskipped argument. */
806 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
807 while (opti
< optind
)
808 argv
[argi
+ opti
++] = NULL
;
811 /* Specifying both -a and -g gets an error. */
812 if (verbose_output
& recoverable_output
)
813 error (EXIT_FAILURE
, 0,
814 _("the options for verbose and stty-readable output styles are\n"
815 "mutually exclusive"));
817 /* Specifying any other arguments with -a or -g gets an error. */
818 if (!noargs
&& (verbose_output
| recoverable_output
))
819 error (EXIT_FAILURE
, 0,
820 _("when specifying an output style, modes may not be set"));
822 /* FIXME: it'd be better not to open the file until we've verified
823 that all arguments are valid. Otherwise, we could end up doing
824 only some of the requested operations and then failing, probably
825 leaving things in an undesirable state. */
830 device_name
= file_name
;
831 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
832 error (EXIT_FAILURE
, errno
, "%s", device_name
);
833 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
834 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
835 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
839 device_name
= _("standard input");
841 if (tcgetattr (STDIN_FILENO
, &mode
))
842 error (EXIT_FAILURE
, errno
, "%s", device_name
);
844 if (verbose_output
| recoverable_output
| noargs
)
846 max_col
= screen_columns ();
848 display_settings (output_type
, &mode
, device_name
);
852 speed_was_set
= false;
853 require_set_attr
= false;
854 for (k
= 1; k
< argc
; k
++)
856 char const *arg
= argv
[k
];
857 bool match_found
= false;
858 bool reversed
= false;
869 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
871 if (STREQ (arg
, mode_info
[i
].name
))
873 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
874 require_set_attr
= true;
878 if (!match_found
& reversed
)
880 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
881 usage (EXIT_FAILURE
);
885 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
887 if (STREQ (arg
, control_info
[i
].name
))
891 error (0, 0, _("missing argument to %s"), quote (arg
));
892 usage (EXIT_FAILURE
);
896 set_control_char (&control_info
[i
], argv
[k
], &mode
);
897 require_set_attr
= true;
904 if (STREQ (arg
, "ispeed"))
908 error (0, 0, _("missing argument to %s"), quote (arg
));
909 usage (EXIT_FAILURE
);
912 set_speed (input_speed
, argv
[k
], &mode
);
913 speed_was_set
= true;
914 require_set_attr
= true;
916 else if (STREQ (arg
, "ospeed"))
920 error (0, 0, _("missing argument to %s"), quote (arg
));
921 usage (EXIT_FAILURE
);
924 set_speed (output_speed
, argv
[k
], &mode
);
925 speed_was_set
= true;
926 require_set_attr
= true;
929 else if (STREQ (arg
, "rows"))
933 error (0, 0, _("missing argument to %s"), quote (arg
));
934 usage (EXIT_FAILURE
);
937 set_window_size (integer_arg (argv
[k
], INT_MAX
), -1,
940 else if (STREQ (arg
, "cols")
941 || STREQ (arg
, "columns"))
945 error (0, 0, _("missing argument to %s"), quote (arg
));
946 usage (EXIT_FAILURE
);
949 set_window_size (-1, integer_arg (argv
[k
], INT_MAX
),
952 else if (STREQ (arg
, "size"))
954 max_col
= screen_columns ();
956 display_window_size (false, device_name
);
960 else if (STREQ (arg
, "line"))
962 unsigned long int value
;
965 error (0, 0, _("missing argument to %s"), quote (arg
));
966 usage (EXIT_FAILURE
);
969 mode
.c_line
= value
= integer_arg (argv
[k
], ULONG_MAX
);
970 if (mode
.c_line
!= value
)
971 error (0, 0, _("invalid line discipline %s"), quote (argv
[k
]));
972 require_set_attr
= true;
975 else if (STREQ (arg
, "speed"))
977 max_col
= screen_columns ();
978 display_speed (&mode
, false);
980 else if (string_to_baud (arg
) != (speed_t
) -1)
982 set_speed (both_speeds
, arg
, &mode
);
983 speed_was_set
= true;
984 require_set_attr
= true;
988 if (! recover_mode (arg
, &mode
))
990 error (0, 0, _("invalid argument %s"), quote (arg
));
991 usage (EXIT_FAILURE
);
993 require_set_attr
= true;
998 if (require_set_attr
)
1000 /* Initialize to all zeroes so there is no risk memcmp will report a
1001 spurious difference in an uninitialized portion of the structure. */
1002 DECLARE_ZEROED_AGGREGATE (struct termios
, new_mode
);
1004 if (tcsetattr (STDIN_FILENO
, TCSADRAIN
, &mode
))
1005 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1007 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1008 it performs *any* of the requested operations. This means it
1009 can report `success' when it has actually failed to perform
1010 some proper subset of the requested operations. To detect
1011 this partial failure, get the current terminal attributes and
1012 compare them to the requested ones. */
1014 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1015 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1017 /* Normally, one shouldn't use memcmp to compare structures that
1018 may have `holes' containing uninitialized data, but we have been
1019 careful to initialize the storage of these two variables to all
1020 zeroes. One might think it more efficient simply to compare the
1021 modified fields, but that would require enumerating those fields --
1022 and not all systems have the same fields in this structure. */
1024 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1027 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1028 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1029 sometimes (m1 != m2). The only difference is in the four bits
1030 of the c_cflag field corresponding to the baud rate. To save
1031 Sun users a little confusion, don't report an error if this
1032 happens. But suppress the error only if we haven't tried to
1033 set the baud rate explicitly -- otherwise we'd never give an
1034 error for a true failure to set the baud rate. */
1036 new_mode
.c_cflag
&= (~CIBAUD
);
1037 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1040 error (EXIT_FAILURE
, 0,
1041 _("%s: unable to perform all requested operations"),
1046 printf ("new_mode: mode\n");
1047 for (i
= 0; i
< sizeof (new_mode
); i
++)
1048 printf ("0x%02x: 0x%02x\n",
1049 *(((unsigned char *) &new_mode
) + i
),
1050 *(((unsigned char *) &mode
) + i
));
1057 exit (EXIT_SUCCESS
);
1060 /* Return false if not applied because not reversible; otherwise
1064 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1068 if (reversed
&& (info
->flags
& REV
) == 0)
1071 bitsp
= mode_type_flag (info
->type
, mode
);
1075 /* Combination mode. */
1076 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1079 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1081 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1083 else if (STREQ (info
->name
, "oddp"))
1086 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1088 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1090 else if (STREQ (info
->name
, "nl"))
1094 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1095 mode
->c_oflag
= (mode
->c_oflag
1110 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1112 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1116 else if (STREQ (info
->name
, "ek"))
1118 mode
->c_cc
[VERASE
] = CERASE
;
1119 mode
->c_cc
[VKILL
] = CKILL
;
1121 else if (STREQ (info
->name
, "sane"))
1123 else if (STREQ (info
->name
, "cbreak"))
1126 mode
->c_lflag
|= ICANON
;
1128 mode
->c_lflag
&= ~ICANON
;
1130 else if (STREQ (info
->name
, "pass8"))
1134 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1135 mode
->c_iflag
|= ISTRIP
;
1139 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1140 mode
->c_iflag
&= ~ISTRIP
;
1143 else if (STREQ (info
->name
, "litout"))
1147 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1148 mode
->c_iflag
|= ISTRIP
;
1149 mode
->c_oflag
|= OPOST
;
1153 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1154 mode
->c_iflag
&= ~ISTRIP
;
1155 mode
->c_oflag
&= ~OPOST
;
1158 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1160 if ((info
->name
[0] == 'r' && reversed
)
1161 || (info
->name
[0] == 'c' && !reversed
))
1164 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1165 mode
->c_oflag
|= OPOST
;
1166 mode
->c_lflag
|= ISIG
| ICANON
;
1168 mode
->c_cc
[VEOF
] = CEOF
;
1171 mode
->c_cc
[VEOL
] = CEOL
;
1178 mode
->c_oflag
&= ~OPOST
;
1179 mode
->c_lflag
&= ~(ISIG
| ICANON
1184 mode
->c_cc
[VMIN
] = 1;
1185 mode
->c_cc
[VTIME
] = 0;
1189 else if (STREQ (info
->name
, "decctlq"))
1192 mode
->c_iflag
|= IXANY
;
1194 mode
->c_iflag
&= ~IXANY
;
1198 else if (STREQ (info
->name
, "tabs"))
1201 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1203 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1207 else if (STREQ (info
->name
, "tabs"))
1210 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1212 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1216 #if defined XCASE && defined IUCLC && defined OLCUC
1217 else if (STREQ (info
->name
, "lcase")
1218 || STREQ (info
->name
, "LCASE"))
1222 mode
->c_lflag
&= ~XCASE
;
1223 mode
->c_iflag
&= ~IUCLC
;
1224 mode
->c_oflag
&= ~OLCUC
;
1228 mode
->c_lflag
|= XCASE
;
1229 mode
->c_iflag
|= IUCLC
;
1230 mode
->c_oflag
|= OLCUC
;
1234 else if (STREQ (info
->name
, "crt"))
1235 mode
->c_lflag
|= ECHOE
1243 else if (STREQ (info
->name
, "dec"))
1245 mode
->c_cc
[VINTR
] = 3; /* ^C */
1246 mode
->c_cc
[VERASE
] = 127; /* DEL */
1247 mode
->c_cc
[VKILL
] = 21; /* ^U */
1248 mode
->c_lflag
|= ECHOE
1257 mode
->c_iflag
&= ~IXANY
;
1262 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1264 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1270 set_control_char (struct control_info
const *info
, const char *arg
,
1271 struct termios
*mode
)
1273 unsigned long int value
;
1275 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1276 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1277 else if (arg
[0] == '\0' || arg
[1] == '\0')
1278 value
= to_uchar (arg
[0]);
1279 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1280 value
= _POSIX_VDISABLE
;
1281 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1286 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1289 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1290 mode
->c_cc
[info
->offset
] = value
;
1294 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1298 baud
= string_to_baud (arg
);
1299 if (type
== input_speed
|| type
== both_speeds
)
1300 cfsetispeed (mode
, baud
);
1301 if (type
== output_speed
|| type
== both_speeds
)
1302 cfsetospeed (mode
, baud
);
1308 get_win_size (int fd
, struct winsize
*win
)
1310 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1315 set_window_size (int rows
, int cols
, char const *device_name
)
1319 if (get_win_size (STDIN_FILENO
, &win
))
1321 if (errno
!= EINVAL
)
1322 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1323 memset (&win
, 0, sizeof (win
));
1332 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1333 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1334 This comment from sys/ttold.h describes Sun's twisted logic - a better
1335 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1336 At any rate, the problem is gone in Solaris 2.x.
1338 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1339 but they can be disambiguated by checking whether a "struct ttysize"
1340 structure's "ts_lines" field is greater than 64K or not. If so,
1341 it's almost certainly a "struct winsize" instead.
1343 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1344 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1345 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1346 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1347 "stty cols 0 rows 0" would do the right thing. On a little-endian
1348 machine like the sun386i, the problem is the same, but for ws_col == 0.
1350 The workaround is to do the ioctl once with row and col = 1 to set the
1351 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1353 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1355 struct ttysize ttysz
;
1357 ttysz
.ts_lines
= win
.ws_row
;
1358 ttysz
.ts_cols
= win
.ws_col
;
1363 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1364 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1366 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1367 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1372 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1373 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1377 display_window_size (bool fancy
, char const *device_name
)
1381 if (get_win_size (STDIN_FILENO
, &win
))
1383 if (errno
!= EINVAL
)
1384 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1386 error (EXIT_FAILURE
, 0,
1387 _("%s: no size information for this device"), device_name
);
1391 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1392 win
.ws_row
, win
.ws_col
);
1400 screen_columns (void)
1405 /* With Solaris 2.[123], this ioctl fails and errno is set to
1406 EINVAL for telnet (but not rlogin) sessions.
1407 On ISC 3.0, it fails for the console and the serial port
1408 (but it works for ptys).
1409 It can also fail on any system when stdout isn't a tty.
1410 In case of any failure, just use the default. */
1411 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1415 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1416 char *col_string
= getenv ("COLUMNS");
1418 if (!(col_string
!= NULL
1419 && xstrtol (col_string
, NULL
, 0, &n_columns
, "") == LONGINT_OK
1421 && n_columns
<= INT_MAX
))
1428 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1433 return &mode
->c_cflag
;
1436 return &mode
->c_iflag
;
1439 return &mode
->c_oflag
;
1442 return &mode
->c_lflag
;
1453 display_settings (enum output_type output_type
, struct termios
*mode
,
1454 char const *device_name
)
1456 switch (output_type
)
1459 display_changed (mode
);
1463 display_all (mode
, device_name
);
1467 display_recoverable (mode
);
1473 display_changed (struct termios
*mode
)
1479 enum mode_type prev_type
= control
;
1481 display_speed (mode
, true);
1483 wrapf ("line = %d;", mode
->c_line
);
1489 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1491 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1493 /* If swtch is the same as susp, don't print both. */
1495 if (STREQ (control_info
[i
].name
, "swtch"))
1498 /* If eof uses the same slot as min, only print whichever applies. */
1500 if ((mode
->c_lflag
& ICANON
) == 0
1501 && (STREQ (control_info
[i
].name
, "eof")
1502 || STREQ (control_info
[i
].name
, "eol")))
1507 wrapf ("%s = %s;", control_info
[i
].name
,
1508 visible (mode
->c_cc
[control_info
[i
].offset
]));
1510 if ((mode
->c_lflag
& ICANON
) == 0)
1512 wrapf ("min = %lu; time = %lu;\n",
1513 (unsigned long int) mode
->c_cc
[VMIN
],
1514 (unsigned long int) mode
->c_cc
[VTIME
]);
1516 else if (!empty_line
)
1521 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1523 if (mode_info
[i
].flags
& OMIT
)
1525 if (mode_info
[i
].type
!= prev_type
)
1533 prev_type
= mode_info
[i
].type
;
1536 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1537 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1538 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1540 if (mode_info
[i
].flags
& SANE_UNSET
)
1542 wrapf ("%s", mode_info
[i
].name
);
1546 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1548 wrapf ("-%s", mode_info
[i
].name
);
1558 display_all (struct termios
*mode
, char const *device_name
)
1563 enum mode_type prev_type
= control
;
1565 display_speed (mode
, true);
1567 display_window_size (true, device_name
);
1570 wrapf ("line = %d;", mode
->c_line
);
1575 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
1577 /* If swtch is the same as susp, don't print both. */
1579 if (STREQ (control_info
[i
].name
, "swtch"))
1582 /* If eof uses the same slot as min, only print whichever applies. */
1584 if ((mode
->c_lflag
& ICANON
) == 0
1585 && (STREQ (control_info
[i
].name
, "eof")
1586 || STREQ (control_info
[i
].name
, "eol")))
1589 wrapf ("%s = %s;", control_info
[i
].name
,
1590 visible (mode
->c_cc
[control_info
[i
].offset
]));
1593 if ((mode
->c_lflag
& ICANON
) == 0)
1595 wrapf ("min = %lu; time = %lu;",
1596 (unsigned long int) mode
->c_cc
[VMIN
],
1597 (unsigned long int) mode
->c_cc
[VTIME
]);
1598 if (current_col
!= 0)
1602 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1604 if (mode_info
[i
].flags
& OMIT
)
1606 if (mode_info
[i
].type
!= prev_type
)
1610 prev_type
= mode_info
[i
].type
;
1613 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1614 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1615 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1616 wrapf ("%s", mode_info
[i
].name
);
1617 else if (mode_info
[i
].flags
& REV
)
1618 wrapf ("-%s", mode_info
[i
].name
);
1625 display_speed (struct termios
*mode
, bool fancy
)
1627 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1628 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1629 baud_to_value (cfgetospeed (mode
)));
1631 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1632 baud_to_value (cfgetispeed (mode
)),
1633 baud_to_value (cfgetospeed (mode
)));
1639 display_recoverable (struct termios
*mode
)
1643 printf ("%lx:%lx:%lx:%lx",
1644 (unsigned long int) mode
->c_iflag
,
1645 (unsigned long int) mode
->c_oflag
,
1646 (unsigned long int) mode
->c_cflag
,
1647 (unsigned long int) mode
->c_lflag
);
1648 for (i
= 0; i
< NCCS
; ++i
)
1649 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
1653 /* NOTE: identical to below, modulo use of tcflag_t */
1655 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
1660 ul
= strtoul (s
, p
, base
);
1661 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
1667 /* NOTE: identical to above, modulo use of cc_t */
1669 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
1673 ul
= strtoul (s
, p
, base
);
1674 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
1680 /* Parse the output of display_recoverable.
1681 Return false if any part of it is invalid. */
1683 recover_mode (char const *arg
, struct termios
*mode
)
1686 char const *s
= arg
;
1688 for (i
= 0; i
< 4; i
++)
1691 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
1695 mode
->c_iflag
= flag
[0];
1696 mode
->c_oflag
= flag
[1];
1697 mode
->c_cflag
= flag
[2];
1698 mode
->c_lflag
= flag
[3];
1700 for (i
= 0; i
< NCCS
; ++i
)
1703 char delim
= i
< NCCS
- 1 ? ':' : '\0';
1704 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
1714 const char *string
; /* ASCII representation. */
1715 speed_t speed
; /* Internal form. */
1716 unsigned long int value
; /* Numeric value. */
1719 static struct speed_map
const speeds
[] =
1726 {"134.5", B134
, 134},
1731 {"1200", B1200
, 1200},
1732 {"1800", B1800
, 1800},
1733 {"2400", B2400
, 2400},
1734 {"4800", B4800
, 4800},
1735 {"9600", B9600
, 9600},
1736 {"19200", B19200
, 19200},
1737 {"38400", B38400
, 38400},
1738 {"exta", B19200
, 19200},
1739 {"extb", B38400
, 38400},
1741 {"57600", B57600
, 57600},
1744 {"115200", B115200
, 115200},
1747 {"230400", B230400
, 230400},
1750 {"460800", B460800
, 460800},
1753 {"500000", B500000
, 500000},
1756 {"576000", B576000
, 576000},
1759 {"921600", B921600
, 921600},
1762 {"1000000", B1000000
, 1000000},
1765 {"1152000", B1152000
, 1152000},
1768 {"1500000", B1500000
, 1500000},
1771 {"2000000", B2000000
, 2000000},
1774 {"2500000", B2500000
, 2500000},
1777 {"3000000", B3000000
, 3000000},
1780 {"3500000", B3500000
, 3500000},
1783 {"4000000", B4000000
, 4000000},
1789 string_to_baud (const char *arg
)
1793 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1794 if (STREQ (arg
, speeds
[i
].string
))
1795 return speeds
[i
].speed
;
1796 return (speed_t
) -1;
1799 static unsigned long int
1800 baud_to_value (speed_t speed
)
1804 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1805 if (speed
== speeds
[i
].speed
)
1806 return speeds
[i
].value
;
1811 sane_mode (struct termios
*mode
)
1816 for (i
= 0; control_info
[i
].name
; ++i
)
1819 if (STREQ (control_info
[i
].name
, "min"))
1822 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1825 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1827 if (mode_info
[i
].flags
& SANE_SET
)
1829 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1830 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1832 else if (mode_info
[i
].flags
& SANE_UNSET
)
1834 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1835 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1840 /* Return a string that is the printable representation of character CH. */
1841 /* Adapted from `cat' by Torbjorn Granlund. */
1846 static char buf
[10];
1849 if (ch
== _POSIX_VDISABLE
)
1868 *bpout
++ = ch
- 128;
1878 *bpout
++ = ch
- 128 + 64;
1888 return (const char *) buf
;
1891 /* Parse string S as an integer, using decimal radix by default,
1892 but allowing octal and hex numbers as in C. Reject values
1893 larger than MAXVAL. */
1895 static unsigned long int
1896 integer_arg (const char *s
, unsigned long int maxval
)
1898 unsigned long int value
;
1899 if (xstrtoul (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
|| maxval
< value
)
1901 error (0, 0, _("invalid integer argument %s"), quote (s
));
1902 usage (EXIT_FAILURE
);