doc: clarify the operation of wc -L
[coreutils.git] / src / stty.c
blobc0057f2d7ef5e30b9f12d1262e93e7be9af3061b
1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2015 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...]
19 Options:
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> */
30 #include <config.h>
32 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
33 # define _XOPEN_SOURCE
34 #endif
36 #include <stdio.h>
37 #include <sys/types.h>
39 #include <termios.h>
40 #if HAVE_STROPTS_H
41 # include <stropts.h>
42 #endif
43 #include <sys/ioctl.h>
45 #ifdef WINSIZE_IN_PTEM
46 # include <sys/stream.h>
47 # include <sys/ptem.h>
48 #endif
49 #ifdef GWINSZ_IN_SYS_PTY
50 # include <sys/tty.h>
51 # include <sys/pty.h>
52 #endif
53 #include <getopt.h>
54 #include <stdarg.h>
55 #include <assert.h>
57 #include "system.h"
58 #include "error.h"
59 #include "fd-reopen.h"
60 #include "quote.h"
61 #include "xdectoint.h"
62 #include "xstrtol.h"
64 /* The official name of this program (e.g., no 'g' prefix). */
65 #define PROGRAM_NAME "stty"
67 #define AUTHORS proper_name ("David MacKenzie")
69 #ifndef _POSIX_VDISABLE
70 # define _POSIX_VDISABLE 0
71 #endif
73 #define Control(c) ((c) & 0x1f)
74 /* Canonical values for control characters. */
75 #ifndef CINTR
76 # define CINTR Control ('c')
77 #endif
78 #ifndef CQUIT
79 # define CQUIT 28
80 #endif
81 #ifndef CERASE
82 # define CERASE 127
83 #endif
84 #ifndef CKILL
85 # define CKILL Control ('u')
86 #endif
87 #ifndef CEOF
88 # define CEOF Control ('d')
89 #endif
90 #ifndef CEOL
91 # define CEOL _POSIX_VDISABLE
92 #endif
93 #ifndef CSTART
94 # define CSTART Control ('q')
95 #endif
96 #ifndef CSTOP
97 # define CSTOP Control ('s')
98 #endif
99 #ifndef CSUSP
100 # define CSUSP Control ('z')
101 #endif
102 #if defined VEOL2 && !defined CEOL2
103 # define CEOL2 _POSIX_VDISABLE
104 #endif
105 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
106 character is initialized by CSWTCH, if present. */
107 #if defined VSWTC && !defined VSWTCH
108 # define VSWTCH VSWTC
109 #endif
110 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
111 #if defined VSUSP && !defined VSWTCH
112 # define VSWTCH VSUSP
113 # if defined CSUSP && !defined CSWTCH
114 # define CSWTCH CSUSP
115 # endif
116 #endif
117 #if defined VSWTCH && !defined CSWTCH
118 # define CSWTCH _POSIX_VDISABLE
119 #endif
121 /* SunOS 5.3 loses (^Z doesn't work) if 'swtch' is the same as 'susp'.
122 So the default is to disable 'swtch.' */
123 #if defined __sparc__ && defined __svr4__
124 # undef CSWTCH
125 # define CSWTCH _POSIX_VDISABLE
126 #endif
128 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
129 # define VWERASE VWERSE
130 #endif
131 #if defined VDSUSP && !defined CDSUSP
132 # define CDSUSP Control ('y')
133 #endif
134 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
135 # define VREPRINT VRPRNT
136 #endif
137 #if defined VREPRINT && !defined CRPRNT
138 # define CRPRNT Control ('r')
139 #endif
140 #if defined CREPRINT && !defined CRPRNT
141 # define CRPRNT Control ('r')
142 #endif
143 #if defined VWERASE && !defined CWERASE
144 # define CWERASE Control ('w')
145 #endif
146 #if defined VLNEXT && !defined CLNEXT
147 # define CLNEXT Control ('v')
148 #endif
149 #if defined VDISCARD && !defined VFLUSHO
150 # define VFLUSHO VDISCARD
151 #endif
152 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
153 # define VFLUSHO VFLUSH
154 #endif
155 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
156 # define ECHOCTL CTLECH
157 #endif
158 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
159 # define ECHOCTL TCTLECH
160 #endif
161 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
162 # define ECHOKE CRTKIL
163 #endif
164 #if defined VFLUSHO && !defined CFLUSHO
165 # define CFLUSHO Control ('o')
166 #endif
167 #if defined VSTATUS && !defined CSTATUS
168 # define CSTATUS Control ('t')
169 #endif
171 /* Which speeds to set. */
172 enum speed_setting
174 input_speed, output_speed, both_speeds
177 /* What to output and how. */
178 enum output_type
180 changed, all, recoverable /* Default, -a, -g. */
183 /* Which member(s) of 'struct termios' a mode uses. */
184 enum mode_type
186 control, input, output, local, combination
189 /* Flags for 'struct mode_info'. */
190 #define SANE_SET 1 /* Set in 'sane' mode. */
191 #define SANE_UNSET 2 /* Unset in 'sane' mode. */
192 #define REV 4 /* Can be turned off by prepending '-'. */
193 #define OMIT 8 /* Don't display value. */
194 #define NO_SETATTR 16 /* tcsetattr not used to set mode bits. */
196 /* Each mode. */
197 struct mode_info
199 const char *name; /* Name given on command line. */
200 enum mode_type type; /* Which structure element to change. */
201 char flags; /* Setting and display options. */
202 unsigned long bits; /* Bits to set for this mode. */
203 unsigned long mask; /* Other bits to turn off for this mode. */
206 static struct mode_info const mode_info[] =
208 {"parenb", control, REV, PARENB, 0},
209 {"parodd", control, REV, PARODD, 0},
210 #ifdef CMSPAR
211 {"cmspar", control, REV, CMSPAR, 0},
212 #endif
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},
222 #ifdef CRTSCTS
223 {"crtscts", control, REV, CRTSCTS, 0},
224 #endif
225 #ifdef CDTRDSR
226 {"cdtrdsr", control, REV, CDTRDSR, 0},
227 #endif
229 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
230 {"brkint", input, SANE_SET | REV, BRKINT, 0},
231 {"ignpar", input, REV, IGNPAR, 0},
232 {"parmrk", input, REV, PARMRK, 0},
233 {"inpck", input, REV, INPCK, 0},
234 {"istrip", input, REV, ISTRIP, 0},
235 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
236 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
237 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
238 {"ixon", input, REV, IXON, 0},
239 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
240 {"tandem", input, REV | OMIT, IXOFF, 0},
241 #ifdef IUCLC
242 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
243 #endif
244 #ifdef IXANY
245 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
246 #endif
247 #ifdef IMAXBEL
248 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
249 #endif
250 #ifdef IUTF8
251 {"iutf8", input, SANE_UNSET | REV, IUTF8, 0},
252 #endif
254 {"opost", output, SANE_SET | REV, OPOST, 0},
255 #ifdef OLCUC
256 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
257 #endif
258 #ifdef OCRNL
259 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
260 #endif
261 #ifdef ONLCR
262 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
263 #endif
264 #ifdef ONOCR
265 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
266 #endif
267 #ifdef ONLRET
268 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
269 #endif
270 #ifdef OFILL
271 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
272 #endif
273 #ifdef OFDEL
274 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
275 #endif
276 #ifdef NLDLY
277 {"nl1", output, SANE_UNSET, NL1, NLDLY},
278 {"nl0", output, SANE_SET, NL0, NLDLY},
279 #endif
280 #ifdef CRDLY
281 {"cr3", output, SANE_UNSET, CR3, CRDLY},
282 {"cr2", output, SANE_UNSET, CR2, CRDLY},
283 {"cr1", output, SANE_UNSET, CR1, CRDLY},
284 {"cr0", output, SANE_SET, CR0, CRDLY},
285 #endif
286 #ifdef TABDLY
287 # ifdef TAB3
288 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
289 # endif
290 # ifdef TAB2
291 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
292 # endif
293 # ifdef TAB1
294 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
295 # endif
296 # ifdef TAB0
297 {"tab0", output, SANE_SET, TAB0, TABDLY},
298 # endif
299 #else
300 # ifdef OXTABS
301 {"tab3", output, SANE_UNSET, OXTABS, 0},
302 # endif
303 #endif
304 #ifdef BSDLY
305 {"bs1", output, SANE_UNSET, BS1, BSDLY},
306 {"bs0", output, SANE_SET, BS0, BSDLY},
307 #endif
308 #ifdef VTDLY
309 {"vt1", output, SANE_UNSET, VT1, VTDLY},
310 {"vt0", output, SANE_SET, VT0, VTDLY},
311 #endif
312 #ifdef FFDLY
313 {"ff1", output, SANE_UNSET, FF1, FFDLY},
314 {"ff0", output, SANE_SET, FF0, FFDLY},
315 #endif
317 {"isig", local, SANE_SET | REV, ISIG, 0},
318 {"icanon", local, SANE_SET | REV, ICANON, 0},
319 #ifdef IEXTEN
320 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
321 #endif
322 {"echo", local, SANE_SET | REV, ECHO, 0},
323 {"echoe", local, SANE_SET | REV, ECHOE, 0},
324 {"crterase", local, REV | OMIT, ECHOE, 0},
325 {"echok", local, SANE_SET | REV, ECHOK, 0},
326 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
327 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
328 #ifdef XCASE
329 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
330 #endif
331 #ifdef TOSTOP
332 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
333 #endif
334 #ifdef ECHOPRT
335 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
336 {"prterase", local, REV | OMIT, ECHOPRT, 0},
337 #endif
338 #ifdef ECHOCTL
339 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
340 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
341 #endif
342 #ifdef ECHOKE
343 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
344 {"crtkill", local, REV | OMIT, ECHOKE, 0},
345 #endif
346 #if defined TIOCEXT
347 {"extproc", local, SANE_UNSET | REV | NO_SETATTR, EXTPROC, 0},
348 #elif defined EXTPROC
349 {"extproc", local, SANE_UNSET | REV, EXTPROC, 0},
350 #endif
352 {"evenp", combination, REV | OMIT, 0, 0},
353 {"parity", combination, REV | OMIT, 0, 0},
354 {"oddp", combination, REV | OMIT, 0, 0},
355 {"nl", combination, REV | OMIT, 0, 0},
356 {"ek", combination, OMIT, 0, 0},
357 {"sane", combination, OMIT, 0, 0},
358 {"cooked", combination, REV | OMIT, 0, 0},
359 {"raw", combination, REV | OMIT, 0, 0},
360 {"pass8", combination, REV | OMIT, 0, 0},
361 {"litout", combination, REV | OMIT, 0, 0},
362 {"cbreak", combination, REV | OMIT, 0, 0},
363 #ifdef IXANY
364 {"decctlq", combination, REV | OMIT, 0, 0},
365 #endif
366 #if defined TABDLY || defined OXTABS
367 {"tabs", combination, REV | OMIT, 0, 0},
368 #endif
369 #if defined XCASE && defined IUCLC && defined OLCUC
370 {"lcase", combination, REV | OMIT, 0, 0},
371 {"LCASE", combination, REV | OMIT, 0, 0},
372 #endif
373 {"crt", combination, OMIT, 0, 0},
374 {"dec", combination, OMIT, 0, 0},
376 {NULL, control, 0, 0, 0}
379 /* Control character settings. */
380 struct control_info
382 const char *name; /* Name given on command line. */
383 cc_t saneval; /* Value to set for 'stty sane'. */
384 size_t offset; /* Offset in c_cc. */
387 /* Control characters. */
389 static struct control_info const control_info[] =
391 {"intr", CINTR, VINTR},
392 {"quit", CQUIT, VQUIT},
393 {"erase", CERASE, VERASE},
394 {"kill", CKILL, VKILL},
395 {"eof", CEOF, VEOF},
396 {"eol", CEOL, VEOL},
397 #ifdef VEOL2
398 {"eol2", CEOL2, VEOL2},
399 #endif
400 #ifdef VSWTCH
401 {"swtch", CSWTCH, VSWTCH},
402 #endif
403 {"start", CSTART, VSTART},
404 {"stop", CSTOP, VSTOP},
405 {"susp", CSUSP, VSUSP},
406 #ifdef VDSUSP
407 {"dsusp", CDSUSP, VDSUSP},
408 #endif
409 #ifdef VREPRINT
410 {"rprnt", CRPRNT, VREPRINT},
411 #else
412 # ifdef CREPRINT /* HPUX 10.20 needs this */
413 {"rprnt", CRPRNT, CREPRINT},
414 # endif
415 #endif
416 #ifdef VWERASE
417 {"werase", CWERASE, VWERASE},
418 #endif
419 #ifdef VLNEXT
420 {"lnext", CLNEXT, VLNEXT},
421 #endif
422 #ifdef VFLUSHO
423 {"flush", CFLUSHO, VFLUSHO}, /* deprecated compat option. */
424 {"discard", CFLUSHO, VFLUSHO},
425 #endif
426 #ifdef VSTATUS
427 {"status", CSTATUS, VSTATUS},
428 #endif
430 /* These must be last because of the display routines. */
431 {"min", 1, VMIN},
432 {"time", 0, VTIME},
433 {NULL, 0, 0}
436 static char const *visible (cc_t ch);
437 static unsigned long int baud_to_value (speed_t speed);
438 static bool recover_mode (char const *arg, struct termios *mode);
439 static int screen_columns (void);
440 static bool set_mode (struct mode_info const *info, bool reversed,
441 struct termios *mode);
442 static unsigned long int integer_arg (const char *s, unsigned long int max);
443 static speed_t string_to_baud (const char *arg);
444 static tcflag_t *mode_type_flag (enum mode_type type, struct termios *mode);
445 static void display_all (struct termios *mode, char const *device_name);
446 static void display_changed (struct termios *mode);
447 static void display_recoverable (struct termios *mode);
448 static void display_settings (enum output_type output_type,
449 struct termios *mode,
450 const char *device_name);
451 static void display_speed (struct termios *mode, bool fancy);
452 static void display_window_size (bool fancy, char const *device_name);
453 static void sane_mode (struct termios *mode);
454 static void set_control_char (struct control_info const *info,
455 const char *arg,
456 struct termios *mode);
457 static void set_speed (enum speed_setting type, const char *arg,
458 struct termios *mode);
459 static void set_window_size (int rows, int cols, char const *device_name);
461 /* The width of the screen, for output wrapping. */
462 static int max_col;
464 /* Current position, to know when to wrap. */
465 static int current_col;
467 static struct option const longopts[] =
469 {"all", no_argument, NULL, 'a'},
470 {"save", no_argument, NULL, 'g'},
471 {"file", required_argument, NULL, 'F'},
472 {GETOPT_HELP_OPTION_DECL},
473 {GETOPT_VERSION_OPTION_DECL},
474 {NULL, 0, NULL, 0}
477 static void wrapf (const char *message, ...)
478 __attribute__ ((__format__ (__printf__, 1, 2)));
480 /* Print format string MESSAGE and optional args.
481 Wrap to next line first if it won't fit.
482 Print a space first unless MESSAGE will start a new line. */
484 static void
485 wrapf (const char *message,...)
487 va_list args;
488 char *buf;
489 int buflen;
491 va_start (args, message);
492 buflen = vasprintf (&buf, message, args);
493 va_end (args);
495 if (buflen < 0)
496 xalloc_die ();
498 if (0 < current_col)
500 if (max_col - current_col < buflen)
502 putchar ('\n');
503 current_col = 0;
505 else
507 putchar (' ');
508 current_col++;
512 fputs (buf, stdout);
513 free (buf);
514 current_col += buflen;
517 void
518 usage (int status)
520 if (status != EXIT_SUCCESS)
521 emit_try_help ();
522 else
524 printf (_("\
525 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
526 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
527 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
529 program_name, program_name, program_name);
530 fputs (_("\
531 Print or change terminal characteristics.\n\
532 "), stdout);
534 emit_mandatory_arg_note ();
536 fputs (_("\
537 -a, --all print all current settings in human-readable form\n\
538 -g, --save print all current settings in a stty-readable form\n\
539 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
540 "), stdout);
541 fputs (HELP_OPTION_DESCRIPTION, stdout);
542 fputs (VERSION_OPTION_DESCRIPTION, stdout);
543 fputs (_("\
545 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
546 settings. The underlying system defines which settings are available.\n\
547 "), stdout);
548 fputs (_("\
550 Special characters:\n"), stdout);
551 #ifdef VFLUSHO
552 fputs (_("\
553 * discard CHAR CHAR will toggle discarding of output\n\
554 "), stdout);
555 #endif
556 #ifdef VDSUSP
557 fputs (_("\
558 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
559 "), stdout);
560 #endif
561 fputs (_("\
562 eof CHAR CHAR will send an end of file (terminate the input)\n\
563 eol CHAR CHAR will end the line\n\
564 "), stdout);
565 #ifdef VEOL2
566 fputs (_("\
567 * eol2 CHAR alternate CHAR for ending the line\n\
568 "), stdout);
569 #endif
570 fputs (_("\
571 erase CHAR CHAR will erase the last character typed\n\
572 intr CHAR CHAR will send an interrupt signal\n\
573 kill CHAR CHAR will erase the current line\n\
574 "), stdout);
575 #ifdef VLNEXT
576 fputs (_("\
577 * lnext CHAR CHAR will enter the next character quoted\n\
578 "), stdout);
579 #endif
580 #ifdef VSTATUS
581 fputs (_("\
582 * status CHAR CHAR will send an info signal\n\
583 "), stdout);
584 #endif
585 fputs (_("\
586 quit CHAR CHAR will send a quit signal\n\
587 "), stdout);
588 #if defined CREPRINT || defined VREPRINT
589 fputs (_("\
590 * rprnt CHAR CHAR will redraw the current line\n\
591 "), stdout);
592 #endif
593 fputs (_("\
594 start CHAR CHAR will restart the output after stopping it\n\
595 stop CHAR CHAR will stop the output\n\
596 susp CHAR CHAR will send a terminal stop signal\n\
597 "), stdout);
598 #ifdef VSWTCH
599 fputs (_("\
600 * swtch CHAR CHAR will switch to a different shell layer\n\
601 "), stdout);
602 #endif
603 #ifdef VWERASE
604 fputs (_("\
605 * werase CHAR CHAR will erase the last word typed\n\
606 "), stdout);
607 #endif
608 fputs (_("\
610 Special settings:\n\
611 N set the input and output speeds to N bauds\n\
612 "), stdout);
613 #ifdef TIOCGWINSZ
614 fputs (_("\
615 * cols N tell the kernel that the terminal has N columns\n\
616 * columns N same as cols N\n\
617 "), stdout);
618 #endif
619 fputs (_("\
620 ispeed N set the input speed to N\n\
621 "), stdout);
622 #ifdef HAVE_C_LINE
623 fputs (_("\
624 * line N use line discipline N\n\
625 "), stdout);
626 #endif
627 fputs (_("\
628 min N with -icanon, set N characters minimum for a completed read\n\
629 ospeed N set the output speed to N\n\
630 "), stdout);
631 #ifdef TIOCGWINSZ
632 fputs (_("\
633 * rows N tell the kernel that the terminal has N rows\n\
634 * size print the number of rows and columns according to the kernel\n\
635 "), stdout);
636 #endif
637 fputs (_("\
638 speed print the terminal speed\n\
639 time N with -icanon, set read timeout of N tenths of a second\n\
640 "), stdout);
641 fputs (_("\
643 Control settings:\n\
644 [-]clocal disable modem control signals\n\
645 [-]cread allow input to be received\n\
646 "), stdout);
647 #ifdef CRTSCTS
648 fputs (_("\
649 * [-]crtscts enable RTS/CTS handshaking\n\
650 "), stdout);
651 #endif
652 #ifdef CDTRDSR
653 fputs (_("\
654 * [-]cdtrdsr enable DTR/DSR handshaking\n\
655 "), stdout);
656 #endif
657 fputs (_("\
658 csN set character size to N bits, N in [5..8]\n\
659 "), stdout);
660 fputs (_("\
661 [-]cstopb use two stop bits per character (one with '-')\n\
662 [-]hup send a hangup signal when the last process closes the tty\n\
663 [-]hupcl same as [-]hup\n\
664 [-]parenb generate parity bit in output and expect parity bit in input\n\
665 [-]parodd set odd parity (or even parity with '-')\n\
666 "), stdout);
667 #ifdef CMSPAR
668 fputs (_("\
669 * [-]cmspar use \"stick\" (mark/space) parity\n\
670 "), stdout);
671 #endif
672 fputs (_("\
674 Input settings:\n\
675 [-]brkint breaks cause an interrupt signal\n\
676 [-]icrnl translate carriage return to newline\n\
677 [-]ignbrk ignore break characters\n\
678 [-]igncr ignore carriage return\n\
679 [-]ignpar ignore characters with parity errors\n\
680 "), stdout);
681 #ifdef IMAXBEL
682 fputs (_("\
683 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
684 "), stdout);
685 #endif
686 fputs (_("\
687 [-]inlcr translate newline to carriage return\n\
688 [-]inpck enable input parity checking\n\
689 [-]istrip clear high (8th) bit of input characters\n\
690 "), stdout);
691 #ifdef IUTF8
692 fputs (_("\
693 * [-]iutf8 assume input characters are UTF-8 encoded\n\
694 "), stdout);
695 #endif
696 #ifdef IUCLC
697 fputs (_("\
698 * [-]iuclc translate uppercase characters to lowercase\n\
699 "), stdout);
700 #endif
701 #ifdef IXANY
702 fputs (_("\
703 * [-]ixany let any character restart output, not only start character\n\
704 "), stdout);
705 #endif
706 fputs (_("\
707 [-]ixoff enable sending of start/stop characters\n\
708 [-]ixon enable XON/XOFF flow control\n\
709 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
710 [-]tandem same as [-]ixoff\n\
711 "), stdout);
712 fputs (_("\
714 Output settings:\n\
715 "), stdout);
716 #ifdef BSDLY
717 fputs (_("\
718 * bsN backspace delay style, N in [0..1]\n\
719 "), stdout);
720 #endif
721 #ifdef CRDLY
722 fputs (_("\
723 * crN carriage return delay style, N in [0..3]\n\
724 "), stdout);
725 #endif
726 #ifdef FFDLY
727 fputs (_("\
728 * ffN form feed delay style, N in [0..1]\n\
729 "), stdout);
730 #endif
731 #ifdef NLDLY
732 fputs (_("\
733 * nlN newline delay style, N in [0..1]\n\
734 "), stdout);
735 #endif
736 #ifdef OCRNL
737 fputs (_("\
738 * [-]ocrnl translate carriage return to newline\n\
739 "), stdout);
740 #endif
741 #ifdef OFDEL
742 fputs (_("\
743 * [-]ofdel use delete characters for fill instead of NUL characters\n\
744 "), stdout);
745 #endif
746 #ifdef OFILL
747 fputs (_("\
748 * [-]ofill use fill (padding) characters instead of timing for delays\n\
749 "), stdout);
750 #endif
751 #ifdef OLCUC
752 fputs (_("\
753 * [-]olcuc translate lowercase characters to uppercase\n\
754 "), stdout);
755 #endif
756 #ifdef ONLCR
757 fputs (_("\
758 * [-]onlcr translate newline to carriage return-newline\n\
759 "), stdout);
760 #endif
761 #ifdef ONLRET
762 fputs (_("\
763 * [-]onlret newline performs a carriage return\n\
764 "), stdout);
765 #endif
766 #ifdef ONOCR
767 fputs (_("\
768 * [-]onocr do not print carriage returns in the first column\n\
769 "), stdout);
770 #endif
771 fputs (_("\
772 [-]opost postprocess output\n\
773 "), stdout);
774 #if defined TABDLY || defined OXTABS
775 fputs (_("\
776 * tabN horizontal tab delay style, N in [0..3]\n\
777 * tabs same as tab0\n\
778 * -tabs same as tab3\n\
779 "), stdout);
780 #endif
781 #ifdef VTDLY
782 fputs (_("\
783 * vtN vertical tab delay style, N in [0..1]\n\
784 "), stdout);
785 #endif
786 fputs (_("\
788 Local settings:\n\
789 [-]crterase echo erase characters as backspace-space-backspace\n\
790 "), stdout);
791 #ifdef ECHOKE
792 fputs (_("\
793 * crtkill kill all line by obeying the echoprt and echoe settings\n\
794 * -crtkill kill all line by obeying the echoctl and echok settings\n\
795 "), stdout);
796 #endif
797 #ifdef ECHOCTL
798 fputs (_("\
799 * [-]ctlecho echo control characters in hat notation ('^c')\n\
800 "), stdout);
801 #endif
802 fputs (_("\
803 [-]echo echo input characters\n\
804 "), stdout);
805 #ifdef ECHOCTL
806 fputs (_("\
807 * [-]echoctl same as [-]ctlecho\n\
808 "), stdout);
809 #endif
810 fputs (_("\
811 [-]echoe same as [-]crterase\n\
812 [-]echok echo a newline after a kill character\n\
813 "), stdout);
814 #ifdef ECHOKE
815 fputs (_("\
816 * [-]echoke same as [-]crtkill\n\
817 "), stdout);
818 #endif
819 fputs (_("\
820 [-]echonl echo newline even if not echoing other characters\n\
821 "), stdout);
822 #ifdef ECHOPRT
823 fputs (_("\
824 * [-]echoprt echo erased characters backward, between '\\' and '/'\n\
825 "), stdout);
826 #endif
827 #if defined EXTPROC || defined TIOCEXT
828 fputs (_("\
829 * [-]extproc enable \"LINEMODE\"; useful with high latency links\n\
830 "), stdout);
831 #endif
832 printf (_("\
833 [-]icanon enable special characters: %s\n\
834 [-]iexten enable non-POSIX special characters\n\
835 "), "erase, kill"
836 #ifdef VWERASE
837 ", werase"
838 #endif
839 #if defined CREPRINT || defined VREPRINT
840 ", rprnt"
841 #endif
843 fputs (_("\
844 [-]isig enable interrupt, quit, and suspend special characters\n\
845 [-]noflsh disable flushing after interrupt and quit special characters\n\
846 "), stdout);
847 #ifdef ECHOPRT
848 fputs (_("\
849 * [-]prterase same as [-]echoprt\n\
850 "), stdout);
851 #endif
852 #ifdef TOSTOP
853 fputs (_("\
854 * [-]tostop stop background jobs that try to write to the terminal\n\
855 "), stdout);
856 #endif
857 #ifdef XCASE
858 fputs (_("\
859 * [-]xcase with icanon, escape with '\\' for uppercase characters\n\
860 "), stdout);
861 #endif
862 fputs (_("\
864 Combination settings:\n\
865 "), stdout);
866 #if defined XCASE && defined IUCLC && defined OLCUC
867 fputs (_("\
868 * [-]LCASE same as [-]lcase\n\
869 "), stdout);
870 #endif
871 fputs (_("\
872 cbreak same as -icanon\n\
873 -cbreak same as icanon\n\
874 "), stdout);
875 fputs (_("\
876 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
877 icanon, eof and eol characters to their default values\n\
878 -cooked same as raw\n\
879 "), stdout);
880 printf (_("\
881 crt same as %s\n\
882 "), "echoe"
883 #ifdef ECHOCTL
884 " echoctl"
885 #endif
886 #ifdef ECHOKE
887 " echoke"
888 #endif
890 printf (_("\
891 dec same as %s intr ^c erase 0177\n\
892 kill ^u\n\
893 "), "echoe"
894 #ifdef ECHOCTL
895 " echoctl"
896 #endif
897 #ifdef ECHOKE
898 " echoke"
899 #endif
900 #ifdef IXANY
901 " -ixany"
902 #endif
904 #ifdef IXANY
905 fputs (_("\
906 * [-]decctlq same as [-]ixany\n\
907 "), stdout);
908 #endif
909 fputs (_("\
910 ek erase and kill characters to their default values\n\
911 evenp same as parenb -parodd cs7\n\
912 -evenp same as -parenb cs8\n\
913 "), stdout);
914 #if defined XCASE && defined IUCLC && defined OLCUC
915 fputs (_("\
916 * [-]lcase same as xcase iuclc olcuc\n\
917 "), stdout);
918 #endif
919 fputs (_("\
920 litout same as -parenb -istrip -opost cs8\n\
921 -litout same as parenb istrip opost cs7\n\
922 "), stdout);
923 printf (_("\
924 nl same as %s\n\
925 -nl same as %s\n\
926 "), "-icrnl"
927 #ifdef ONLCR
928 " -onlcr"
929 #endif
930 , "icrnl -inlcr -igncr"
931 #ifdef ONLCR
932 " onlcr"
933 #endif
934 #ifdef OCRNL
935 " -ocrnl"
936 #endif
937 #ifdef ONLRET
938 " -onlret"
939 #endif
941 fputs (_("\
942 "), stdout);
943 fputs (_("\
944 oddp same as parenb parodd cs7\n\
945 -oddp same as -parenb cs8\n\
946 [-]parity same as [-]evenp\n\
947 pass8 same as -parenb -istrip cs8\n\
948 -pass8 same as parenb istrip cs7\n\
949 "), stdout);
950 printf (_("\
951 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
952 -inlcr -igncr -icrnl -ixon -ixoff -icanon -opost\n\
953 -isig%s min 1 time 0\n\
954 -raw same as cooked\n\
956 #ifdef IUCLC
957 " -iuclc"
958 #endif
959 #ifdef IXANY
960 " -ixany"
961 #endif
962 #ifdef IMAXBEL
963 " -imaxbel"
964 #endif
965 #ifdef XCASE
966 " -xcase"
967 #endif
969 printf (_("\
970 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
971 icanon iexten echo echoe echok -echonl -noflsh\n\
972 %s\n\
973 %s\n\
974 %s,\n\
975 all special characters to their default values\n\
977 "-ixoff"
978 #ifdef IUTF8
979 " -iutf8"
980 #endif
981 #ifdef IUCLC
982 " -iuclc"
983 #endif
984 #ifdef IXANY
985 " -ixany"
986 #endif
987 #ifdef IMAXBEL
988 " imaxbel"
989 #endif
990 #ifdef XCASE
991 " -xcase"
992 #endif
993 #ifdef OLCUC
994 " -olcuc"
995 #endif
996 #ifdef OCRNL
997 " -ocrnl"
998 #endif
1000 , "opost"
1001 #ifdef OFILL
1002 " -ofill"
1003 #endif
1004 #ifdef ONLCR
1005 " onlcr"
1006 #endif
1007 #ifdef ONOCR
1008 " -onocr"
1009 #endif
1010 #ifdef ONLRET
1011 " -onlret"
1012 #endif
1013 #ifdef NLDLY
1014 " nl0"
1015 #endif
1016 #ifdef CRDLY
1017 " cr0"
1018 #endif
1019 #ifdef TAB0
1020 " tab0"
1021 #endif
1022 #ifdef BSDLY
1023 " bs0"
1024 #endif
1025 #ifdef VTDLY
1026 " vt0"
1027 #endif
1028 #ifdef FFDLY
1029 " ff0"
1030 #endif
1032 , "isig"
1033 #ifdef TOSTOP
1034 " -tostop"
1035 #endif
1036 #ifdef OFDEL
1037 " -ofdel"
1038 #endif
1039 #ifdef ECHOPRT
1040 " -echoprt"
1041 #endif
1042 #ifdef ECHOCTL
1043 " echoctl"
1044 #endif
1045 #ifdef ECHOKE
1046 " echoke"
1047 #endif
1048 #ifdef EXTPROC
1049 " -extproc"
1050 #endif
1052 fputs (_("\
1054 Handle the tty line connected to standard input. Without arguments,\n\
1055 prints baud rate, line discipline, and deviations from stty sane. In\n\
1056 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
1057 127; special values ^- or undef used to disable special characters.\n\
1058 "), stdout);
1059 emit_ancillary_info (PROGRAM_NAME);
1061 exit (status);
1065 main (int argc, char **argv)
1067 /* Initialize to all zeroes so there is no risk memcmp will report a
1068 spurious difference in an uninitialized portion of the structure. */
1069 static struct termios mode;
1071 enum output_type output_type;
1072 int optc;
1073 int argi = 0;
1074 int opti = 1;
1075 bool require_set_attr;
1076 bool speed_was_set _GL_UNUSED;
1077 bool verbose_output;
1078 bool recoverable_output;
1079 int k;
1080 bool noargs = true;
1081 char *file_name = NULL;
1082 const char *device_name;
1084 initialize_main (&argc, &argv);
1085 set_program_name (argv[0]);
1086 setlocale (LC_ALL, "");
1087 bindtextdomain (PACKAGE, LOCALEDIR);
1088 textdomain (PACKAGE);
1090 atexit (close_stdout);
1092 output_type = changed;
1093 verbose_output = false;
1094 recoverable_output = false;
1096 /* Don't print error messages for unrecognized options. */
1097 opterr = 0;
1099 /* If any new options are ever added to stty, the short options MUST
1100 NOT allow any ambiguity with the stty settings. For example, the
1101 stty setting "-gagFork" would not be feasible, since it will be
1102 parsed as "-g -a -g -F ork". If you change anything about how
1103 stty parses options, be sure it still works with combinations of
1104 short and long options, --, POSIXLY_CORRECT, etc. */
1106 while ((optc = getopt_long (argc - argi, argv + argi, "-agF:",
1107 longopts, NULL))
1108 != -1)
1110 switch (optc)
1112 case 'a':
1113 verbose_output = true;
1114 output_type = all;
1115 break;
1117 case 'g':
1118 recoverable_output = true;
1119 output_type = recoverable;
1120 break;
1122 case 'F':
1123 if (file_name)
1124 error (EXIT_FAILURE, 0, _("only one device may be specified"));
1125 file_name = optarg;
1126 break;
1128 case_GETOPT_HELP_CHAR;
1130 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1132 default:
1133 noargs = false;
1135 /* Skip the argument containing this unrecognized option;
1136 the 2nd pass will analyze it. */
1137 argi += opti;
1139 /* Restart getopt_long from the first unskipped argument. */
1140 opti = 1;
1141 optind = 0;
1143 break;
1146 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
1147 while (opti < optind)
1148 argv[argi + opti++] = NULL;
1151 /* Specifying both -a and -g gets an error. */
1152 if (verbose_output && recoverable_output)
1153 error (EXIT_FAILURE, 0,
1154 _("the options for verbose and stty-readable output styles are\n"
1155 "mutually exclusive"));
1157 /* Specifying any other arguments with -a or -g gets an error. */
1158 if (!noargs && (verbose_output || recoverable_output))
1159 error (EXIT_FAILURE, 0,
1160 _("when specifying an output style, modes may not be set"));
1162 /* FIXME: it'd be better not to open the file until we've verified
1163 that all arguments are valid. Otherwise, we could end up doing
1164 only some of the requested operations and then failing, probably
1165 leaving things in an undesirable state. */
1167 if (file_name)
1169 int fdflags;
1170 device_name = file_name;
1171 if (fd_reopen (STDIN_FILENO, device_name, O_RDONLY | O_NONBLOCK, 0) < 0)
1172 error (EXIT_FAILURE, errno, "%s", device_name);
1173 if ((fdflags = fcntl (STDIN_FILENO, F_GETFL)) == -1
1174 || fcntl (STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
1175 error (EXIT_FAILURE, errno, _("%s: couldn't reset non-blocking mode"),
1176 device_name);
1178 else
1179 device_name = _("standard input");
1181 if (tcgetattr (STDIN_FILENO, &mode))
1182 error (EXIT_FAILURE, errno, "%s", device_name);
1184 if (verbose_output || recoverable_output || noargs)
1186 max_col = screen_columns ();
1187 current_col = 0;
1188 display_settings (output_type, &mode, device_name);
1189 return EXIT_SUCCESS;
1192 speed_was_set = false;
1193 require_set_attr = false;
1194 for (k = 1; k < argc; k++)
1196 char const *arg = argv[k];
1197 bool match_found = false;
1198 bool not_set_attr = false;
1199 bool reversed = false;
1200 int i;
1202 if (! arg)
1203 continue;
1205 if (arg[0] == '-')
1207 ++arg;
1208 reversed = true;
1210 for (i = 0; mode_info[i].name != NULL; ++i)
1212 if (STREQ (arg, mode_info[i].name))
1214 if ((mode_info[i].flags & NO_SETATTR) == 0)
1216 match_found = set_mode (&mode_info[i], reversed, &mode);
1217 require_set_attr = true;
1219 else
1220 match_found = not_set_attr = true;
1221 break;
1224 if (!match_found && reversed)
1226 error (0, 0, _("invalid argument %s"), quote (arg - 1));
1227 usage (EXIT_FAILURE);
1229 if (!match_found)
1231 for (i = 0; control_info[i].name != NULL; ++i)
1233 if (STREQ (arg, control_info[i].name))
1235 if (k == argc - 1)
1237 error (0, 0, _("missing argument to %s"), quote (arg));
1238 usage (EXIT_FAILURE);
1240 match_found = true;
1241 ++k;
1242 set_control_char (&control_info[i], argv[k], &mode);
1243 require_set_attr = true;
1244 break;
1248 if (!match_found || not_set_attr)
1250 if (STREQ (arg, "ispeed"))
1252 if (k == argc - 1)
1254 error (0, 0, _("missing argument to %s"), quote (arg));
1255 usage (EXIT_FAILURE);
1257 ++k;
1258 set_speed (input_speed, argv[k], &mode);
1259 speed_was_set = true;
1260 require_set_attr = true;
1262 else if (STREQ (arg, "ospeed"))
1264 if (k == argc - 1)
1266 error (0, 0, _("missing argument to %s"), quote (arg));
1267 usage (EXIT_FAILURE);
1269 ++k;
1270 set_speed (output_speed, argv[k], &mode);
1271 speed_was_set = true;
1272 require_set_attr = true;
1274 #ifdef TIOCEXT
1275 /* This is the BSD interface to "extproc".
1276 Even though it's an lflag, an ioctl is used to set it. */
1277 else if (STREQ (arg, "extproc"))
1279 int val = ! reversed;
1281 if (ioctl (STDIN_FILENO, TIOCEXT, &val) != 0)
1283 error (EXIT_FAILURE, errno, _("%s: error setting %s"),
1284 device_name, quote (arg));
1287 #endif
1288 #ifdef TIOCGWINSZ
1289 else if (STREQ (arg, "rows"))
1291 if (k == argc - 1)
1293 error (0, 0, _("missing argument to %s"), quote (arg));
1294 usage (EXIT_FAILURE);
1296 ++k;
1297 set_window_size (integer_arg (argv[k], INT_MAX), -1,
1298 device_name);
1300 else if (STREQ (arg, "cols")
1301 || STREQ (arg, "columns"))
1303 if (k == argc - 1)
1305 error (0, 0, _("missing argument to %s"), quote (arg));
1306 usage (EXIT_FAILURE);
1308 ++k;
1309 set_window_size (-1, integer_arg (argv[k], INT_MAX),
1310 device_name);
1312 else if (STREQ (arg, "size"))
1314 max_col = screen_columns ();
1315 current_col = 0;
1316 display_window_size (false, device_name);
1318 #endif
1319 #ifdef HAVE_C_LINE
1320 else if (STREQ (arg, "line"))
1322 unsigned long int value;
1323 if (k == argc - 1)
1325 error (0, 0, _("missing argument to %s"), quote (arg));
1326 usage (EXIT_FAILURE);
1328 ++k;
1329 mode.c_line = value = integer_arg (argv[k], ULONG_MAX);
1330 if (mode.c_line != value)
1331 error (0, 0, _("invalid line discipline %s"), quote (argv[k]));
1332 require_set_attr = true;
1334 #endif
1335 else if (STREQ (arg, "speed"))
1337 max_col = screen_columns ();
1338 display_speed (&mode, false);
1340 else if (string_to_baud (arg) != (speed_t) -1)
1342 set_speed (both_speeds, arg, &mode);
1343 speed_was_set = true;
1344 require_set_attr = true;
1346 else
1348 if (! recover_mode (arg, &mode))
1350 error (0, 0, _("invalid argument %s"), quote (arg));
1351 usage (EXIT_FAILURE);
1353 require_set_attr = true;
1358 if (require_set_attr)
1360 /* Initialize to all zeroes so there is no risk memcmp will report a
1361 spurious difference in an uninitialized portion of the structure. */
1362 static struct termios new_mode;
1364 if (tcsetattr (STDIN_FILENO, TCSADRAIN, &mode))
1365 error (EXIT_FAILURE, errno, "%s", device_name);
1367 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1368 it performs *any* of the requested operations. This means it
1369 can report 'success' when it has actually failed to perform
1370 some proper subset of the requested operations. To detect
1371 this partial failure, get the current terminal attributes and
1372 compare them to the requested ones. */
1374 if (tcgetattr (STDIN_FILENO, &new_mode))
1375 error (EXIT_FAILURE, errno, "%s", device_name);
1377 /* Normally, one shouldn't use memcmp to compare structures that
1378 may have 'holes' containing uninitialized data, but we have been
1379 careful to initialize the storage of these two variables to all
1380 zeroes. One might think it more efficient simply to compare the
1381 modified fields, but that would require enumerating those fields --
1382 and not all systems have the same fields in this structure. */
1384 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1386 #ifdef CIBAUD
1387 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1388 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1389 sometimes (m1 != m2). The only difference is in the four bits
1390 of the c_cflag field corresponding to the baud rate. To save
1391 Sun users a little confusion, don't report an error if this
1392 happens. But suppress the error only if we haven't tried to
1393 set the baud rate explicitly -- otherwise we'd never give an
1394 error for a true failure to set the baud rate. */
1396 new_mode.c_cflag &= (~CIBAUD);
1397 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1398 #endif
1400 error (EXIT_FAILURE, 0,
1401 _("%s: unable to perform all requested operations"),
1402 device_name);
1403 #ifdef TESTING
1405 size_t i;
1406 printf ("new_mode: mode\n");
1407 for (i = 0; i < sizeof (new_mode); i++)
1408 printf ("0x%02x: 0x%02x\n",
1409 *(((unsigned char *) &new_mode) + i),
1410 *(((unsigned char *) &mode) + i));
1412 #endif
1417 return EXIT_SUCCESS;
1420 /* Return false if not applied because not reversible; otherwise
1421 return true. */
1423 static bool
1424 set_mode (struct mode_info const *info, bool reversed, struct termios *mode)
1426 tcflag_t *bitsp;
1428 if (reversed && (info->flags & REV) == 0)
1429 return false;
1431 bitsp = mode_type_flag (info->type, mode);
1433 if (bitsp == NULL)
1435 /* Combination mode. */
1436 if (STREQ (info->name, "evenp") || STREQ (info->name, "parity"))
1438 if (reversed)
1439 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1440 else
1441 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
1443 else if (STREQ (info->name, "oddp"))
1445 if (reversed)
1446 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1447 else
1448 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
1450 else if (STREQ (info->name, "nl"))
1452 if (reversed)
1454 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
1455 mode->c_oflag = (mode->c_oflag
1456 #ifdef ONLCR
1457 | ONLCR
1458 #endif
1460 #ifdef OCRNL
1461 & ~OCRNL
1462 #endif
1463 #ifdef ONLRET
1464 & ~ONLRET
1465 #endif
1468 else
1470 mode->c_iflag = mode->c_iflag & ~ICRNL;
1471 #ifdef ONLCR
1472 mode->c_oflag = mode->c_oflag & ~ONLCR;
1473 #endif
1476 else if (STREQ (info->name, "ek"))
1478 mode->c_cc[VERASE] = CERASE;
1479 mode->c_cc[VKILL] = CKILL;
1481 else if (STREQ (info->name, "sane"))
1482 sane_mode (mode);
1483 else if (STREQ (info->name, "cbreak"))
1485 if (reversed)
1486 mode->c_lflag |= ICANON;
1487 else
1488 mode->c_lflag &= ~ICANON;
1490 else if (STREQ (info->name, "pass8"))
1492 if (reversed)
1494 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1495 mode->c_iflag |= ISTRIP;
1497 else
1499 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1500 mode->c_iflag &= ~ISTRIP;
1503 else if (STREQ (info->name, "litout"))
1505 if (reversed)
1507 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1508 mode->c_iflag |= ISTRIP;
1509 mode->c_oflag |= OPOST;
1511 else
1513 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1514 mode->c_iflag &= ~ISTRIP;
1515 mode->c_oflag &= ~OPOST;
1518 else if (STREQ (info->name, "raw") || STREQ (info->name, "cooked"))
1520 if ((info->name[0] == 'r' && reversed)
1521 || (info->name[0] == 'c' && !reversed))
1523 /* Cooked mode. */
1524 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1525 mode->c_oflag |= OPOST;
1526 mode->c_lflag |= ISIG | ICANON;
1527 #if VMIN == VEOF
1528 mode->c_cc[VEOF] = CEOF;
1529 #endif
1530 #if VTIME == VEOL
1531 mode->c_cc[VEOL] = CEOL;
1532 #endif
1534 else
1536 /* Raw mode. */
1537 mode->c_iflag = 0;
1538 mode->c_oflag &= ~OPOST;
1539 mode->c_lflag &= ~(ISIG | ICANON
1540 #ifdef XCASE
1541 | XCASE
1542 #endif
1544 mode->c_cc[VMIN] = 1;
1545 mode->c_cc[VTIME] = 0;
1548 #ifdef IXANY
1549 else if (STREQ (info->name, "decctlq"))
1551 if (reversed)
1552 mode->c_iflag |= IXANY;
1553 else
1554 mode->c_iflag &= ~IXANY;
1556 #endif
1557 #ifdef TABDLY
1558 else if (STREQ (info->name, "tabs"))
1560 if (reversed)
1561 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1562 else
1563 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1565 #else
1566 # ifdef OXTABS
1567 else if (STREQ (info->name, "tabs"))
1569 if (reversed)
1570 mode->c_oflag = mode->c_oflag | OXTABS;
1571 else
1572 mode->c_oflag = mode->c_oflag & ~OXTABS;
1574 # endif
1575 #endif
1576 #if defined XCASE && defined IUCLC && defined OLCUC
1577 else if (STREQ (info->name, "lcase")
1578 || STREQ (info->name, "LCASE"))
1580 if (reversed)
1582 mode->c_lflag &= ~XCASE;
1583 mode->c_iflag &= ~IUCLC;
1584 mode->c_oflag &= ~OLCUC;
1586 else
1588 mode->c_lflag |= XCASE;
1589 mode->c_iflag |= IUCLC;
1590 mode->c_oflag |= OLCUC;
1593 #endif
1594 else if (STREQ (info->name, "crt"))
1595 mode->c_lflag |= ECHOE
1596 #ifdef ECHOCTL
1597 | ECHOCTL
1598 #endif
1599 #ifdef ECHOKE
1600 | ECHOKE
1601 #endif
1603 else if (STREQ (info->name, "dec"))
1605 mode->c_cc[VINTR] = 3; /* ^C */
1606 mode->c_cc[VERASE] = 127; /* DEL */
1607 mode->c_cc[VKILL] = 21; /* ^U */
1608 mode->c_lflag |= ECHOE
1609 #ifdef ECHOCTL
1610 | ECHOCTL
1611 #endif
1612 #ifdef ECHOKE
1613 | ECHOKE
1614 #endif
1616 #ifdef IXANY
1617 mode->c_iflag &= ~IXANY;
1618 #endif
1621 else if (reversed)
1622 *bitsp = *bitsp & ~info->mask & ~info->bits;
1623 else
1624 *bitsp = (*bitsp & ~info->mask) | info->bits;
1626 return true;
1629 static void
1630 set_control_char (struct control_info const *info, const char *arg,
1631 struct termios *mode)
1633 unsigned long int value;
1635 if (STREQ (info->name, "min") || STREQ (info->name, "time"))
1636 value = integer_arg (arg, TYPE_MAXIMUM (cc_t));
1637 else if (arg[0] == '\0' || arg[1] == '\0')
1638 value = to_uchar (arg[0]);
1639 else if (STREQ (arg, "^-") || STREQ (arg, "undef"))
1640 value = _POSIX_VDISABLE;
1641 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1643 if (arg[1] == '?')
1644 value = 127;
1645 else
1646 value = to_uchar (arg[1]) & ~0140; /* Non-letters get weird results. */
1648 else
1649 value = integer_arg (arg, TYPE_MAXIMUM (cc_t));
1650 mode->c_cc[info->offset] = value;
1653 static void
1654 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1656 speed_t baud;
1658 baud = string_to_baud (arg);
1659 if (type == input_speed || type == both_speeds)
1660 cfsetispeed (mode, baud);
1661 if (type == output_speed || type == both_speeds)
1662 cfsetospeed (mode, baud);
1665 #ifdef TIOCGWINSZ
1667 static int
1668 get_win_size (int fd, struct winsize *win)
1670 int err = ioctl (fd, TIOCGWINSZ, (char *) win);
1671 return err;
1674 static void
1675 set_window_size (int rows, int cols, char const *device_name)
1677 struct winsize win;
1679 if (get_win_size (STDIN_FILENO, &win))
1681 if (errno != EINVAL)
1682 error (EXIT_FAILURE, errno, "%s", device_name);
1683 memset (&win, 0, sizeof (win));
1686 if (rows >= 0)
1687 win.ws_row = rows;
1688 if (cols >= 0)
1689 win.ws_col = cols;
1691 # ifdef TIOCSSIZE
1692 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1693 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1694 This comment from sys/ttold.h describes Sun's twisted logic - a better
1695 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1696 At any rate, the problem is gone in Solaris 2.x.
1698 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1699 but they can be disambiguated by checking whether a "struct ttysize"
1700 structure's "ts_lines" field is greater than 64K or not. If so,
1701 it's almost certainly a "struct winsize" instead.
1703 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1704 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16)
1705 + ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1706 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1707 "stty cols 0 rows 0" would do the right thing. On a little-endian
1708 machine like the sun386i, the problem is the same, but for ws_col == 0.
1710 The workaround is to do the ioctl once with row and col = 1 to set the
1711 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1713 if (win.ws_row == 0 || win.ws_col == 0)
1715 struct ttysize ttysz;
1717 ttysz.ts_lines = win.ws_row;
1718 ttysz.ts_cols = win.ws_col;
1720 win.ws_row = 1;
1721 win.ws_col = 1;
1723 if (ioctl (STDIN_FILENO, TIOCSWINSZ, (char *) &win))
1724 error (EXIT_FAILURE, errno, "%s", device_name);
1726 if (ioctl (STDIN_FILENO, TIOCSSIZE, (char *) &ttysz))
1727 error (EXIT_FAILURE, errno, "%s", device_name);
1728 return;
1730 # endif
1732 if (ioctl (STDIN_FILENO, TIOCSWINSZ, (char *) &win))
1733 error (EXIT_FAILURE, errno, "%s", device_name);
1736 static void
1737 display_window_size (bool fancy, char const *device_name)
1739 struct winsize win;
1741 if (get_win_size (STDIN_FILENO, &win))
1743 if (errno != EINVAL)
1744 error (EXIT_FAILURE, errno, "%s", device_name);
1745 if (!fancy)
1746 error (EXIT_FAILURE, 0,
1747 _("%s: no size information for this device"), device_name);
1749 else
1751 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1752 win.ws_row, win.ws_col);
1753 if (!fancy)
1754 current_col = 0;
1757 #endif
1759 static int
1760 screen_columns (void)
1762 #ifdef TIOCGWINSZ
1763 struct winsize win;
1765 /* With Solaris 2.[123], this ioctl fails and errno is set to
1766 EINVAL for telnet (but not rlogin) sessions.
1767 On ISC 3.0, it fails for the console and the serial port
1768 (but it works for ptys).
1769 It can also fail on any system when stdout isn't a tty.
1770 In case of any failure, just use the default. */
1771 if (get_win_size (STDOUT_FILENO, &win) == 0 && 0 < win.ws_col)
1772 return win.ws_col;
1773 #endif
1775 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1776 char *col_string = getenv ("COLUMNS");
1777 long int n_columns;
1778 if (!(col_string != NULL
1779 && xstrtol (col_string, NULL, 0, &n_columns, "") == LONGINT_OK
1780 && 0 < n_columns
1781 && n_columns <= INT_MAX))
1782 n_columns = 80;
1783 return n_columns;
1787 static tcflag_t * _GL_ATTRIBUTE_PURE
1788 mode_type_flag (enum mode_type type, struct termios *mode)
1790 switch (type)
1792 case control:
1793 return &mode->c_cflag;
1795 case input:
1796 return &mode->c_iflag;
1798 case output:
1799 return &mode->c_oflag;
1801 case local:
1802 return &mode->c_lflag;
1804 case combination:
1805 return NULL;
1807 default:
1808 abort ();
1812 static void
1813 display_settings (enum output_type output_type, struct termios *mode,
1814 char const *device_name)
1816 switch (output_type)
1818 case changed:
1819 display_changed (mode);
1820 break;
1822 case all:
1823 display_all (mode, device_name);
1824 break;
1826 case recoverable:
1827 display_recoverable (mode);
1828 break;
1832 static void
1833 display_changed (struct termios *mode)
1835 int i;
1836 bool empty_line;
1837 tcflag_t *bitsp;
1838 unsigned long mask;
1839 enum mode_type prev_type = control;
1841 display_speed (mode, true);
1842 #ifdef HAVE_C_LINE
1843 wrapf ("line = %d;", mode->c_line);
1844 #endif
1845 putchar ('\n');
1846 current_col = 0;
1848 empty_line = true;
1849 for (i = 0; !STREQ (control_info[i].name, "min"); ++i)
1851 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1852 continue;
1854 #ifdef VFLUSHO
1855 /* 'flush' is the deprecated equivalent of 'discard'. */
1856 if (STREQ (control_info[i].name, "flush"))
1857 continue;
1858 #endif
1859 /* If swtch is the same as susp, don't print both. */
1860 #if VSWTCH == VSUSP
1861 if (STREQ (control_info[i].name, "swtch"))
1862 continue;
1863 #endif
1864 /* If eof uses the same slot as min, only print whichever applies. */
1865 #if VEOF == VMIN
1866 if ((mode->c_lflag & ICANON) == 0
1867 && (STREQ (control_info[i].name, "eof")
1868 || STREQ (control_info[i].name, "eol")))
1869 continue;
1870 #endif
1872 empty_line = false;
1873 wrapf ("%s = %s;", control_info[i].name,
1874 visible (mode->c_cc[control_info[i].offset]));
1876 if ((mode->c_lflag & ICANON) == 0)
1878 wrapf ("min = %lu; time = %lu;\n",
1879 (unsigned long int) mode->c_cc[VMIN],
1880 (unsigned long int) mode->c_cc[VTIME]);
1882 else if (!empty_line)
1883 putchar ('\n');
1884 current_col = 0;
1886 empty_line = true;
1887 for (i = 0; mode_info[i].name != NULL; ++i)
1889 if (mode_info[i].flags & OMIT)
1890 continue;
1891 if (mode_info[i].type != prev_type)
1893 if (!empty_line)
1895 putchar ('\n');
1896 current_col = 0;
1897 empty_line = true;
1899 prev_type = mode_info[i].type;
1902 bitsp = mode_type_flag (mode_info[i].type, mode);
1903 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1905 /* bitsp would be NULL only for "combination" modes, yet those
1906 are filtered out above via the OMIT flag. Tell static analysis
1907 tools that it's ok to dereference bitsp here. */
1908 assert (bitsp);
1910 if ((*bitsp & mask) == mode_info[i].bits)
1912 if (mode_info[i].flags & SANE_UNSET)
1914 wrapf ("%s", mode_info[i].name);
1915 empty_line = false;
1918 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1920 wrapf ("-%s", mode_info[i].name);
1921 empty_line = false;
1924 if (!empty_line)
1925 putchar ('\n');
1926 current_col = 0;
1929 static void
1930 display_all (struct termios *mode, char const *device_name)
1932 int i;
1933 tcflag_t *bitsp;
1934 unsigned long mask;
1935 enum mode_type prev_type = control;
1937 display_speed (mode, true);
1938 #ifdef TIOCGWINSZ
1939 display_window_size (true, device_name);
1940 #endif
1941 #ifdef HAVE_C_LINE
1942 wrapf ("line = %d;", mode->c_line);
1943 #endif
1944 putchar ('\n');
1945 current_col = 0;
1947 for (i = 0; ! STREQ (control_info[i].name, "min"); ++i)
1949 #ifdef VFLUSHO
1950 /* 'flush' is the deprecated equivalent of 'discard'. */
1951 if (STREQ (control_info[i].name, "flush"))
1952 continue;
1953 #endif
1954 /* If swtch is the same as susp, don't print both. */
1955 #if VSWTCH == VSUSP
1956 if (STREQ (control_info[i].name, "swtch"))
1957 continue;
1958 #endif
1959 /* If eof uses the same slot as min, only print whichever applies. */
1960 #if VEOF == VMIN
1961 if ((mode->c_lflag & ICANON) == 0
1962 && (STREQ (control_info[i].name, "eof")
1963 || STREQ (control_info[i].name, "eol")))
1964 continue;
1965 #endif
1966 wrapf ("%s = %s;", control_info[i].name,
1967 visible (mode->c_cc[control_info[i].offset]));
1969 #if VEOF == VMIN
1970 if ((mode->c_lflag & ICANON) == 0)
1971 #endif
1972 wrapf ("min = %lu; time = %lu;",
1973 (unsigned long int) mode->c_cc[VMIN],
1974 (unsigned long int) mode->c_cc[VTIME]);
1975 if (current_col != 0)
1976 putchar ('\n');
1977 current_col = 0;
1979 for (i = 0; mode_info[i].name != NULL; ++i)
1981 if (mode_info[i].flags & OMIT)
1982 continue;
1983 if (mode_info[i].type != prev_type)
1985 putchar ('\n');
1986 current_col = 0;
1987 prev_type = mode_info[i].type;
1990 bitsp = mode_type_flag (mode_info[i].type, mode);
1991 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1992 assert (bitsp); /* See the identical assertion and comment above. */
1993 if ((*bitsp & mask) == mode_info[i].bits)
1994 wrapf ("%s", mode_info[i].name);
1995 else if (mode_info[i].flags & REV)
1996 wrapf ("-%s", mode_info[i].name);
1998 putchar ('\n');
1999 current_col = 0;
2002 static void
2003 display_speed (struct termios *mode, bool fancy)
2005 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
2006 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
2007 baud_to_value (cfgetospeed (mode)));
2008 else
2009 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
2010 baud_to_value (cfgetispeed (mode)),
2011 baud_to_value (cfgetospeed (mode)));
2012 if (!fancy)
2013 current_col = 0;
2016 static void
2017 display_recoverable (struct termios *mode)
2019 size_t i;
2021 printf ("%lx:%lx:%lx:%lx",
2022 (unsigned long int) mode->c_iflag,
2023 (unsigned long int) mode->c_oflag,
2024 (unsigned long int) mode->c_cflag,
2025 (unsigned long int) mode->c_lflag);
2026 for (i = 0; i < NCCS; ++i)
2027 printf (":%lx", (unsigned long int) mode->c_cc[i]);
2028 putchar ('\n');
2031 /* NOTE: identical to below, modulo use of tcflag_t */
2032 static int
2033 strtoul_tcflag_t (char const *s, int base, char **p, tcflag_t *result,
2034 char delim)
2036 unsigned long ul;
2037 errno = 0;
2038 ul = strtoul (s, p, base);
2039 if (errno || **p != delim || *p == s || (tcflag_t) ul != ul)
2040 return -1;
2041 *result = ul;
2042 return 0;
2045 /* NOTE: identical to above, modulo use of cc_t */
2046 static int
2047 strtoul_cc_t (char const *s, int base, char **p, cc_t *result, char delim)
2049 unsigned long ul;
2050 errno = 0;
2051 ul = strtoul (s, p, base);
2052 if (errno || **p != delim || *p == s || (cc_t) ul != ul)
2053 return -1;
2054 *result = ul;
2055 return 0;
2058 /* Parse the output of display_recoverable.
2059 Return false if any part of it is invalid. */
2060 static bool
2061 recover_mode (char const *arg, struct termios *mode)
2063 tcflag_t flag[4];
2064 char const *s = arg;
2065 size_t i;
2066 for (i = 0; i < 4; i++)
2068 char *p;
2069 if (strtoul_tcflag_t (s, 16, &p, flag + i, ':') != 0)
2070 return false;
2071 s = p + 1;
2073 mode->c_iflag = flag[0];
2074 mode->c_oflag = flag[1];
2075 mode->c_cflag = flag[2];
2076 mode->c_lflag = flag[3];
2078 for (i = 0; i < NCCS; ++i)
2080 char *p;
2081 char delim = i < NCCS - 1 ? ':' : '\0';
2082 if (strtoul_cc_t (s, 16, &p, mode->c_cc + i, delim) != 0)
2083 return false;
2084 s = p + 1;
2087 return true;
2090 struct speed_map
2092 const char *string; /* ASCII representation. */
2093 speed_t speed; /* Internal form. */
2094 unsigned long int value; /* Numeric value. */
2097 static struct speed_map const speeds[] =
2099 {"0", B0, 0},
2100 {"50", B50, 50},
2101 {"75", B75, 75},
2102 {"110", B110, 110},
2103 {"134", B134, 134},
2104 {"134.5", B134, 134},
2105 {"150", B150, 150},
2106 {"200", B200, 200},
2107 {"300", B300, 300},
2108 {"600", B600, 600},
2109 {"1200", B1200, 1200},
2110 {"1800", B1800, 1800},
2111 {"2400", B2400, 2400},
2112 {"4800", B4800, 4800},
2113 {"9600", B9600, 9600},
2114 {"19200", B19200, 19200},
2115 {"38400", B38400, 38400},
2116 {"exta", B19200, 19200},
2117 {"extb", B38400, 38400},
2118 #ifdef B57600
2119 {"57600", B57600, 57600},
2120 #endif
2121 #ifdef B115200
2122 {"115200", B115200, 115200},
2123 #endif
2124 #ifdef B230400
2125 {"230400", B230400, 230400},
2126 #endif
2127 #ifdef B460800
2128 {"460800", B460800, 460800},
2129 #endif
2130 #ifdef B500000
2131 {"500000", B500000, 500000},
2132 #endif
2133 #ifdef B576000
2134 {"576000", B576000, 576000},
2135 #endif
2136 #ifdef B921600
2137 {"921600", B921600, 921600},
2138 #endif
2139 #ifdef B1000000
2140 {"1000000", B1000000, 1000000},
2141 #endif
2142 #ifdef B1152000
2143 {"1152000", B1152000, 1152000},
2144 #endif
2145 #ifdef B1500000
2146 {"1500000", B1500000, 1500000},
2147 #endif
2148 #ifdef B2000000
2149 {"2000000", B2000000, 2000000},
2150 #endif
2151 #ifdef B2500000
2152 {"2500000", B2500000, 2500000},
2153 #endif
2154 #ifdef B3000000
2155 {"3000000", B3000000, 3000000},
2156 #endif
2157 #ifdef B3500000
2158 {"3500000", B3500000, 3500000},
2159 #endif
2160 #ifdef B4000000
2161 {"4000000", B4000000, 4000000},
2162 #endif
2163 {NULL, 0, 0}
2166 static speed_t _GL_ATTRIBUTE_PURE
2167 string_to_baud (const char *arg)
2169 int i;
2171 for (i = 0; speeds[i].string != NULL; ++i)
2172 if (STREQ (arg, speeds[i].string))
2173 return speeds[i].speed;
2174 return (speed_t) -1;
2177 static unsigned long int _GL_ATTRIBUTE_PURE
2178 baud_to_value (speed_t speed)
2180 int i;
2182 for (i = 0; speeds[i].string != NULL; ++i)
2183 if (speed == speeds[i].speed)
2184 return speeds[i].value;
2185 return 0;
2188 static void
2189 sane_mode (struct termios *mode)
2191 int i;
2192 tcflag_t *bitsp;
2194 for (i = 0; control_info[i].name; ++i)
2196 #if VMIN == VEOF
2197 if (STREQ (control_info[i].name, "min"))
2198 break;
2199 #endif
2200 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
2203 for (i = 0; mode_info[i].name != NULL; ++i)
2205 if (mode_info[i].flags & NO_SETATTR)
2206 continue;
2208 if (mode_info[i].flags & SANE_SET)
2210 bitsp = mode_type_flag (mode_info[i].type, mode);
2211 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
2213 else if (mode_info[i].flags & SANE_UNSET)
2215 bitsp = mode_type_flag (mode_info[i].type, mode);
2216 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
2221 /* Return a string that is the printable representation of character CH. */
2222 /* Adapted from 'cat' by Torbjorn Granlund. */
2224 static const char *
2225 visible (cc_t ch)
2227 static char buf[10];
2228 char *bpout = buf;
2230 if (ch == _POSIX_VDISABLE)
2231 return "<undef>";
2233 if (ch >= 32)
2235 if (ch < 127)
2236 *bpout++ = ch;
2237 else if (ch == 127)
2239 *bpout++ = '^';
2240 *bpout++ = '?';
2242 else
2244 *bpout++ = 'M';
2245 *bpout++ = '-';
2246 if (ch >= 128 + 32)
2248 if (ch < 128 + 127)
2249 *bpout++ = ch - 128;
2250 else
2252 *bpout++ = '^';
2253 *bpout++ = '?';
2256 else
2258 *bpout++ = '^';
2259 *bpout++ = ch - 128 + 64;
2263 else
2265 *bpout++ = '^';
2266 *bpout++ = ch + 64;
2268 *bpout = '\0';
2269 return (const char *) buf;
2272 /* Parse string S as an integer, using decimal radix by default,
2273 but allowing octal and hex numbers as in C. Reject values
2274 larger than MAXVAL. */
2276 static unsigned long int
2277 integer_arg (const char *s, unsigned long int maxval)
2279 return xnumtoumax (s, 0, 0, maxval, "bB", _("invalid integer argument"), 0);