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
},
283 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
286 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
289 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
292 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
296 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
300 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
301 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
304 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
305 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
308 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
309 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
312 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
313 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
315 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
317 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
318 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
319 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
320 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
321 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
322 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
324 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
327 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
330 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
331 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
334 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
335 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
338 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
339 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
342 {"evenp", combination
, REV
| OMIT
, 0, 0},
343 {"parity", combination
, REV
| OMIT
, 0, 0},
344 {"oddp", combination
, REV
| OMIT
, 0, 0},
345 {"nl", combination
, REV
| OMIT
, 0, 0},
346 {"ek", combination
, OMIT
, 0, 0},
347 {"sane", combination
, OMIT
, 0, 0},
348 {"cooked", combination
, REV
| OMIT
, 0, 0},
349 {"raw", combination
, REV
| OMIT
, 0, 0},
350 {"pass8", combination
, REV
| OMIT
, 0, 0},
351 {"litout", combination
, REV
| OMIT
, 0, 0},
352 {"cbreak", combination
, REV
| OMIT
, 0, 0},
354 {"decctlq", combination
, REV
| OMIT
, 0, 0},
356 #if defined TABDLY || defined OXTABS
357 {"tabs", combination
, REV
| OMIT
, 0, 0},
359 #if defined XCASE && defined IUCLC && defined OLCUC
360 {"lcase", combination
, REV
| OMIT
, 0, 0},
361 {"LCASE", combination
, REV
| OMIT
, 0, 0},
363 {"crt", combination
, OMIT
, 0, 0},
364 {"dec", combination
, OMIT
, 0, 0},
366 {NULL
, control
, 0, 0, 0}
369 /* Control character settings. */
372 const char *name
; /* Name given on command line. */
373 cc_t saneval
; /* Value to set for `stty sane'. */
374 size_t offset
; /* Offset in c_cc. */
377 /* Control characters. */
379 static struct control_info
const control_info
[] =
381 {"intr", CINTR
, VINTR
},
382 {"quit", CQUIT
, VQUIT
},
383 {"erase", CERASE
, VERASE
},
384 {"kill", CKILL
, VKILL
},
388 {"eol2", CEOL2
, VEOL2
},
391 {"swtch", CSWTCH
, VSWTCH
},
393 {"start", CSTART
, VSTART
},
394 {"stop", CSTOP
, VSTOP
},
395 {"susp", CSUSP
, VSUSP
},
397 {"dsusp", CDSUSP
, VDSUSP
},
400 {"rprnt", CRPRNT
, VREPRINT
},
402 # ifdef CREPRINT /* HPUX 10.20 needs this */
403 {"rprnt", CRPRNT
, CREPRINT
},
407 {"werase", CWERASE
, VWERASE
},
410 {"lnext", CLNEXT
, VLNEXT
},
413 {"flush", CFLUSHO
, VFLUSHO
},
416 {"status", CSTATUS
, VSTATUS
},
419 /* These must be last because of the display routines. */
425 static char const *visible (cc_t ch
);
426 static unsigned long int baud_to_value (speed_t speed
);
427 static bool recover_mode (char const *arg
, struct termios
*mode
);
428 static int screen_columns (void);
429 static bool set_mode (struct mode_info
const *info
, bool reversed
,
430 struct termios
*mode
);
431 static unsigned long int integer_arg (const char *s
, unsigned long int max
);
432 static speed_t
string_to_baud (const char *arg
);
433 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
434 static void display_all (struct termios
*mode
, char const *device_name
);
435 static void display_changed (struct termios
*mode
);
436 static void display_recoverable (struct termios
*mode
);
437 static void display_settings (enum output_type output_type
,
438 struct termios
*mode
,
439 const char *device_name
);
440 static void display_speed (struct termios
*mode
, bool fancy
);
441 static void display_window_size (bool fancy
, char const *device_name
);
442 static void sane_mode (struct termios
*mode
);
443 static void set_control_char (struct control_info
const *info
,
445 struct termios
*mode
);
446 static void set_speed (enum speed_setting type
, const char *arg
,
447 struct termios
*mode
);
448 static void set_window_size (int rows
, int cols
, char const *device_name
);
450 /* The width of the screen, for output wrapping. */
453 /* Current position, to know when to wrap. */
454 static int current_col
;
456 static struct option
const longopts
[] =
458 {"all", no_argument
, NULL
, 'a'},
459 {"save", no_argument
, NULL
, 'g'},
460 {"file", required_argument
, NULL
, 'F'},
461 {GETOPT_HELP_OPTION_DECL
},
462 {GETOPT_VERSION_OPTION_DECL
},
466 static void wrapf (const char *message
, ...)
467 __attribute__ ((__format__ (__printf__
, 1, 2)));
469 /* Print format string MESSAGE and optional args.
470 Wrap to next line first if it won't fit.
471 Print a space first unless MESSAGE will start a new line. */
474 wrapf (const char *message
,...)
480 va_start (args
, message
);
481 buflen
= vasprintf (&buf
, message
, args
);
489 if (max_col
- current_col
< buflen
)
503 current_col
+= buflen
;
509 if (status
!= EXIT_SUCCESS
)
510 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
515 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
516 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
517 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
519 program_name
, program_name
, program_name
);
521 Print or change terminal characteristics.\n\
523 -a, --all print all current settings in human-readable form\n\
524 -g, --save print all current settings in a stty-readable form\n\
525 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
527 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
528 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
531 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
532 settings. The underlying system defines which settings are available.\n\
536 Special characters:\n\
537 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
538 eof CHAR CHAR will send an end of file (terminate the input)\n\
539 eol CHAR CHAR will end the line\n\
542 * eol2 CHAR alternate CHAR for ending the line\n\
543 erase CHAR CHAR will erase the last character typed\n\
544 intr CHAR CHAR will send an interrupt signal\n\
545 kill CHAR CHAR will erase the current line\n\
548 * lnext CHAR CHAR will enter the next character quoted\n\
549 quit CHAR CHAR will send a quit signal\n\
550 * rprnt CHAR CHAR will redraw the current line\n\
551 start CHAR CHAR will restart the output after stopping it\n\
554 stop CHAR CHAR will stop the output\n\
555 susp CHAR CHAR will send a terminal stop signal\n\
556 * swtch CHAR CHAR will switch to a different shell layer\n\
557 * werase CHAR CHAR will erase the last word typed\n\
562 N set the input and output speeds to N bauds\n\
563 * cols N tell the kernel that the terminal has N columns\n\
564 * columns N same as cols N\n\
567 ispeed N set the input speed to N\n\
568 * line N use line discipline N\n\
569 min N with -icanon, set N characters minimum for a completed read\n\
570 ospeed N set the output speed to N\n\
573 * rows N tell the kernel that the terminal has N rows\n\
574 * size print the number of rows and columns according to the kernel\n\
575 speed print the terminal speed\n\
576 time N with -icanon, set read timeout of N tenths of a second\n\
581 [-]clocal disable modem control signals\n\
582 [-]cread allow input to be received\n\
583 * [-]crtscts enable RTS/CTS handshaking\n\
584 csN set character size to N bits, N in [5..8]\n\
587 [-]cstopb use two stop bits per character (one with `-')\n\
588 [-]hup send a hangup signal when the last process closes the tty\n\
589 [-]hupcl same as [-]hup\n\
590 [-]parenb generate parity bit in output and expect parity bit in input\n\
591 [-]parodd set odd parity (even with `-')\n\
596 [-]brkint breaks cause an interrupt signal\n\
597 [-]icrnl translate carriage return to newline\n\
598 [-]ignbrk ignore break characters\n\
599 [-]igncr ignore carriage return\n\
602 [-]ignpar ignore characters with parity errors\n\
603 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
604 [-]inlcr translate newline to carriage return\n\
605 [-]inpck enable input parity checking\n\
606 [-]istrip clear high (8th) bit of input characters\n\
609 * [-]iutf8 assume input characters are UTF-8 encoded\n\
612 * [-]iuclc translate uppercase characters to lowercase\n\
613 * [-]ixany let any character restart output, not only start character\n\
614 [-]ixoff enable sending of start/stop characters\n\
615 [-]ixon enable XON/XOFF flow control\n\
616 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
617 [-]tandem same as [-]ixoff\n\
622 * bsN backspace delay style, N in [0..1]\n\
623 * crN carriage return delay style, N in [0..3]\n\
624 * ffN form feed delay style, N in [0..1]\n\
625 * nlN newline delay style, N in [0..1]\n\
628 * [-]ocrnl translate carriage return to newline\n\
629 * [-]ofdel use delete characters for fill instead of null characters\n\
630 * [-]ofill use fill (padding) characters instead of timing for delays\n\
631 * [-]olcuc translate lowercase characters to uppercase\n\
632 * [-]onlcr translate newline to carriage return-newline\n\
633 * [-]onlret newline performs a carriage return\n\
636 * [-]onocr do not print carriage returns in the first column\n\
637 [-]opost postprocess output\n\
638 * tabN horizontal tab delay style, N in [0..3]\n\
639 * tabs same as tab0\n\
640 * -tabs same as tab3\n\
641 * vtN vertical tab delay style, N in [0..1]\n\
646 [-]crterase echo erase characters as backspace-space-backspace\n\
647 * crtkill kill all line by obeying the echoprt and echoe settings\n\
648 * -crtkill kill all line by obeying the echoctl and echok settings\n\
651 * [-]ctlecho echo control characters in hat notation (`^c')\n\
652 [-]echo echo input characters\n\
653 * [-]echoctl same as [-]ctlecho\n\
654 [-]echoe same as [-]crterase\n\
655 [-]echok echo a newline after a kill character\n\
658 * [-]echoke same as [-]crtkill\n\
659 [-]echonl echo newline even if not echoing other characters\n\
660 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
661 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
662 [-]iexten enable non-POSIX special characters\n\
665 [-]isig enable interrupt, quit, and suspend special characters\n\
666 [-]noflsh disable flushing after interrupt and quit special characters\n\
667 * [-]prterase same as [-]echoprt\n\
668 * [-]tostop stop background jobs that try to write to the terminal\n\
669 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
673 Combination settings:\n\
674 * [-]LCASE same as [-]lcase\n\
675 cbreak same as -icanon\n\
676 -cbreak same as icanon\n\
679 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
680 icanon, eof and eol characters to their default values\n\
681 -cooked same as raw\n\
682 crt same as echoe echoctl echoke\n\
685 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
687 * [-]decctlq same as [-]ixany\n\
688 ek erase and kill characters to their default values\n\
689 evenp same as parenb -parodd cs7\n\
692 -evenp same as -parenb cs8\n\
693 * [-]lcase same as xcase iuclc olcuc\n\
694 litout same as -parenb -istrip -opost cs8\n\
695 -litout same as parenb istrip opost cs7\n\
696 nl same as -icrnl -onlcr\n\
697 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
700 oddp same as parenb parodd cs7\n\
701 -oddp same as -parenb cs8\n\
702 [-]parity same as [-]evenp\n\
703 pass8 same as -parenb -istrip cs8\n\
704 -pass8 same as parenb istrip cs7\n\
707 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
708 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
709 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
710 -raw same as cooked\n\
713 sane same as cread -ignbrk brkint -inlcr -igncr icrnl -iutf8\n\
714 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
715 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
716 isig icanon iexten echo echoe echok -echonl -noflsh\n\
717 -xcase -tostop -echoprt echoctl echoke, all special\n\
718 characters to their default values\n\
722 Handle the tty line connected to standard input. Without arguments,\n\
723 prints baud rate, line discipline, and deviations from stty sane. In\n\
724 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
725 127; special values ^- or undef used to disable special characters.\n\
727 emit_ancillary_info ();
733 main (int argc
, char **argv
)
735 /* Initialize to all zeroes so there is no risk memcmp will report a
736 spurious difference in an uninitialized portion of the structure. */
737 DECLARE_ZEROED_AGGREGATE (struct termios
, mode
);
739 enum output_type output_type
;
743 bool require_set_attr
;
746 bool recoverable_output
;
749 char *file_name
= NULL
;
750 const char *device_name
;
752 initialize_main (&argc
, &argv
);
753 set_program_name (argv
[0]);
754 setlocale (LC_ALL
, "");
755 bindtextdomain (PACKAGE
, LOCALEDIR
);
756 textdomain (PACKAGE
);
758 atexit (close_stdout
);
760 output_type
= changed
;
761 verbose_output
= false;
762 recoverable_output
= false;
764 /* Don't print error messages for unrecognized options. */
767 /* If any new options are ever added to stty, the short options MUST
768 NOT allow any ambiguity with the stty settings. For example, the
769 stty setting "-gagFork" would not be feasible, since it will be
770 parsed as "-g -a -g -F ork". If you change anything about how
771 stty parses options, be sure it still works with combinations of
772 short and long options, --, POSIXLY_CORRECT, etc. */
774 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
781 verbose_output
= true;
786 recoverable_output
= true;
787 output_type
= recoverable
;
792 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
796 case_GETOPT_HELP_CHAR
;
798 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
803 /* Skip the argument containing this unrecognized option;
804 the 2nd pass will analyze it. */
807 /* Restart getopt_long from the first unskipped argument. */
814 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
815 while (opti
< optind
)
816 argv
[argi
+ opti
++] = NULL
;
819 /* Specifying both -a and -g gets an error. */
820 if (verbose_output
&& recoverable_output
)
821 error (EXIT_FAILURE
, 0,
822 _("the options for verbose and stty-readable output styles are\n"
823 "mutually exclusive"));
825 /* Specifying any other arguments with -a or -g gets an error. */
826 if (!noargs
&& (verbose_output
|| recoverable_output
))
827 error (EXIT_FAILURE
, 0,
828 _("when specifying an output style, modes may not be set"));
830 /* FIXME: it'd be better not to open the file until we've verified
831 that all arguments are valid. Otherwise, we could end up doing
832 only some of the requested operations and then failing, probably
833 leaving things in an undesirable state. */
838 device_name
= file_name
;
839 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
840 error (EXIT_FAILURE
, errno
, "%s", device_name
);
841 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
842 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
843 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
847 device_name
= _("standard input");
849 if (tcgetattr (STDIN_FILENO
, &mode
))
850 error (EXIT_FAILURE
, errno
, "%s", device_name
);
852 if (verbose_output
|| recoverable_output
|| noargs
)
854 max_col
= screen_columns ();
856 display_settings (output_type
, &mode
, device_name
);
860 speed_was_set
= false;
861 require_set_attr
= false;
862 for (k
= 1; k
< argc
; k
++)
864 char const *arg
= argv
[k
];
865 bool match_found
= false;
866 bool reversed
= false;
877 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
879 if (STREQ (arg
, mode_info
[i
].name
))
881 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
882 require_set_attr
= true;
886 if (!match_found
&& reversed
)
888 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
889 usage (EXIT_FAILURE
);
893 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
895 if (STREQ (arg
, control_info
[i
].name
))
899 error (0, 0, _("missing argument to %s"), quote (arg
));
900 usage (EXIT_FAILURE
);
904 set_control_char (&control_info
[i
], argv
[k
], &mode
);
905 require_set_attr
= true;
912 if (STREQ (arg
, "ispeed"))
916 error (0, 0, _("missing argument to %s"), quote (arg
));
917 usage (EXIT_FAILURE
);
920 set_speed (input_speed
, argv
[k
], &mode
);
921 speed_was_set
= true;
922 require_set_attr
= true;
924 else if (STREQ (arg
, "ospeed"))
928 error (0, 0, _("missing argument to %s"), quote (arg
));
929 usage (EXIT_FAILURE
);
932 set_speed (output_speed
, argv
[k
], &mode
);
933 speed_was_set
= true;
934 require_set_attr
= true;
937 else if (STREQ (arg
, "rows"))
941 error (0, 0, _("missing argument to %s"), quote (arg
));
942 usage (EXIT_FAILURE
);
945 set_window_size (integer_arg (argv
[k
], INT_MAX
), -1,
948 else if (STREQ (arg
, "cols")
949 || STREQ (arg
, "columns"))
953 error (0, 0, _("missing argument to %s"), quote (arg
));
954 usage (EXIT_FAILURE
);
957 set_window_size (-1, integer_arg (argv
[k
], INT_MAX
),
960 else if (STREQ (arg
, "size"))
962 max_col
= screen_columns ();
964 display_window_size (false, device_name
);
968 else if (STREQ (arg
, "line"))
970 unsigned long int value
;
973 error (0, 0, _("missing argument to %s"), quote (arg
));
974 usage (EXIT_FAILURE
);
977 mode
.c_line
= value
= integer_arg (argv
[k
], ULONG_MAX
);
978 if (mode
.c_line
!= value
)
979 error (0, 0, _("invalid line discipline %s"), quote (argv
[k
]));
980 require_set_attr
= true;
983 else if (STREQ (arg
, "speed"))
985 max_col
= screen_columns ();
986 display_speed (&mode
, false);
988 else if (string_to_baud (arg
) != (speed_t
) -1)
990 set_speed (both_speeds
, arg
, &mode
);
991 speed_was_set
= true;
992 require_set_attr
= true;
996 if (! recover_mode (arg
, &mode
))
998 error (0, 0, _("invalid argument %s"), quote (arg
));
999 usage (EXIT_FAILURE
);
1001 require_set_attr
= true;
1006 if (require_set_attr
)
1008 /* Initialize to all zeroes so there is no risk memcmp will report a
1009 spurious difference in an uninitialized portion of the structure. */
1010 DECLARE_ZEROED_AGGREGATE (struct termios
, new_mode
);
1012 if (tcsetattr (STDIN_FILENO
, TCSADRAIN
, &mode
))
1013 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1015 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1016 it performs *any* of the requested operations. This means it
1017 can report `success' when it has actually failed to perform
1018 some proper subset of the requested operations. To detect
1019 this partial failure, get the current terminal attributes and
1020 compare them to the requested ones. */
1022 if (tcgetattr (STDIN_FILENO
, &new_mode
))
1023 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1025 /* Normally, one shouldn't use memcmp to compare structures that
1026 may have `holes' containing uninitialized data, but we have been
1027 careful to initialize the storage of these two variables to all
1028 zeroes. One might think it more efficient simply to compare the
1029 modified fields, but that would require enumerating those fields --
1030 and not all systems have the same fields in this structure. */
1032 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1035 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1036 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1037 sometimes (m1 != m2). The only difference is in the four bits
1038 of the c_cflag field corresponding to the baud rate. To save
1039 Sun users a little confusion, don't report an error if this
1040 happens. But suppress the error only if we haven't tried to
1041 set the baud rate explicitly -- otherwise we'd never give an
1042 error for a true failure to set the baud rate. */
1044 new_mode
.c_cflag
&= (~CIBAUD
);
1045 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
1048 error (EXIT_FAILURE
, 0,
1049 _("%s: unable to perform all requested operations"),
1054 printf ("new_mode: mode\n");
1055 for (i
= 0; i
< sizeof (new_mode
); i
++)
1056 printf ("0x%02x: 0x%02x\n",
1057 *(((unsigned char *) &new_mode
) + i
),
1058 *(((unsigned char *) &mode
) + i
));
1065 exit (EXIT_SUCCESS
);
1068 /* Return false if not applied because not reversible; otherwise
1072 set_mode (struct mode_info
const *info
, bool reversed
, struct termios
*mode
)
1076 if (reversed
&& (info
->flags
& REV
) == 0)
1079 bitsp
= mode_type_flag (info
->type
, mode
);
1083 /* Combination mode. */
1084 if (STREQ (info
->name
, "evenp") || STREQ (info
->name
, "parity"))
1087 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1089 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
1091 else if (STREQ (info
->name
, "oddp"))
1094 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1096 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
1098 else if (STREQ (info
->name
, "nl"))
1102 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
1103 mode
->c_oflag
= (mode
->c_oflag
1118 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
1120 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
1124 else if (STREQ (info
->name
, "ek"))
1126 mode
->c_cc
[VERASE
] = CERASE
;
1127 mode
->c_cc
[VKILL
] = CKILL
;
1129 else if (STREQ (info
->name
, "sane"))
1131 else if (STREQ (info
->name
, "cbreak"))
1134 mode
->c_lflag
|= ICANON
;
1136 mode
->c_lflag
&= ~ICANON
;
1138 else if (STREQ (info
->name
, "pass8"))
1142 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1143 mode
->c_iflag
|= ISTRIP
;
1147 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1148 mode
->c_iflag
&= ~ISTRIP
;
1151 else if (STREQ (info
->name
, "litout"))
1155 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1156 mode
->c_iflag
|= ISTRIP
;
1157 mode
->c_oflag
|= OPOST
;
1161 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1162 mode
->c_iflag
&= ~ISTRIP
;
1163 mode
->c_oflag
&= ~OPOST
;
1166 else if (STREQ (info
->name
, "raw") || STREQ (info
->name
, "cooked"))
1168 if ((info
->name
[0] == 'r' && reversed
)
1169 || (info
->name
[0] == 'c' && !reversed
))
1172 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1173 mode
->c_oflag
|= OPOST
;
1174 mode
->c_lflag
|= ISIG
| ICANON
;
1176 mode
->c_cc
[VEOF
] = CEOF
;
1179 mode
->c_cc
[VEOL
] = CEOL
;
1186 mode
->c_oflag
&= ~OPOST
;
1187 mode
->c_lflag
&= ~(ISIG
| ICANON
1192 mode
->c_cc
[VMIN
] = 1;
1193 mode
->c_cc
[VTIME
] = 0;
1197 else if (STREQ (info
->name
, "decctlq"))
1200 mode
->c_iflag
|= IXANY
;
1202 mode
->c_iflag
&= ~IXANY
;
1206 else if (STREQ (info
->name
, "tabs"))
1209 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1211 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1215 else if (STREQ (info
->name
, "tabs"))
1218 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1220 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1224 #if defined XCASE && defined IUCLC && defined OLCUC
1225 else if (STREQ (info
->name
, "lcase")
1226 || STREQ (info
->name
, "LCASE"))
1230 mode
->c_lflag
&= ~XCASE
;
1231 mode
->c_iflag
&= ~IUCLC
;
1232 mode
->c_oflag
&= ~OLCUC
;
1236 mode
->c_lflag
|= XCASE
;
1237 mode
->c_iflag
|= IUCLC
;
1238 mode
->c_oflag
|= OLCUC
;
1242 else if (STREQ (info
->name
, "crt"))
1243 mode
->c_lflag
|= ECHOE
1251 else if (STREQ (info
->name
, "dec"))
1253 mode
->c_cc
[VINTR
] = 3; /* ^C */
1254 mode
->c_cc
[VERASE
] = 127; /* DEL */
1255 mode
->c_cc
[VKILL
] = 21; /* ^U */
1256 mode
->c_lflag
|= ECHOE
1265 mode
->c_iflag
&= ~IXANY
;
1270 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1272 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1278 set_control_char (struct control_info
const *info
, const char *arg
,
1279 struct termios
*mode
)
1281 unsigned long int value
;
1283 if (STREQ (info
->name
, "min") || STREQ (info
->name
, "time"))
1284 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1285 else if (arg
[0] == '\0' || arg
[1] == '\0')
1286 value
= to_uchar (arg
[0]);
1287 else if (STREQ (arg
, "^-") || STREQ (arg
, "undef"))
1288 value
= _POSIX_VDISABLE
;
1289 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1294 value
= to_uchar (arg
[1]) & ~0140; /* Non-letters get weird results. */
1297 value
= integer_arg (arg
, TYPE_MAXIMUM (cc_t
));
1298 mode
->c_cc
[info
->offset
] = value
;
1302 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1306 baud
= string_to_baud (arg
);
1307 if (type
== input_speed
|| type
== both_speeds
)
1308 cfsetispeed (mode
, baud
);
1309 if (type
== output_speed
|| type
== both_speeds
)
1310 cfsetospeed (mode
, baud
);
1316 get_win_size (int fd
, struct winsize
*win
)
1318 int err
= ioctl (fd
, TIOCGWINSZ
, (char *) win
);
1323 set_window_size (int rows
, int cols
, char const *device_name
)
1327 if (get_win_size (STDIN_FILENO
, &win
))
1329 if (errno
!= EINVAL
)
1330 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1331 memset (&win
, 0, sizeof (win
));
1340 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1341 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1342 This comment from sys/ttold.h describes Sun's twisted logic - a better
1343 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1344 At any rate, the problem is gone in Solaris 2.x.
1346 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1347 but they can be disambiguated by checking whether a "struct ttysize"
1348 structure's "ts_lines" field is greater than 64K or not. If so,
1349 it's almost certainly a "struct winsize" instead.
1351 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1352 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1353 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1354 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1355 "stty cols 0 rows 0" would do the right thing. On a little-endian
1356 machine like the sun386i, the problem is the same, but for ws_col == 0.
1358 The workaround is to do the ioctl once with row and col = 1 to set the
1359 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1361 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1363 struct ttysize ttysz
;
1365 ttysz
.ts_lines
= win
.ws_row
;
1366 ttysz
.ts_cols
= win
.ws_col
;
1371 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1372 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1374 if (ioctl (STDIN_FILENO
, TIOCSSIZE
, (char *) &ttysz
))
1375 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1380 if (ioctl (STDIN_FILENO
, TIOCSWINSZ
, (char *) &win
))
1381 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1385 display_window_size (bool fancy
, char const *device_name
)
1389 if (get_win_size (STDIN_FILENO
, &win
))
1391 if (errno
!= EINVAL
)
1392 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1394 error (EXIT_FAILURE
, 0,
1395 _("%s: no size information for this device"), device_name
);
1399 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1400 win
.ws_row
, win
.ws_col
);
1408 screen_columns (void)
1413 /* With Solaris 2.[123], this ioctl fails and errno is set to
1414 EINVAL for telnet (but not rlogin) sessions.
1415 On ISC 3.0, it fails for the console and the serial port
1416 (but it works for ptys).
1417 It can also fail on any system when stdout isn't a tty.
1418 In case of any failure, just use the default. */
1419 if (get_win_size (STDOUT_FILENO
, &win
) == 0 && 0 < win
.ws_col
)
1423 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1424 char *col_string
= getenv ("COLUMNS");
1426 if (!(col_string
!= NULL
1427 && xstrtol (col_string
, NULL
, 0, &n_columns
, "") == LONGINT_OK
1429 && n_columns
<= INT_MAX
))
1436 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1441 return &mode
->c_cflag
;
1444 return &mode
->c_iflag
;
1447 return &mode
->c_oflag
;
1450 return &mode
->c_lflag
;
1461 display_settings (enum output_type output_type
, struct termios
*mode
,
1462 char const *device_name
)
1464 switch (output_type
)
1467 display_changed (mode
);
1471 display_all (mode
, device_name
);
1475 display_recoverable (mode
);
1481 display_changed (struct termios
*mode
)
1487 enum mode_type prev_type
= control
;
1489 display_speed (mode
, true);
1491 wrapf ("line = %d;", mode
->c_line
);
1497 for (i
= 0; !STREQ (control_info
[i
].name
, "min"); ++i
)
1499 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1501 /* If swtch is the same as susp, don't print both. */
1503 if (STREQ (control_info
[i
].name
, "swtch"))
1506 /* If eof uses the same slot as min, only print whichever applies. */
1508 if ((mode
->c_lflag
& ICANON
) == 0
1509 && (STREQ (control_info
[i
].name
, "eof")
1510 || STREQ (control_info
[i
].name
, "eol")))
1515 wrapf ("%s = %s;", control_info
[i
].name
,
1516 visible (mode
->c_cc
[control_info
[i
].offset
]));
1518 if ((mode
->c_lflag
& ICANON
) == 0)
1520 wrapf ("min = %lu; time = %lu;\n",
1521 (unsigned long int) mode
->c_cc
[VMIN
],
1522 (unsigned long int) mode
->c_cc
[VTIME
]);
1524 else if (!empty_line
)
1529 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1531 if (mode_info
[i
].flags
& OMIT
)
1533 if (mode_info
[i
].type
!= prev_type
)
1541 prev_type
= mode_info
[i
].type
;
1544 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1545 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1546 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1548 if (mode_info
[i
].flags
& SANE_UNSET
)
1550 wrapf ("%s", mode_info
[i
].name
);
1554 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1556 wrapf ("-%s", mode_info
[i
].name
);
1566 display_all (struct termios
*mode
, char const *device_name
)
1571 enum mode_type prev_type
= control
;
1573 display_speed (mode
, true);
1575 display_window_size (true, device_name
);
1578 wrapf ("line = %d;", mode
->c_line
);
1583 for (i
= 0; ! STREQ (control_info
[i
].name
, "min"); ++i
)
1585 /* If swtch is the same as susp, don't print both. */
1587 if (STREQ (control_info
[i
].name
, "swtch"))
1590 /* If eof uses the same slot as min, only print whichever applies. */
1592 if ((mode
->c_lflag
& ICANON
) == 0
1593 && (STREQ (control_info
[i
].name
, "eof")
1594 || STREQ (control_info
[i
].name
, "eol")))
1597 wrapf ("%s = %s;", control_info
[i
].name
,
1598 visible (mode
->c_cc
[control_info
[i
].offset
]));
1601 if ((mode
->c_lflag
& ICANON
) == 0)
1603 wrapf ("min = %lu; time = %lu;",
1604 (unsigned long int) mode
->c_cc
[VMIN
],
1605 (unsigned long int) mode
->c_cc
[VTIME
]);
1606 if (current_col
!= 0)
1610 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1612 if (mode_info
[i
].flags
& OMIT
)
1614 if (mode_info
[i
].type
!= prev_type
)
1618 prev_type
= mode_info
[i
].type
;
1621 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1622 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1623 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1624 wrapf ("%s", mode_info
[i
].name
);
1625 else if (mode_info
[i
].flags
& REV
)
1626 wrapf ("-%s", mode_info
[i
].name
);
1633 display_speed (struct termios
*mode
, bool fancy
)
1635 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1636 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1637 baud_to_value (cfgetospeed (mode
)));
1639 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1640 baud_to_value (cfgetispeed (mode
)),
1641 baud_to_value (cfgetospeed (mode
)));
1647 display_recoverable (struct termios
*mode
)
1651 printf ("%lx:%lx:%lx:%lx",
1652 (unsigned long int) mode
->c_iflag
,
1653 (unsigned long int) mode
->c_oflag
,
1654 (unsigned long int) mode
->c_cflag
,
1655 (unsigned long int) mode
->c_lflag
);
1656 for (i
= 0; i
< NCCS
; ++i
)
1657 printf (":%lx", (unsigned long int) mode
->c_cc
[i
]);
1661 /* NOTE: identical to below, modulo use of tcflag_t */
1663 strtoul_tcflag_t (char const *s
, int base
, char **p
, tcflag_t
*result
,
1668 ul
= strtoul (s
, p
, base
);
1669 if (errno
|| **p
!= delim
|| *p
== s
|| (tcflag_t
) ul
!= ul
)
1675 /* NOTE: identical to above, modulo use of cc_t */
1677 strtoul_cc_t (char const *s
, int base
, char **p
, cc_t
*result
, char delim
)
1681 ul
= strtoul (s
, p
, base
);
1682 if (errno
|| **p
!= delim
|| *p
== s
|| (cc_t
) ul
!= ul
)
1688 /* Parse the output of display_recoverable.
1689 Return false if any part of it is invalid. */
1691 recover_mode (char const *arg
, struct termios
*mode
)
1694 char const *s
= arg
;
1696 for (i
= 0; i
< 4; i
++)
1699 if (strtoul_tcflag_t (s
, 16, &p
, flag
+ i
, ':') != 0)
1703 mode
->c_iflag
= flag
[0];
1704 mode
->c_oflag
= flag
[1];
1705 mode
->c_cflag
= flag
[2];
1706 mode
->c_lflag
= flag
[3];
1708 for (i
= 0; i
< NCCS
; ++i
)
1711 char delim
= i
< NCCS
- 1 ? ':' : '\0';
1712 if (strtoul_cc_t (s
, 16, &p
, mode
->c_cc
+ i
, delim
) != 0)
1722 const char *string
; /* ASCII representation. */
1723 speed_t speed
; /* Internal form. */
1724 unsigned long int value
; /* Numeric value. */
1727 static struct speed_map
const speeds
[] =
1734 {"134.5", B134
, 134},
1739 {"1200", B1200
, 1200},
1740 {"1800", B1800
, 1800},
1741 {"2400", B2400
, 2400},
1742 {"4800", B4800
, 4800},
1743 {"9600", B9600
, 9600},
1744 {"19200", B19200
, 19200},
1745 {"38400", B38400
, 38400},
1746 {"exta", B19200
, 19200},
1747 {"extb", B38400
, 38400},
1749 {"57600", B57600
, 57600},
1752 {"115200", B115200
, 115200},
1755 {"230400", B230400
, 230400},
1758 {"460800", B460800
, 460800},
1761 {"500000", B500000
, 500000},
1764 {"576000", B576000
, 576000},
1767 {"921600", B921600
, 921600},
1770 {"1000000", B1000000
, 1000000},
1773 {"1152000", B1152000
, 1152000},
1776 {"1500000", B1500000
, 1500000},
1779 {"2000000", B2000000
, 2000000},
1782 {"2500000", B2500000
, 2500000},
1785 {"3000000", B3000000
, 3000000},
1788 {"3500000", B3500000
, 3500000},
1791 {"4000000", B4000000
, 4000000},
1797 string_to_baud (const char *arg
)
1801 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1802 if (STREQ (arg
, speeds
[i
].string
))
1803 return speeds
[i
].speed
;
1804 return (speed_t
) -1;
1807 static unsigned long int
1808 baud_to_value (speed_t speed
)
1812 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1813 if (speed
== speeds
[i
].speed
)
1814 return speeds
[i
].value
;
1819 sane_mode (struct termios
*mode
)
1824 for (i
= 0; control_info
[i
].name
; ++i
)
1827 if (STREQ (control_info
[i
].name
, "min"))
1830 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1833 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1835 if (mode_info
[i
].flags
& SANE_SET
)
1837 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1838 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1840 else if (mode_info
[i
].flags
& SANE_UNSET
)
1842 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1843 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1848 /* Return a string that is the printable representation of character CH. */
1849 /* Adapted from `cat' by Torbjorn Granlund. */
1854 static char buf
[10];
1857 if (ch
== _POSIX_VDISABLE
)
1876 *bpout
++ = ch
- 128;
1886 *bpout
++ = ch
- 128 + 64;
1896 return (const char *) buf
;
1899 /* Parse string S as an integer, using decimal radix by default,
1900 but allowing octal and hex numbers as in C. Reject values
1901 larger than MAXVAL. */
1903 static unsigned long int
1904 integer_arg (const char *s
, unsigned long int maxval
)
1906 unsigned long int value
;
1907 if (xstrtoul (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
|| maxval
< value
)
1909 error (0, 0, _("invalid integer argument %s"), quote (s
));
1910 usage (EXIT_FAILURE
);