(memcasecmp): Declare local I to be unsigned to avoid warning from gcc -Wall.
[coreutils.git] / src / stty.c
blob72a6f1afe02fb1d53f9bfcb5f8ca6762b3955316
1 /* stty -- change and print terminal line settings
2 Copyright (C) 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 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, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Usage: stty [-ag] [--all] [--save] [setting...]
20 Options:
21 -a, --all Write all current settings to stdout in human-readable form.
22 -g, --save Write all current settings to stdout in stty-readable form.
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 stdin.
28 David MacKenzie <djm@gnu.ai.mit.edu> */
30 #include <config.h>
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <termios.h>
34 #ifdef GWINSZ_IN_SYS_IOCTL
35 # include <sys/ioctl.h>
36 #endif
37 #ifdef WINSIZE_IN_PTEM
38 # include <sys/stream.h>
39 # include <sys/ptem.h>
40 #endif
41 #include <getopt.h>
42 #ifdef __STDC__
43 # include <stdarg.h>
44 # define VA_START(args, lastarg) va_start(args, lastarg)
45 #else
46 # include <varargs.h>
47 # define VA_START(args, lastarg) va_start(args)
48 #endif
50 #include "system.h"
51 #include "version.h"
52 #include "long-options.h"
53 #include "error.h"
54 #include "xstrtol.h"
56 #if defined(GWINSZ_BROKEN) /* Such as for SCO UNIX 3.2.2. */
57 # undef TIOCGWINSZ
58 #endif
60 #ifndef _POSIX_VDISABLE
61 # define _POSIX_VDISABLE ((unsigned char) 0)
62 #endif
64 #define Control(c) ((c) & 0x1f)
65 /* Canonical values for control characters. */
66 #ifndef CINTR
67 # define CINTR Control ('c')
68 #endif
69 #ifndef CQUIT
70 # define CQUIT 28
71 #endif
72 #ifndef CERASE
73 # define CERASE 127
74 #endif
75 #ifndef CKILL
76 # define CKILL Control ('u')
77 #endif
78 #ifndef CEOF
79 # define CEOF Control ('d')
80 #endif
81 #ifndef CEOL
82 # define CEOL _POSIX_VDISABLE
83 #endif
84 #ifndef CSTART
85 # define CSTART Control ('q')
86 #endif
87 #ifndef CSTOP
88 # define CSTOP Control ('s')
89 #endif
90 #ifndef CSUSP
91 # define CSUSP Control ('z')
92 #endif
93 #if defined(VEOL2) && !defined(CEOL2)
94 # define CEOL2 _POSIX_VDISABLE
95 #endif
96 #if defined(VSWTCH) && !defined(CSWTCH)
97 # define CSWTCH _POSIX_VDISABLE
98 #endif
100 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
101 So the default is to disable `swtch.' */
102 #if defined (__sparc__) && defined (__svr4__)
103 # undef CSWTCH
104 # define CSWTCH _POSIX_VDISABLE
105 #endif
107 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
108 # define VWERASE VWERSE
109 #endif
110 #if defined(VDSUSP) && !defined (CDSUSP)
111 # define CDSUSP Control ('y')
112 #endif
113 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
114 # define VREPRINT VRPRNT
115 #endif
116 #if defined(VREPRINT) && !defined(CRPRNT)
117 # define CRPRNT Control ('r')
118 #endif
119 #if defined(VWERASE) && !defined(CWERASE)
120 # define CWERASE Control ('w')
121 #endif
122 #if defined(VLNEXT) && !defined(CLNEXT)
123 # define CLNEXT Control ('v')
124 #endif
125 #if defined(VDISCARD) && !defined(VFLUSHO)
126 # define VFLUSHO VDISCARD
127 #endif
128 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
129 # define VFLUSHO VFLUSH
130 #endif
131 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
132 # define ECHOCTL CTLECH
133 #endif
134 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
135 # define ECHOCTL TCTLECH
136 #endif
137 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
138 # define ECHOKE CRTKIL
139 #endif
140 #if defined(VFLUSHO) && !defined(CFLUSHO)
141 # define CFLUSHO Control ('o')
142 #endif
143 #if defined(VSTATUS) && !defined(CSTATUS)
144 # define CSTATUS Control ('t')
145 #endif
147 /* Which speeds to set. */
148 enum speed_setting
150 input_speed, output_speed, both_speeds
153 /* What to output and how. */
154 enum output_type
156 changed, all, recoverable /* Default, -a, -g. */
159 /* Which member(s) of `struct termios' a mode uses. */
160 enum mode_type
162 control, input, output, local, combination
165 /* Flags for `struct mode_info'. */
166 #define SANE_SET 1 /* Set in `sane' mode. */
167 #define SANE_UNSET 2 /* Unset in `sane' mode. */
168 #define REV 4 /* Can be turned off by prepending `-'. */
169 #define OMIT 8 /* Don't display value. */
171 /* Each mode. */
172 struct mode_info
174 const char *name; /* Name given on command line. */
175 enum mode_type type; /* Which structure element to change. */
176 char flags; /* Setting and display options. */
177 unsigned long bits; /* Bits to set for this mode. */
178 unsigned long mask; /* Other bits to turn off for this mode. */
181 static struct mode_info mode_info[] =
183 {"parenb", control, REV, PARENB, 0},
184 {"parodd", control, REV, PARODD, 0},
185 {"cs5", control, 0, CS5, CSIZE},
186 {"cs6", control, 0, CS6, CSIZE},
187 {"cs7", control, 0, CS7, CSIZE},
188 {"cs8", control, 0, CS8, CSIZE},
189 {"hupcl", control, REV, HUPCL, 0},
190 {"hup", control, REV | OMIT, HUPCL, 0},
191 {"cstopb", control, REV, CSTOPB, 0},
192 {"cread", control, SANE_SET | REV, CREAD, 0},
193 {"clocal", control, REV, CLOCAL, 0},
194 #ifdef CRTSCTS
195 {"crtscts", control, REV, CRTSCTS, 0},
196 #endif
198 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
199 {"brkint", input, SANE_SET | REV, BRKINT, 0},
200 {"ignpar", input, REV, IGNPAR, 0},
201 {"parmrk", input, REV, PARMRK, 0},
202 {"inpck", input, REV, INPCK, 0},
203 {"istrip", input, REV, ISTRIP, 0},
204 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
205 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
206 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
207 {"ixon", input, REV, IXON, 0},
208 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
209 {"tandem", input, REV | OMIT, IXOFF, 0},
210 #ifdef IUCLC
211 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
212 #endif
213 #ifdef IXANY
214 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
215 #endif
216 #ifdef IMAXBEL
217 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
218 #endif
220 {"opost", output, SANE_SET | REV, OPOST, 0},
221 #ifdef OLCUC
222 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
223 #endif
224 #ifdef OCRNL
225 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
226 #endif
227 #ifdef ONLCR
228 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
229 #endif
230 #ifdef ONOCR
231 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
232 #endif
233 #ifdef ONLRET
234 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
235 #endif
236 #ifdef OFILL
237 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
238 #endif
239 #ifdef OFDEL
240 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
241 #endif
242 #ifdef NLDLY
243 {"nl1", output, SANE_UNSET, NL1, NLDLY},
244 {"nl0", output, SANE_SET, NL0, NLDLY},
245 #endif
246 #ifdef CRDLY
247 {"cr3", output, SANE_UNSET, CR3, CRDLY},
248 {"cr2", output, SANE_UNSET, CR2, CRDLY},
249 {"cr1", output, SANE_UNSET, CR1, CRDLY},
250 {"cr0", output, SANE_SET, CR0, CRDLY},
251 #endif
252 #ifdef TABDLY
253 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
254 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
255 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
256 {"tab0", output, SANE_SET, TAB0, TABDLY},
257 #else
258 # ifdef OXTABS
259 {"tab3", output, SANE_UNSET, OXTABS, 0},
260 # endif
261 #endif
262 #ifdef BSDLY
263 {"bs1", output, SANE_UNSET, BS1, BSDLY},
264 {"bs0", output, SANE_SET, BS0, BSDLY},
265 #endif
266 #ifdef VTDLY
267 {"vt1", output, SANE_UNSET, VT1, VTDLY},
268 {"vt0", output, SANE_SET, VT0, VTDLY},
269 #endif
270 #ifdef FFDLY
271 {"ff1", output, SANE_UNSET, FF1, FFDLY},
272 {"ff0", output, SANE_SET, FF0, FFDLY},
273 #endif
275 {"isig", local, SANE_SET | REV, ISIG, 0},
276 {"icanon", local, SANE_SET | REV, ICANON, 0},
277 #ifdef IEXTEN
278 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
279 #endif
280 {"echo", local, SANE_SET | REV, ECHO, 0},
281 {"echoe", local, SANE_SET | REV, ECHOE, 0},
282 {"crterase", local, REV | OMIT, ECHOE, 0},
283 {"echok", local, SANE_SET | REV, ECHOK, 0},
284 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
285 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
286 #ifdef XCASE
287 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
288 #endif
289 #ifdef TOSTOP
290 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
291 #endif
292 #ifdef ECHOPRT
293 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
294 {"prterase", local, REV | OMIT, ECHOPRT, 0},
295 #endif
296 #ifdef ECHOCTL
297 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
298 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
299 #endif
300 #ifdef ECHOKE
301 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
302 {"crtkill", local, REV | OMIT, ECHOKE, 0},
303 #endif
305 {"evenp", combination, REV | OMIT, 0, 0},
306 {"parity", combination, REV | OMIT, 0, 0},
307 {"oddp", combination, REV | OMIT, 0, 0},
308 {"nl", combination, REV | OMIT, 0, 0},
309 {"ek", combination, OMIT, 0, 0},
310 {"sane", combination, OMIT, 0, 0},
311 {"cooked", combination, REV | OMIT, 0, 0},
312 {"raw", combination, REV | OMIT, 0, 0},
313 {"pass8", combination, REV | OMIT, 0, 0},
314 {"litout", combination, REV | OMIT, 0, 0},
315 {"cbreak", combination, REV | OMIT, 0, 0},
316 #ifdef IXANY
317 {"decctlq", combination, REV | OMIT, 0, 0},
318 #endif
319 #if defined (TABDLY) || defined (OXTABS)
320 {"tabs", combination, REV | OMIT, 0, 0},
321 #endif
322 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
323 {"lcase", combination, REV | OMIT, 0, 0},
324 {"LCASE", combination, REV | OMIT, 0, 0},
325 #endif
326 {"crt", combination, OMIT, 0, 0},
327 {"dec", combination, OMIT, 0, 0},
329 {NULL, control, 0, 0, 0}
332 /* Control character settings. */
333 struct control_info
335 const char *name; /* Name given on command line. */
336 unsigned char saneval; /* Value to set for `stty sane'. */
337 int offset; /* Offset in c_cc. */
340 /* Control characters. */
342 static struct control_info control_info[] =
344 {"intr", CINTR, VINTR},
345 {"quit", CQUIT, VQUIT},
346 {"erase", CERASE, VERASE},
347 {"kill", CKILL, VKILL},
348 {"eof", CEOF, VEOF},
349 {"eol", CEOL, VEOL},
350 #ifdef VEOL2
351 {"eol2", CEOL2, VEOL2},
352 #endif
353 #ifdef VSWTCH
354 {"swtch", CSWTCH, VSWTCH},
355 #endif
356 {"start", CSTART, VSTART},
357 {"stop", CSTOP, VSTOP},
358 {"susp", CSUSP, VSUSP},
359 #ifdef VDSUSP
360 {"dsusp", CDSUSP, VDSUSP},
361 #endif
362 #ifdef VREPRINT
363 {"rprnt", CRPRNT, VREPRINT},
364 #endif
365 #ifdef VWERASE
366 {"werase", CWERASE, VWERASE},
367 #endif
368 #ifdef VLNEXT
369 {"lnext", CLNEXT, VLNEXT},
370 #endif
371 #ifdef VFLUSHO
372 {"flush", CFLUSHO, VFLUSHO},
373 #endif
374 #ifdef VSTATUS
375 {"status", CSTATUS, VSTATUS},
376 #endif
378 /* These must be last because of the display routines. */
379 {"min", 1, VMIN},
380 {"time", 0, VTIME},
381 {NULL, 0, 0}
384 static const char *visible __P ((unsigned int ch));
385 static unsigned long baud_to_value __P ((speed_t speed));
386 static int recover_mode __P ((char *arg, struct termios *mode));
387 static int screen_columns __P ((void));
388 static int set_mode __P ((struct mode_info *info, int reversed,
389 struct termios *mode));
390 static long integer_arg __P ((const char *s));
391 static speed_t string_to_baud __P ((const char *arg));
392 static tcflag_t *mode_type_flag __P ((enum mode_type type,
393 struct termios *mode));
394 static void display_all __P ((struct termios *mode));
395 static void display_changed __P ((struct termios *mode));
396 static void display_recoverable __P ((struct termios *mode));
397 static void display_settings __P ((enum output_type output_type,
398 struct termios *mode));
399 static void display_speed __P ((struct termios *mode, int fancy));
400 static void display_window_size __P ((int fancy));
401 static void sane_mode __P ((struct termios *mode));
402 static void set_control_char __P ((struct control_info *info, const char *arg,
403 struct termios *mode));
404 static void set_speed __P ((enum speed_setting type, const char *arg,
405 struct termios *mode));
406 static void set_window_size __P ((int rows, int cols));
408 /* The width of the screen, for output wrapping. */
409 static int max_col;
411 /* Current position, to know when to wrap. */
412 static int current_col;
414 static struct option longopts[] =
416 {"all", no_argument, NULL, 'a'},
417 {"save", no_argument, NULL, 'g'},
418 {NULL, 0, NULL, 0}
421 /* The name this program was run with. */
422 char *program_name;
424 /* Print format string MESSAGE and optional args.
425 Wrap to next line first if it won't fit.
426 Print a space first unless MESSAGE will start a new line. */
428 /* VARARGS */
429 static void
430 #ifdef __STDC__
431 wrapf (const char *message,...)
432 #else
433 wrapf (message, va_alist)
434 const char *message;
435 va_dcl
436 #endif
438 va_list args;
439 char buf[1024]; /* Plenty long for our needs. */
440 int buflen;
442 VA_START (args, message);
443 vsprintf (buf, message, args);
444 va_end (args);
445 buflen = strlen (buf);
446 if (current_col + (current_col > 0) + buflen >= max_col)
448 putchar ('\n');
449 current_col = 0;
451 if (current_col > 0)
453 putchar (' ');
454 current_col++;
456 fputs (buf, stdout);
457 current_col += buflen;
460 static void
461 usage (int status)
463 if (status != 0)
464 fprintf (stderr, _("Try `%s --help' for more information.\n"),
465 program_name);
466 else
468 printf (_("\
469 Usage: %s [SETTING]...\n\
470 or: %s OPTION\n\
472 program_name, program_name);
473 printf (_("\
474 Print or change terminal characteristics.\n\
476 -a, --all print all current settings in human-readable form\n\
477 -g, --save print all current settings in a stty-readable form\n\
478 --help display this help and exit\n\
479 --version output version information and exit\n\
481 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
482 settings. The underlying system defines which settings are available.\n\
483 "));
484 printf (_("\
486 Special characters:\n\
487 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
488 eof CHAR CHAR will send an end of file (terminate the input)\n\
489 eol CHAR CHAR will end the line\n\
490 * eol2 CHAR alternate CHAR for ending the line\n\
491 erase CHAR CHAR will erase the last character typed\n\
492 intr CHAR CHAR will send an interrupt signal\n\
493 kill CHAR CHAR will erase the current line\n\
494 * lnext CHAR CHAR will enter the next character quoted\n\
495 quit CHAR CHAR will send a quit signal\n\
496 * rprnt CHAR CHAR will redraw the current line\n\
497 start CHAR CHAR will restart the output after stopping it\n\
498 stop CHAR CHAR will stop the output\n\
499 susp CHAR CHAR will send a terminal stop signal\n\
500 * swtch CHAR CHAR will switch to a different shell layer\n\
501 * werase CHAR CHAR will erase the last word typed\n\
502 "));
503 printf (_("\
505 Special settings:\n\
506 N set the input and output speeds to N bauds\n\
507 * cols N tell the kernel that the terminal has N columns\n\
508 * columns N same as cols N\n\
509 ispeed N set the input speed to N\n\
510 * line N use line discipline N\n\
511 min N with -icanon, set N characters minimum for a completed read\n\
512 ospeed N set the output speed to N\n\
513 * rows N tell the kernel that the terminal has N rows\n\
514 * size print the number of rows and columns according to the kernel\n\
515 speed print the terminal speed\n\
516 time N with -icanon, set read timeout of N tenths of a second\n\
517 "));
518 printf (_("\
520 Control settings:\n\
521 [-]clocal disable modem control signals\n\
522 [-]cread allow input to be received\n\
523 * [-]crtscts enable RTS/CTS handshaking\n\
524 csN set character size to N bits, N in [5..8]\n\
525 [-]cstopb use two stop bits per character (one with `-')\n\
526 [-]hup send a hangup signal when the last process closes the tty\n\
527 [-]hupcl same as [-]hup\n\
528 [-]parenb generate parity bit in output and expect parity bit in input\n\
529 [-]parodd set odd parity (even with `-')\n\
530 "));
531 printf (_("\
533 Input settings:\n\
534 [-]brkint breaks cause an interrupt signal\n\
535 [-]icrnl translate carriage return to newline\n\
536 [-]ignbrk ignore break characters\n\
537 [-]igncr ignore carriage return\n\
538 [-]ignpar ignore characters with parity errors\n\
539 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
540 [-]inlcr translate newline to carriage return\n\
541 [-]inpck enable input parity checking\n\
542 [-]istrip clear high (8th) bit of input characters\n\
543 * [-]iuclc translate uppercase characters to lowercase\n\
544 * [-]ixany let any character restart output, not only start character\n\
545 [-]ixoff enable sending of start/stop characters\n\
546 [-]ixon enable XON/XOFF flow control\n\
547 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
548 [-]tandem same as [-]ixoff\n\
549 "));
550 printf (_("\
552 Output settings:\n\
553 * bsN backspace delay style, N in [0..1]\n\
554 * crN carriage return delay style, N in [0..3]\n\
555 * ffN form feed delay style, N in [0..1]\n\
556 * nlN newline delay style, N in [0..1]\n\
557 * [-]ocrnl translate carriage return to newline\n\
558 * [-]ofdel use delete characters for fill instead of null characters\n\
559 * [-]ofill use fill (padding) characters instead of timing for delays\n\
560 * [-]olcuc translate lowercase characters to uppercase\n\
561 * [-]onlcr translate newline to carriage return-newline\n\
562 * [-]onlret newline performs a carriage return\n\
563 * [-]onocr do not print carriage returns in the first column\n\
564 [-]opost postprocess output\n\
565 * tabN horizontal tab delay style, N in [0..3]\n\
566 * tabs same as tab0\n\
567 * -tabs same as tab3\n\
568 * vtN vertical tab delay style, N in [0..1]\n\
569 "));
570 printf (_("\
572 Local settings:\n\
573 [-]crterase echo erase characters as backspace-space-backspace\n\
574 * crtkill kill all line by obeying the echoprt and echoe settings\n\
575 * -crtkill kill all line by obeying the echoctl and echok settings\n\
576 * [-]ctlecho echo control characters in hat notation (`^c')\n\
577 [-]echo echo input characters\n\
578 * [-]echoctl same as [-]ctlecho\n\
579 [-]echoe same as [-]crterase\n\
580 [-]echok echo a newline after a kill character\n\
581 * [-]echoke same as [-]crtkill\n\
582 [-]echonl echo newline even if not echoing other characters\n\
583 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
584 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
585 [-]iexten enable non-POSIX special characters\n\
586 [-]isig enable interrupt, quit, and suspend special characters\n\
587 [-]noflsh disable flushing after interrupt and quit special characters\n\
588 * [-]prterase same as [-]echoprt\n\
589 * [-]tostop stop background jobs that try to write to the terminal\n\
590 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
591 "));
592 printf (_("\
594 Combination settings:\n\
595 * [-]LCASE same as [-]lcase\n\
596 cbreak same as -icanon\n\
597 -cbreak same as icanon\n\
598 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
599 icanon, eof and eol characters to their default values\n\
600 -cooked same as raw\n\
601 crt same as echoe echoctl echoke\n\
602 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
603 kill ^u\n\
604 * [-]decctlq same as [-]ixany\n\
605 ek erase and kill characters to their default values\n\
606 evenp same as parenb -parodd cs7\n\
607 -evenp same as -parenb cs8\n\
608 * [-]lcase same as xcase iuclc olcuc\n\
609 litout same as -parenb -istrip -opost cs8\n\
610 -litout same as parenb istrip opost cs7\n\
611 nl same as -icrnl -onlcr\n\
612 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
613 oddp same as parenb parodd cs7\n\
614 -oddp same as -parenb cs8\n\
615 [-]parity same as [-]evenp\n\
616 pass8 same as -parenb -istrip cs8\n\
617 -pass8 same as parenb istrip cs7\n\
618 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
619 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
620 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
621 -raw same as cooked\n\
622 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
623 -ixoff -iucl -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
624 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
625 isig icanon iexten echo echoe echok -echonl -noflsh\n\
626 -xcase -tostop -echoprt echoctl echoke, all special\n\
627 characters to their default values.\n\
628 "));
629 printf (_("\
631 Handle the tty line connected to standard input. Without arguments,\n\
632 prints baud rate, line discipline, and deviations from stty sane. In\n\
633 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
634 127; special values ^- or undef used to disable special characters.\n\
635 "));
637 exit (status);
640 void
641 main (int argc, char **argv)
643 struct termios mode;
644 enum output_type output_type;
645 int optc;
646 int require_set_attr;
647 int speed_was_set;
648 int verbose_output;
649 int recoverable_output;
650 int k;
652 program_name = argv[0];
654 parse_long_options (argc, argv, "stty", version_string, usage);
656 output_type = changed;
657 verbose_output = 0;
658 recoverable_output = 0;
660 /* Recognize the long options only. */
661 opterr = 0;
662 while ((optc = getopt_long_only (argc, argv, "ag", longopts, (int *) 0))
663 != EOF)
665 switch (optc)
667 case 'a':
668 verbose_output = 1;
669 output_type = all;
670 break;
672 case 'g':
673 recoverable_output = 1;
674 output_type = recoverable;
675 break;
677 default:
678 break;
682 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
683 They need not precede non-options. We cannot use GNU getopt because
684 it would treat -tabs and -ixany as uses of the -a option. */
685 for (k = optind; k < argc; k++)
687 if (argv[k][0] == '-')
689 if (argv[k][1] == 'a'
690 && argv[k][2] == '\0')
692 ++optind;
693 verbose_output = 1;
695 else if (argv[k][1] == 'g'
696 && argv[k][2] == '\0')
698 ++optind;
699 recoverable_output = 1;
701 else if ((argv[k][1] == 'g'
702 && argv[k][2] == 'a'
703 && argv[k][3] == '\0')
704 || (argv[k][1] == 'a'
705 && argv[k][2] == 'g'
706 && argv[k][3] == '\0'))
708 ++optind;
709 verbose_output = 1;
710 recoverable_output = 1;
715 /* Specifying both -a and -g gets an error. */
716 if (verbose_output && recoverable_output)
717 error (2, 0,
718 _("the options for verbose and stty-readable output styles are\n\
719 \tmutually exclusive"));
721 /* Specifying any other arguments with -a or -g gets an error. */
722 if (argc - optind > 0 && (verbose_output || recoverable_output))
723 error (2, 0, _("when specifying an output style, modes may not be set"));
725 /* Initialize to all zeroes so there is no risk memcmp will report a
726 spurious difference in an uninitialized portion of the structure. */
727 memset (&mode, 0, sizeof (mode));
728 if (tcgetattr (0, &mode))
729 error (1, errno, _("standard input"));
731 if (verbose_output || recoverable_output || argc == 1)
733 max_col = screen_columns ();
734 current_col = 0;
735 display_settings (output_type, &mode);
736 exit (0);
739 speed_was_set = 0;
740 require_set_attr = 0;
741 k = 1;
742 while (k < argc)
744 int match_found = 0;
745 int reversed = 0;
746 int i;
748 if (argv[k][0] == '-')
750 ++argv[k];
751 reversed = 1;
753 for (i = 0; mode_info[i].name != NULL; ++i)
755 if (!strcmp (argv[k], mode_info[i].name))
757 match_found = set_mode (&mode_info[i], reversed, &mode);
758 require_set_attr = 1;
759 break;
762 if (match_found == 0 && reversed)
764 error (0, 0, _("invalid argument `%s'"), --argv[k]);
765 usage (1);
767 if (match_found == 0)
769 for (i = 0; control_info[i].name != NULL; ++i)
771 if (!strcmp (argv[k], control_info[i].name))
773 if (k == argc - 1)
775 error (0, 0, _("missing argument to `%s'"), argv[k]);
776 usage (1);
778 match_found = 1;
779 ++k;
780 set_control_char (&control_info[i], argv[k], &mode);
781 require_set_attr = 1;
782 break;
786 if (match_found == 0)
788 if (!strcmp (argv[k], "ispeed"))
790 if (k == argc - 1)
792 error (0, 0, _("missing argument to `%s'"), argv[k]);
793 usage (1);
795 ++k;
796 set_speed (input_speed, argv[k], &mode);
797 speed_was_set = 1;
798 require_set_attr = 1;
800 else if (!strcmp (argv[k], "ospeed"))
802 if (k == argc - 1)
804 error (0, 0, _("missing argument to `%s'"), argv[k]);
805 usage (1);
807 ++k;
808 set_speed (output_speed, argv[k], &mode);
809 speed_was_set = 1;
810 require_set_attr = 1;
812 #ifdef TIOCGWINSZ
813 else if (!strcmp (argv[k], "rows"))
815 if (k == argc - 1)
817 error (0, 0, _("missing argument to `%s'"), argv[k]);
818 usage (1);
820 ++k;
821 set_window_size ((int) integer_arg (argv[k]), -1);
823 else if (!strcmp (argv[k], "cols")
824 || !strcmp (argv[k], "columns"))
826 if (k == argc - 1)
828 error (0, 0, _("missing argument to `%s'"), argv[k]);
829 usage (1);
831 ++k;
832 set_window_size (-1, (int) integer_arg (argv[k]));
834 else if (!strcmp (argv[k], "size"))
836 max_col = screen_columns ();
837 current_col = 0;
838 display_window_size (0);
840 #endif
841 #ifdef HAVE_C_LINE
842 else if (!strcmp (argv[k], "line"))
844 if (k == argc - 1)
846 error (0, 0, _("missing argument to `%s'"), argv[k]);
847 usage (1);
849 ++k;
850 mode.c_line = integer_arg (argv[k]);
851 require_set_attr = 1;
853 #endif
854 else if (!strcmp (argv[k], "speed"))
856 max_col = screen_columns ();
857 display_speed (&mode, 0);
859 else if (string_to_baud (argv[k]) != (speed_t) -1)
861 set_speed (both_speeds, argv[k], &mode);
862 speed_was_set = 1;
863 require_set_attr = 1;
865 else
867 if (recover_mode (argv[k], &mode) == 0)
869 error (0, 0, _("invalid argument `%s'"), argv[k]);
870 usage (1);
872 require_set_attr = 1;
875 k++;
878 if (require_set_attr)
880 struct termios new_mode;
882 if (tcsetattr (0, TCSADRAIN, &mode))
883 error (1, errno, _("standard input"));
885 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
886 it performs *any* of the requested operations. This means it
887 can report `success' when it has actually failed to perform
888 some proper subset of the requested operations. To detect
889 this partial failure, get the current terminal attributes and
890 compare them to the requested ones. */
892 /* Initialize to all zeroes so there is no risk memcmp will report a
893 spurious difference in an uninitialized portion of the structure. */
894 memset (&new_mode, 0, sizeof (new_mode));
895 if (tcgetattr (0, &new_mode))
896 error (1, errno, _("standard input"));
898 /* Normally, one shouldn't use memcmp to compare structures that
899 may have `holes' containing uninitialized data, but we have been
900 careful to initialize the storage of these two variables to all
901 zeroes. One might think it more efficient simply to compare the
902 modified fields, but that would require enumerating those fields --
903 and not all systems have the same fields in this structure. */
905 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
907 #ifdef CIBAUD
908 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
909 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
910 sometimes (m1 != m2). The only difference is in the four bits
911 of the c_cflag field corresponding to the baud rate. To save
912 Sun users a little confusion, don't report an error if this
913 happens. But suppress the error only if we haven't tried to
914 set the baud rate explicitly -- otherwise we'd never give an
915 error for a true failure to set the baud rate. */
917 new_mode.c_cflag &= (~CIBAUD);
918 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
919 #endif
921 int i;
922 error (1, 0,
923 _("standard input: unable to perform all requested operations"));
924 printf (_("new_mode: mode\n"));
925 for (i=0; i<sizeof(new_mode); i++)
926 printf ("0x%02x: 0x%02x\n",
927 *(((unsigned char *) &new_mode) + i),
928 *(((unsigned char *) &mode) + i));
933 exit (0);
936 /* Return 0 if not applied because not reversible; otherwise return 1. */
938 static int
939 set_mode (struct mode_info *info, int reversed, struct termios *mode)
941 tcflag_t *bitsp;
943 if (reversed && (info->flags & REV) == 0)
944 return 0;
946 bitsp = mode_type_flag (info->type, mode);
948 if (bitsp == NULL)
950 /* Combination mode. */
951 if (!strcmp (info->name, "evenp") || !strcmp (info->name, "parity"))
953 if (reversed)
954 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
955 else
956 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
958 else if (!strcmp (info->name, "oddp"))
960 if (reversed)
961 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
962 else
963 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
965 else if (!strcmp (info->name, "nl"))
967 if (reversed)
969 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
970 mode->c_oflag = (mode->c_oflag
971 #ifdef ONLCR
972 | ONLCR
973 #endif
975 #ifdef OCRNL
976 & ~OCRNL
977 #endif
978 #ifdef ONLRET
979 & ~ONLRET
980 #endif
983 else
985 mode->c_iflag = mode->c_iflag & ~ICRNL;
986 #ifdef ONLCR
987 mode->c_oflag = mode->c_oflag & ~ONLCR;
988 #endif
991 else if (!strcmp (info->name, "ek"))
993 mode->c_cc[VERASE] = CERASE;
994 mode->c_cc[VKILL] = CKILL;
996 else if (!strcmp (info->name, "sane"))
997 sane_mode (mode);
998 else if (!strcmp (info->name, "cbreak"))
1000 if (reversed)
1001 mode->c_lflag |= ICANON;
1002 else
1003 mode->c_lflag &= ~ICANON;
1005 else if (!strcmp (info->name, "pass8"))
1007 if (reversed)
1009 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1010 mode->c_iflag |= ISTRIP;
1012 else
1014 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1015 mode->c_iflag &= ~ISTRIP;
1018 else if (!strcmp (info->name, "litout"))
1020 if (reversed)
1022 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1023 mode->c_iflag |= ISTRIP;
1024 mode->c_oflag |= OPOST;
1026 else
1028 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1029 mode->c_iflag &= ~ISTRIP;
1030 mode->c_oflag &= ~OPOST;
1033 else if (!strcmp (info->name, "raw") || !strcmp (info->name, "cooked"))
1035 if ((info->name[0] == 'r' && reversed)
1036 || (info->name[0] == 'c' && !reversed))
1038 /* Cooked mode. */
1039 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1040 mode->c_oflag |= OPOST;
1041 mode->c_lflag |= ISIG | ICANON;
1042 #if VMIN == VEOF
1043 mode->c_cc[VEOF] = CEOF;
1044 #endif
1045 #if VTIME == VEOL
1046 mode->c_cc[VEOL] = CEOL;
1047 #endif
1049 else
1051 /* Raw mode. */
1052 mode->c_iflag = 0;
1053 mode->c_oflag &= ~OPOST;
1054 mode->c_lflag &= ~(ISIG | ICANON
1055 #ifdef XCASE
1056 | XCASE
1057 #endif
1059 mode->c_cc[VMIN] = 1;
1060 mode->c_cc[VTIME] = 0;
1063 #ifdef IXANY
1064 else if (!strcmp (info->name, "decctlq"))
1066 if (reversed)
1067 mode->c_iflag |= IXANY;
1068 else
1069 mode->c_iflag &= ~IXANY;
1071 #endif
1072 #ifdef TABDLY
1073 else if (!strcmp (info->name, "tabs"))
1075 if (reversed)
1076 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1077 else
1078 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1080 #else
1081 # ifdef OXTABS
1082 else if (!strcmp (info->name, "tabs"))
1084 if (reversed)
1085 mode->c_oflag = mode->c_oflag | OXTABS;
1086 else
1087 mode->c_oflag = mode->c_oflag & ~OXTABS;
1089 # endif
1090 #endif
1091 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1092 else if (!strcmp (info->name, "lcase")
1093 || !strcmp (info->name, "LCASE"))
1095 if (reversed)
1097 mode->c_lflag &= ~XCASE;
1098 mode->c_iflag &= ~IUCLC;
1099 mode->c_oflag &= ~OLCUC;
1101 else
1103 mode->c_lflag |= XCASE;
1104 mode->c_iflag |= IUCLC;
1105 mode->c_oflag |= OLCUC;
1108 #endif
1109 else if (!strcmp (info->name, "crt"))
1110 mode->c_lflag |= ECHOE
1111 #ifdef ECHOCTL
1112 | ECHOCTL
1113 #endif
1114 #ifdef ECHOKE
1115 | ECHOKE
1116 #endif
1118 else if (!strcmp (info->name, "dec"))
1120 mode->c_cc[VINTR] = 3; /* ^C */
1121 mode->c_cc[VERASE] = 127; /* DEL */
1122 mode->c_cc[VKILL] = 21; /* ^U */
1123 mode->c_lflag |= ECHOE
1124 #ifdef ECHOCTL
1125 | ECHOCTL
1126 #endif
1127 #ifdef ECHOKE
1128 | ECHOKE
1129 #endif
1131 #ifdef IXANY
1132 mode->c_iflag &= ~IXANY;
1133 #endif
1136 else if (reversed)
1137 *bitsp = *bitsp & ~info->mask & ~info->bits;
1138 else
1139 *bitsp = (*bitsp & ~info->mask) | info->bits;
1141 return 1;
1144 static void
1145 set_control_char (struct control_info *info, const char *arg,
1146 struct termios *mode)
1148 unsigned char value;
1150 if (!strcmp (info->name, "min") || !strcmp (info->name, "time"))
1151 value = integer_arg (arg);
1152 else if (arg[0] == '\0' || arg[1] == '\0')
1153 value = arg[0];
1154 else if (!strcmp (arg, "^-") || !strcmp (arg, "undef"))
1155 value = _POSIX_VDISABLE;
1156 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1158 if (arg[1] == '?')
1159 value = 127;
1160 else
1161 value = arg[1] & ~0140; /* Non-letters get weird results. */
1163 else
1164 value = integer_arg (arg);
1165 mode->c_cc[info->offset] = value;
1168 static void
1169 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1171 speed_t baud;
1173 baud = string_to_baud (arg);
1174 if (type == input_speed || type == both_speeds)
1175 cfsetispeed (mode, baud);
1176 if (type == output_speed || type == both_speeds)
1177 cfsetospeed (mode, baud);
1180 #ifdef TIOCGWINSZ
1182 /* Get window size information. First try getting the information
1183 associated with standard output and if that fails, try standard input.
1184 Return zero for success, nonzero if both ioctl's failed. */
1186 static int
1187 get_win_size (struct winsize *win)
1189 int err;
1191 err = ioctl (1, TIOCGWINSZ, (char *) win);
1192 if (err != 0)
1193 err = ioctl (0, TIOCGWINSZ, (char *) win);
1194 return err;
1197 static void
1198 set_window_size (int rows, int cols)
1200 struct winsize win;
1202 if (get_win_size (&win))
1204 if (errno != EINVAL)
1205 error (1, errno, _("standard input"));
1206 memset (&win, 0, sizeof (win));
1209 if (rows >= 0)
1210 win.ws_row = rows;
1211 if (cols >= 0)
1212 win.ws_col = cols;
1214 # ifdef TIOCSSIZE
1215 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1216 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1217 This comment from sys/ttold.h describes Sun's twisted logic - a better
1218 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1219 At any rate, the problem is gone in Solaris 2.x.
1221 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1222 but they can be disambiguated by checking whether a "struct ttysize"
1223 structure's "ts_lines" field is greater than 64K or not. If so,
1224 it's almost certainly a "struct winsize" instead.
1226 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1227 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1228 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1229 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1230 "stty cols 0 rows 0" would do the right thing. On a little-endian
1231 machine like the sun386i, the problem is the same, but for ws_col == 0.
1233 The workaround is to do the ioctl once with row and col = 1 to set the
1234 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1236 if (win.ws_row == 0 || win.ws_col == 0)
1238 struct ttysize ttysz;
1240 ttysz.ts_lines = win.ws_row;
1241 ttysz.ts_cols = win.ws_col;
1243 win.ws_row = 1;
1244 win.ws_col = 1;
1246 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1247 error (1, errno, _("standard input"));
1249 if (ioctl (0, TIOCSSIZE, (char *) &ttysz))
1250 error (1, errno, _("standard input"));
1251 return;
1253 # endif
1255 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1256 error (1, errno, _("standard input"));
1259 static void
1260 display_window_size (int fancy)
1262 struct winsize win;
1264 if (get_win_size (&win))
1266 if (errno != EINVAL)
1267 error (1, errno, _("standard input"));
1269 else
1271 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1272 win.ws_row, win.ws_col);
1273 if (!fancy)
1274 current_col = 0;
1277 #endif
1279 static int
1280 screen_columns (void)
1282 #ifdef TIOCGWINSZ
1283 struct winsize win;
1285 if (get_win_size (&win))
1287 /* With Solaris 2.[123], this ioctl fails and errno is set to
1288 EINVAL for telnet (but not rlogin) sessions. */
1289 if (errno != EINVAL)
1290 error (1, errno, _("standard input"));
1292 else if (win.ws_col > 0)
1293 return win.ws_col;
1294 #endif
1295 if (getenv ("COLUMNS"))
1296 return atoi (getenv ("COLUMNS"));
1297 return 80;
1300 static tcflag_t *
1301 mode_type_flag (enum mode_type type, struct termios *mode)
1303 switch (type)
1305 case control:
1306 return &mode->c_cflag;
1308 case input:
1309 return &mode->c_iflag;
1311 case output:
1312 return &mode->c_oflag;
1314 case local:
1315 return &mode->c_lflag;
1317 case combination:
1318 return NULL;
1320 default:
1321 abort ();
1325 static void
1326 display_settings (enum output_type output_type, struct termios *mode)
1328 switch (output_type)
1330 case changed:
1331 display_changed (mode);
1332 break;
1334 case all:
1335 display_all (mode);
1336 break;
1338 case recoverable:
1339 display_recoverable (mode);
1340 break;
1344 static void
1345 display_changed (struct termios *mode)
1347 int i;
1348 int empty_line;
1349 tcflag_t *bitsp;
1350 unsigned long mask;
1351 enum mode_type prev_type = control;
1353 display_speed (mode, 1);
1354 #ifdef HAVE_C_LINE
1355 wrapf ("line = %d;", mode->c_line);
1356 #endif
1357 putchar ('\n');
1358 current_col = 0;
1360 empty_line = 1;
1361 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1363 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1364 continue;
1365 empty_line = 0;
1366 wrapf ("%s = %s;", control_info[i].name,
1367 visible (mode->c_cc[control_info[i].offset]));
1369 if ((mode->c_lflag & ICANON) == 0)
1371 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1372 (int) mode->c_cc[VTIME]);
1374 else if (empty_line == 0)
1375 putchar ('\n');
1376 current_col = 0;
1378 empty_line = 1;
1379 for (i = 0; mode_info[i].name != NULL; ++i)
1381 if (mode_info[i].flags & OMIT)
1382 continue;
1383 if (mode_info[i].type != prev_type)
1385 if (empty_line == 0)
1387 putchar ('\n');
1388 current_col = 0;
1389 empty_line = 1;
1391 prev_type = mode_info[i].type;
1394 bitsp = mode_type_flag (mode_info[i].type, mode);
1395 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1396 if ((*bitsp & mask) == mode_info[i].bits)
1398 if (mode_info[i].flags & SANE_UNSET)
1400 wrapf ("%s", mode_info[i].name);
1401 empty_line = 0;
1404 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1406 wrapf ("-%s", mode_info[i].name);
1407 empty_line = 0;
1410 if (empty_line == 0)
1411 putchar ('\n');
1412 current_col = 0;
1415 static void
1416 display_all (struct termios *mode)
1418 int i;
1419 tcflag_t *bitsp;
1420 unsigned long mask;
1421 enum mode_type prev_type = control;
1423 display_speed (mode, 1);
1424 #ifdef TIOCGWINSZ
1425 display_window_size (1);
1426 #endif
1427 #ifdef HAVE_C_LINE
1428 wrapf ("line = %d;", mode->c_line);
1429 #endif
1430 putchar ('\n');
1431 current_col = 0;
1433 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1435 wrapf ("%s = %s;", control_info[i].name,
1436 visible (mode->c_cc[control_info[i].offset]));
1438 wrapf ("min = %d; time = %d;\n", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1439 current_col = 0;
1441 for (i = 0; mode_info[i].name != NULL; ++i)
1443 if (mode_info[i].flags & OMIT)
1444 continue;
1445 if (mode_info[i].type != prev_type)
1447 putchar ('\n');
1448 current_col = 0;
1449 prev_type = mode_info[i].type;
1452 bitsp = mode_type_flag (mode_info[i].type, mode);
1453 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1454 if ((*bitsp & mask) == mode_info[i].bits)
1455 wrapf ("%s", mode_info[i].name);
1456 else if (mode_info[i].flags & REV)
1457 wrapf ("-%s", mode_info[i].name);
1459 putchar ('\n');
1460 current_col = 0;
1463 static void
1464 display_speed (struct termios *mode, int fancy)
1466 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1467 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1468 baud_to_value (cfgetospeed (mode)));
1469 else
1470 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1471 baud_to_value (cfgetispeed (mode)),
1472 baud_to_value (cfgetospeed (mode)));
1473 if (!fancy)
1474 current_col = 0;
1477 static void
1478 display_recoverable (struct termios *mode)
1480 int i;
1482 printf ("%lx:%lx:%lx:%lx",
1483 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1484 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1485 for (i = 0; i < NCCS; ++i)
1486 printf (":%x", (unsigned int) mode->c_cc[i]);
1487 putchar ('\n');
1490 static int
1491 recover_mode (char *arg, struct termios *mode)
1493 int i, n;
1494 unsigned int chr;
1495 unsigned long iflag, oflag, cflag, lflag;
1497 /* Scan into temporaries since it is too much trouble to figure out
1498 the right format for `tcflag_t'. */
1499 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1500 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1501 return 0;
1502 mode->c_iflag = iflag;
1503 mode->c_oflag = oflag;
1504 mode->c_cflag = cflag;
1505 mode->c_lflag = lflag;
1506 arg += n;
1507 for (i = 0; i < NCCS; ++i)
1509 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1510 return 0;
1511 mode->c_cc[i] = chr;
1512 arg += n;
1514 return 1;
1517 struct speed_map
1519 const char *string; /* ASCII representation. */
1520 speed_t speed; /* Internal form. */
1521 unsigned long value; /* Numeric value. */
1524 struct speed_map speeds[] =
1526 {"0", B0, 0},
1527 {"50", B50, 50},
1528 {"75", B75, 75},
1529 {"110", B110, 110},
1530 {"134", B134, 134},
1531 {"134.5", B134, 134},
1532 {"150", B150, 150},
1533 {"200", B200, 200},
1534 {"300", B300, 300},
1535 {"600", B600, 600},
1536 {"1200", B1200, 1200},
1537 {"1800", B1800, 1800},
1538 {"2400", B2400, 2400},
1539 {"4800", B4800, 4800},
1540 {"9600", B9600, 9600},
1541 {"19200", B19200, 19200},
1542 {"38400", B38400, 38400},
1543 {"exta", B19200, 19200},
1544 {"extb", B38400, 38400},
1545 #ifdef B57600
1546 {"57600", B57600, 57600},
1547 #endif
1548 #ifdef B115200
1549 {"115200", B115200, 115200},
1550 #endif
1551 {NULL, 0, 0}
1554 static speed_t
1555 string_to_baud (const char *arg)
1557 int i;
1559 for (i = 0; speeds[i].string != NULL; ++i)
1560 if (!strcmp (arg, speeds[i].string))
1561 return speeds[i].speed;
1562 return (speed_t) -1;
1565 static unsigned long
1566 baud_to_value (speed_t speed)
1568 int i;
1570 for (i = 0; speeds[i].string != NULL; ++i)
1571 if (speed == speeds[i].speed)
1572 return speeds[i].value;
1573 return 0;
1576 static void
1577 sane_mode (struct termios *mode)
1579 int i;
1580 tcflag_t *bitsp;
1582 for (i = 0; control_info[i].name; ++i)
1584 #if VMIN == VEOF
1585 if (!strcmp (control_info[i].name, "min"))
1586 break;
1587 #endif
1588 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1591 for (i = 0; mode_info[i].name != NULL; ++i)
1593 if (mode_info[i].flags & SANE_SET)
1595 bitsp = mode_type_flag (mode_info[i].type, mode);
1596 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1598 else if (mode_info[i].flags & SANE_UNSET)
1600 bitsp = mode_type_flag (mode_info[i].type, mode);
1601 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1606 /* Return a string that is the printable representation of character CH. */
1607 /* Adapted from `cat' by Torbjorn Granlund. */
1609 static const char *
1610 visible (unsigned int ch)
1612 static char buf[10];
1613 char *bpout = buf;
1615 if (ch == _POSIX_VDISABLE)
1616 return _("<undef>");
1618 if (ch >= 32)
1620 if (ch < 127)
1621 *bpout++ = ch;
1622 else if (ch == 127)
1624 *bpout++ = '^';
1625 *bpout++ = '?';
1627 else
1629 *bpout++ = 'M',
1630 *bpout++ = '-';
1631 if (ch >= 128 + 32)
1633 if (ch < 128 + 127)
1634 *bpout++ = ch - 128;
1635 else
1637 *bpout++ = '^';
1638 *bpout++ = '?';
1641 else
1643 *bpout++ = '^';
1644 *bpout++ = ch - 128 + 64;
1648 else
1650 *bpout++ = '^';
1651 *bpout++ = ch + 64;
1653 *bpout = '\0';
1654 return (const char *) buf;
1657 /* Parse string S as an integer, using decimal radix by default,
1658 but allowing octal and hex numbers as in C. */
1659 /* From `od' by Richard Stallman. */
1661 static long
1662 integer_arg (const char *s)
1664 long value;
1665 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1667 error (0, 0, _("invalid integer argument `%s'"), s);
1668 usage (1);
1670 return value;