.
[coreutils.git] / src / stty.c
blobd771160f30811cf74399e2802e5f479c6af864f1
1 /* stty -- change and print terminal line settings
2 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 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 Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "long-options.h"
52 #include "error.h"
53 #include "xstrtol.h"
55 #ifndef _POSIX_VDISABLE
56 # define _POSIX_VDISABLE ((unsigned char) 0)
57 #endif
59 #define Control(c) ((c) & 0x1f)
60 /* Canonical values for control characters. */
61 #ifndef CINTR
62 # define CINTR Control ('c')
63 #endif
64 #ifndef CQUIT
65 # define CQUIT 28
66 #endif
67 #ifndef CERASE
68 # define CERASE 127
69 #endif
70 #ifndef CKILL
71 # define CKILL Control ('u')
72 #endif
73 #ifndef CEOF
74 # define CEOF Control ('d')
75 #endif
76 #ifndef CEOL
77 # define CEOL _POSIX_VDISABLE
78 #endif
79 #ifndef CSTART
80 # define CSTART Control ('q')
81 #endif
82 #ifndef CSTOP
83 # define CSTOP Control ('s')
84 #endif
85 #ifndef CSUSP
86 # define CSUSP Control ('z')
87 #endif
88 #if defined(VEOL2) && !defined(CEOL2)
89 # define CEOL2 _POSIX_VDISABLE
90 #endif
91 #if defined(VSWTCH) && !defined(CSWTCH)
92 # define CSWTCH _POSIX_VDISABLE
93 #endif
95 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
96 So the default is to disable `swtch.' */
97 #if defined (__sparc__) && defined (__svr4__)
98 # undef CSWTCH
99 # define CSWTCH _POSIX_VDISABLE
100 #endif
102 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
103 # define VWERASE VWERSE
104 #endif
105 #if defined(VDSUSP) && !defined (CDSUSP)
106 # define CDSUSP Control ('y')
107 #endif
108 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
109 # define VREPRINT VRPRNT
110 #endif
111 #if defined(VREPRINT) && !defined(CRPRNT)
112 # define CRPRNT Control ('r')
113 #endif
114 #if defined(VWERASE) && !defined(CWERASE)
115 # define CWERASE Control ('w')
116 #endif
117 #if defined(VLNEXT) && !defined(CLNEXT)
118 # define CLNEXT Control ('v')
119 #endif
120 #if defined(VDISCARD) && !defined(VFLUSHO)
121 # define VFLUSHO VDISCARD
122 #endif
123 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
124 # define VFLUSHO VFLUSH
125 #endif
126 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
127 # define ECHOCTL CTLECH
128 #endif
129 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
130 # define ECHOCTL TCTLECH
131 #endif
132 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
133 # define ECHOKE CRTKIL
134 #endif
135 #if defined(VFLUSHO) && !defined(CFLUSHO)
136 # define CFLUSHO Control ('o')
137 #endif
138 #if defined(VSTATUS) && !defined(CSTATUS)
139 # define CSTATUS Control ('t')
140 #endif
142 /* Which speeds to set. */
143 enum speed_setting
145 input_speed, output_speed, both_speeds
148 /* What to output and how. */
149 enum output_type
151 changed, all, recoverable /* Default, -a, -g. */
154 /* Which member(s) of `struct termios' a mode uses. */
155 enum mode_type
157 control, input, output, local, combination
160 /* Flags for `struct mode_info'. */
161 #define SANE_SET 1 /* Set in `sane' mode. */
162 #define SANE_UNSET 2 /* Unset in `sane' mode. */
163 #define REV 4 /* Can be turned off by prepending `-'. */
164 #define OMIT 8 /* Don't display value. */
166 /* Each mode. */
167 struct mode_info
169 const char *name; /* Name given on command line. */
170 enum mode_type type; /* Which structure element to change. */
171 char flags; /* Setting and display options. */
172 unsigned long bits; /* Bits to set for this mode. */
173 unsigned long mask; /* Other bits to turn off for this mode. */
176 static struct mode_info mode_info[] =
178 {"parenb", control, REV, PARENB, 0},
179 {"parodd", control, REV, PARODD, 0},
180 {"cs5", control, 0, CS5, CSIZE},
181 {"cs6", control, 0, CS6, CSIZE},
182 {"cs7", control, 0, CS7, CSIZE},
183 {"cs8", control, 0, CS8, CSIZE},
184 {"hupcl", control, REV, HUPCL, 0},
185 {"hup", control, REV | OMIT, HUPCL, 0},
186 {"cstopb", control, REV, CSTOPB, 0},
187 {"cread", control, SANE_SET | REV, CREAD, 0},
188 {"clocal", control, REV, CLOCAL, 0},
189 #ifdef CRTSCTS
190 {"crtscts", control, REV, CRTSCTS, 0},
191 #endif
193 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
194 {"brkint", input, SANE_SET | REV, BRKINT, 0},
195 {"ignpar", input, REV, IGNPAR, 0},
196 {"parmrk", input, REV, PARMRK, 0},
197 {"inpck", input, REV, INPCK, 0},
198 {"istrip", input, REV, ISTRIP, 0},
199 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
200 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
201 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
202 {"ixon", input, REV, IXON, 0},
203 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
204 {"tandem", input, REV | OMIT, IXOFF, 0},
205 #ifdef IUCLC
206 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
207 #endif
208 #ifdef IXANY
209 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
210 #endif
211 #ifdef IMAXBEL
212 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
213 #endif
215 {"opost", output, SANE_SET | REV, OPOST, 0},
216 #ifdef OLCUC
217 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
218 #endif
219 #ifdef OCRNL
220 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
221 #endif
222 #ifdef ONLCR
223 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
224 #endif
225 #ifdef ONOCR
226 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
227 #endif
228 #ifdef ONLRET
229 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
230 #endif
231 #ifdef OFILL
232 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
233 #endif
234 #ifdef OFDEL
235 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
236 #endif
237 #ifdef NLDLY
238 {"nl1", output, SANE_UNSET, NL1, NLDLY},
239 {"nl0", output, SANE_SET, NL0, NLDLY},
240 #endif
241 #ifdef CRDLY
242 {"cr3", output, SANE_UNSET, CR3, CRDLY},
243 {"cr2", output, SANE_UNSET, CR2, CRDLY},
244 {"cr1", output, SANE_UNSET, CR1, CRDLY},
245 {"cr0", output, SANE_SET, CR0, CRDLY},
246 #endif
247 #ifdef TABDLY
248 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
249 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
250 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
251 {"tab0", output, SANE_SET, TAB0, TABDLY},
252 #else
253 # ifdef OXTABS
254 {"tab3", output, SANE_UNSET, OXTABS, 0},
255 # endif
256 #endif
257 #ifdef BSDLY
258 {"bs1", output, SANE_UNSET, BS1, BSDLY},
259 {"bs0", output, SANE_SET, BS0, BSDLY},
260 #endif
261 #ifdef VTDLY
262 {"vt1", output, SANE_UNSET, VT1, VTDLY},
263 {"vt0", output, SANE_SET, VT0, VTDLY},
264 #endif
265 #ifdef FFDLY
266 {"ff1", output, SANE_UNSET, FF1, FFDLY},
267 {"ff0", output, SANE_SET, FF0, FFDLY},
268 #endif
270 {"isig", local, SANE_SET | REV, ISIG, 0},
271 {"icanon", local, SANE_SET | REV, ICANON, 0},
272 #ifdef IEXTEN
273 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
274 #endif
275 {"echo", local, SANE_SET | REV, ECHO, 0},
276 {"echoe", local, SANE_SET | REV, ECHOE, 0},
277 {"crterase", local, REV | OMIT, ECHOE, 0},
278 {"echok", local, SANE_SET | REV, ECHOK, 0},
279 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
280 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
281 #ifdef XCASE
282 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
283 #endif
284 #ifdef TOSTOP
285 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
286 #endif
287 #ifdef ECHOPRT
288 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
289 {"prterase", local, REV | OMIT, ECHOPRT, 0},
290 #endif
291 #ifdef ECHOCTL
292 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
293 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
294 #endif
295 #ifdef ECHOKE
296 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
297 {"crtkill", local, REV | OMIT, ECHOKE, 0},
298 #endif
300 {"evenp", combination, REV | OMIT, 0, 0},
301 {"parity", combination, REV | OMIT, 0, 0},
302 {"oddp", combination, REV | OMIT, 0, 0},
303 {"nl", combination, REV | OMIT, 0, 0},
304 {"ek", combination, OMIT, 0, 0},
305 {"sane", combination, OMIT, 0, 0},
306 {"cooked", combination, REV | OMIT, 0, 0},
307 {"raw", combination, REV | OMIT, 0, 0},
308 {"pass8", combination, REV | OMIT, 0, 0},
309 {"litout", combination, REV | OMIT, 0, 0},
310 {"cbreak", combination, REV | OMIT, 0, 0},
311 #ifdef IXANY
312 {"decctlq", combination, REV | OMIT, 0, 0},
313 #endif
314 #if defined (TABDLY) || defined (OXTABS)
315 {"tabs", combination, REV | OMIT, 0, 0},
316 #endif
317 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
318 {"lcase", combination, REV | OMIT, 0, 0},
319 {"LCASE", combination, REV | OMIT, 0, 0},
320 #endif
321 {"crt", combination, OMIT, 0, 0},
322 {"dec", combination, OMIT, 0, 0},
324 {NULL, control, 0, 0, 0}
327 /* Control character settings. */
328 struct control_info
330 const char *name; /* Name given on command line. */
331 unsigned char saneval; /* Value to set for `stty sane'. */
332 int offset; /* Offset in c_cc. */
335 /* Control characters. */
337 static struct control_info control_info[] =
339 {"intr", CINTR, VINTR},
340 {"quit", CQUIT, VQUIT},
341 {"erase", CERASE, VERASE},
342 {"kill", CKILL, VKILL},
343 {"eof", CEOF, VEOF},
344 {"eol", CEOL, VEOL},
345 #ifdef VEOL2
346 {"eol2", CEOL2, VEOL2},
347 #endif
348 #ifdef VSWTCH
349 {"swtch", CSWTCH, VSWTCH},
350 #endif
351 {"start", CSTART, VSTART},
352 {"stop", CSTOP, VSTOP},
353 {"susp", CSUSP, VSUSP},
354 #ifdef VDSUSP
355 {"dsusp", CDSUSP, VDSUSP},
356 #endif
357 #ifdef VREPRINT
358 {"rprnt", CRPRNT, VREPRINT},
359 #endif
360 #ifdef VWERASE
361 {"werase", CWERASE, VWERASE},
362 #endif
363 #ifdef VLNEXT
364 {"lnext", CLNEXT, VLNEXT},
365 #endif
366 #ifdef VFLUSHO
367 {"flush", CFLUSHO, VFLUSHO},
368 #endif
369 #ifdef VSTATUS
370 {"status", CSTATUS, VSTATUS},
371 #endif
373 /* These must be last because of the display routines. */
374 {"min", 1, VMIN},
375 {"time", 0, VTIME},
376 {NULL, 0, 0}
379 static const char *visible __P ((unsigned int ch));
380 static unsigned long baud_to_value __P ((speed_t speed));
381 static int recover_mode __P ((char *arg, struct termios *mode));
382 static int screen_columns __P ((void));
383 static int set_mode __P ((struct mode_info *info, int reversed,
384 struct termios *mode));
385 static long integer_arg __P ((const char *s));
386 static speed_t string_to_baud __P ((const char *arg));
387 static tcflag_t *mode_type_flag __P ((enum mode_type type,
388 struct termios *mode));
389 static void display_all __P ((struct termios *mode));
390 static void display_changed __P ((struct termios *mode));
391 static void display_recoverable __P ((struct termios *mode));
392 static void display_settings __P ((enum output_type output_type,
393 struct termios *mode));
394 static void display_speed __P ((struct termios *mode, int fancy));
395 static void display_window_size __P ((int fancy));
396 static void sane_mode __P ((struct termios *mode));
397 static void set_control_char __P ((struct control_info *info, const char *arg,
398 struct termios *mode));
399 static void set_speed __P ((enum speed_setting type, const char *arg,
400 struct termios *mode));
401 static void set_window_size __P ((int rows, int cols));
403 /* The width of the screen, for output wrapping. */
404 static int max_col;
406 /* Current position, to know when to wrap. */
407 static int current_col;
409 static struct option longopts[] =
411 {"all", no_argument, NULL, 'a'},
412 {"save", no_argument, NULL, 'g'},
413 {NULL, 0, NULL, 0}
416 /* The name this program was run with. */
417 char *program_name;
419 /* Print format string MESSAGE and optional args.
420 Wrap to next line first if it won't fit.
421 Print a space first unless MESSAGE will start a new line. */
423 /* VARARGS */
424 static void
425 #ifdef __STDC__
426 wrapf (const char *message,...)
427 #else
428 wrapf (message, va_alist)
429 const char *message;
430 va_dcl
431 #endif
433 va_list args;
434 char buf[1024]; /* Plenty long for our needs. */
435 int buflen;
437 VA_START (args, message);
438 vsprintf (buf, message, args);
439 va_end (args);
440 buflen = strlen (buf);
441 if (current_col + (current_col > 0) + buflen >= max_col)
443 putchar ('\n');
444 current_col = 0;
446 if (current_col > 0)
448 putchar (' ');
449 current_col++;
451 fputs (buf, stdout);
452 current_col += buflen;
455 static void
456 usage (int status)
458 if (status != 0)
459 fprintf (stderr, _("Try `%s --help' for more information.\n"),
460 program_name);
461 else
463 printf (_("\
464 Usage: %s [SETTING]...\n\
465 or: %s OPTION\n\
467 program_name, program_name);
468 printf (_("\
469 Print or change terminal characteristics.\n\
471 -a, --all print all current settings in human-readable form\n\
472 -g, --save print all current settings in a stty-readable form\n\
473 --help display this help and exit\n\
474 --version output version information and exit\n\
476 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
477 settings. The underlying system defines which settings are available.\n\
478 "));
479 printf (_("\
481 Special characters:\n\
482 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
483 eof CHAR CHAR will send an end of file (terminate the input)\n\
484 eol CHAR CHAR will end the line\n\
485 * eol2 CHAR alternate CHAR for ending the line\n\
486 erase CHAR CHAR will erase the last character typed\n\
487 intr CHAR CHAR will send an interrupt signal\n\
488 kill CHAR CHAR will erase the current line\n\
489 * lnext CHAR CHAR will enter the next character quoted\n\
490 quit CHAR CHAR will send a quit signal\n\
491 * rprnt CHAR CHAR will redraw the current line\n\
492 start CHAR CHAR will restart the output after stopping it\n\
493 stop CHAR CHAR will stop the output\n\
494 susp CHAR CHAR will send a terminal stop signal\n\
495 * swtch CHAR CHAR will switch to a different shell layer\n\
496 * werase CHAR CHAR will erase the last word typed\n\
497 "));
498 printf (_("\
500 Special settings:\n\
501 N set the input and output speeds to N bauds\n\
502 * cols N tell the kernel that the terminal has N columns\n\
503 * columns N same as cols N\n\
504 ispeed N set the input speed to N\n\
505 * line N use line discipline N\n\
506 min N with -icanon, set N characters minimum for a completed read\n\
507 ospeed N set the output speed to N\n\
508 * rows N tell the kernel that the terminal has N rows\n\
509 * size print the number of rows and columns according to the kernel\n\
510 speed print the terminal speed\n\
511 time N with -icanon, set read timeout of N tenths of a second\n\
512 "));
513 printf (_("\
515 Control settings:\n\
516 [-]clocal disable modem control signals\n\
517 [-]cread allow input to be received\n\
518 * [-]crtscts enable RTS/CTS handshaking\n\
519 csN set character size to N bits, N in [5..8]\n\
520 [-]cstopb use two stop bits per character (one with `-')\n\
521 [-]hup send a hangup signal when the last process closes the tty\n\
522 [-]hupcl same as [-]hup\n\
523 [-]parenb generate parity bit in output and expect parity bit in input\n\
524 [-]parodd set odd parity (even with `-')\n\
525 "));
526 printf (_("\
528 Input settings:\n\
529 [-]brkint breaks cause an interrupt signal\n\
530 [-]icrnl translate carriage return to newline\n\
531 [-]ignbrk ignore break characters\n\
532 [-]igncr ignore carriage return\n\
533 [-]ignpar ignore characters with parity errors\n\
534 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
535 [-]inlcr translate newline to carriage return\n\
536 [-]inpck enable input parity checking\n\
537 [-]istrip clear high (8th) bit of input characters\n\
538 * [-]iuclc translate uppercase characters to lowercase\n\
539 * [-]ixany let any character restart output, not only start character\n\
540 [-]ixoff enable sending of start/stop characters\n\
541 [-]ixon enable XON/XOFF flow control\n\
542 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
543 [-]tandem same as [-]ixoff\n\
544 "));
545 printf (_("\
547 Output settings:\n\
548 * bsN backspace delay style, N in [0..1]\n\
549 * crN carriage return delay style, N in [0..3]\n\
550 * ffN form feed delay style, N in [0..1]\n\
551 * nlN newline delay style, N in [0..1]\n\
552 * [-]ocrnl translate carriage return to newline\n\
553 * [-]ofdel use delete characters for fill instead of null characters\n\
554 * [-]ofill use fill (padding) characters instead of timing for delays\n\
555 * [-]olcuc translate lowercase characters to uppercase\n\
556 * [-]onlcr translate newline to carriage return-newline\n\
557 * [-]onlret newline performs a carriage return\n\
558 * [-]onocr do not print carriage returns in the first column\n\
559 [-]opost postprocess output\n\
560 * tabN horizontal tab delay style, N in [0..3]\n\
561 * tabs same as tab0\n\
562 * -tabs same as tab3\n\
563 * vtN vertical tab delay style, N in [0..1]\n\
564 "));
565 printf (_("\
567 Local settings:\n\
568 [-]crterase echo erase characters as backspace-space-backspace\n\
569 * crtkill kill all line by obeying the echoprt and echoe settings\n\
570 * -crtkill kill all line by obeying the echoctl and echok settings\n\
571 * [-]ctlecho echo control characters in hat notation (`^c')\n\
572 [-]echo echo input characters\n\
573 * [-]echoctl same as [-]ctlecho\n\
574 [-]echoe same as [-]crterase\n\
575 [-]echok echo a newline after a kill character\n\
576 * [-]echoke same as [-]crtkill\n\
577 [-]echonl echo newline even if not echoing other characters\n\
578 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
579 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
580 [-]iexten enable non-POSIX special characters\n\
581 [-]isig enable interrupt, quit, and suspend special characters\n\
582 [-]noflsh disable flushing after interrupt and quit special characters\n\
583 * [-]prterase same as [-]echoprt\n\
584 * [-]tostop stop background jobs that try to write to the terminal\n\
585 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
586 "));
587 printf (_("\
589 Combination settings:\n\
590 * [-]LCASE same as [-]lcase\n\
591 cbreak same as -icanon\n\
592 -cbreak same as icanon\n\
593 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
594 icanon, eof and eol characters to their default values\n\
595 -cooked same as raw\n\
596 crt same as echoe echoctl echoke\n\
597 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
598 kill ^u\n\
599 * [-]decctlq same as [-]ixany\n\
600 ek erase and kill characters to their default values\n\
601 evenp same as parenb -parodd cs7\n\
602 -evenp same as -parenb cs8\n\
603 * [-]lcase same as xcase iuclc olcuc\n\
604 litout same as -parenb -istrip -opost cs8\n\
605 -litout same as parenb istrip opost cs7\n\
606 nl same as -icrnl -onlcr\n\
607 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
608 oddp same as parenb parodd cs7\n\
609 -oddp same as -parenb cs8\n\
610 [-]parity same as [-]evenp\n\
611 pass8 same as -parenb -istrip cs8\n\
612 -pass8 same as parenb istrip cs7\n\
613 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
614 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
615 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
616 -raw same as cooked\n\
617 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
618 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
619 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
620 isig icanon iexten echo echoe echok -echonl -noflsh\n\
621 -xcase -tostop -echoprt echoctl echoke, all special\n\
622 characters to their default values.\n\
623 "));
624 printf (_("\
626 Handle the tty line connected to standard input. Without arguments,\n\
627 prints baud rate, line discipline, and deviations from stty sane. In\n\
628 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
629 127; special values ^- or undef used to disable special characters.\n\
630 "));
632 exit (status);
636 main (int argc, char **argv)
638 struct termios mode;
639 enum output_type output_type;
640 int optc;
641 int require_set_attr;
642 int speed_was_set;
643 int verbose_output;
644 int recoverable_output;
645 int k;
647 program_name = argv[0];
648 setlocale (LC_ALL, "");
649 bindtextdomain (PACKAGE, LOCALEDIR);
650 textdomain (PACKAGE);
652 parse_long_options (argc, argv, "stty", PACKAGE_VERSION, usage);
654 output_type = changed;
655 verbose_output = 0;
656 recoverable_output = 0;
658 /* Recognize the long options only. */
659 opterr = 0;
660 while ((optc = getopt_long_only (argc, argv, "ag", longopts, (int *) 0))
661 != EOF)
663 switch (optc)
665 case 'a':
666 verbose_output = 1;
667 output_type = all;
668 break;
670 case 'g':
671 recoverable_output = 1;
672 output_type = recoverable;
673 break;
675 default:
676 break;
680 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
681 They need not precede non-options. We cannot use GNU getopt because
682 it would treat -tabs and -ixany as uses of the -a option. */
683 for (k = optind; k < argc; k++)
685 if (argv[k][0] == '-')
687 if (argv[k][1] == 'a'
688 && argv[k][2] == '\0')
690 ++optind;
691 verbose_output = 1;
693 else if (argv[k][1] == 'g'
694 && argv[k][2] == '\0')
696 ++optind;
697 recoverable_output = 1;
699 else if ((argv[k][1] == 'g'
700 && argv[k][2] == 'a'
701 && argv[k][3] == '\0')
702 || (argv[k][1] == 'a'
703 && argv[k][2] == 'g'
704 && argv[k][3] == '\0'))
706 ++optind;
707 verbose_output = 1;
708 recoverable_output = 1;
713 /* Specifying both -a and -g gets an error. */
714 if (verbose_output && recoverable_output)
715 error (2, 0,
716 _("the options for verbose and stty-readable output styles are\n\
717 \tmutually exclusive"));
719 /* Specifying any other arguments with -a or -g gets an error. */
720 if (argc - optind > 0 && (verbose_output || recoverable_output))
721 error (2, 0, _("when specifying an output style, modes may not be set"));
723 /* Initialize to all zeroes so there is no risk memcmp will report a
724 spurious difference in an uninitialized portion of the structure. */
725 memset (&mode, 0, sizeof (mode));
726 if (tcgetattr (0, &mode))
727 error (1, errno, _("standard input"));
729 if (verbose_output || recoverable_output || argc == 1)
731 max_col = screen_columns ();
732 current_col = 0;
733 display_settings (output_type, &mode);
734 exit (0);
737 speed_was_set = 0;
738 require_set_attr = 0;
739 k = 1;
740 while (k < argc)
742 int match_found = 0;
743 int reversed = 0;
744 int i;
746 if (argv[k][0] == '-')
748 ++argv[k];
749 reversed = 1;
751 for (i = 0; mode_info[i].name != NULL; ++i)
753 if (!strcmp (argv[k], mode_info[i].name))
755 match_found = set_mode (&mode_info[i], reversed, &mode);
756 require_set_attr = 1;
757 break;
760 if (match_found == 0 && reversed)
762 error (0, 0, _("invalid argument `%s'"), --argv[k]);
763 usage (1);
765 if (match_found == 0)
767 for (i = 0; control_info[i].name != NULL; ++i)
769 if (!strcmp (argv[k], control_info[i].name))
771 if (k == argc - 1)
773 error (0, 0, _("missing argument to `%s'"), argv[k]);
774 usage (1);
776 match_found = 1;
777 ++k;
778 set_control_char (&control_info[i], argv[k], &mode);
779 require_set_attr = 1;
780 break;
784 if (match_found == 0)
786 if (!strcmp (argv[k], "ispeed"))
788 if (k == argc - 1)
790 error (0, 0, _("missing argument to `%s'"), argv[k]);
791 usage (1);
793 ++k;
794 set_speed (input_speed, argv[k], &mode);
795 speed_was_set = 1;
796 require_set_attr = 1;
798 else if (!strcmp (argv[k], "ospeed"))
800 if (k == argc - 1)
802 error (0, 0, _("missing argument to `%s'"), argv[k]);
803 usage (1);
805 ++k;
806 set_speed (output_speed, argv[k], &mode);
807 speed_was_set = 1;
808 require_set_attr = 1;
810 #ifdef TIOCGWINSZ
811 else if (!strcmp (argv[k], "rows"))
813 if (k == argc - 1)
815 error (0, 0, _("missing argument to `%s'"), argv[k]);
816 usage (1);
818 ++k;
819 set_window_size ((int) integer_arg (argv[k]), -1);
821 else if (!strcmp (argv[k], "cols")
822 || !strcmp (argv[k], "columns"))
824 if (k == argc - 1)
826 error (0, 0, _("missing argument to `%s'"), argv[k]);
827 usage (1);
829 ++k;
830 set_window_size (-1, (int) integer_arg (argv[k]));
832 else if (!strcmp (argv[k], "size"))
834 max_col = screen_columns ();
835 current_col = 0;
836 display_window_size (0);
838 #endif
839 #ifdef HAVE_C_LINE
840 else if (!strcmp (argv[k], "line"))
842 if (k == argc - 1)
844 error (0, 0, _("missing argument to `%s'"), argv[k]);
845 usage (1);
847 ++k;
848 mode.c_line = integer_arg (argv[k]);
849 require_set_attr = 1;
851 #endif
852 else if (!strcmp (argv[k], "speed"))
854 max_col = screen_columns ();
855 display_speed (&mode, 0);
857 else if (string_to_baud (argv[k]) != (speed_t) -1)
859 set_speed (both_speeds, argv[k], &mode);
860 speed_was_set = 1;
861 require_set_attr = 1;
863 else
865 if (recover_mode (argv[k], &mode) == 0)
867 error (0, 0, _("invalid argument `%s'"), argv[k]);
868 usage (1);
870 require_set_attr = 1;
873 k++;
876 if (require_set_attr)
878 struct termios new_mode;
880 if (tcsetattr (0, TCSADRAIN, &mode))
881 error (1, errno, _("standard input"));
883 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
884 it performs *any* of the requested operations. This means it
885 can report `success' when it has actually failed to perform
886 some proper subset of the requested operations. To detect
887 this partial failure, get the current terminal attributes and
888 compare them to the requested ones. */
890 /* Initialize to all zeroes so there is no risk memcmp will report a
891 spurious difference in an uninitialized portion of the structure. */
892 memset (&new_mode, 0, sizeof (new_mode));
893 if (tcgetattr (0, &new_mode))
894 error (1, errno, _("standard input"));
896 /* Normally, one shouldn't use memcmp to compare structures that
897 may have `holes' containing uninitialized data, but we have been
898 careful to initialize the storage of these two variables to all
899 zeroes. One might think it more efficient simply to compare the
900 modified fields, but that would require enumerating those fields --
901 and not all systems have the same fields in this structure. */
903 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
905 #ifdef CIBAUD
906 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
907 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
908 sometimes (m1 != m2). The only difference is in the four bits
909 of the c_cflag field corresponding to the baud rate. To save
910 Sun users a little confusion, don't report an error if this
911 happens. But suppress the error only if we haven't tried to
912 set the baud rate explicitly -- otherwise we'd never give an
913 error for a true failure to set the baud rate. */
915 new_mode.c_cflag &= (~CIBAUD);
916 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
917 #endif
919 size_t i;
920 error (1, 0,
921 _("standard input: unable to perform all requested operations"));
922 printf (_("new_mode: mode\n"));
923 for (i = 0; i < sizeof (new_mode); i++)
924 printf ("0x%02x: 0x%02x\n",
925 *(((unsigned char *) &new_mode) + i),
926 *(((unsigned char *) &mode) + i));
931 exit (0);
934 /* Return 0 if not applied because not reversible; otherwise return 1. */
936 static int
937 set_mode (struct mode_info *info, int reversed, struct termios *mode)
939 tcflag_t *bitsp;
941 if (reversed && (info->flags & REV) == 0)
942 return 0;
944 bitsp = mode_type_flag (info->type, mode);
946 if (bitsp == NULL)
948 /* Combination mode. */
949 if (!strcmp (info->name, "evenp") || !strcmp (info->name, "parity"))
951 if (reversed)
952 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
953 else
954 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
956 else if (!strcmp (info->name, "oddp"))
958 if (reversed)
959 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
960 else
961 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
963 else if (!strcmp (info->name, "nl"))
965 if (reversed)
967 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
968 mode->c_oflag = (mode->c_oflag
969 #ifdef ONLCR
970 | ONLCR
971 #endif
973 #ifdef OCRNL
974 & ~OCRNL
975 #endif
976 #ifdef ONLRET
977 & ~ONLRET
978 #endif
981 else
983 mode->c_iflag = mode->c_iflag & ~ICRNL;
984 #ifdef ONLCR
985 mode->c_oflag = mode->c_oflag & ~ONLCR;
986 #endif
989 else if (!strcmp (info->name, "ek"))
991 mode->c_cc[VERASE] = CERASE;
992 mode->c_cc[VKILL] = CKILL;
994 else if (!strcmp (info->name, "sane"))
995 sane_mode (mode);
996 else if (!strcmp (info->name, "cbreak"))
998 if (reversed)
999 mode->c_lflag |= ICANON;
1000 else
1001 mode->c_lflag &= ~ICANON;
1003 else if (!strcmp (info->name, "pass8"))
1005 if (reversed)
1007 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1008 mode->c_iflag |= ISTRIP;
1010 else
1012 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1013 mode->c_iflag &= ~ISTRIP;
1016 else if (!strcmp (info->name, "litout"))
1018 if (reversed)
1020 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1021 mode->c_iflag |= ISTRIP;
1022 mode->c_oflag |= OPOST;
1024 else
1026 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1027 mode->c_iflag &= ~ISTRIP;
1028 mode->c_oflag &= ~OPOST;
1031 else if (!strcmp (info->name, "raw") || !strcmp (info->name, "cooked"))
1033 if ((info->name[0] == 'r' && reversed)
1034 || (info->name[0] == 'c' && !reversed))
1036 /* Cooked mode. */
1037 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1038 mode->c_oflag |= OPOST;
1039 mode->c_lflag |= ISIG | ICANON;
1040 #if VMIN == VEOF
1041 mode->c_cc[VEOF] = CEOF;
1042 #endif
1043 #if VTIME == VEOL
1044 mode->c_cc[VEOL] = CEOL;
1045 #endif
1047 else
1049 /* Raw mode. */
1050 mode->c_iflag = 0;
1051 mode->c_oflag &= ~OPOST;
1052 mode->c_lflag &= ~(ISIG | ICANON
1053 #ifdef XCASE
1054 | XCASE
1055 #endif
1057 mode->c_cc[VMIN] = 1;
1058 mode->c_cc[VTIME] = 0;
1061 #ifdef IXANY
1062 else if (!strcmp (info->name, "decctlq"))
1064 if (reversed)
1065 mode->c_iflag |= IXANY;
1066 else
1067 mode->c_iflag &= ~IXANY;
1069 #endif
1070 #ifdef TABDLY
1071 else if (!strcmp (info->name, "tabs"))
1073 if (reversed)
1074 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1075 else
1076 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1078 #else
1079 # ifdef OXTABS
1080 else if (!strcmp (info->name, "tabs"))
1082 if (reversed)
1083 mode->c_oflag = mode->c_oflag | OXTABS;
1084 else
1085 mode->c_oflag = mode->c_oflag & ~OXTABS;
1087 # endif
1088 #endif
1089 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1090 else if (!strcmp (info->name, "lcase")
1091 || !strcmp (info->name, "LCASE"))
1093 if (reversed)
1095 mode->c_lflag &= ~XCASE;
1096 mode->c_iflag &= ~IUCLC;
1097 mode->c_oflag &= ~OLCUC;
1099 else
1101 mode->c_lflag |= XCASE;
1102 mode->c_iflag |= IUCLC;
1103 mode->c_oflag |= OLCUC;
1106 #endif
1107 else if (!strcmp (info->name, "crt"))
1108 mode->c_lflag |= ECHOE
1109 #ifdef ECHOCTL
1110 | ECHOCTL
1111 #endif
1112 #ifdef ECHOKE
1113 | ECHOKE
1114 #endif
1116 else if (!strcmp (info->name, "dec"))
1118 mode->c_cc[VINTR] = 3; /* ^C */
1119 mode->c_cc[VERASE] = 127; /* DEL */
1120 mode->c_cc[VKILL] = 21; /* ^U */
1121 mode->c_lflag |= ECHOE
1122 #ifdef ECHOCTL
1123 | ECHOCTL
1124 #endif
1125 #ifdef ECHOKE
1126 | ECHOKE
1127 #endif
1129 #ifdef IXANY
1130 mode->c_iflag &= ~IXANY;
1131 #endif
1134 else if (reversed)
1135 *bitsp = *bitsp & ~info->mask & ~info->bits;
1136 else
1137 *bitsp = (*bitsp & ~info->mask) | info->bits;
1139 return 1;
1142 static void
1143 set_control_char (struct control_info *info, const char *arg,
1144 struct termios *mode)
1146 unsigned char value;
1148 if (!strcmp (info->name, "min") || !strcmp (info->name, "time"))
1149 value = integer_arg (arg);
1150 else if (arg[0] == '\0' || arg[1] == '\0')
1151 value = arg[0];
1152 else if (!strcmp (arg, "^-") || !strcmp (arg, "undef"))
1153 value = _POSIX_VDISABLE;
1154 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1156 if (arg[1] == '?')
1157 value = 127;
1158 else
1159 value = arg[1] & ~0140; /* Non-letters get weird results. */
1161 else
1162 value = integer_arg (arg);
1163 mode->c_cc[info->offset] = value;
1166 static void
1167 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1169 speed_t baud;
1171 baud = string_to_baud (arg);
1172 if (type == input_speed || type == both_speeds)
1173 cfsetispeed (mode, baud);
1174 if (type == output_speed || type == both_speeds)
1175 cfsetospeed (mode, baud);
1178 #ifdef TIOCGWINSZ
1180 /* Get window size information. First try getting the information
1181 associated with standard output and if that fails, try standard input.
1182 Return zero for success, nonzero if both ioctl's failed. */
1184 static int
1185 get_win_size (struct winsize *win)
1187 int err;
1189 err = ioctl (1, TIOCGWINSZ, (char *) win);
1190 if (err != 0)
1191 err = ioctl (0, TIOCGWINSZ, (char *) win);
1192 return err;
1195 static void
1196 set_window_size (int rows, int cols)
1198 struct winsize win;
1200 if (get_win_size (&win))
1202 if (errno != EINVAL)
1203 error (1, errno, _("standard input"));
1204 memset (&win, 0, sizeof (win));
1207 if (rows >= 0)
1208 win.ws_row = rows;
1209 if (cols >= 0)
1210 win.ws_col = cols;
1212 # ifdef TIOCSSIZE
1213 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1214 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1215 This comment from sys/ttold.h describes Sun's twisted logic - a better
1216 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1217 At any rate, the problem is gone in Solaris 2.x.
1219 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1220 but they can be disambiguated by checking whether a "struct ttysize"
1221 structure's "ts_lines" field is greater than 64K or not. If so,
1222 it's almost certainly a "struct winsize" instead.
1224 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1225 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1226 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1227 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1228 "stty cols 0 rows 0" would do the right thing. On a little-endian
1229 machine like the sun386i, the problem is the same, but for ws_col == 0.
1231 The workaround is to do the ioctl once with row and col = 1 to set the
1232 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1234 if (win.ws_row == 0 || win.ws_col == 0)
1236 struct ttysize ttysz;
1238 ttysz.ts_lines = win.ws_row;
1239 ttysz.ts_cols = win.ws_col;
1241 win.ws_row = 1;
1242 win.ws_col = 1;
1244 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1245 error (1, errno, _("standard input"));
1247 if (ioctl (0, TIOCSSIZE, (char *) &ttysz))
1248 error (1, errno, _("standard input"));
1249 return;
1251 # endif
1253 if (ioctl (0, TIOCSWINSZ, (char *) &win))
1254 error (1, errno, _("standard input"));
1257 static void
1258 display_window_size (int fancy)
1260 struct winsize win;
1262 if (get_win_size (&win))
1264 if (errno != EINVAL)
1265 error (1, errno, _("standard input"));
1267 else
1269 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1270 win.ws_row, win.ws_col);
1271 if (!fancy)
1272 current_col = 0;
1275 #endif
1277 static int
1278 screen_columns (void)
1280 #ifdef TIOCGWINSZ
1281 struct winsize win;
1283 if (get_win_size (&win))
1285 /* With Solaris 2.[123], this ioctl fails and errno is set to
1286 EINVAL for telnet (but not rlogin) sessions. */
1287 if (errno != EINVAL)
1288 error (1, errno, _("standard input"));
1290 else if (win.ws_col > 0)
1291 return win.ws_col;
1292 #endif
1293 if (getenv ("COLUMNS"))
1294 return atoi (getenv ("COLUMNS"));
1295 return 80;
1298 static tcflag_t *
1299 mode_type_flag (enum mode_type type, struct termios *mode)
1301 switch (type)
1303 case control:
1304 return &mode->c_cflag;
1306 case input:
1307 return &mode->c_iflag;
1309 case output:
1310 return &mode->c_oflag;
1312 case local:
1313 return &mode->c_lflag;
1315 case combination:
1316 return NULL;
1318 default:
1319 abort ();
1323 static void
1324 display_settings (enum output_type output_type, struct termios *mode)
1326 switch (output_type)
1328 case changed:
1329 display_changed (mode);
1330 break;
1332 case all:
1333 display_all (mode);
1334 break;
1336 case recoverable:
1337 display_recoverable (mode);
1338 break;
1342 static void
1343 display_changed (struct termios *mode)
1345 int i;
1346 int empty_line;
1347 tcflag_t *bitsp;
1348 unsigned long mask;
1349 enum mode_type prev_type = control;
1351 display_speed (mode, 1);
1352 #ifdef HAVE_C_LINE
1353 wrapf ("line = %d;", mode->c_line);
1354 #endif
1355 putchar ('\n');
1356 current_col = 0;
1358 empty_line = 1;
1359 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1361 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1362 continue;
1363 empty_line = 0;
1364 wrapf ("%s = %s;", control_info[i].name,
1365 visible (mode->c_cc[control_info[i].offset]));
1367 if ((mode->c_lflag & ICANON) == 0)
1369 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1370 (int) mode->c_cc[VTIME]);
1372 else if (empty_line == 0)
1373 putchar ('\n');
1374 current_col = 0;
1376 empty_line = 1;
1377 for (i = 0; mode_info[i].name != NULL; ++i)
1379 if (mode_info[i].flags & OMIT)
1380 continue;
1381 if (mode_info[i].type != prev_type)
1383 if (empty_line == 0)
1385 putchar ('\n');
1386 current_col = 0;
1387 empty_line = 1;
1389 prev_type = mode_info[i].type;
1392 bitsp = mode_type_flag (mode_info[i].type, mode);
1393 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1394 if ((*bitsp & mask) == mode_info[i].bits)
1396 if (mode_info[i].flags & SANE_UNSET)
1398 wrapf ("%s", mode_info[i].name);
1399 empty_line = 0;
1402 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1404 wrapf ("-%s", mode_info[i].name);
1405 empty_line = 0;
1408 if (empty_line == 0)
1409 putchar ('\n');
1410 current_col = 0;
1413 static void
1414 display_all (struct termios *mode)
1416 int i;
1417 tcflag_t *bitsp;
1418 unsigned long mask;
1419 enum mode_type prev_type = control;
1421 display_speed (mode, 1);
1422 #ifdef TIOCGWINSZ
1423 display_window_size (1);
1424 #endif
1425 #ifdef HAVE_C_LINE
1426 wrapf ("line = %d;", mode->c_line);
1427 #endif
1428 putchar ('\n');
1429 current_col = 0;
1431 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1433 wrapf ("%s = %s;", control_info[i].name,
1434 visible (mode->c_cc[control_info[i].offset]));
1436 wrapf ("min = %d; time = %d;\n", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1437 current_col = 0;
1439 for (i = 0; mode_info[i].name != NULL; ++i)
1441 if (mode_info[i].flags & OMIT)
1442 continue;
1443 if (mode_info[i].type != prev_type)
1445 putchar ('\n');
1446 current_col = 0;
1447 prev_type = mode_info[i].type;
1450 bitsp = mode_type_flag (mode_info[i].type, mode);
1451 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1452 if ((*bitsp & mask) == mode_info[i].bits)
1453 wrapf ("%s", mode_info[i].name);
1454 else if (mode_info[i].flags & REV)
1455 wrapf ("-%s", mode_info[i].name);
1457 putchar ('\n');
1458 current_col = 0;
1461 static void
1462 display_speed (struct termios *mode, int fancy)
1464 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1465 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1466 baud_to_value (cfgetospeed (mode)));
1467 else
1468 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1469 baud_to_value (cfgetispeed (mode)),
1470 baud_to_value (cfgetospeed (mode)));
1471 if (!fancy)
1472 current_col = 0;
1475 static void
1476 display_recoverable (struct termios *mode)
1478 int i;
1480 printf ("%lx:%lx:%lx:%lx",
1481 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1482 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1483 for (i = 0; i < NCCS; ++i)
1484 printf (":%x", (unsigned int) mode->c_cc[i]);
1485 putchar ('\n');
1488 static int
1489 recover_mode (char *arg, struct termios *mode)
1491 int i, n;
1492 unsigned int chr;
1493 unsigned long iflag, oflag, cflag, lflag;
1495 /* Scan into temporaries since it is too much trouble to figure out
1496 the right format for `tcflag_t'. */
1497 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1498 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1499 return 0;
1500 mode->c_iflag = iflag;
1501 mode->c_oflag = oflag;
1502 mode->c_cflag = cflag;
1503 mode->c_lflag = lflag;
1504 arg += n;
1505 for (i = 0; i < NCCS; ++i)
1507 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1508 return 0;
1509 mode->c_cc[i] = chr;
1510 arg += n;
1512 return 1;
1515 struct speed_map
1517 const char *string; /* ASCII representation. */
1518 speed_t speed; /* Internal form. */
1519 unsigned long value; /* Numeric value. */
1522 struct speed_map speeds[] =
1524 {"0", B0, 0},
1525 {"50", B50, 50},
1526 {"75", B75, 75},
1527 {"110", B110, 110},
1528 {"134", B134, 134},
1529 {"134.5", B134, 134},
1530 {"150", B150, 150},
1531 {"200", B200, 200},
1532 {"300", B300, 300},
1533 {"600", B600, 600},
1534 {"1200", B1200, 1200},
1535 {"1800", B1800, 1800},
1536 {"2400", B2400, 2400},
1537 {"4800", B4800, 4800},
1538 {"9600", B9600, 9600},
1539 {"19200", B19200, 19200},
1540 {"38400", B38400, 38400},
1541 {"exta", B19200, 19200},
1542 {"extb", B38400, 38400},
1543 #ifdef B57600
1544 {"57600", B57600, 57600},
1545 #endif
1546 #ifdef B115200
1547 {"115200", B115200, 115200},
1548 #endif
1549 {NULL, 0, 0}
1552 static speed_t
1553 string_to_baud (const char *arg)
1555 int i;
1557 for (i = 0; speeds[i].string != NULL; ++i)
1558 if (!strcmp (arg, speeds[i].string))
1559 return speeds[i].speed;
1560 return (speed_t) -1;
1563 static unsigned long
1564 baud_to_value (speed_t speed)
1566 int i;
1568 for (i = 0; speeds[i].string != NULL; ++i)
1569 if (speed == speeds[i].speed)
1570 return speeds[i].value;
1571 return 0;
1574 static void
1575 sane_mode (struct termios *mode)
1577 int i;
1578 tcflag_t *bitsp;
1580 for (i = 0; control_info[i].name; ++i)
1582 #if VMIN == VEOF
1583 if (!strcmp (control_info[i].name, "min"))
1584 break;
1585 #endif
1586 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1589 for (i = 0; mode_info[i].name != NULL; ++i)
1591 if (mode_info[i].flags & SANE_SET)
1593 bitsp = mode_type_flag (mode_info[i].type, mode);
1594 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1596 else if (mode_info[i].flags & SANE_UNSET)
1598 bitsp = mode_type_flag (mode_info[i].type, mode);
1599 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1604 /* Return a string that is the printable representation of character CH. */
1605 /* Adapted from `cat' by Torbjorn Granlund. */
1607 static const char *
1608 visible (unsigned int ch)
1610 static char buf[10];
1611 char *bpout = buf;
1613 if (ch == _POSIX_VDISABLE)
1614 return _("<undef>");
1616 if (ch >= 32)
1618 if (ch < 127)
1619 *bpout++ = ch;
1620 else if (ch == 127)
1622 *bpout++ = '^';
1623 *bpout++ = '?';
1625 else
1627 *bpout++ = 'M',
1628 *bpout++ = '-';
1629 if (ch >= 128 + 32)
1631 if (ch < 128 + 127)
1632 *bpout++ = ch - 128;
1633 else
1635 *bpout++ = '^';
1636 *bpout++ = '?';
1639 else
1641 *bpout++ = '^';
1642 *bpout++ = ch - 128 + 64;
1646 else
1648 *bpout++ = '^';
1649 *bpout++ = ch + 64;
1651 *bpout = '\0';
1652 return (const char *) buf;
1655 /* Parse string S as an integer, using decimal radix by default,
1656 but allowing octal and hex numbers as in C. */
1657 /* From `od' by Richard Stallman. */
1659 static long
1660 integer_arg (const char *s)
1662 long value;
1663 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1665 error (0, 0, _("invalid integer argument `%s'"), s);
1666 usage (1);
1668 return value;