1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2005 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 2, or (at your option)
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, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Usage: stty [-ag] [--all] [--save] [-F device] [--file=device] [setting...]
21 -a, --all Write all current settings to stdout in human-readable form.
22 -g, --save Write all current settings to stdout in stty-readable form.
23 -F, --file Open and use the specified device instead of stdin
25 If no args are given, write to stdout the baud rate and settings that
26 have been changed from their defaults. Mode reading and changes
27 are done on the specified device, or stdin if none was specified.
29 David MacKenzie <djm@gnu.ai.mit.edu> */
33 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
34 # define _XOPEN_SOURCE
38 #include <sys/types.h>
46 #ifdef HAVE_SYS_IOCTL_H
47 # include <sys/ioctl.h>
50 #ifdef WINSIZE_IN_PTEM
51 # include <sys/stream.h>
52 # include <sys/ptem.h>
54 #ifdef GWINSZ_IN_SYS_PTY
63 #include "fd-reopen.h"
65 #include "vasprintf.h"
68 /* The official name of this program (e.g., no `g' prefix). */
69 #define PROGRAM_NAME "stty"
71 #define AUTHORS "David MacKenzie"
73 #ifndef _POSIX_VDISABLE
74 # define _POSIX_VDISABLE 0
77 #define Control(c) ((c) & 0x1f)
78 /* Canonical values for control characters. */
80 # define CINTR Control ('c')
89 # define CKILL Control ('u')
92 # define CEOF Control ('d')
95 # define CEOL _POSIX_VDISABLE
98 # define CSTART Control ('q')
101 # define CSTOP Control ('s')
104 # define CSUSP Control ('z')
106 #if defined VEOL2 && !defined CEOL2
107 # define CEOL2 _POSIX_VDISABLE
109 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
110 character is initialized by CSWTCH, if present. */
111 #if defined VSWTC && !defined VSWTCH
112 # define VSWTCH VSWTC
114 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
115 #if defined VSUSP && !defined VSWTCH
116 # define VSWTCH VSUSP
117 # if defined CSUSP && !defined CSWTCH
118 # define CSWTCH CSUSP
121 #if defined VSWTCH && !defined CSWTCH
122 # define CSWTCH _POSIX_VDISABLE
125 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
126 So the default is to disable `swtch.' */
127 #if defined __sparc__ && defined __svr4__
129 # define CSWTCH _POSIX_VDISABLE
132 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
133 # define VWERASE VWERSE
135 #if defined VDSUSP && !defined CDSUSP
136 # define CDSUSP Control ('y')
138 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
139 # define VREPRINT VRPRNT
141 #if defined VREPRINT && !defined CRPRNT
142 # define CRPRNT Control ('r')
144 #if defined CREPRINT && !defined CRPRNT
145 # define CRPRNT Control ('r')
147 #if defined VWERASE && !defined CWERASE
148 # define CWERASE Control ('w')
150 #if defined VLNEXT && !defined CLNEXT
151 # define CLNEXT Control ('v')
153 #if defined VDISCARD && !defined VFLUSHO
154 # define VFLUSHO VDISCARD
156 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
157 # define VFLUSHO VFLUSH
159 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
160 # define ECHOCTL CTLECH
162 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
163 # define ECHOCTL TCTLECH
165 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
166 # define ECHOKE CRTKIL
168 #if defined VFLUSHO && !defined CFLUSHO
169 # define CFLUSHO Control ('o')
171 #if defined VSTATUS && !defined CSTATUS
172 # define CSTATUS Control ('t')
175 /* Which speeds to set. */
178 input_speed
, output_speed
, both_speeds
181 /* What to output and how. */
184 changed
, all
, recoverable
/* Default, -a, -g. */
187 /* Which member(s) of `struct termios' a mode uses. */
190 control
, input
, output
, local
, combination
193 /* Flags for `struct mode_info'. */
194 #define SANE_SET 1 /* Set in `sane' mode. */
195 #define SANE_UNSET 2 /* Unset in `sane' mode. */
196 #define REV 4 /* Can be turned off by prepending `-'. */
197 #define OMIT 8 /* Don't display value. */
202 const char *name
; /* Name given on command line. */
203 enum mode_type type
; /* Which structure element to change. */
204 char flags
; /* Setting and display options. */
205 unsigned long bits
; /* Bits to set for this mode. */
206 unsigned long mask
; /* Other bits to turn off for this mode. */
209 static struct mode_info mode_info
[] =
211 {"parenb", control
, REV
, PARENB
, 0},
212 {"parodd", control
, REV
, PARODD
, 0},
213 {"cs5", control
, 0, CS5
, CSIZE
},
214 {"cs6", control
, 0, CS6
, CSIZE
},
215 {"cs7", control
, 0, CS7
, CSIZE
},
216 {"cs8", control
, 0, CS8
, CSIZE
},
217 {"hupcl", control
, REV
, HUPCL
, 0},
218 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
219 {"cstopb", control
, REV
, CSTOPB
, 0},
220 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
221 {"clocal", control
, REV
, CLOCAL
, 0},
223 {"crtscts", control
, REV
, CRTSCTS
, 0},
226 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
227 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
228 {"ignpar", input
, REV
, IGNPAR
, 0},
229 {"parmrk", input
, REV
, PARMRK
, 0},
230 {"inpck", input
, REV
, INPCK
, 0},
231 {"istrip", input
, REV
, ISTRIP
, 0},
232 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
233 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
234 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
235 {"ixon", input
, REV
, IXON
, 0},
236 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
237 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
239 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
242 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
245 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
248 {"iutf8", input
, SANE_UNSET
| REV
, IUTF8
, 0},
251 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
253 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
256 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
259 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
262 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
265 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
268 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
271 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
274 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
275 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
278 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
279 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
280 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
281 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
284 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
285 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
286 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
287 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
290 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
294 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
295 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
298 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
299 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
302 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
303 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
306 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
307 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
309 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
311 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
312 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
313 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
314 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
315 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
316 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
318 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
321 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
324 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
325 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
328 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
329 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
332 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
333 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
336 {"evenp", combination
, REV
| OMIT
, 0, 0},
337 {"parity", combination
, REV
| OMIT
, 0, 0},
338 {"oddp", combination
, REV
| OMIT
, 0, 0},
339 {"nl", combination
, REV
| OMIT
, 0, 0},
340 {"ek", combination
, OMIT
, 0, 0},
341 {"sane", combination
, OMIT
, 0, 0},
342 {"cooked", combination
, REV
| OMIT
, 0, 0},
343 {"raw", combination
, REV
| OMIT
, 0, 0},
344 {"pass8", combination
, REV
| OMIT
, 0, 0},
345 {"litout", combination
, REV
| OMIT
, 0, 0},
346 {"cbreak", combination
, REV
| OMIT
, 0, 0},
348 {"decctlq", combination
, REV
| OMIT
, 0, 0},
350 #if defined TABDLY || defined OXTABS
351 {"tabs", combination
, REV
| OMIT
, 0, 0},
353 #if defined XCASE && defined IUCLC && defined OLCUC
354 {"lcase", combination
, REV
| OMIT
, 0, 0},
355 {"LCASE", combination
, REV
| OMIT
, 0, 0},
357 {"crt", combination
, OMIT
, 0, 0},
358 {"dec", combination
, OMIT
, 0, 0},
360 {NULL
, control
, 0, 0, 0}
363 /* Control character settings. */
366 const char *name
; /* Name given on command line. */
367 cc_t saneval
; /* Value to set for `stty sane'. */
368 size_t offset
; /* Offset in c_cc. */
371 /* Control characters. */
373 static struct control_info control_info
[] =
375 {"intr", CINTR
, VINTR
},
376 {"quit", CQUIT
, VQUIT
},
377 {"erase", CERASE
, VERASE
},
378 {"kill", CKILL
, VKILL
},
382 {"eol2", CEOL2
, VEOL2
},
385 {"swtch", CSWTCH
, VSWTCH
},
387 {"start", CSTART
, VSTART
},
388 {"stop", CSTOP
, VSTOP
},
389 {"susp", CSUSP
, VSUSP
},
391 {"dsusp", CDSUSP
, VDSUSP
},
394 {"rprnt", CRPRNT
, VREPRINT
},
396 # ifdef CREPRINT /* HPUX 10.20 needs this */
397 {"rprnt", CRPRNT
, CREPRINT
},
401 {"werase", CWERASE
, VWERASE
},
404 {"lnext", CLNEXT
, VLNEXT
},
407 {"flush", CFLUSHO
, VFLUSHO
},
410 {"status", CSTATUS
, VSTATUS
},
413 /* These must be last because of the display routines. */
419 static char const *visible (cc_t ch
);
420 static unsigned long int baud_to_value (speed_t speed
);
421 static bool recover_mode (char const *arg
, struct termios
*mode
);
422 static int screen_columns (void);
423 static bool set_mode (struct mode_info
*info
, bool reversed
,
424 struct termios
*mode
);
425 static unsigned long int integer_arg (const char *s
, unsigned long int max
);
426 static speed_t
string_to_baud (const char *arg
);
427 static tcflag_t
*mode_type_flag (enum mode_type type
, struct termios
*mode
);
428 static void display_all (struct termios
*mode
, char const *device_name
);
429 static void display_changed (struct termios
*mode
);
430 static void display_recoverable (struct termios
*mode
);
431 static void display_settings (enum output_type output_type
,
432 struct termios
*mode
,
433 const char *device_name
);
434 static void display_speed (struct termios
*mode
, bool fancy
);
435 static void display_window_size (bool fancy
, char const *device_name
);
436 static void sane_mode (struct termios
*mode
);
437 static void set_control_char (struct control_info
*info
,
439 struct termios
*mode
);
440 static void set_speed (enum speed_setting type
, const char *arg
,
441 struct termios
*mode
);
442 static void set_window_size (int rows
, int cols
, char const *device_name
);
444 /* The width of the screen, for output wrapping. */
447 /* Current position, to know when to wrap. */
448 static int current_col
;
450 static struct option longopts
[] =
452 {"all", no_argument
, NULL
, 'a'},
453 {"save", no_argument
, NULL
, 'g'},
454 {"file", required_argument
, NULL
, 'F'},
455 {GETOPT_HELP_OPTION_DECL
},
456 {GETOPT_VERSION_OPTION_DECL
},
460 /* The name this program was run with. */
463 static void wrapf (const char *message
, ...)
464 __attribute__ ((__format__ (__printf__
, 1, 2)));
466 /* Print format string MESSAGE and optional args.
467 Wrap to next line first if it won't fit.
468 Print a space first unless MESSAGE will start a new line. */
471 wrapf (const char *message
,...)
477 va_start (args
, message
);
478 buflen
= vasprintf (&buf
, message
, args
);
486 if (max_col
- current_col
< buflen
)
500 current_col
+= buflen
;
506 if (status
!= EXIT_SUCCESS
)
507 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
512 Usage: %s [-F DEVICE] [--file=DEVICE] [SETTING]...\n\
513 or: %s [-F DEVICE] [--file=DEVICE] [-a|--all]\n\
514 or: %s [-F DEVICE] [--file=DEVICE] [-g|--save]\n\
516 program_name
, program_name
, program_name
);
518 Print or change terminal characteristics.\n\
520 -a, --all print all current settings in human-readable form\n\
521 -g, --save print all current settings in a stty-readable form\n\
522 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
524 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
525 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
528 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
529 settings. The underlying system defines which settings are available.\n\
533 Special characters:\n\
534 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
535 eof CHAR CHAR will send an end of file (terminate the input)\n\
536 eol CHAR CHAR will end the line\n\
539 * eol2 CHAR alternate CHAR for ending the line\n\
540 erase CHAR CHAR will erase the last character typed\n\
541 intr CHAR CHAR will send an interrupt signal\n\
542 kill CHAR CHAR will erase the current line\n\
545 * lnext CHAR CHAR will enter the next character quoted\n\
546 quit CHAR CHAR will send a quit signal\n\
547 * rprnt CHAR CHAR will redraw the current line\n\
548 start CHAR CHAR will restart the output after stopping it\n\
551 stop CHAR CHAR will stop the output\n\
552 susp CHAR CHAR will send a terminal stop signal\n\
553 * swtch CHAR CHAR will switch to a different shell layer\n\
554 * werase CHAR CHAR will erase the last word typed\n\
559 N set the input and output speeds to N bauds\n\
560 * cols N tell the kernel that the terminal has N columns\n\
561 * columns N same as cols N\n\
564 ispeed N set the input speed to N\n\
565 * line N use line discipline N\n\
566 min N with -icanon, set N characters minimum for a completed read\n\
567 ospeed N set the output speed to N\n\
570 * rows N tell the kernel that the terminal has N rows\n\
571 * size print the number of rows and columns according to the kernel\n\
572 speed print the terminal speed\n\
573 time N with -icanon, set read timeout of N tenths of a second\n\
578 [-]clocal disable modem control signals\n\
579 [-]cread allow input to be received\n\
580 * [-]crtscts enable RTS/CTS handshaking\n\
581 csN set character size to N bits, N in [5..8]\n\
584 [-]cstopb use two stop bits per character (one with `-')\n\
585 [-]hup send a hangup signal when the last process closes the tty\n\
586 [-]hupcl same as [-]hup\n\
587 [-]parenb generate parity bit in output and expect parity bit in input\n\
588 [-]parodd set odd parity (even with `-')\n\
593 [-]brkint breaks cause an interrupt signal\n\
594 [-]icrnl translate carriage return to newline\n\
595 [-]ignbrk ignore break characters\n\
596 [-]igncr ignore carriage return\n\
599 [-]ignpar ignore characters with parity errors\n\
600 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
601 [-]inlcr translate newline to carriage return\n\
602 [-]inpck enable input parity checking\n\
603 [-]istrip clear high (8th) bit of input characters\n\
606 * [-]iutf8 assume input characters are UTF-8 encoded\n\
609 * [-]iuclc translate uppercase characters to lowercase\n\
610 * [-]ixany let any character restart output, not only start character\n\
611 [-]ixoff enable sending of start/stop characters\n\
612 [-]ixon enable XON/XOFF flow control\n\
613 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
614 [-]tandem same as [-]ixoff\n\
619 * bsN backspace delay style, N in [0..1]\n\
620 * crN carriage return delay style, N in [0..3]\n\
621 * ffN form feed delay style, N in [0..1]\n\
622 * nlN newline delay style, N in [0..1]\n\
625 * [-]ocrnl translate carriage return to newline\n\
626 * [-]ofdel use delete characters for fill instead of null characters\n\
627 * [-]ofill use fill (padding) characters instead of timing for delays\n\
628 * [-]olcuc translate lowercase characters to uppercase\n\
629 * [-]onlcr translate newline to carriage return-newline\n\
630 * [-]onlret newline performs a carriage return\n\
633 * [-]onocr do not print carriage returns in the first column\n\
634 [-]opost postprocess output\n\
635 * tabN horizontal tab delay style, N in [0..3]\n\
636 * tabs same as tab0\n\
637 * -tabs same as tab3\n\
638 * vtN vertical tab delay style, N in [0..1]\n\
643 [-]crterase echo erase characters as backspace-space-backspace\n\
644 * crtkill kill all line by obeying the echoprt and echoe settings\n\
645 * -crtkill kill all line by obeying the echoctl and echok settings\n\
648 * [-]ctlecho echo control characters in hat notation (`^c')\n\
649 [-]echo echo input characters\n\
650 * [-]echoctl same as [-]ctlecho\n\
651 [-]echoe same as [-]crterase\n\
652 [-]echok echo a newline after a kill character\n\
655 * [-]echoke same as [-]crtkill\n\
656 [-]echonl echo newline even if not echoing other characters\n\
657 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
658 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
659 [-]iexten enable non-POSIX special characters\n\
662 [-]isig enable interrupt, quit, and suspend special characters\n\
663 [-]noflsh disable flushing after interrupt and quit special characters\n\
664 * [-]prterase same as [-]echoprt\n\
665 * [-]tostop stop background jobs that try to write to the terminal\n\
666 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
670 Combination settings:\n\
671 * [-]LCASE same as [-]lcase\n\
672 cbreak same as -icanon\n\
673 -cbreak same as icanon\n\
676 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
677 icanon, eof and eol characters to their default values\n\
678 -cooked same as raw\n\
679 crt same as echoe echoctl echoke\n\
682 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
684 * [-]decctlq same as [-]ixany\n\
685 ek erase and kill characters to their default values\n\
686 evenp same as parenb -parodd cs7\n\
689 -evenp same as -parenb cs8\n\
690 * [-]lcase same as xcase iuclc olcuc\n\
691 litout same as -parenb -istrip -opost cs8\n\
692 -litout same as parenb istrip opost cs7\n\
693 nl same as -icrnl -onlcr\n\
694 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
697 oddp same as parenb parodd cs7\n\
698 -oddp same as -parenb cs8\n\
699 [-]parity same as [-]evenp\n\
700 pass8 same as -parenb -istrip cs8\n\
701 -pass8 same as parenb istrip cs7\n\
704 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
705 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
706 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
707 -raw same as cooked\n\
710 sane same as cread -ignbrk brkint -inlcr -igncr icrnl -iutf8\n\
711 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
712 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
713 isig icanon iexten echo echoe echok -echonl -noflsh\n\
714 -xcase -tostop -echoprt echoctl echoke, all special\n\
715 characters to their default values.\n\
719 Handle the tty line connected to standard input. Without arguments,\n\
720 prints baud rate, line discipline, and deviations from stty sane. In\n\
721 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
722 127; special values ^- or undef used to disable special characters.\n\
724 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
730 main (int argc
, char **argv
)
733 enum output_type output_type
;
737 bool require_set_attr
;
740 bool recoverable_output
;
743 char *file_name
= NULL
;
744 const char *device_name
;
746 initialize_main (&argc
, &argv
);
747 program_name
= argv
[0];
748 setlocale (LC_ALL
, "");
749 bindtextdomain (PACKAGE
, LOCALEDIR
);
750 textdomain (PACKAGE
);
752 atexit (close_stdout
);
754 output_type
= changed
;
755 verbose_output
= false;
756 recoverable_output
= false;
758 /* Don't print error messages for unrecognized options. */
761 /* If any new options are ever added to stty, the short options MUST
762 NOT allow any ambiguity with the stty settings. For example, the
763 stty setting "-gagFork" would not be feasible, since it will be
764 parsed as "-g -a -g -F ork". If you change anything about how
765 stty parses options, be sure it still works with combinations of
766 short and long options, --, POSIXLY_CORRECT, etc. */
768 while ((optc
= getopt_long (argc
- argi
, argv
+ argi
, "-agF:",
775 verbose_output
= true;
780 recoverable_output
= true;
781 output_type
= recoverable
;
786 error (EXIT_FAILURE
, 0, _("only one device may be specified"));
790 case_GETOPT_HELP_CHAR
;
792 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
797 /* Skip the argument containing this unrecognized option;
798 the 2nd pass will analyze it. */
801 /* Restart getopt_long from the first unskipped argument. */
808 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
809 while (opti
< optind
)
810 argv
[argi
+ opti
++] = NULL
;
813 /* Specifying both -a and -g gets an error. */
814 if (verbose_output
& recoverable_output
)
815 error (EXIT_FAILURE
, 0,
816 _("the options for verbose and stty-readable output styles are\n"
817 "mutually exclusive"));
819 /* Specifying any other arguments with -a or -g gets an error. */
820 if (!noargs
& (verbose_output
| recoverable_output
))
821 error (EXIT_FAILURE
, 0,
822 _("when specifying an output style, modes may not be set"));
824 /* FIXME: it'd be better not to open the file until we've verified
825 that all arguments are valid. Otherwise, we could end up doing
826 only some of the requested operations and then failing, probably
827 leaving things in an undesirable state. */
832 device_name
= file_name
;
833 if (fd_reopen (STDIN_FILENO
, device_name
, O_RDONLY
| O_NONBLOCK
, 0) < 0)
834 error (EXIT_FAILURE
, errno
, "%s", device_name
);
835 if ((fdflags
= fcntl (STDIN_FILENO
, F_GETFL
)) == -1
836 || fcntl (STDIN_FILENO
, F_SETFL
, fdflags
& ~O_NONBLOCK
) < 0)
837 error (EXIT_FAILURE
, errno
, _("%s: couldn't reset non-blocking mode"),
841 device_name
= _("standard input");
843 /* Initialize to all zeroes so there is no risk memcmp will report a
844 spurious difference in an uninitialized portion of the structure. */
845 memset (&mode
, 0, sizeof (mode
));
846 if (tcgetattr (STDIN_FILENO
, &mode
))
847 error (EXIT_FAILURE
, errno
, "%s", device_name
);
849 if (verbose_output
| recoverable_output
| noargs
)
851 max_col
= screen_columns ();
853 display_settings (output_type
, &mode
, device_name
);
857 speed_was_set
= false;
858 require_set_attr
= false;
859 for (k
= 1; k
< argc
; k
++)
861 char const *arg
= argv
[k
];
862 bool match_found
= false;
863 bool reversed
= false;
874 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
876 if (STREQ (arg
, mode_info
[i
].name
))
878 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
879 require_set_attr
= true;
883 if (!match_found
& reversed
)
885 error (0, 0, _("invalid argument %s"), quote (arg
- 1));
886 usage (EXIT_FAILURE
);
890 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
892 if (STREQ (arg
, control_info
[i
].name
))
896 error (0, 0, _("missing argument to %s"), quote (arg
));
897 usage (EXIT_FAILURE
);
901 set_control_char (&control_info
[i
], argv
[k
], &mode
);
902 require_set_attr
= true;
909 if (STREQ (arg
, "ispeed"))
913 error (0, 0, _("missing argument to %s"), quote (arg
));
914 usage (EXIT_FAILURE
);
917 set_speed (input_speed
, argv
[k
], &mode
);
918 speed_was_set
= true;
919 require_set_attr
= true;
921 else if (STREQ (arg
, "ospeed"))
925 error (0, 0, _("missing argument to %s"), quote (arg
));
926 usage (EXIT_FAILURE
);
929 set_speed (output_speed
, argv
[k
], &mode
);
930 speed_was_set
= true;
931 require_set_attr
= true;
934 else if (STREQ (arg
, "rows"))
938 error (0, 0, _("missing argument to %s"), quote (arg
));
939 usage (EXIT_FAILURE
);
942 set_window_size (integer_arg (argv
[k
], INT_MAX
), -1,
945 else if (STREQ (arg
, "cols")
946 || STREQ (arg
, "columns"))
950 error (0, 0, _("missing argument to %s"), quote (arg
));
951 usage (EXIT_FAILURE
);
954 set_window_size (-1, integer_arg (argv
[k
], INT_MAX
),
957 else if (STREQ (arg
, "size"))
959 max_col
= screen_columns ();
961 display_window_size (false, device_name
);
965 else if (STREQ (arg
, "line"))
967 unsigned long int value
;
970 error (0, 0, _("missing argument to %s"), quote (arg
));
971 usage (EXIT_FAILURE
);
974 mode
.c_line
= value
= integer_arg (argv
[k
], ULONG_MAX
);
975 if (mode
.c_line
!= value
)
976 error (0, 0, _("invalid line discipline %s"), quote (argv
[k
]));
977 require_set_attr
= true;
980 else if (STREQ (arg
, "speed"))
982 max_col
= screen_columns ();
983 display_speed (&mode
, false);
985 else if (string_to_baud (arg
) != (speed_t
) -1)
987 set_speed (both_speeds
, arg
, &mode
);
988 speed_was_set
= true;
989 require_set_attr
= true;
993 if (! recover_mode (arg
, &mode
))
995 error (0, 0, _("invalid argument %s"), quote (arg
));
996 usage (EXIT_FAILURE
);
998 require_set_attr
= true;
1003 if (require_set_attr
)
1005 struct termios new_mode
;
1007 if (tcsetattr (STDIN_FILENO
, TCSADRAIN
, &mode
))
1008 error (EXIT_FAILURE
, errno
, "%s", device_name
);
1010 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1011 it performs *any* of the requested operations. This means it
1012 can report `success' when it has actually failed to perform
1013 some proper subset of the requested operations. To detect
1014 this partial failure, get the current terminal attributes and
1015 compare them to the requested ones. */
1017 /* Initialize to all zeroes so there is no risk memcmp will report a
1018 spurious difference in an uninitialized portion of the structure. */
1019 memset (&new_mode
, 0, sizeof (new_mode
));
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
*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
*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
]);
1660 recover_mode (char const *arg
, struct termios
*mode
)
1664 unsigned long int chr
;
1665 unsigned long int iflag
, oflag
, cflag
, lflag
;
1667 /* Scan into temporaries since it is too much trouble to figure out
1668 the right format for `tcflag_t'. */
1669 if (sscanf (arg
, "%lx:%lx:%lx:%lx%n",
1670 &iflag
, &oflag
, &cflag
, &lflag
, &n
) != 4)
1672 mode
->c_iflag
= iflag
;
1673 mode
->c_oflag
= oflag
;
1674 mode
->c_cflag
= cflag
;
1675 mode
->c_lflag
= lflag
;
1676 if (mode
->c_iflag
!= iflag
1677 || mode
->c_oflag
!= oflag
1678 || mode
->c_cflag
!= cflag
1679 || mode
->c_lflag
!= lflag
)
1682 for (i
= 0; i
< NCCS
; ++i
)
1684 if (sscanf (arg
, ":%lx%n", &chr
, &n
) != 1)
1686 mode
->c_cc
[i
] = chr
;
1687 if (mode
->c_cc
[i
] != chr
)
1692 /* Fail if there are too many fields. */
1701 const char *string
; /* ASCII representation. */
1702 speed_t speed
; /* Internal form. */
1703 unsigned long int value
; /* Numeric value. */
1706 static struct speed_map speeds
[] =
1713 {"134.5", B134
, 134},
1718 {"1200", B1200
, 1200},
1719 {"1800", B1800
, 1800},
1720 {"2400", B2400
, 2400},
1721 {"4800", B4800
, 4800},
1722 {"9600", B9600
, 9600},
1723 {"19200", B19200
, 19200},
1724 {"38400", B38400
, 38400},
1725 {"exta", B19200
, 19200},
1726 {"extb", B38400
, 38400},
1728 {"57600", B57600
, 57600},
1731 {"115200", B115200
, 115200},
1734 {"230400", B230400
, 230400},
1737 {"460800", B460800
, 460800},
1740 {"500000", B500000
, 500000},
1743 {"576000", B576000
, 576000},
1746 {"921600", B921600
, 921600},
1749 {"1000000", B1000000
, 1000000},
1752 {"1152000", B1152000
, 1152000},
1755 {"1500000", B1500000
, 1500000},
1758 {"2000000", B2000000
, 2000000},
1761 {"2500000", B2500000
, 2500000},
1764 {"3000000", B3000000
, 3000000},
1767 {"3500000", B3500000
, 3500000},
1770 {"4000000", B4000000
, 4000000},
1776 string_to_baud (const char *arg
)
1780 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1781 if (STREQ (arg
, speeds
[i
].string
))
1782 return speeds
[i
].speed
;
1783 return (speed_t
) -1;
1786 static unsigned long int
1787 baud_to_value (speed_t speed
)
1791 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1792 if (speed
== speeds
[i
].speed
)
1793 return speeds
[i
].value
;
1798 sane_mode (struct termios
*mode
)
1803 for (i
= 0; control_info
[i
].name
; ++i
)
1806 if (STREQ (control_info
[i
].name
, "min"))
1809 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1812 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1814 if (mode_info
[i
].flags
& SANE_SET
)
1816 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1817 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1819 else if (mode_info
[i
].flags
& SANE_UNSET
)
1821 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1822 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1827 /* Return a string that is the printable representation of character CH. */
1828 /* Adapted from `cat' by Torbjorn Granlund. */
1833 static char buf
[10];
1836 if (ch
== _POSIX_VDISABLE
)
1855 *bpout
++ = ch
- 128;
1865 *bpout
++ = ch
- 128 + 64;
1875 return (const char *) buf
;
1878 /* Parse string S as an integer, using decimal radix by default,
1879 but allowing octal and hex numbers as in C. Reject values
1880 larger than MAXVAL. */
1882 static unsigned long int
1883 integer_arg (const char *s
, unsigned long int maxval
)
1885 unsigned long int value
;
1886 if (xstrtoul (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
1889 error (0, 0, _("invalid integer argument %s"), quote (s
));
1890 usage (EXIT_FAILURE
);