.
[coreutils.git] / src / stty.c
blobe18e34bb33bf9a49d35f21b48902378e913d8ad2
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];
653 setlocale (LC_ALL, "");
654 bindtextdomain (PACKAGE, LOCALEDIR);
655 textdomain (PACKAGE);
657 parse_long_options (argc, argv, "stty", version_string, usage);
659 output_type = changed;
660 verbose_output = 0;
661 recoverable_output = 0;
663 /* Recognize the long options only. */
664 opterr = 0;
665 while ((optc = getopt_long_only (argc, argv, "ag", longopts, (int *) 0))
666 != EOF)
668 switch (optc)
670 case 'a':
671 verbose_output = 1;
672 output_type = all;
673 break;
675 case 'g':
676 recoverable_output = 1;
677 output_type = recoverable;
678 break;
680 default:
681 break;
685 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
686 They need not precede non-options. We cannot use GNU getopt because
687 it would treat -tabs and -ixany as uses of the -a option. */
688 for (k = optind; k < argc; k++)
690 if (argv[k][0] == '-')
692 if (argv[k][1] == 'a'
693 && argv[k][2] == '\0')
695 ++optind;
696 verbose_output = 1;
698 else if (argv[k][1] == 'g'
699 && argv[k][2] == '\0')
701 ++optind;
702 recoverable_output = 1;
704 else if ((argv[k][1] == 'g'
705 && argv[k][2] == 'a'
706 && argv[k][3] == '\0')
707 || (argv[k][1] == 'a'
708 && argv[k][2] == 'g'
709 && argv[k][3] == '\0'))
711 ++optind;
712 verbose_output = 1;
713 recoverable_output = 1;
718 /* Specifying both -a and -g gets an error. */
719 if (verbose_output && recoverable_output)
720 error (2, 0,
721 _("the options for verbose and stty-readable output styles are\n\
722 \tmutually exclusive"));
724 /* Specifying any other arguments with -a or -g gets an error. */
725 if (argc - optind > 0 && (verbose_output || recoverable_output))
726 error (2, 0, _("when specifying an output style, modes may not be set"));
728 /* Initialize to all zeroes so there is no risk memcmp will report a
729 spurious difference in an uninitialized portion of the structure. */
730 memset (&mode, 0, sizeof (mode));
731 if (tcgetattr (0, &mode))
732 error (1, errno, _("standard input"));
734 if (verbose_output || recoverable_output || argc == 1)
736 max_col = screen_columns ();
737 current_col = 0;
738 display_settings (output_type, &mode);
739 exit (0);
742 speed_was_set = 0;
743 require_set_attr = 0;
744 k = 1;
745 while (k < argc)
747 int match_found = 0;
748 int reversed = 0;
749 int i;
751 if (argv[k][0] == '-')
753 ++argv[k];
754 reversed = 1;
756 for (i = 0; mode_info[i].name != NULL; ++i)
758 if (!strcmp (argv[k], mode_info[i].name))
760 match_found = set_mode (&mode_info[i], reversed, &mode);
761 require_set_attr = 1;
762 break;
765 if (match_found == 0 && reversed)
767 error (0, 0, _("invalid argument `%s'"), --argv[k]);
768 usage (1);
770 if (match_found == 0)
772 for (i = 0; control_info[i].name != NULL; ++i)
774 if (!strcmp (argv[k], control_info[i].name))
776 if (k == argc - 1)
778 error (0, 0, _("missing argument to `%s'"), argv[k]);
779 usage (1);
781 match_found = 1;
782 ++k;
783 set_control_char (&control_info[i], argv[k], &mode);
784 require_set_attr = 1;
785 break;
789 if (match_found == 0)
791 if (!strcmp (argv[k], "ispeed"))
793 if (k == argc - 1)
795 error (0, 0, _("missing argument to `%s'"), argv[k]);
796 usage (1);
798 ++k;
799 set_speed (input_speed, argv[k], &mode);
800 speed_was_set = 1;
801 require_set_attr = 1;
803 else if (!strcmp (argv[k], "ospeed"))
805 if (k == argc - 1)
807 error (0, 0, _("missing argument to `%s'"), argv[k]);
808 usage (1);
810 ++k;
811 set_speed (output_speed, argv[k], &mode);
812 speed_was_set = 1;
813 require_set_attr = 1;
815 #ifdef TIOCGWINSZ
816 else if (!strcmp (argv[k], "rows"))
818 if (k == argc - 1)
820 error (0, 0, _("missing argument to `%s'"), argv[k]);
821 usage (1);
823 ++k;
824 set_window_size ((int) integer_arg (argv[k]), -1);
826 else if (!strcmp (argv[k], "cols")
827 || !strcmp (argv[k], "columns"))
829 if (k == argc - 1)
831 error (0, 0, _("missing argument to `%s'"), argv[k]);
832 usage (1);
834 ++k;
835 set_window_size (-1, (int) integer_arg (argv[k]));
837 else if (!strcmp (argv[k], "size"))
839 max_col = screen_columns ();
840 current_col = 0;
841 display_window_size (0);
843 #endif
844 #ifdef HAVE_C_LINE
845 else if (!strcmp (argv[k], "line"))
847 if (k == argc - 1)
849 error (0, 0, _("missing argument to `%s'"), argv[k]);
850 usage (1);
852 ++k;
853 mode.c_line = integer_arg (argv[k]);
854 require_set_attr = 1;
856 #endif
857 else if (!strcmp (argv[k], "speed"))
859 max_col = screen_columns ();
860 display_speed (&mode, 0);
862 else if (string_to_baud (argv[k]) != (speed_t) -1)
864 set_speed (both_speeds, argv[k], &mode);
865 speed_was_set = 1;
866 require_set_attr = 1;
868 else
870 if (recover_mode (argv[k], &mode) == 0)
872 error (0, 0, _("invalid argument `%s'"), argv[k]);
873 usage (1);
875 require_set_attr = 1;
878 k++;
881 if (require_set_attr)
883 struct termios new_mode;
885 if (tcsetattr (0, TCSADRAIN, &mode))
886 error (1, errno, _("standard input"));
888 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
889 it performs *any* of the requested operations. This means it
890 can report `success' when it has actually failed to perform
891 some proper subset of the requested operations. To detect
892 this partial failure, get the current terminal attributes and
893 compare them to the requested ones. */
895 /* Initialize to all zeroes so there is no risk memcmp will report a
896 spurious difference in an uninitialized portion of the structure. */
897 memset (&new_mode, 0, sizeof (new_mode));
898 if (tcgetattr (0, &new_mode))
899 error (1, errno, _("standard input"));
901 /* Normally, one shouldn't use memcmp to compare structures that
902 may have `holes' containing uninitialized data, but we have been
903 careful to initialize the storage of these two variables to all
904 zeroes. One might think it more efficient simply to compare the
905 modified fields, but that would require enumerating those fields --
906 and not all systems have the same fields in this structure. */
908 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
910 #ifdef CIBAUD
911 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
912 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
913 sometimes (m1 != m2). The only difference is in the four bits
914 of the c_cflag field corresponding to the baud rate. To save
915 Sun users a little confusion, don't report an error if this
916 happens. But suppress the error only if we haven't tried to
917 set the baud rate explicitly -- otherwise we'd never give an
918 error for a true failure to set the baud rate. */
920 new_mode.c_cflag &= (~CIBAUD);
921 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
922 #endif
924 int i;
925 error (1, 0,
926 _("standard input: unable to perform all requested operations"));
927 printf (_("new_mode: mode\n"));
928 for (i=0; i<sizeof(new_mode); i++)
929 printf ("0x%02x: 0x%02x\n",
930 *(((unsigned char *) &new_mode) + i),
931 *(((unsigned char *) &mode) + i));
936 exit (0);
939 /* Return 0 if not applied because not reversible; otherwise return 1. */
941 static int
942 set_mode (struct mode_info *info, int reversed, struct termios *mode)
944 tcflag_t *bitsp;
946 if (reversed && (info->flags & REV) == 0)
947 return 0;
949 bitsp = mode_type_flag (info->type, mode);
951 if (bitsp == NULL)
953 /* Combination mode. */
954 if (!strcmp (info->name, "evenp") || !strcmp (info->name, "parity"))
956 if (reversed)
957 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
958 else
959 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
961 else if (!strcmp (info->name, "oddp"))
963 if (reversed)
964 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
965 else
966 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
968 else if (!strcmp (info->name, "nl"))
970 if (reversed)
972 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
973 mode->c_oflag = (mode->c_oflag
974 #ifdef ONLCR
975 | ONLCR
976 #endif
978 #ifdef OCRNL
979 & ~OCRNL
980 #endif
981 #ifdef ONLRET
982 & ~ONLRET
983 #endif
986 else
988 mode->c_iflag = mode->c_iflag & ~ICRNL;
989 #ifdef ONLCR
990 mode->c_oflag = mode->c_oflag & ~ONLCR;
991 #endif
994 else if (!strcmp (info->name, "ek"))
996 mode->c_cc[VERASE] = CERASE;
997 mode->c_cc[VKILL] = CKILL;
999 else if (!strcmp (info->name, "sane"))
1000 sane_mode (mode);
1001 else if (!strcmp (info->name, "cbreak"))
1003 if (reversed)
1004 mode->c_lflag |= ICANON;
1005 else
1006 mode->c_lflag &= ~ICANON;
1008 else if (!strcmp (info->name, "pass8"))
1010 if (reversed)
1012 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1013 mode->c_iflag |= ISTRIP;
1015 else
1017 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1018 mode->c_iflag &= ~ISTRIP;
1021 else if (!strcmp (info->name, "litout"))
1023 if (reversed)
1025 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1026 mode->c_iflag |= ISTRIP;
1027 mode->c_oflag |= OPOST;
1029 else
1031 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1032 mode->c_iflag &= ~ISTRIP;
1033 mode->c_oflag &= ~OPOST;
1036 else if (!strcmp (info->name, "raw") || !strcmp (info->name, "cooked"))
1038 if ((info->name[0] == 'r' && reversed)
1039 || (info->name[0] == 'c' && !reversed))
1041 /* Cooked mode. */
1042 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1043 mode->c_oflag |= OPOST;
1044 mode->c_lflag |= ISIG | ICANON;
1045 #if VMIN == VEOF
1046 mode->c_cc[VEOF] = CEOF;
1047 #endif
1048 #if VTIME == VEOL
1049 mode->c_cc[VEOL] = CEOL;
1050 #endif
1052 else
1054 /* Raw mode. */
1055 mode->c_iflag = 0;
1056 mode->c_oflag &= ~OPOST;
1057 mode->c_lflag &= ~(ISIG | ICANON
1058 #ifdef XCASE
1059 | XCASE
1060 #endif
1062 mode->c_cc[VMIN] = 1;
1063 mode->c_cc[VTIME] = 0;
1066 #ifdef IXANY
1067 else if (!strcmp (info->name, "decctlq"))
1069 if (reversed)
1070 mode->c_iflag |= IXANY;
1071 else
1072 mode->c_iflag &= ~IXANY;
1074 #endif
1075 #ifdef TABDLY
1076 else if (!strcmp (info->name, "tabs"))
1078 if (reversed)
1079 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1080 else
1081 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1083 #else
1084 # ifdef OXTABS
1085 else if (!strcmp (info->name, "tabs"))
1087 if (reversed)
1088 mode->c_oflag = mode->c_oflag | OXTABS;
1089 else
1090 mode->c_oflag = mode->c_oflag & ~OXTABS;
1092 # endif
1093 #endif
1094 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1095 else if (!strcmp (info->name, "lcase")
1096 || !strcmp (info->name, "LCASE"))
1098 if (reversed)
1100 mode->c_lflag &= ~XCASE;
1101 mode->c_iflag &= ~IUCLC;
1102 mode->c_oflag &= ~OLCUC;
1104 else
1106 mode->c_lflag |= XCASE;
1107 mode->c_iflag |= IUCLC;
1108 mode->c_oflag |= OLCUC;
1111 #endif
1112 else if (!strcmp (info->name, "crt"))
1113 mode->c_lflag |= ECHOE
1114 #ifdef ECHOCTL
1115 | ECHOCTL
1116 #endif
1117 #ifdef ECHOKE
1118 | ECHOKE
1119 #endif
1121 else if (!strcmp (info->name, "dec"))
1123 mode->c_cc[VINTR] = 3; /* ^C */
1124 mode->c_cc[VERASE] = 127; /* DEL */
1125 mode->c_cc[VKILL] = 21; /* ^U */
1126 mode->c_lflag |= ECHOE
1127 #ifdef ECHOCTL
1128 | ECHOCTL
1129 #endif
1130 #ifdef ECHOKE
1131 | ECHOKE
1132 #endif
1134 #ifdef IXANY
1135 mode->c_iflag &= ~IXANY;
1136 #endif
1139 else if (reversed)
1140 *bitsp = *bitsp & ~info->mask & ~info->bits;
1141 else
1142 *bitsp = (*bitsp & ~info->mask) | info->bits;
1144 return 1;
1147 static void
1148 set_control_char (struct control_info *info, const char *arg,
1149 struct termios *mode)
1151 unsigned char value;
1153 if (!strcmp (info->name, "min") || !strcmp (info->name, "time"))
1154 value = integer_arg (arg);
1155 else if (arg[0] == '\0' || arg[1] == '\0')
1156 value = arg[0];
1157 else if (!strcmp (arg, "^-") || !strcmp (arg, "undef"))
1158 value = _POSIX_VDISABLE;
1159 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1161 if (arg[1] == '?')
1162 value = 127;
1163 else
1164 value = arg[1] & ~0140; /* Non-letters get weird results. */
1166 else
1167 value = integer_arg (arg);
1168 mode->c_cc[info->offset] = value;
1171 static void
1172 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1174 speed_t baud;
1176 baud = string_to_baud (arg);
1177 if (type == input_speed || type == both_speeds)
1178 cfsetispeed (mode, baud);
1179 if (type == output_speed || type == both_speeds)
1180 cfsetospeed (mode, baud);
1183 #ifdef TIOCGWINSZ
1185 /* Get window size information. First try getting the information
1186 associated with standard output and if that fails, try standard input.
1187 Return zero for success, nonzero if both ioctl's failed. */
1189 static int
1190 get_win_size (struct winsize *win)
1192 int err;
1194 err = ioctl (1, TIOCGWINSZ, (char *) win);
1195 if (err != 0)
1196 err = ioctl (0, TIOCGWINSZ, (char *) win);
1197 return err;
1200 static void
1201 set_window_size (int rows, int cols)
1203 struct winsize win;
1205 if (get_win_size (&win))
1207 if (errno != EINVAL)
1208 error (1, errno, _("standard input"));
1209 memset (&win, 0, sizeof (win));
1212 if (rows >= 0)
1213 win.ws_row = rows;
1214 if (cols >= 0)
1215 win.ws_col = cols;
1217 # ifdef TIOCSSIZE
1218 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1219 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1220 This comment from sys/ttold.h describes Sun's twisted logic - a better
1221 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1222 At any rate, the problem is gone in Solaris 2.x.
1224 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1225 but they can be disambiguated by checking whether a "struct ttysize"
1226 structure's "ts_lines" field is greater than 64K or not. If so,
1227 it's almost certainly a "struct winsize" instead.
1229 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1230 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1231 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1232 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1233 "stty cols 0 rows 0" would do the right thing. On a little-endian
1234 machine like the sun386i, the problem is the same, but for ws_col == 0.
1236 The workaround is to do the ioctl once with row and col = 1 to set the
1237 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1239 if (win.ws_row == 0 || win.ws_col == 0)
1241 struct ttysize ttysz;
1243 ttysz.ts_lines = win.ws_row;
1244 ttysz.ts_cols = win.ws_col;
1246 win.ws_row = 1;
1247 win.ws_col = 1;
1249 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1250 error (1, errno, _("standard input"));
1252 if (ioctl (0, TIOCSSIZE, (char *) &ttysz))
1253 error (1, errno, _("standard input"));
1254 return;
1256 # endif
1258 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1259 error (1, errno, _("standard input"));
1262 static void
1263 display_window_size (int fancy)
1265 struct winsize win;
1267 if (get_win_size (&win))
1269 if (errno != EINVAL)
1270 error (1, errno, _("standard input"));
1272 else
1274 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1275 win.ws_row, win.ws_col);
1276 if (!fancy)
1277 current_col = 0;
1280 #endif
1282 static int
1283 screen_columns (void)
1285 #ifdef TIOCGWINSZ
1286 struct winsize win;
1288 if (get_win_size (&win))
1290 /* With Solaris 2.[123], this ioctl fails and errno is set to
1291 EINVAL for telnet (but not rlogin) sessions. */
1292 if (errno != EINVAL)
1293 error (1, errno, _("standard input"));
1295 else if (win.ws_col > 0)
1296 return win.ws_col;
1297 #endif
1298 if (getenv ("COLUMNS"))
1299 return atoi (getenv ("COLUMNS"));
1300 return 80;
1303 static tcflag_t *
1304 mode_type_flag (enum mode_type type, struct termios *mode)
1306 switch (type)
1308 case control:
1309 return &mode->c_cflag;
1311 case input:
1312 return &mode->c_iflag;
1314 case output:
1315 return &mode->c_oflag;
1317 case local:
1318 return &mode->c_lflag;
1320 case combination:
1321 return NULL;
1323 default:
1324 abort ();
1328 static void
1329 display_settings (enum output_type output_type, struct termios *mode)
1331 switch (output_type)
1333 case changed:
1334 display_changed (mode);
1335 break;
1337 case all:
1338 display_all (mode);
1339 break;
1341 case recoverable:
1342 display_recoverable (mode);
1343 break;
1347 static void
1348 display_changed (struct termios *mode)
1350 int i;
1351 int empty_line;
1352 tcflag_t *bitsp;
1353 unsigned long mask;
1354 enum mode_type prev_type = control;
1356 display_speed (mode, 1);
1357 #ifdef HAVE_C_LINE
1358 wrapf ("line = %d;", mode->c_line);
1359 #endif
1360 putchar ('\n');
1361 current_col = 0;
1363 empty_line = 1;
1364 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1366 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1367 continue;
1368 empty_line = 0;
1369 wrapf ("%s = %s;", control_info[i].name,
1370 visible (mode->c_cc[control_info[i].offset]));
1372 if ((mode->c_lflag & ICANON) == 0)
1374 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1375 (int) mode->c_cc[VTIME]);
1377 else if (empty_line == 0)
1378 putchar ('\n');
1379 current_col = 0;
1381 empty_line = 1;
1382 for (i = 0; mode_info[i].name != NULL; ++i)
1384 if (mode_info[i].flags & OMIT)
1385 continue;
1386 if (mode_info[i].type != prev_type)
1388 if (empty_line == 0)
1390 putchar ('\n');
1391 current_col = 0;
1392 empty_line = 1;
1394 prev_type = mode_info[i].type;
1397 bitsp = mode_type_flag (mode_info[i].type, mode);
1398 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1399 if ((*bitsp & mask) == mode_info[i].bits)
1401 if (mode_info[i].flags & SANE_UNSET)
1403 wrapf ("%s", mode_info[i].name);
1404 empty_line = 0;
1407 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1409 wrapf ("-%s", mode_info[i].name);
1410 empty_line = 0;
1413 if (empty_line == 0)
1414 putchar ('\n');
1415 current_col = 0;
1418 static void
1419 display_all (struct termios *mode)
1421 int i;
1422 tcflag_t *bitsp;
1423 unsigned long mask;
1424 enum mode_type prev_type = control;
1426 display_speed (mode, 1);
1427 #ifdef TIOCGWINSZ
1428 display_window_size (1);
1429 #endif
1430 #ifdef HAVE_C_LINE
1431 wrapf ("line = %d;", mode->c_line);
1432 #endif
1433 putchar ('\n');
1434 current_col = 0;
1436 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1438 wrapf ("%s = %s;", control_info[i].name,
1439 visible (mode->c_cc[control_info[i].offset]));
1441 wrapf ("min = %d; time = %d;\n", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1442 current_col = 0;
1444 for (i = 0; mode_info[i].name != NULL; ++i)
1446 if (mode_info[i].flags & OMIT)
1447 continue;
1448 if (mode_info[i].type != prev_type)
1450 putchar ('\n');
1451 current_col = 0;
1452 prev_type = mode_info[i].type;
1455 bitsp = mode_type_flag (mode_info[i].type, mode);
1456 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1457 if ((*bitsp & mask) == mode_info[i].bits)
1458 wrapf ("%s", mode_info[i].name);
1459 else if (mode_info[i].flags & REV)
1460 wrapf ("-%s", mode_info[i].name);
1462 putchar ('\n');
1463 current_col = 0;
1466 static void
1467 display_speed (struct termios *mode, int fancy)
1469 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1470 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1471 baud_to_value (cfgetospeed (mode)));
1472 else
1473 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1474 baud_to_value (cfgetispeed (mode)),
1475 baud_to_value (cfgetospeed (mode)));
1476 if (!fancy)
1477 current_col = 0;
1480 static void
1481 display_recoverable (struct termios *mode)
1483 int i;
1485 printf ("%lx:%lx:%lx:%lx",
1486 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1487 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1488 for (i = 0; i < NCCS; ++i)
1489 printf (":%x", (unsigned int) mode->c_cc[i]);
1490 putchar ('\n');
1493 static int
1494 recover_mode (char *arg, struct termios *mode)
1496 int i, n;
1497 unsigned int chr;
1498 unsigned long iflag, oflag, cflag, lflag;
1500 /* Scan into temporaries since it is too much trouble to figure out
1501 the right format for `tcflag_t'. */
1502 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1503 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1504 return 0;
1505 mode->c_iflag = iflag;
1506 mode->c_oflag = oflag;
1507 mode->c_cflag = cflag;
1508 mode->c_lflag = lflag;
1509 arg += n;
1510 for (i = 0; i < NCCS; ++i)
1512 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1513 return 0;
1514 mode->c_cc[i] = chr;
1515 arg += n;
1517 return 1;
1520 struct speed_map
1522 const char *string; /* ASCII representation. */
1523 speed_t speed; /* Internal form. */
1524 unsigned long value; /* Numeric value. */
1527 struct speed_map speeds[] =
1529 {"0", B0, 0},
1530 {"50", B50, 50},
1531 {"75", B75, 75},
1532 {"110", B110, 110},
1533 {"134", B134, 134},
1534 {"134.5", B134, 134},
1535 {"150", B150, 150},
1536 {"200", B200, 200},
1537 {"300", B300, 300},
1538 {"600", B600, 600},
1539 {"1200", B1200, 1200},
1540 {"1800", B1800, 1800},
1541 {"2400", B2400, 2400},
1542 {"4800", B4800, 4800},
1543 {"9600", B9600, 9600},
1544 {"19200", B19200, 19200},
1545 {"38400", B38400, 38400},
1546 {"exta", B19200, 19200},
1547 {"extb", B38400, 38400},
1548 #ifdef B57600
1549 {"57600", B57600, 57600},
1550 #endif
1551 #ifdef B115200
1552 {"115200", B115200, 115200},
1553 #endif
1554 {NULL, 0, 0}
1557 static speed_t
1558 string_to_baud (const char *arg)
1560 int i;
1562 for (i = 0; speeds[i].string != NULL; ++i)
1563 if (!strcmp (arg, speeds[i].string))
1564 return speeds[i].speed;
1565 return (speed_t) -1;
1568 static unsigned long
1569 baud_to_value (speed_t speed)
1571 int i;
1573 for (i = 0; speeds[i].string != NULL; ++i)
1574 if (speed == speeds[i].speed)
1575 return speeds[i].value;
1576 return 0;
1579 static void
1580 sane_mode (struct termios *mode)
1582 int i;
1583 tcflag_t *bitsp;
1585 for (i = 0; control_info[i].name; ++i)
1587 #if VMIN == VEOF
1588 if (!strcmp (control_info[i].name, "min"))
1589 break;
1590 #endif
1591 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1594 for (i = 0; mode_info[i].name != NULL; ++i)
1596 if (mode_info[i].flags & SANE_SET)
1598 bitsp = mode_type_flag (mode_info[i].type, mode);
1599 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1601 else if (mode_info[i].flags & SANE_UNSET)
1603 bitsp = mode_type_flag (mode_info[i].type, mode);
1604 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1609 /* Return a string that is the printable representation of character CH. */
1610 /* Adapted from `cat' by Torbjorn Granlund. */
1612 static const char *
1613 visible (unsigned int ch)
1615 static char buf[10];
1616 char *bpout = buf;
1618 if (ch == _POSIX_VDISABLE)
1619 return _("<undef>");
1621 if (ch >= 32)
1623 if (ch < 127)
1624 *bpout++ = ch;
1625 else if (ch == 127)
1627 *bpout++ = '^';
1628 *bpout++ = '?';
1630 else
1632 *bpout++ = 'M',
1633 *bpout++ = '-';
1634 if (ch >= 128 + 32)
1636 if (ch < 128 + 127)
1637 *bpout++ = ch - 128;
1638 else
1640 *bpout++ = '^';
1641 *bpout++ = '?';
1644 else
1646 *bpout++ = '^';
1647 *bpout++ = ch - 128 + 64;
1651 else
1653 *bpout++ = '^';
1654 *bpout++ = ch + 64;
1656 *bpout = '\0';
1657 return (const char *) buf;
1660 /* Parse string S as an integer, using decimal radix by default,
1661 but allowing octal and hex numbers as in C. */
1662 /* From `od' by Richard Stallman. */
1664 static long
1665 integer_arg (const char *s)
1667 long value;
1668 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1670 error (0, 0, _("invalid integer argument `%s'"), s);
1671 usage (1);
1673 return value;