split: be more careful about buffer sizes
[coreutils.git] / src / stty.c
blobfb7feefaba8c71a9cc01be06d149273b6ba0350b
1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2023 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 <https://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 "die.h"
59 #include "error.h"
60 #include "fd-reopen.h"
61 #include "quote.h"
62 #include "xdectoint.h"
63 #include "xstrtol.h"
65 /* The official name of this program (e.g., no 'g' prefix). */
66 #define PROGRAM_NAME "stty"
68 #define AUTHORS proper_name ("David MacKenzie")
70 #ifndef _POSIX_VDISABLE
71 # define _POSIX_VDISABLE 0
72 #endif
74 #define Control(c) ((c) & 0x1f)
75 /* Canonical values for control characters. */
76 #ifndef CINTR
77 # define CINTR Control ('c')
78 #endif
79 #ifndef CQUIT
80 # define CQUIT 28
81 #endif
82 #ifndef CERASE
83 # define CERASE 127
84 #endif
85 #ifndef CKILL
86 # define CKILL Control ('u')
87 #endif
88 #ifndef CEOF
89 # define CEOF Control ('d')
90 #endif
91 #ifndef CEOL
92 # define CEOL _POSIX_VDISABLE
93 #endif
94 #ifndef CSTART
95 # define CSTART Control ('q')
96 #endif
97 #ifndef CSTOP
98 # define CSTOP Control ('s')
99 #endif
100 #ifndef CSUSP
101 # define CSUSP Control ('z')
102 #endif
103 #if defined VEOL2 && !defined CEOL2
104 # define CEOL2 _POSIX_VDISABLE
105 #endif
106 /* Some platforms have VSWTC, others VSWTCH. In both cases, this control
107 character is initialized by CSWTCH, if present. */
108 #if defined VSWTC && !defined VSWTCH
109 # define VSWTCH VSWTC
110 #endif
111 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
112 #if defined VSUSP && !defined VSWTCH
113 # define VSWTCH VSUSP
114 # if defined CSUSP && !defined CSWTCH
115 # define CSWTCH CSUSP
116 # endif
117 #endif
118 #if defined VSWTCH && !defined CSWTCH
119 # define CSWTCH _POSIX_VDISABLE
120 #endif
122 /* SunOS >= 5.3 loses (^Z doesn't work) if 'swtch' is the same as 'susp'.
123 So the default is to disable 'swtch.' */
124 #if defined __sun
125 # undef CSWTCH
126 # define CSWTCH _POSIX_VDISABLE
127 #endif
129 #if defined VWERSE && !defined VWERASE /* AIX-3.2.5 */
130 # define VWERASE VWERSE
131 #endif
132 #if defined VDSUSP && !defined CDSUSP
133 # define CDSUSP Control ('y')
134 #endif
135 #if !defined VREPRINT && defined VRPRNT /* Irix 4.0.5 */
136 # define VREPRINT VRPRNT
137 #endif
138 #if defined VREPRINT && !defined CRPRNT
139 # define CRPRNT Control ('r')
140 #endif
141 #if defined CREPRINT && !defined CRPRNT
142 # define CRPRNT Control ('r')
143 #endif
144 #if defined VWERASE && !defined CWERASE
145 # define CWERASE Control ('w')
146 #endif
147 #if defined VLNEXT && !defined CLNEXT
148 # define CLNEXT Control ('v')
149 #endif
150 #if defined VDISCARD && !defined VFLUSHO
151 # define VFLUSHO VDISCARD
152 #endif
153 #if defined VFLUSH && !defined VFLUSHO /* Ultrix 4.2 */
154 # define VFLUSHO VFLUSH
155 #endif
156 #if defined CTLECH && !defined ECHOCTL /* Ultrix 4.3 */
157 # define ECHOCTL CTLECH
158 #endif
159 #if defined TCTLECH && !defined ECHOCTL /* Ultrix 4.2 */
160 # define ECHOCTL TCTLECH
161 #endif
162 #if defined CRTKIL && !defined ECHOKE /* Ultrix 4.2 and 4.3 */
163 # define ECHOKE CRTKIL
164 #endif
165 #if defined VFLUSHO && !defined CFLUSHO
166 # define CFLUSHO Control ('o')
167 #endif
168 #if defined VSTATUS && !defined CSTATUS
169 # define CSTATUS Control ('t')
170 #endif
172 /* Which speeds to set. */
173 enum speed_setting
175 input_speed, output_speed, both_speeds
178 /* What to output and how. */
179 enum output_type
181 changed, all, recoverable /* Default, -a, -g. */
184 /* Which member(s) of 'struct termios' a mode uses. */
185 enum mode_type
187 control, input, output, local, combination
190 /* Flags for 'struct mode_info'. */
191 #define SANE_SET 1 /* Set in 'sane' mode. */
192 #define SANE_UNSET 2 /* Unset in 'sane' mode. */
193 #define REV 4 /* Can be turned off by prepending '-'. */
194 #define OMIT 8 /* Don't display value. */
195 #define NO_SETATTR 16 /* tcsetattr not used to set mode bits. */
197 /* Each mode. */
198 struct mode_info
200 char const *name; /* Name given on command line. */
201 enum mode_type type; /* Which structure element to change. */
202 char flags; /* Setting and display options. */
203 unsigned long bits; /* Bits to set for this mode. */
204 unsigned long mask; /* Other bits to turn off for this mode. */
207 static struct mode_info const mode_info[] =
209 {"parenb", control, REV, PARENB, 0},
210 {"parodd", control, REV, PARODD, 0},
211 #ifdef CMSPAR
212 {"cmspar", control, REV, CMSPAR, 0},
213 #endif
214 {"cs5", control, 0, CS5, CSIZE},
215 {"cs6", control, 0, CS6, CSIZE},
216 {"cs7", control, 0, CS7, CSIZE},
217 {"cs8", control, 0, CS8, CSIZE},
218 {"hupcl", control, REV, HUPCL, 0},
219 {"hup", control, REV | OMIT, HUPCL, 0},
220 {"cstopb", control, REV, CSTOPB, 0},
221 {"cread", control, SANE_SET | REV, CREAD, 0},
222 {"clocal", control, REV, CLOCAL, 0},
223 #ifdef CRTSCTS
224 {"crtscts", control, REV, CRTSCTS, 0},
225 #endif
226 #ifdef CDTRDSR
227 {"cdtrdsr", control, REV, CDTRDSR, 0},
228 #endif
230 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
231 {"brkint", input, SANE_SET | REV, BRKINT, 0},
232 {"ignpar", input, REV, IGNPAR, 0},
233 {"parmrk", input, REV, PARMRK, 0},
234 {"inpck", input, REV, INPCK, 0},
235 {"istrip", input, REV, ISTRIP, 0},
236 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
237 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
238 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
239 {"ixon", input, REV, IXON, 0},
240 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
241 {"tandem", input, REV | OMIT, IXOFF, 0},
242 #ifdef IUCLC
243 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
244 #endif
245 #ifdef IXANY
246 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
247 #endif
248 #ifdef IMAXBEL
249 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
250 #endif
251 #ifdef IUTF8
252 {"iutf8", input, SANE_UNSET | REV, IUTF8, 0},
253 #endif
255 {"opost", output, SANE_SET | REV, OPOST, 0},
256 #ifdef OLCUC
257 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
258 #endif
259 #ifdef OCRNL
260 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
261 #endif
262 #ifdef ONLCR
263 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
264 #endif
265 #ifdef ONOCR
266 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
267 #endif
268 #ifdef ONLRET
269 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
270 #endif
271 #ifdef OFILL
272 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
273 #endif
274 #ifdef OFDEL
275 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
276 #endif
277 #ifdef NLDLY
278 {"nl1", output, SANE_UNSET, NL1, NLDLY},
279 {"nl0", output, SANE_SET, NL0, NLDLY},
280 #endif
281 #ifdef CRDLY
282 {"cr3", output, SANE_UNSET, CR3, CRDLY},
283 {"cr2", output, SANE_UNSET, CR2, CRDLY},
284 {"cr1", output, SANE_UNSET, CR1, CRDLY},
285 {"cr0", output, SANE_SET, CR0, CRDLY},
286 #endif
287 #ifdef TABDLY
288 # ifdef TAB3
289 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
290 # endif
291 # ifdef TAB2
292 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
293 # endif
294 # ifdef TAB1
295 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
296 # endif
297 # ifdef TAB0
298 {"tab0", output, SANE_SET, TAB0, TABDLY},
299 # endif
300 #else
301 # ifdef OXTABS
302 {"tab3", output, SANE_UNSET, OXTABS, 0},
303 # endif
304 #endif
305 #ifdef BSDLY
306 {"bs1", output, SANE_UNSET, BS1, BSDLY},
307 {"bs0", output, SANE_SET, BS0, BSDLY},
308 #endif
309 #ifdef VTDLY
310 {"vt1", output, SANE_UNSET, VT1, VTDLY},
311 {"vt0", output, SANE_SET, VT0, VTDLY},
312 #endif
313 #ifdef FFDLY
314 {"ff1", output, SANE_UNSET, FF1, FFDLY},
315 {"ff0", output, SANE_SET, FF0, FFDLY},
316 #endif
318 {"isig", local, SANE_SET | REV, ISIG, 0},
319 {"icanon", local, SANE_SET | REV, ICANON, 0},
320 #ifdef IEXTEN
321 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
322 #endif
323 {"echo", local, SANE_SET | REV, ECHO, 0},
324 {"echoe", local, SANE_SET | REV, ECHOE, 0},
325 {"crterase", local, REV | OMIT, ECHOE, 0},
326 {"echok", local, SANE_SET | REV, ECHOK, 0},
327 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
328 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
329 #ifdef XCASE
330 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
331 #endif
332 #ifdef TOSTOP
333 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
334 #endif
335 #ifdef ECHOPRT
336 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
337 {"prterase", local, REV | OMIT, ECHOPRT, 0},
338 #endif
339 #ifdef ECHOCTL
340 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
341 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
342 #endif
343 #ifdef ECHOKE
344 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
345 {"crtkill", local, REV | OMIT, ECHOKE, 0},
346 #endif
347 #ifdef FLUSHO
348 {"flusho", local, SANE_UNSET | REV, FLUSHO, 0},
349 #endif
350 #if defined TIOCEXT
351 {"extproc", local, SANE_UNSET | REV | NO_SETATTR, EXTPROC, 0},
352 #elif defined EXTPROC
353 {"extproc", local, SANE_UNSET | REV, EXTPROC, 0},
354 #endif
356 {"evenp", combination, REV | OMIT, 0, 0},
357 {"parity", combination, REV | OMIT, 0, 0},
358 {"oddp", combination, REV | OMIT, 0, 0},
359 {"nl", combination, REV | OMIT, 0, 0},
360 {"ek", combination, OMIT, 0, 0},
361 {"sane", combination, OMIT, 0, 0},
362 {"cooked", combination, REV | OMIT, 0, 0},
363 {"raw", combination, REV | OMIT, 0, 0},
364 {"pass8", combination, REV | OMIT, 0, 0},
365 {"litout", combination, REV | OMIT, 0, 0},
366 {"cbreak", combination, REV | OMIT, 0, 0},
367 #ifdef IXANY
368 {"decctlq", combination, REV | OMIT, 0, 0},
369 #endif
370 #if defined TABDLY || defined OXTABS
371 {"tabs", combination, REV | OMIT, 0, 0},
372 #endif
373 #if defined XCASE && defined IUCLC && defined OLCUC
374 {"lcase", combination, REV | OMIT, 0, 0},
375 {"LCASE", combination, REV | OMIT, 0, 0},
376 #endif
377 {"crt", combination, OMIT, 0, 0},
378 {"dec", combination, OMIT, 0, 0},
380 {NULL, control, 0, 0, 0}
383 /* Control character settings. */
384 struct control_info
386 char const *name; /* Name given on command line. */
387 cc_t saneval; /* Value to set for 'stty sane'. */
388 size_t offset; /* Offset in c_cc. */
391 /* Control characters. */
393 static struct control_info const control_info[] =
395 {"intr", CINTR, VINTR},
396 {"quit", CQUIT, VQUIT},
397 {"erase", CERASE, VERASE},
398 {"kill", CKILL, VKILL},
399 {"eof", CEOF, VEOF},
400 {"eol", CEOL, VEOL},
401 #ifdef VEOL2
402 {"eol2", CEOL2, VEOL2},
403 #endif
404 #ifdef VSWTCH
405 {"swtch", CSWTCH, VSWTCH},
406 #endif
407 {"start", CSTART, VSTART},
408 {"stop", CSTOP, VSTOP},
409 {"susp", CSUSP, VSUSP},
410 #ifdef VDSUSP
411 {"dsusp", CDSUSP, VDSUSP},
412 #endif
413 #ifdef VREPRINT
414 {"rprnt", CRPRNT, VREPRINT},
415 #else
416 # ifdef CREPRINT /* HPUX 10.20 needs this */
417 {"rprnt", CRPRNT, CREPRINT},
418 # endif
419 #endif
420 #ifdef VWERASE
421 {"werase", CWERASE, VWERASE},
422 #endif
423 #ifdef VLNEXT
424 {"lnext", CLNEXT, VLNEXT},
425 #endif
426 #ifdef VFLUSHO
427 {"flush", CFLUSHO, VFLUSHO}, /* deprecated compat option. */
428 {"discard", CFLUSHO, VFLUSHO},
429 #endif
430 #ifdef VSTATUS
431 {"status", CSTATUS, VSTATUS},
432 #endif
434 /* These must be last because of the display routines. */
435 {"min", 1, VMIN},
436 {"time", 0, VTIME},
437 {NULL, 0, 0}
440 static char const *visible (cc_t ch);
441 static unsigned long int baud_to_value (speed_t speed);
442 static bool recover_mode (char const *arg, struct termios *mode);
443 static int screen_columns (void);
444 static bool set_mode (struct mode_info const *info, bool reversed,
445 struct termios *mode);
446 static bool eq_mode (struct termios *mode1, struct termios *mode2);
447 static unsigned long int integer_arg (char const *s, unsigned long int max);
448 static speed_t string_to_baud (char const *arg);
449 static tcflag_t *mode_type_flag (enum mode_type type, struct termios *mode);
450 static void display_all (struct termios *mode, char const *device_name);
451 static void display_changed (struct termios *mode);
452 static void display_recoverable (struct termios *mode);
453 static void display_settings (enum output_type output_type,
454 struct termios *mode,
455 char const *device_name);
456 static void check_speed (struct termios *mode);
457 static void display_speed (struct termios *mode, bool fancy);
458 static void display_window_size (bool fancy, char const *device_name);
459 static void sane_mode (struct termios *mode);
460 static void set_control_char (struct control_info const *info,
461 char const *arg,
462 struct termios *mode);
463 static void set_speed (enum speed_setting type, char const *arg,
464 struct termios *mode);
465 static void set_window_size (int rows, int cols, char const *device_name);
467 /* The width of the screen, for output wrapping. */
468 static int max_col;
470 /* Current position, to know when to wrap. */
471 static int current_col;
473 /* Default "drain" mode for tcsetattr. */
474 static int tcsetattr_options = TCSADRAIN;
476 /* Extra info to aid stty development. */
477 static bool dev_debug;
479 /* Record last speed set for correlation. */
480 static speed_t last_ibaud = (speed_t) -1;
481 static speed_t last_obaud = (speed_t) -1;
483 /* For long options that have no equivalent short option, use a
484 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
485 enum
487 DEV_DEBUG_OPTION = CHAR_MAX + 1,
490 static struct option const longopts[] =
492 {"all", no_argument, NULL, 'a'},
493 {"save", no_argument, NULL, 'g'},
494 {"file", required_argument, NULL, 'F'},
495 {"-debug", no_argument, NULL, DEV_DEBUG_OPTION},
496 {GETOPT_HELP_OPTION_DECL},
497 {GETOPT_VERSION_OPTION_DECL},
498 {NULL, 0, NULL, 0}
501 /* Print format string MESSAGE and optional args.
502 Wrap to next line first if it won't fit.
503 Print a space first unless MESSAGE will start a new line. */
505 ATTRIBUTE_FORMAT ((printf, 1, 2))
506 static void
507 wrapf (char const *message,...)
509 va_list args;
510 char *buf;
511 int buflen;
513 va_start (args, message);
514 buflen = vasprintf (&buf, message, args);
515 va_end (args);
517 if (buflen < 0)
518 xalloc_die ();
520 if (0 < current_col)
522 if (max_col - current_col <= buflen)
524 putchar ('\n');
525 current_col = 0;
527 else
529 putchar (' ');
530 current_col++;
534 fputs (buf, stdout);
535 free (buf);
536 current_col += buflen;
539 void
540 usage (int status)
542 if (status != EXIT_SUCCESS)
543 emit_try_help ();
544 else
546 printf (_("\
547 Usage: %s [-F DEVICE | --file=DEVICE] [SETTING]...\n\
548 or: %s [-F DEVICE | --file=DEVICE] [-a|--all]\n\
549 or: %s [-F DEVICE | --file=DEVICE] [-g|--save]\n\
551 program_name, program_name, program_name);
552 fputs (_("\
553 Print or change terminal characteristics.\n\
554 "), stdout);
556 emit_mandatory_arg_note ();
558 fputs (_("\
559 -a, --all print all current settings in human-readable form\n\
560 -g, --save print all current settings in a stty-readable form\n\
561 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
562 "), stdout);
563 fputs (HELP_OPTION_DESCRIPTION, stdout);
564 fputs (VERSION_OPTION_DESCRIPTION, stdout);
565 fputs (_("\
567 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
568 settings. The underlying system defines which settings are available.\n\
569 "), stdout);
570 fputs (_("\
572 Special characters:\n"), stdout);
573 #ifdef VFLUSHO
574 fputs (_("\
575 * discard CHAR CHAR will toggle discarding of output\n\
576 "), stdout);
577 #endif
578 #ifdef VDSUSP
579 fputs (_("\
580 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
581 "), stdout);
582 #endif
583 fputs (_("\
584 eof CHAR CHAR will send an end of file (terminate the input)\n\
585 eol CHAR CHAR will end the line\n\
586 "), stdout);
587 #ifdef VEOL2
588 fputs (_("\
589 * eol2 CHAR alternate CHAR for ending the line\n\
590 "), stdout);
591 #endif
592 fputs (_("\
593 erase CHAR CHAR will erase the last character typed\n\
594 intr CHAR CHAR will send an interrupt signal\n\
595 kill CHAR CHAR will erase the current line\n\
596 "), stdout);
597 #ifdef VLNEXT
598 fputs (_("\
599 * lnext CHAR CHAR will enter the next character quoted\n\
600 "), stdout);
601 #endif
602 #ifdef VSTATUS
603 fputs (_("\
604 * status CHAR CHAR will send an info signal\n\
605 "), stdout);
606 #endif
607 fputs (_("\
608 quit CHAR CHAR will send a quit signal\n\
609 "), stdout);
610 #if defined CREPRINT || defined VREPRINT
611 fputs (_("\
612 * rprnt CHAR CHAR will redraw the current line\n\
613 "), stdout);
614 #endif
615 fputs (_("\
616 start CHAR CHAR will restart the output after stopping it\n\
617 stop CHAR CHAR will stop the output\n\
618 susp CHAR CHAR will send a terminal stop signal\n\
619 "), stdout);
620 #ifdef VSWTCH
621 fputs (_("\
622 * swtch CHAR CHAR will switch to a different shell layer\n\
623 "), stdout);
624 #endif
625 #ifdef VWERASE
626 fputs (_("\
627 * werase CHAR CHAR will erase the last word typed\n\
628 "), stdout);
629 #endif
630 fputs (_("\
632 Special settings:\n\
633 N set the input and output speeds to N bauds\n\
634 "), stdout);
635 #ifdef TIOCGWINSZ
636 fputs (_("\
637 * cols N tell the kernel that the terminal has N columns\n\
638 * columns N same as cols N\n\
639 "), stdout);
640 #endif
641 printf (_("\
642 * [-]drain wait for transmission before applying settings (%s by default)\
643 \n"), tcsetattr_options == TCSADRAIN ? _("on") : _("off"));
644 fputs (_("\
645 ispeed N set the input speed to N\n\
646 "), stdout);
647 #ifdef HAVE_C_LINE
648 fputs (_("\
649 * line N use line discipline N\n\
650 "), stdout);
651 #endif
652 fputs (_("\
653 min N with -icanon, set N characters minimum for a completed read\n\
654 ospeed N set the output speed to N\n\
655 "), stdout);
656 #ifdef TIOCGWINSZ
657 fputs (_("\
658 * rows N tell the kernel that the terminal has N rows\n\
659 * size print the number of rows and columns according to the kernel\n\
660 "), stdout);
661 #endif
662 fputs (_("\
663 speed print the terminal speed\n\
664 time N with -icanon, set read timeout of N tenths of a second\n\
665 "), stdout);
666 fputs (_("\
668 Control settings:\n\
669 [-]clocal disable modem control signals\n\
670 [-]cread allow input to be received\n\
671 "), stdout);
672 #ifdef CRTSCTS
673 fputs (_("\
674 * [-]crtscts enable RTS/CTS handshaking\n\
675 "), stdout);
676 #endif
677 #ifdef CDTRDSR
678 fputs (_("\
679 * [-]cdtrdsr enable DTR/DSR handshaking\n\
680 "), stdout);
681 #endif
682 fputs (_("\
683 csN set character size to N bits, N in [5..8]\n\
684 "), stdout);
685 fputs (_("\
686 [-]cstopb use two stop bits per character (one with '-')\n\
687 [-]hup send a hangup signal when the last process closes the tty\n\
688 [-]hupcl same as [-]hup\n\
689 [-]parenb generate parity bit in output and expect parity bit in input\n\
690 [-]parodd set odd parity (or even parity with '-')\n\
691 "), stdout);
692 #ifdef CMSPAR
693 fputs (_("\
694 * [-]cmspar use \"stick\" (mark/space) parity\n\
695 "), stdout);
696 #endif
697 fputs (_("\
699 Input settings:\n\
700 [-]brkint breaks cause an interrupt signal\n\
701 [-]icrnl translate carriage return to newline\n\
702 [-]ignbrk ignore break characters\n\
703 [-]igncr ignore carriage return\n\
704 [-]ignpar ignore characters with parity errors\n\
705 "), stdout);
706 #ifdef IMAXBEL
707 fputs (_("\
708 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
709 "), stdout);
710 #endif
711 fputs (_("\
712 [-]inlcr translate newline to carriage return\n\
713 [-]inpck enable input parity checking\n\
714 [-]istrip clear high (8th) bit of input characters\n\
715 "), stdout);
716 #ifdef IUTF8
717 fputs (_("\
718 * [-]iutf8 assume input characters are UTF-8 encoded\n\
719 "), stdout);
720 #endif
721 #ifdef IUCLC
722 fputs (_("\
723 * [-]iuclc translate uppercase characters to lowercase\n\
724 "), stdout);
725 #endif
726 #ifdef IXANY
727 fputs (_("\
728 * [-]ixany let any character restart output, not only start character\n\
729 "), stdout);
730 #endif
731 fputs (_("\
732 [-]ixoff enable sending of start/stop characters\n\
733 [-]ixon enable XON/XOFF flow control\n\
734 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
735 [-]tandem same as [-]ixoff\n\
736 "), stdout);
737 fputs (_("\
739 Output settings:\n\
740 "), stdout);
741 #ifdef BSDLY
742 fputs (_("\
743 * bsN backspace delay style, N in [0..1]\n\
744 "), stdout);
745 #endif
746 #ifdef CRDLY
747 fputs (_("\
748 * crN carriage return delay style, N in [0..3]\n\
749 "), stdout);
750 #endif
751 #ifdef FFDLY
752 fputs (_("\
753 * ffN form feed delay style, N in [0..1]\n\
754 "), stdout);
755 #endif
756 #ifdef NLDLY
757 fputs (_("\
758 * nlN newline delay style, N in [0..1]\n\
759 "), stdout);
760 #endif
761 #ifdef OCRNL
762 fputs (_("\
763 * [-]ocrnl translate carriage return to newline\n\
764 "), stdout);
765 #endif
766 #ifdef OFDEL
767 fputs (_("\
768 * [-]ofdel use delete characters for fill instead of NUL characters\n\
769 "), stdout);
770 #endif
771 #ifdef OFILL
772 fputs (_("\
773 * [-]ofill use fill (padding) characters instead of timing for delays\n\
774 "), stdout);
775 #endif
776 #ifdef OLCUC
777 fputs (_("\
778 * [-]olcuc translate lowercase characters to uppercase\n\
779 "), stdout);
780 #endif
781 #ifdef ONLCR
782 fputs (_("\
783 * [-]onlcr translate newline to carriage return-newline\n\
784 "), stdout);
785 #endif
786 #ifdef ONLRET
787 fputs (_("\
788 * [-]onlret newline performs a carriage return\n\
789 "), stdout);
790 #endif
791 #ifdef ONOCR
792 fputs (_("\
793 * [-]onocr do not print carriage returns in the first column\n\
794 "), stdout);
795 #endif
796 fputs (_("\
797 [-]opost postprocess output\n\
798 "), stdout);
799 #if defined TABDLY || defined OXTABS
800 fputs (_("\
801 * tabN horizontal tab delay style, N in [0..3]\n\
802 * tabs same as tab0\n\
803 * -tabs same as tab3\n\
804 "), stdout);
805 #endif
806 #ifdef VTDLY
807 fputs (_("\
808 * vtN vertical tab delay style, N in [0..1]\n\
809 "), stdout);
810 #endif
811 fputs (_("\
813 Local settings:\n\
814 [-]crterase echo erase characters as backspace-space-backspace\n\
815 "), stdout);
816 #ifdef ECHOKE
817 fputs (_("\
818 * crtkill kill all line by obeying the echoprt and echoe settings\n\
819 * -crtkill kill all line by obeying the echoctl and echok settings\n\
820 "), stdout);
821 #endif
822 #ifdef ECHOCTL
823 fputs (_("\
824 * [-]ctlecho echo control characters in hat notation ('^c')\n\
825 "), stdout);
826 #endif
827 fputs (_("\
828 [-]echo echo input characters\n\
829 "), stdout);
830 #ifdef ECHOCTL
831 fputs (_("\
832 * [-]echoctl same as [-]ctlecho\n\
833 "), stdout);
834 #endif
835 fputs (_("\
836 [-]echoe same as [-]crterase\n\
837 [-]echok echo a newline after a kill character\n\
838 "), stdout);
839 #ifdef ECHOKE
840 fputs (_("\
841 * [-]echoke same as [-]crtkill\n\
842 "), stdout);
843 #endif
844 fputs (_("\
845 [-]echonl echo newline even if not echoing other characters\n\
846 "), stdout);
847 #ifdef ECHOPRT
848 fputs (_("\
849 * [-]echoprt echo erased characters backward, between '\\' and '/'\n\
850 "), stdout);
851 #endif
852 #if defined EXTPROC || defined TIOCEXT
853 fputs (_("\
854 * [-]extproc enable \"LINEMODE\"; useful with high latency links\n\
855 "), stdout);
856 #endif
857 #if defined FLUSHO
858 fputs (_("\
859 * [-]flusho discard output\n\
860 "), stdout);
861 #endif
862 printf (_("\
863 [-]icanon enable special characters: %s\n\
864 [-]iexten enable non-POSIX special characters\n\
865 "), "erase, kill"
866 #ifdef VWERASE
867 ", werase"
868 #endif
869 #if defined CREPRINT || defined VREPRINT
870 ", rprnt"
871 #endif
873 fputs (_("\
874 [-]isig enable interrupt, quit, and suspend special characters\n\
875 [-]noflsh disable flushing after interrupt and quit special characters\n\
876 "), stdout);
877 #ifdef ECHOPRT
878 fputs (_("\
879 * [-]prterase same as [-]echoprt\n\
880 "), stdout);
881 #endif
882 #ifdef TOSTOP
883 fputs (_("\
884 * [-]tostop stop background jobs that try to write to the terminal\n\
885 "), stdout);
886 #endif
887 #ifdef XCASE
888 fputs (_("\
889 * [-]xcase with icanon, escape with '\\' for uppercase characters\n\
890 "), stdout);
891 #endif
892 fputs (_("\
894 Combination settings:\n\
895 "), stdout);
896 #if defined XCASE && defined IUCLC && defined OLCUC
897 fputs (_("\
898 * [-]LCASE same as [-]lcase\n\
899 "), stdout);
900 #endif
901 fputs (_("\
902 cbreak same as -icanon\n\
903 -cbreak same as icanon\n\
904 "), stdout);
905 fputs (_("\
906 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
907 icanon, eof and eol characters to their default values\n\
908 -cooked same as raw\n\
909 "), stdout);
910 printf (_("\
911 crt same as %s\n\
912 "), "echoe"
913 #ifdef ECHOCTL
914 " echoctl"
915 #endif
916 #ifdef ECHOKE
917 " echoke"
918 #endif
920 printf (_("\
921 dec same as %s intr ^c erase 0177\n\
922 kill ^u\n\
923 "), "echoe"
924 #ifdef ECHOCTL
925 " echoctl"
926 #endif
927 #ifdef ECHOKE
928 " echoke"
929 #endif
930 #ifdef IXANY
931 " -ixany"
932 #endif
934 #ifdef IXANY
935 fputs (_("\
936 * [-]decctlq same as [-]ixany\n\
937 "), stdout);
938 #endif
939 fputs (_("\
940 ek erase and kill characters to their default values\n\
941 evenp same as parenb -parodd cs7\n\
942 -evenp same as -parenb cs8\n\
943 "), stdout);
944 #if defined XCASE && defined IUCLC && defined OLCUC
945 fputs (_("\
946 * [-]lcase same as xcase iuclc olcuc\n\
947 "), stdout);
948 #endif
949 fputs (_("\
950 litout same as -parenb -istrip -opost cs8\n\
951 -litout same as parenb istrip opost cs7\n\
952 "), stdout);
953 printf (_("\
954 nl same as %s\n\
955 -nl same as %s\n\
956 "), "-icrnl"
957 #ifdef ONLCR
958 " -onlcr"
959 #endif
960 , "icrnl -inlcr -igncr"
961 #ifdef ONLCR
962 " onlcr"
963 #endif
964 #ifdef OCRNL
965 " -ocrnl"
966 #endif
967 #ifdef ONLRET
968 " -onlret"
969 #endif
971 fputs (_("\
972 oddp same as parenb parodd cs7\n\
973 -oddp same as -parenb cs8\n\
974 [-]parity same as [-]evenp\n\
975 pass8 same as -parenb -istrip cs8\n\
976 -pass8 same as parenb istrip cs7\n\
977 "), stdout);
978 printf (_("\
979 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
980 -inlcr -igncr -icrnl -ixon -ixoff -icanon -opost\n\
981 -isig%s min 1 time 0\n\
982 -raw same as cooked\n\
984 #ifdef IUCLC
985 " -iuclc"
986 #endif
987 #ifdef IXANY
988 " -ixany"
989 #endif
990 #ifdef IMAXBEL
991 " -imaxbel"
992 #endif
993 #ifdef XCASE
994 " -xcase"
995 #endif
997 printf (_("\
998 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
999 icanon iexten echo echoe echok -echonl -noflsh\n\
1000 %s\n\
1001 %s\n\
1002 %s,\n\
1003 all special characters to their default values\n\
1005 "-ixoff"
1006 #ifdef IUTF8
1007 " -iutf8"
1008 #endif
1009 #ifdef IUCLC
1010 " -iuclc"
1011 #endif
1012 #ifdef IXANY
1013 " -ixany"
1014 #endif
1015 #ifdef IMAXBEL
1016 " imaxbel"
1017 #endif
1018 #ifdef XCASE
1019 " -xcase"
1020 #endif
1021 #ifdef OLCUC
1022 " -olcuc"
1023 #endif
1024 #ifdef OCRNL
1025 " -ocrnl"
1026 #endif
1028 , "opost"
1029 #ifdef OFILL
1030 " -ofill"
1031 #endif
1032 #ifdef ONLCR
1033 " onlcr"
1034 #endif
1035 #ifdef ONOCR
1036 " -onocr"
1037 #endif
1038 #ifdef ONLRET
1039 " -onlret"
1040 #endif
1041 #ifdef NLDLY
1042 " nl0"
1043 #endif
1044 #ifdef CRDLY
1045 " cr0"
1046 #endif
1047 #ifdef TAB0
1048 " tab0"
1049 #endif
1050 #ifdef BSDLY
1051 " bs0"
1052 #endif
1053 #ifdef VTDLY
1054 " vt0"
1055 #endif
1056 #ifdef FFDLY
1057 " ff0"
1058 #endif
1060 , "isig"
1061 #ifdef TOSTOP
1062 " -tostop"
1063 #endif
1064 #ifdef OFDEL
1065 " -ofdel"
1066 #endif
1067 #ifdef ECHOPRT
1068 " -echoprt"
1069 #endif
1070 #ifdef ECHOCTL
1071 " echoctl"
1072 #endif
1073 #ifdef ECHOKE
1074 " echoke"
1075 #endif
1076 #ifdef EXTPROC
1077 " -extproc"
1078 #endif
1079 #ifdef FLUSHO
1080 " -flusho"
1081 #endif
1083 fputs (_("\
1085 Handle the tty line connected to standard input. Without arguments,\n\
1086 prints baud rate, line discipline, and deviations from stty sane. In\n\
1087 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
1088 127; special values ^- or undef used to disable special characters.\n\
1089 "), stdout);
1090 emit_ancillary_info (PROGRAM_NAME);
1092 exit (status);
1096 /* Apply specified settings to MODE and REQUIRE_SET_ATTR as required.
1097 If CHECKING is true, this function doesn't interact
1098 with a device, and only validates specified settings. */
1100 static void
1101 apply_settings (bool checking, char const *device_name,
1102 char * const *settings, int n_settings,
1103 struct termios *mode, bool *require_set_attr)
1105 #define check_argument(arg) \
1106 do \
1108 if (k == n_settings - 1 || ! settings[k + 1]) \
1110 error (0, 0, _("missing argument to %s"), quote (arg)); \
1111 usage (EXIT_FAILURE); \
1114 while (0)
1116 for (int k = 1; k < n_settings; k++)
1118 char const *arg = settings[k];
1119 bool match_found = false;
1120 bool not_set_attr = false;
1121 bool reversed = false;
1122 int i;
1124 if (! arg)
1125 continue;
1127 if (arg[0] == '-')
1129 ++arg;
1130 reversed = true;
1132 if (STREQ (arg, "drain"))
1134 tcsetattr_options = reversed ? TCSANOW : TCSADRAIN;
1135 continue;
1137 for (i = 0; mode_info[i].name != NULL; ++i)
1139 if (STREQ (arg, mode_info[i].name))
1141 if ((mode_info[i].flags & NO_SETATTR) == 0)
1143 match_found = set_mode (&mode_info[i], reversed, mode);
1144 *require_set_attr = true;
1146 else
1147 match_found = not_set_attr = true;
1148 break;
1151 if (!match_found && reversed)
1153 error (0, 0, _("invalid argument %s"), quote (arg - 1));
1154 usage (EXIT_FAILURE);
1156 if (!match_found)
1158 for (i = 0; control_info[i].name != NULL; ++i)
1160 if (STREQ (arg, control_info[i].name))
1162 check_argument (arg);
1163 match_found = true;
1164 ++k;
1165 set_control_char (&control_info[i], settings[k], mode);
1166 *require_set_attr = true;
1167 break;
1171 if (!match_found || not_set_attr)
1173 if (STREQ (arg, "ispeed"))
1175 check_argument (arg);
1176 ++k;
1177 if (string_to_baud (settings[k]) == (speed_t) -1)
1179 error (0, 0, _("invalid ispeed %s"), quote (settings[k]));
1180 usage (EXIT_FAILURE);
1182 set_speed (input_speed, settings[k], mode);
1183 if (checking)
1184 continue;
1185 *require_set_attr = true;
1187 else if (STREQ (arg, "ospeed"))
1189 check_argument (arg);
1190 ++k;
1191 if (string_to_baud (settings[k]) == (speed_t) -1)
1193 error (0, 0, _("invalid ospeed %s"), quote (settings[k]));
1194 usage (EXIT_FAILURE);
1196 set_speed (output_speed, settings[k], mode);
1197 if (checking)
1198 continue;
1199 *require_set_attr = true;
1201 #ifdef TIOCEXT
1202 /* This is the BSD interface to "extproc".
1203 Even though it's an lflag, an ioctl is used to set it. */
1204 else if (STREQ (arg, "extproc"))
1206 int val = ! reversed;
1208 if (checking)
1209 continue;
1211 if (ioctl (STDIN_FILENO, TIOCEXT, &val) != 0)
1213 die (EXIT_FAILURE, errno, _("%s: error setting %s"),
1214 quotef_n (0, device_name), quote_n (1, arg));
1217 #endif
1218 #ifdef TIOCGWINSZ
1219 else if (STREQ (arg, "rows"))
1221 check_argument (arg);
1222 ++k;
1223 if (checking)
1224 continue;
1225 set_window_size (integer_arg (settings[k], INT_MAX), -1,
1226 device_name);
1228 else if (STREQ (arg, "cols")
1229 || STREQ (arg, "columns"))
1231 check_argument (arg);
1232 ++k;
1233 if (checking)
1234 continue;
1235 set_window_size (-1, integer_arg (settings[k], INT_MAX),
1236 device_name);
1238 else if (STREQ (arg, "size"))
1240 if (checking)
1241 continue;
1242 max_col = screen_columns ();
1243 current_col = 0;
1244 display_window_size (false, device_name);
1246 #endif
1247 #ifdef HAVE_C_LINE
1248 else if (STREQ (arg, "line"))
1250 unsigned long int value;
1251 check_argument (arg);
1252 ++k;
1253 mode->c_line = value = integer_arg (settings[k], ULONG_MAX);
1254 if (mode->c_line != value)
1255 error (0, 0, _("invalid line discipline %s"),
1256 quote (settings[k]));
1257 *require_set_attr = true;
1259 #endif
1260 else if (STREQ (arg, "speed"))
1262 if (checking)
1263 continue;
1264 max_col = screen_columns ();
1265 display_speed (mode, false);
1267 else if (string_to_baud (arg) != (speed_t) -1)
1269 set_speed (both_speeds, arg, mode);
1270 if (checking)
1271 continue;
1272 *require_set_attr = true;
1274 else
1276 if (! recover_mode (arg, mode))
1278 error (0, 0, _("invalid argument %s"), quote (arg));
1279 usage (EXIT_FAILURE);
1281 *require_set_attr = true;
1286 if (checking)
1287 check_speed (mode);
1291 main (int argc, char **argv)
1293 struct termios mode;
1295 enum output_type output_type;
1296 int optc;
1297 int argi = 0;
1298 int opti = 1;
1299 bool require_set_attr;
1300 bool verbose_output;
1301 bool recoverable_output;
1302 bool noargs = true;
1303 char *file_name = NULL;
1304 char const *device_name;
1306 initialize_main (&argc, &argv);
1307 set_program_name (argv[0]);
1308 setlocale (LC_ALL, "");
1309 bindtextdomain (PACKAGE, LOCALEDIR);
1310 textdomain (PACKAGE);
1312 atexit (close_stdout);
1314 output_type = changed;
1315 verbose_output = false;
1316 recoverable_output = false;
1318 /* Don't print error messages for unrecognized options. */
1319 opterr = 0;
1321 /* If any new options are ever added to stty, the short options MUST
1322 NOT allow any ambiguity with the stty settings. For example, the
1323 stty setting "-gagFork" would not be feasible, since it will be
1324 parsed as "-g -a -g -F ork". If you change anything about how
1325 stty parses options, be sure it still works with combinations of
1326 short and long options, --, POSIXLY_CORRECT, etc. */
1328 while ((optc = getopt_long (argc - argi, argv + argi, "-agF:",
1329 longopts, NULL))
1330 != -1)
1332 switch (optc)
1334 case 'a':
1335 verbose_output = true;
1336 output_type = all;
1337 break;
1339 case 'g':
1340 recoverable_output = true;
1341 output_type = recoverable;
1342 break;
1344 case 'F':
1345 if (file_name)
1346 die (EXIT_FAILURE, 0, _("only one device may be specified"));
1347 file_name = optarg;
1348 break;
1350 case DEV_DEBUG_OPTION:
1351 dev_debug = true;
1352 break;
1354 case_GETOPT_HELP_CHAR;
1356 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1358 default:
1359 /* Consider "drain" as an option rather than a setting,
1360 to support: alias stty='stty -drain' etc. */
1361 if (! STREQ (argv[argi + opti], "-drain")
1362 && ! STREQ (argv[argi + opti], "drain"))
1363 noargs = false;
1365 /* Skip the argument containing this unrecognized option;
1366 the 2nd pass will analyze it. */
1367 argi += opti;
1369 /* Restart getopt_long from the first unskipped argument. */
1370 opti = 1;
1371 optind = 0;
1373 break;
1376 /* Clear fully-parsed arguments, so they don't confuse the 2nd pass. */
1377 while (opti < optind)
1378 argv[argi + opti++] = NULL;
1381 /* Specifying both -a and -g gets an error. */
1382 if (verbose_output && recoverable_output)
1383 die (EXIT_FAILURE, 0,
1384 _("the options for verbose and stty-readable output styles are\n"
1385 "mutually exclusive"));
1387 /* Specifying any other arguments with -a or -g gets an error. */
1388 if (!noargs && (verbose_output || recoverable_output))
1389 die (EXIT_FAILURE, 0,
1390 _("when specifying an output style, modes may not be set"));
1392 device_name = file_name ? file_name : _("standard input");
1394 if (!noargs && !verbose_output && !recoverable_output)
1396 static struct termios check_mode;
1397 apply_settings (/* checking= */ true, device_name, argv, argc,
1398 &check_mode, &require_set_attr);
1401 if (file_name)
1403 int fdflags;
1404 if (fd_reopen (STDIN_FILENO, device_name, O_RDONLY | O_NONBLOCK, 0) < 0)
1405 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1406 if ((fdflags = fcntl (STDIN_FILENO, F_GETFL)) == -1
1407 || fcntl (STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
1408 die (EXIT_FAILURE, errno, _("%s: couldn't reset non-blocking mode"),
1409 quotef (device_name));
1412 if (tcgetattr (STDIN_FILENO, &mode))
1413 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1415 if (verbose_output || recoverable_output || noargs)
1417 max_col = screen_columns ();
1418 current_col = 0;
1419 display_settings (output_type, &mode, device_name);
1420 return EXIT_SUCCESS;
1423 require_set_attr = false;
1424 apply_settings (/* checking= */ false, device_name, argv, argc,
1425 &mode, &require_set_attr);
1427 if (require_set_attr)
1429 struct termios new_mode;
1431 if (tcsetattr (STDIN_FILENO, tcsetattr_options, &mode))
1432 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1434 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1435 it performs *any* of the requested operations. This means it
1436 can report 'success' when it has actually failed to perform
1437 some proper subset of the requested operations. To detect
1438 this partial failure, get the current terminal attributes and
1439 compare them to the requested ones. */
1441 if (tcgetattr (STDIN_FILENO, &new_mode))
1442 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1444 if (! eq_mode (&mode, &new_mode))
1446 if (dev_debug)
1448 error (0, 0, _("indx: mode: actual mode"));
1449 for (unsigned int i = 0; i < sizeof (new_mode); i++)
1451 unsigned int newc = *(((unsigned char *) &new_mode) + i);
1452 unsigned int oldc = *(((unsigned char *) &mode) + i);
1453 error (0, 0, "0x%02x, 0x%02x: 0x%02x%s", i, oldc, newc,
1454 newc == oldc ? "" : " *");
1458 die (EXIT_FAILURE, 0,
1459 _("%s: unable to perform all requested operations"),
1460 quotef (device_name));
1464 return EXIT_SUCCESS;
1467 /* Return true if modes are equivalent. */
1469 static bool
1470 eq_mode (struct termios *mode1, struct termios *mode2)
1472 return mode1->c_iflag == mode2->c_iflag
1473 && mode1->c_oflag == mode2->c_oflag
1474 && mode1->c_cflag == mode2->c_cflag
1475 && mode1->c_lflag == mode2->c_lflag
1476 #ifdef HAVE_C_LINE
1477 && mode1->c_line == mode2->c_line
1478 #endif
1479 && memcmp (mode1->c_cc, mode2->c_cc, sizeof (mode1->c_cc)) == 0
1480 && cfgetispeed (mode1) == cfgetispeed (mode2)
1481 && cfgetospeed (mode1) == cfgetospeed (mode2);
1484 /* Return false if not applied because not reversible; otherwise
1485 return true. */
1487 static bool
1488 set_mode (struct mode_info const *info, bool reversed, struct termios *mode)
1490 tcflag_t *bitsp;
1492 if (reversed && (info->flags & REV) == 0)
1493 return false;
1495 bitsp = mode_type_flag (info->type, mode);
1497 if (bitsp == NULL)
1499 /* Combination mode. */
1500 if (STREQ (info->name, "evenp") || STREQ (info->name, "parity"))
1502 if (reversed)
1503 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1504 else
1505 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
1507 else if (STREQ (info->name, "oddp"))
1509 if (reversed)
1510 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1511 else
1512 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
1514 else if (STREQ (info->name, "nl"))
1516 if (reversed)
1518 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
1519 mode->c_oflag = (mode->c_oflag
1520 #ifdef ONLCR
1521 | ONLCR
1522 #endif
1524 #ifdef OCRNL
1525 & ~OCRNL
1526 #endif
1527 #ifdef ONLRET
1528 & ~ONLRET
1529 #endif
1532 else
1534 mode->c_iflag = mode->c_iflag & ~ICRNL;
1535 #ifdef ONLCR
1536 mode->c_oflag = mode->c_oflag & ~ONLCR;
1537 #endif
1540 else if (STREQ (info->name, "ek"))
1542 mode->c_cc[VERASE] = CERASE;
1543 mode->c_cc[VKILL] = CKILL;
1545 else if (STREQ (info->name, "sane"))
1546 sane_mode (mode);
1547 else if (STREQ (info->name, "cbreak"))
1549 if (reversed)
1550 mode->c_lflag |= ICANON;
1551 else
1552 mode->c_lflag &= ~ICANON;
1554 else if (STREQ (info->name, "pass8"))
1556 if (reversed)
1558 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1559 mode->c_iflag |= ISTRIP;
1561 else
1563 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1564 mode->c_iflag &= ~ISTRIP;
1567 else if (STREQ (info->name, "litout"))
1569 if (reversed)
1571 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1572 mode->c_iflag |= ISTRIP;
1573 mode->c_oflag |= OPOST;
1575 else
1577 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1578 mode->c_iflag &= ~ISTRIP;
1579 mode->c_oflag &= ~OPOST;
1582 else if (STREQ (info->name, "raw") || STREQ (info->name, "cooked"))
1584 if ((info->name[0] == 'r' && reversed)
1585 || (info->name[0] == 'c' && !reversed))
1587 /* Cooked mode. */
1588 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1589 mode->c_oflag |= OPOST;
1590 mode->c_lflag |= ISIG | ICANON;
1591 #if VMIN == VEOF
1592 mode->c_cc[VEOF] = CEOF;
1593 #endif
1594 #if VTIME == VEOL
1595 mode->c_cc[VEOL] = CEOL;
1596 #endif
1598 else
1600 /* Raw mode. */
1601 mode->c_iflag = 0;
1602 mode->c_oflag &= ~OPOST;
1603 mode->c_lflag &= ~(ISIG | ICANON
1604 #ifdef XCASE
1605 | XCASE
1606 #endif
1608 mode->c_cc[VMIN] = 1;
1609 mode->c_cc[VTIME] = 0;
1612 #ifdef IXANY
1613 else if (STREQ (info->name, "decctlq"))
1615 if (reversed)
1616 mode->c_iflag |= IXANY;
1617 else
1618 mode->c_iflag &= ~IXANY;
1620 #endif
1621 #ifdef TABDLY
1622 else if (STREQ (info->name, "tabs"))
1624 if (reversed)
1625 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1626 else
1627 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1629 #else
1630 # ifdef OXTABS
1631 else if (STREQ (info->name, "tabs"))
1633 if (reversed)
1634 mode->c_oflag = mode->c_oflag | OXTABS;
1635 else
1636 mode->c_oflag = mode->c_oflag & ~OXTABS;
1638 # endif
1639 #endif
1640 #if defined XCASE && defined IUCLC && defined OLCUC
1641 else if (STREQ (info->name, "lcase")
1642 || STREQ (info->name, "LCASE"))
1644 if (reversed)
1646 mode->c_lflag &= ~XCASE;
1647 mode->c_iflag &= ~IUCLC;
1648 mode->c_oflag &= ~OLCUC;
1650 else
1652 mode->c_lflag |= XCASE;
1653 mode->c_iflag |= IUCLC;
1654 mode->c_oflag |= OLCUC;
1657 #endif
1658 else if (STREQ (info->name, "crt"))
1659 mode->c_lflag |= ECHOE
1660 #ifdef ECHOCTL
1661 | ECHOCTL
1662 #endif
1663 #ifdef ECHOKE
1664 | ECHOKE
1665 #endif
1667 else if (STREQ (info->name, "dec"))
1669 mode->c_cc[VINTR] = 3; /* ^C */
1670 mode->c_cc[VERASE] = 127; /* DEL */
1671 mode->c_cc[VKILL] = 21; /* ^U */
1672 mode->c_lflag |= ECHOE
1673 #ifdef ECHOCTL
1674 | ECHOCTL
1675 #endif
1676 #ifdef ECHOKE
1677 | ECHOKE
1678 #endif
1680 #ifdef IXANY
1681 mode->c_iflag &= ~IXANY;
1682 #endif
1685 else if (reversed)
1686 *bitsp = *bitsp & ~info->mask & ~info->bits;
1687 else
1688 *bitsp = (*bitsp & ~info->mask) | info->bits;
1690 return true;
1693 static void
1694 set_control_char (struct control_info const *info, char const *arg,
1695 struct termios *mode)
1697 unsigned long int value;
1699 if (STREQ (info->name, "min") || STREQ (info->name, "time"))
1700 value = integer_arg (arg, TYPE_MAXIMUM (cc_t));
1701 else if (arg[0] == '\0' || arg[1] == '\0')
1702 value = to_uchar (arg[0]);
1703 else if (STREQ (arg, "^-") || STREQ (arg, "undef"))
1704 value = _POSIX_VDISABLE;
1705 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1707 if (arg[1] == '?')
1708 value = 127;
1709 else
1710 value = to_uchar (arg[1]) & ~0140; /* Non-letters get weird results. */
1712 else
1713 value = integer_arg (arg, TYPE_MAXIMUM (cc_t));
1714 mode->c_cc[info->offset] = value;
1717 static void
1718 set_speed (enum speed_setting type, char const *arg, struct termios *mode)
1720 /* Note cfset[io]speed(), do not check with the device,
1721 and only check whether the system logic supports the specified speed.
1722 Therefore we don't report the device name in any errors. */
1724 speed_t baud = string_to_baud (arg);
1725 assert (baud != (speed_t) -1);
1727 if (type == input_speed || type == both_speeds)
1729 last_ibaud = baud;
1730 if (cfsetispeed (mode, baud))
1731 die (EXIT_FAILURE, 0, "unsupported ispeed %s", quotef (arg));
1733 if (type == output_speed || type == both_speeds)
1735 last_obaud = baud;
1736 if (cfsetospeed (mode, baud))
1737 die (EXIT_FAILURE, 0, "unsupported ospeed %s", quotef (arg));
1741 #ifdef TIOCGWINSZ
1743 static int
1744 get_win_size (int fd, struct winsize *win)
1746 int err = ioctl (fd, TIOCGWINSZ, (char *) win);
1747 return err;
1750 static void
1751 set_window_size (int rows, int cols, char const *device_name)
1753 struct winsize win;
1755 if (get_win_size (STDIN_FILENO, &win))
1757 if (errno != EINVAL)
1758 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1759 memset (&win, 0, sizeof (win));
1762 if (rows >= 0)
1763 win.ws_row = rows;
1764 if (cols >= 0)
1765 win.ws_col = cols;
1767 # ifdef TIOCSSIZE
1768 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1769 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1770 This comment from sys/ttold.h describes Sun's twisted logic - a better
1771 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1772 At any rate, the problem is gone in Solaris 2.x.
1774 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1775 but they can be disambiguated by checking whether a "struct ttysize"
1776 structure's "ts_lines" field is greater than 64K or not. If so,
1777 it's almost certainly a "struct winsize" instead.
1779 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1780 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16)
1781 + ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1782 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1783 "stty cols 0 rows 0" would do the right thing. On a little-endian
1784 machine like the sun386i, the problem is the same, but for ws_col == 0.
1786 The workaround is to do the ioctl once with row and col = 1 to set the
1787 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1789 if (win.ws_row == 0 || win.ws_col == 0)
1791 struct ttysize ttysz;
1793 ttysz.ts_lines = win.ws_row;
1794 ttysz.ts_cols = win.ws_col;
1796 win.ws_row = 1;
1797 win.ws_col = 1;
1799 if (ioctl (STDIN_FILENO, TIOCSWINSZ, (char *) &win))
1800 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1802 if (ioctl (STDIN_FILENO, TIOCSSIZE, (char *) &ttysz))
1803 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1804 return;
1806 # endif
1808 if (ioctl (STDIN_FILENO, TIOCSWINSZ, (char *) &win))
1809 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1812 static void
1813 display_window_size (bool fancy, char const *device_name)
1815 struct winsize win;
1817 if (get_win_size (STDIN_FILENO, &win))
1819 if (errno != EINVAL)
1820 die (EXIT_FAILURE, errno, "%s", quotef (device_name));
1821 if (!fancy)
1822 die (EXIT_FAILURE, 0,
1823 _("%s: no size information for this device"),
1824 quotef (device_name));
1826 else
1828 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1829 win.ws_row, win.ws_col);
1830 if (!fancy)
1831 current_col = 0;
1834 #endif
1836 static int
1837 screen_columns (void)
1839 #ifdef TIOCGWINSZ
1840 struct winsize win;
1842 /* With Solaris 2.[123], this ioctl fails and errno is set to
1843 EINVAL for telnet (but not rlogin) sessions.
1844 On ISC 3.0, it fails for the console and the serial port
1845 (but it works for ptys).
1846 It can also fail on any system when stdout isn't a tty.
1847 In case of any failure, just use the default. */
1848 if (get_win_size (STDOUT_FILENO, &win) == 0 && 0 < win.ws_col)
1849 return win.ws_col;
1850 #endif
1852 /* Use $COLUMNS if it's in [1..INT_MAX]. */
1853 char *col_string = getenv ("COLUMNS");
1854 long int n_columns;
1855 if (!(col_string != NULL
1856 && xstrtol (col_string, NULL, 0, &n_columns, "") == LONGINT_OK
1857 && 0 < n_columns
1858 && n_columns <= INT_MAX))
1859 n_columns = 80;
1860 return n_columns;
1864 ATTRIBUTE_PURE
1865 static tcflag_t *
1866 mode_type_flag (enum mode_type type, struct termios *mode)
1868 switch (type)
1870 case control:
1871 return &mode->c_cflag;
1873 case input:
1874 return &mode->c_iflag;
1876 case output:
1877 return &mode->c_oflag;
1879 case local:
1880 return &mode->c_lflag;
1882 case combination:
1883 return NULL;
1885 default:
1886 abort ();
1890 static void
1891 display_settings (enum output_type output_type, struct termios *mode,
1892 char const *device_name)
1894 switch (output_type)
1896 case changed:
1897 display_changed (mode);
1898 break;
1900 case all:
1901 display_all (mode, device_name);
1902 break;
1904 case recoverable:
1905 display_recoverable (mode);
1906 break;
1910 static void
1911 display_changed (struct termios *mode)
1913 int i;
1914 bool empty_line;
1915 tcflag_t *bitsp;
1916 unsigned long mask;
1917 enum mode_type prev_type = control;
1919 display_speed (mode, true);
1920 #ifdef HAVE_C_LINE
1921 wrapf ("line = %d;", mode->c_line);
1922 #endif
1923 putchar ('\n');
1924 current_col = 0;
1926 empty_line = true;
1927 for (i = 0; !STREQ (control_info[i].name, "min"); ++i)
1929 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1930 continue;
1932 #ifdef VFLUSHO
1933 /* 'flush' is the deprecated equivalent of 'discard'. */
1934 if (STREQ (control_info[i].name, "flush"))
1935 continue;
1936 #endif
1937 /* If swtch is the same as susp, don't print both. */
1938 #if VSWTCH == VSUSP
1939 if (STREQ (control_info[i].name, "swtch"))
1940 continue;
1941 #endif
1942 /* If eof uses the same slot as min, only print whichever applies. */
1943 #if VEOF == VMIN
1944 if ((mode->c_lflag & ICANON) == 0
1945 && (STREQ (control_info[i].name, "eof")
1946 || STREQ (control_info[i].name, "eol")))
1947 continue;
1948 #endif
1950 empty_line = false;
1951 wrapf ("%s = %s;", control_info[i].name,
1952 visible (mode->c_cc[control_info[i].offset]));
1954 if ((mode->c_lflag & ICANON) == 0)
1956 wrapf ("min = %lu; time = %lu;\n",
1957 (unsigned long int) mode->c_cc[VMIN],
1958 (unsigned long int) mode->c_cc[VTIME]);
1960 else if (!empty_line)
1961 putchar ('\n');
1962 current_col = 0;
1964 empty_line = true;
1965 for (i = 0; mode_info[i].name != NULL; ++i)
1967 if (mode_info[i].flags & OMIT)
1968 continue;
1969 if (mode_info[i].type != prev_type)
1971 if (!empty_line)
1973 putchar ('\n');
1974 current_col = 0;
1975 empty_line = true;
1977 prev_type = mode_info[i].type;
1980 bitsp = mode_type_flag (mode_info[i].type, mode);
1981 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1983 /* bitsp would be NULL only for "combination" modes, yet those
1984 are filtered out above via the OMIT flag. Tell static analysis
1985 tools that it's ok to dereference bitsp here. */
1986 assert (bitsp);
1988 if ((*bitsp & mask) == mode_info[i].bits)
1990 if (mode_info[i].flags & SANE_UNSET)
1992 wrapf ("%s", mode_info[i].name);
1993 empty_line = false;
1996 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1998 wrapf ("-%s", mode_info[i].name);
1999 empty_line = false;
2002 if (!empty_line)
2003 putchar ('\n');
2004 current_col = 0;
2007 static void
2008 display_all (struct termios *mode, char const *device_name)
2010 int i;
2011 tcflag_t *bitsp;
2012 unsigned long mask;
2013 enum mode_type prev_type = control;
2015 display_speed (mode, true);
2016 #ifdef TIOCGWINSZ
2017 display_window_size (true, device_name);
2018 #endif
2019 #ifdef HAVE_C_LINE
2020 wrapf ("line = %d;", mode->c_line);
2021 #endif
2022 putchar ('\n');
2023 current_col = 0;
2025 for (i = 0; ! STREQ (control_info[i].name, "min"); ++i)
2027 #ifdef VFLUSHO
2028 /* 'flush' is the deprecated equivalent of 'discard'. */
2029 if (STREQ (control_info[i].name, "flush"))
2030 continue;
2031 #endif
2032 /* If swtch is the same as susp, don't print both. */
2033 #if VSWTCH == VSUSP
2034 if (STREQ (control_info[i].name, "swtch"))
2035 continue;
2036 #endif
2037 /* If eof uses the same slot as min, only print whichever applies. */
2038 #if VEOF == VMIN
2039 if ((mode->c_lflag & ICANON) == 0
2040 && (STREQ (control_info[i].name, "eof")
2041 || STREQ (control_info[i].name, "eol")))
2042 continue;
2043 #endif
2044 wrapf ("%s = %s;", control_info[i].name,
2045 visible (mode->c_cc[control_info[i].offset]));
2047 #if VEOF == VMIN
2048 if ((mode->c_lflag & ICANON) == 0)
2049 #endif
2050 wrapf ("min = %lu; time = %lu;",
2051 (unsigned long int) mode->c_cc[VMIN],
2052 (unsigned long int) mode->c_cc[VTIME]);
2053 if (current_col != 0)
2054 putchar ('\n');
2055 current_col = 0;
2057 for (i = 0; mode_info[i].name != NULL; ++i)
2059 if (mode_info[i].flags & OMIT)
2060 continue;
2061 if (mode_info[i].type != prev_type)
2063 putchar ('\n');
2064 current_col = 0;
2065 prev_type = mode_info[i].type;
2068 bitsp = mode_type_flag (mode_info[i].type, mode);
2069 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
2070 assert (bitsp); /* See the identical assertion and comment above. */
2071 if ((*bitsp & mask) == mode_info[i].bits)
2072 wrapf ("%s", mode_info[i].name);
2073 else if (mode_info[i].flags & REV)
2074 wrapf ("-%s", mode_info[i].name);
2076 putchar ('\n');
2077 current_col = 0;
2080 /* Verify requested asymmetric speeds are supported.
2081 Note we don't flag the case where only ispeed or
2082 ospeed is set, when that would set both. */
2084 static void
2085 check_speed (struct termios *mode)
2087 if (last_ibaud != -1 && last_obaud != -1)
2089 if (cfgetispeed (mode) != last_ibaud
2090 || cfgetospeed (mode) != last_obaud)
2091 die (EXIT_FAILURE, 0,
2092 _("asymmetric input (%lu), output (%lu) speeds not supported"),
2093 baud_to_value (last_ibaud), baud_to_value (last_obaud));
2097 static void
2098 display_speed (struct termios *mode, bool fancy)
2100 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
2101 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
2102 baud_to_value (cfgetospeed (mode)));
2103 else
2104 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
2105 baud_to_value (cfgetispeed (mode)),
2106 baud_to_value (cfgetospeed (mode)));
2107 if (!fancy)
2108 current_col = 0;
2111 static void
2112 display_recoverable (struct termios *mode)
2114 printf ("%lx:%lx:%lx:%lx",
2115 (unsigned long int) mode->c_iflag,
2116 (unsigned long int) mode->c_oflag,
2117 (unsigned long int) mode->c_cflag,
2118 (unsigned long int) mode->c_lflag);
2119 for (size_t i = 0; i < NCCS; ++i)
2120 printf (":%lx", (unsigned long int) mode->c_cc[i]);
2121 putchar ('\n');
2124 /* NOTE: identical to below, modulo use of tcflag_t */
2125 static int
2126 strtoul_tcflag_t (char const *s, int base, char **p, tcflag_t *result,
2127 char delim)
2129 unsigned long ul;
2130 errno = 0;
2131 ul = strtoul (s, p, base);
2132 if (errno || **p != delim || *p == s || (tcflag_t) ul != ul)
2133 return -1;
2134 *result = ul;
2135 return 0;
2138 /* NOTE: identical to above, modulo use of cc_t */
2139 static int
2140 strtoul_cc_t (char const *s, int base, char **p, cc_t *result, char delim)
2142 unsigned long ul;
2143 errno = 0;
2144 ul = strtoul (s, p, base);
2145 if (errno || **p != delim || *p == s || (cc_t) ul != ul)
2146 return -1;
2147 *result = ul;
2148 return 0;
2151 /* Parse the output of display_recoverable.
2152 Return false if any part of it is invalid. */
2153 static bool
2154 recover_mode (char const *arg, struct termios *mode)
2156 tcflag_t flag[4];
2157 char const *s = arg;
2158 size_t i;
2159 for (i = 0; i < 4; i++)
2161 char *p;
2162 if (strtoul_tcflag_t (s, 16, &p, flag + i, ':') != 0)
2163 return false;
2164 s = p + 1;
2166 mode->c_iflag = flag[0];
2167 mode->c_oflag = flag[1];
2168 mode->c_cflag = flag[2];
2169 mode->c_lflag = flag[3];
2171 for (i = 0; i < NCCS; ++i)
2173 char *p;
2174 char delim = i < NCCS - 1 ? ':' : '\0';
2175 if (strtoul_cc_t (s, 16, &p, mode->c_cc + i, delim) != 0)
2176 return false;
2177 s = p + 1;
2180 return true;
2183 struct speed_map
2185 char const *string; /* ASCII representation. */
2186 speed_t speed; /* Internal form. */
2187 unsigned long int value; /* Numeric value. */
2190 static struct speed_map const speeds[] =
2192 {"0", B0, 0},
2193 {"50", B50, 50},
2194 {"75", B75, 75},
2195 {"110", B110, 110},
2196 {"134", B134, 134},
2197 {"134.5", B134, 134},
2198 {"150", B150, 150},
2199 {"200", B200, 200},
2200 {"300", B300, 300},
2201 {"600", B600, 600},
2202 {"1200", B1200, 1200},
2203 {"1800", B1800, 1800},
2204 {"2400", B2400, 2400},
2205 {"4800", B4800, 4800},
2206 {"9600", B9600, 9600},
2207 {"19200", B19200, 19200},
2208 {"38400", B38400, 38400},
2209 {"exta", B19200, 19200},
2210 {"extb", B38400, 38400},
2211 #ifdef B57600
2212 {"57600", B57600, 57600},
2213 #endif
2214 #ifdef B115200
2215 {"115200", B115200, 115200},
2216 #endif
2217 #ifdef B230400
2218 {"230400", B230400, 230400},
2219 #endif
2220 #ifdef B460800
2221 {"460800", B460800, 460800},
2222 #endif
2223 #ifdef B500000
2224 {"500000", B500000, 500000},
2225 #endif
2226 #ifdef B576000
2227 {"576000", B576000, 576000},
2228 #endif
2229 #ifdef B921600
2230 {"921600", B921600, 921600},
2231 #endif
2232 #ifdef B1000000
2233 {"1000000", B1000000, 1000000},
2234 #endif
2235 #ifdef B1152000
2236 {"1152000", B1152000, 1152000},
2237 #endif
2238 #ifdef B1500000
2239 {"1500000", B1500000, 1500000},
2240 #endif
2241 #ifdef B2000000
2242 {"2000000", B2000000, 2000000},
2243 #endif
2244 #ifdef B2500000
2245 {"2500000", B2500000, 2500000},
2246 #endif
2247 #ifdef B3000000
2248 {"3000000", B3000000, 3000000},
2249 #endif
2250 #ifdef B3500000
2251 {"3500000", B3500000, 3500000},
2252 #endif
2253 #ifdef B4000000
2254 {"4000000", B4000000, 4000000},
2255 #endif
2256 {NULL, 0, 0}
2259 ATTRIBUTE_PURE
2260 static speed_t
2261 string_to_baud (char const *arg)
2263 for (int i = 0; speeds[i].string != NULL; ++i)
2264 if (STREQ (arg, speeds[i].string))
2265 return speeds[i].speed;
2266 return (speed_t) -1;
2269 ATTRIBUTE_PURE
2270 static unsigned long int
2271 baud_to_value (speed_t speed)
2273 for (int i = 0; speeds[i].string != NULL; ++i)
2274 if (speed == speeds[i].speed)
2275 return speeds[i].value;
2276 return 0;
2279 static void
2280 sane_mode (struct termios *mode)
2282 int i;
2283 tcflag_t *bitsp;
2285 for (i = 0; control_info[i].name; ++i)
2287 #if VMIN == VEOF
2288 if (STREQ (control_info[i].name, "min"))
2289 break;
2290 #endif
2291 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
2294 for (i = 0; mode_info[i].name != NULL; ++i)
2296 if (mode_info[i].flags & NO_SETATTR)
2297 continue;
2299 if (mode_info[i].flags & SANE_SET)
2301 bitsp = mode_type_flag (mode_info[i].type, mode);
2302 assert (bitsp); /* combination modes will not have SANE_SET. */
2303 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
2305 else if (mode_info[i].flags & SANE_UNSET)
2307 bitsp = mode_type_flag (mode_info[i].type, mode);
2308 assert (bitsp); /* combination modes will not have SANE_UNSET. */
2309 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
2314 /* Return a string that is the printable representation of character CH. */
2315 /* Adapted from 'cat' by Torbjorn Granlund. */
2317 static char const *
2318 visible (cc_t ch)
2320 static char buf[10];
2321 char *bpout = buf;
2323 if (ch == _POSIX_VDISABLE)
2324 return "<undef>";
2326 if (ch >= 32)
2328 if (ch < 127)
2329 *bpout++ = ch;
2330 else if (ch == 127)
2332 *bpout++ = '^';
2333 *bpout++ = '?';
2335 else
2337 *bpout++ = 'M';
2338 *bpout++ = '-';
2339 if (ch >= 128 + 32)
2341 if (ch < 128 + 127)
2342 *bpout++ = ch - 128;
2343 else
2345 *bpout++ = '^';
2346 *bpout++ = '?';
2349 else
2351 *bpout++ = '^';
2352 *bpout++ = ch - 128 + 64;
2356 else
2358 *bpout++ = '^';
2359 *bpout++ = ch + 64;
2361 *bpout = '\0';
2362 return (char const *) buf;
2365 /* Parse string S as an integer, using decimal radix by default,
2366 but allowing octal and hex numbers as in C. Reject values
2367 larger than MAXVAL. */
2369 static unsigned long int
2370 integer_arg (char const *s, unsigned long int maxval)
2372 return xnumtoumax (s, 0, 0, maxval, "bB", _("invalid integer argument"), 0);