Add tests with filenames containing newline and backslash characters.
[coreutils.git] / src / stty.c
blob268c87a1b5439ffebcfbc043477e135a146a8538
1 /* stty -- change and print terminal line settings
2 Copyright (C) 90,91,92,93,94,95,96,97,1998 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] [-F device] [--file=device] [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.
23 -F, --file Open and use the specified device instead of stdin
25 If no args are given, write to stdout the baud rate and settings that
26 have been changed from their defaults. Mode reading and changes
27 are done on the specified device, or stdin if none was specified.
29 David MacKenzie <djm@gnu.ai.mit.edu> */
31 #include <config.h>
33 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
34 # define _XOPEN_SOURCE
35 #endif
37 #include <stdio.h>
38 #include <sys/types.h>
39 #if HAVE_TERMIOS_H
40 # include <termios.h>
41 #endif
42 #ifdef GWINSZ_IN_SYS_IOCTL
43 # include <sys/ioctl.h>
44 #endif
45 #ifdef WINSIZE_IN_PTEM
46 # include <sys/stream.h>
47 # include <sys/ptem.h>
48 #endif
49 #ifdef GWINSZ_IN_SYS_PTY
50 # include <sys/ioctl.h>
51 # include <sys/tty.h>
52 # include <sys/pty.h>
53 #endif
54 #include <getopt.h>
55 #if PROTOTYPES
56 # include <stdarg.h>
57 # define VA_START(args, lastarg) va_start(args, lastarg)
58 #else
59 # include <varargs.h>
60 # define VA_START(args, lastarg) va_start(args)
61 #endif
63 #include "system.h"
64 #include "long-options.h"
65 #include "error.h"
66 #include "xstrtol.h"
68 #ifndef _POSIX_VDISABLE
69 # define _POSIX_VDISABLE ((unsigned char) 0)
70 #endif
72 #define Control(c) ((c) & 0x1f)
73 /* Canonical values for control characters. */
74 #ifndef CINTR
75 # define CINTR Control ('c')
76 #endif
77 #ifndef CQUIT
78 # define CQUIT 28
79 #endif
80 #ifndef CERASE
81 # define CERASE 127
82 #endif
83 #ifndef CKILL
84 # define CKILL Control ('u')
85 #endif
86 #ifndef CEOF
87 # define CEOF Control ('d')
88 #endif
89 #ifndef CEOL
90 # define CEOL _POSIX_VDISABLE
91 #endif
92 #ifndef CSTART
93 # define CSTART Control ('q')
94 #endif
95 #ifndef CSTOP
96 # define CSTOP Control ('s')
97 #endif
98 #ifndef CSUSP
99 # define CSUSP Control ('z')
100 #endif
101 #if defined(VEOL2) && !defined(CEOL2)
102 # define CEOL2 _POSIX_VDISABLE
103 #endif
104 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
105 #if defined(VSUSP) && !defined(VSWTCH)
106 # define VSWTCH VSUSP
107 # define CSWTCH CSUSP
108 #endif
109 #if defined(VSWTCH) && !defined(CSWTCH)
110 # define CSWTCH _POSIX_VDISABLE
111 #endif
113 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
114 So the default is to disable `swtch.' */
115 #if defined (__sparc__) && defined (__svr4__)
116 # undef CSWTCH
117 # define CSWTCH _POSIX_VDISABLE
118 #endif
120 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
121 # define VWERASE VWERSE
122 #endif
123 #if defined(VDSUSP) && !defined (CDSUSP)
124 # define CDSUSP Control ('y')
125 #endif
126 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
127 # define VREPRINT VRPRNT
128 #endif
129 #if defined(VREPRINT) && !defined(CRPRNT)
130 # define CRPRNT Control ('r')
131 #endif
132 #if defined(VWERASE) && !defined(CWERASE)
133 # define CWERASE Control ('w')
134 #endif
135 #if defined(VLNEXT) && !defined(CLNEXT)
136 # define CLNEXT Control ('v')
137 #endif
138 #if defined(VDISCARD) && !defined(VFLUSHO)
139 # define VFLUSHO VDISCARD
140 #endif
141 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
142 # define VFLUSHO VFLUSH
143 #endif
144 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
145 # define ECHOCTL CTLECH
146 #endif
147 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
148 # define ECHOCTL TCTLECH
149 #endif
150 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
151 # define ECHOKE CRTKIL
152 #endif
153 #if defined(VFLUSHO) && !defined(CFLUSHO)
154 # define CFLUSHO Control ('o')
155 #endif
156 #if defined(VSTATUS) && !defined(CSTATUS)
157 # define CSTATUS Control ('t')
158 #endif
160 /* Which speeds to set. */
161 enum speed_setting
163 input_speed, output_speed, both_speeds
166 /* What to output and how. */
167 enum output_type
169 changed, all, recoverable /* Default, -a, -g. */
172 /* Which member(s) of `struct termios' a mode uses. */
173 enum mode_type
175 control, input, output, local, combination
178 /* Flags for `struct mode_info'. */
179 #define SANE_SET 1 /* Set in `sane' mode. */
180 #define SANE_UNSET 2 /* Unset in `sane' mode. */
181 #define REV 4 /* Can be turned off by prepending `-'. */
182 #define OMIT 8 /* Don't display value. */
184 /* Each mode. */
185 struct mode_info
187 const char *name; /* Name given on command line. */
188 enum mode_type type; /* Which structure element to change. */
189 char flags; /* Setting and display options. */
190 unsigned long bits; /* Bits to set for this mode. */
191 unsigned long mask; /* Other bits to turn off for this mode. */
194 static struct mode_info mode_info[] =
196 {"parenb", control, REV, PARENB, 0},
197 {"parodd", control, REV, PARODD, 0},
198 {"cs5", control, 0, CS5, CSIZE},
199 {"cs6", control, 0, CS6, CSIZE},
200 {"cs7", control, 0, CS7, CSIZE},
201 {"cs8", control, 0, CS8, CSIZE},
202 {"hupcl", control, REV, HUPCL, 0},
203 {"hup", control, REV | OMIT, HUPCL, 0},
204 {"cstopb", control, REV, CSTOPB, 0},
205 {"cread", control, SANE_SET | REV, CREAD, 0},
206 {"clocal", control, REV, CLOCAL, 0},
207 #ifdef CRTSCTS
208 {"crtscts", control, REV, CRTSCTS, 0},
209 #endif
211 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
212 {"brkint", input, SANE_SET | REV, BRKINT, 0},
213 {"ignpar", input, REV, IGNPAR, 0},
214 {"parmrk", input, REV, PARMRK, 0},
215 {"inpck", input, REV, INPCK, 0},
216 {"istrip", input, REV, ISTRIP, 0},
217 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
218 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
219 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
220 {"ixon", input, REV, IXON, 0},
221 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
222 {"tandem", input, REV | OMIT, IXOFF, 0},
223 #ifdef IUCLC
224 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
225 #endif
226 #ifdef IXANY
227 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
228 #endif
229 #ifdef IMAXBEL
230 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
231 #endif
233 {"opost", output, SANE_SET | REV, OPOST, 0},
234 #ifdef OLCUC
235 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
236 #endif
237 #ifdef OCRNL
238 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
239 #endif
240 #ifdef ONLCR
241 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
242 #endif
243 #ifdef ONOCR
244 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
245 #endif
246 #ifdef ONLRET
247 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
248 #endif
249 #ifdef OFILL
250 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
251 #endif
252 #ifdef OFDEL
253 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
254 #endif
255 #ifdef NLDLY
256 {"nl1", output, SANE_UNSET, NL1, NLDLY},
257 {"nl0", output, SANE_SET, NL0, NLDLY},
258 #endif
259 #ifdef CRDLY
260 {"cr3", output, SANE_UNSET, CR3, CRDLY},
261 {"cr2", output, SANE_UNSET, CR2, CRDLY},
262 {"cr1", output, SANE_UNSET, CR1, CRDLY},
263 {"cr0", output, SANE_SET, CR0, CRDLY},
264 #endif
265 #ifdef TABDLY
266 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
267 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
268 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
269 {"tab0", output, SANE_SET, TAB0, TABDLY},
270 #else
271 # ifdef OXTABS
272 {"tab3", output, SANE_UNSET, OXTABS, 0},
273 # endif
274 #endif
275 #ifdef BSDLY
276 {"bs1", output, SANE_UNSET, BS1, BSDLY},
277 {"bs0", output, SANE_SET, BS0, BSDLY},
278 #endif
279 #ifdef VTDLY
280 {"vt1", output, SANE_UNSET, VT1, VTDLY},
281 {"vt0", output, SANE_SET, VT0, VTDLY},
282 #endif
283 #ifdef FFDLY
284 {"ff1", output, SANE_UNSET, FF1, FFDLY},
285 {"ff0", output, SANE_SET, FF0, FFDLY},
286 #endif
288 {"isig", local, SANE_SET | REV, ISIG, 0},
289 {"icanon", local, SANE_SET | REV, ICANON, 0},
290 #ifdef IEXTEN
291 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
292 #endif
293 {"echo", local, SANE_SET | REV, ECHO, 0},
294 {"echoe", local, SANE_SET | REV, ECHOE, 0},
295 {"crterase", local, REV | OMIT, ECHOE, 0},
296 {"echok", local, SANE_SET | REV, ECHOK, 0},
297 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
298 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
299 #ifdef XCASE
300 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
301 #endif
302 #ifdef TOSTOP
303 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
304 #endif
305 #ifdef ECHOPRT
306 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
307 {"prterase", local, REV | OMIT, ECHOPRT, 0},
308 #endif
309 #ifdef ECHOCTL
310 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
311 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
312 #endif
313 #ifdef ECHOKE
314 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
315 {"crtkill", local, REV | OMIT, ECHOKE, 0},
316 #endif
318 {"evenp", combination, REV | OMIT, 0, 0},
319 {"parity", combination, REV | OMIT, 0, 0},
320 {"oddp", combination, REV | OMIT, 0, 0},
321 {"nl", combination, REV | OMIT, 0, 0},
322 {"ek", combination, OMIT, 0, 0},
323 {"sane", combination, OMIT, 0, 0},
324 {"cooked", combination, REV | OMIT, 0, 0},
325 {"raw", combination, REV | OMIT, 0, 0},
326 {"pass8", combination, REV | OMIT, 0, 0},
327 {"litout", combination, REV | OMIT, 0, 0},
328 {"cbreak", combination, REV | OMIT, 0, 0},
329 #ifdef IXANY
330 {"decctlq", combination, REV | OMIT, 0, 0},
331 #endif
332 #if defined (TABDLY) || defined (OXTABS)
333 {"tabs", combination, REV | OMIT, 0, 0},
334 #endif
335 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
336 {"lcase", combination, REV | OMIT, 0, 0},
337 {"LCASE", combination, REV | OMIT, 0, 0},
338 #endif
339 {"crt", combination, OMIT, 0, 0},
340 {"dec", combination, OMIT, 0, 0},
342 {NULL, control, 0, 0, 0}
345 /* Control character settings. */
346 struct control_info
348 const char *name; /* Name given on command line. */
349 unsigned char saneval; /* Value to set for `stty sane'. */
350 int offset; /* Offset in c_cc. */
353 /* Control characters. */
355 static struct control_info control_info[] =
357 {"intr", CINTR, VINTR},
358 {"quit", CQUIT, VQUIT},
359 {"erase", CERASE, VERASE},
360 {"kill", CKILL, VKILL},
361 {"eof", CEOF, VEOF},
362 {"eol", CEOL, VEOL},
363 #ifdef VEOL2
364 {"eol2", CEOL2, VEOL2},
365 #endif
366 #ifdef VSWTCH
367 {"swtch", CSWTCH, VSWTCH},
368 #endif
369 {"start", CSTART, VSTART},
370 {"stop", CSTOP, VSTOP},
371 {"susp", CSUSP, VSUSP},
372 #ifdef VDSUSP
373 {"dsusp", CDSUSP, VDSUSP},
374 #endif
375 #ifdef VREPRINT
376 {"rprnt", CRPRNT, VREPRINT},
377 #endif
378 #ifdef VWERASE
379 {"werase", CWERASE, VWERASE},
380 #endif
381 #ifdef VLNEXT
382 {"lnext", CLNEXT, VLNEXT},
383 #endif
384 #ifdef VFLUSHO
385 {"flush", CFLUSHO, VFLUSHO},
386 #endif
387 #ifdef VSTATUS
388 {"status", CSTATUS, VSTATUS},
389 #endif
391 /* These must be last because of the display routines. */
392 {"min", 1, VMIN},
393 {"time", 0, VTIME},
394 {NULL, 0, 0}
397 static const char *visible PARAMS ((unsigned int ch));
398 static unsigned long baud_to_value PARAMS ((speed_t speed));
399 static int recover_mode PARAMS ((char *arg, struct termios *mode));
400 static int screen_columns PARAMS ((void));
401 static int set_mode PARAMS ((struct mode_info *info, int reversed,
402 struct termios *mode));
403 static long integer_arg PARAMS ((const char *s));
404 static speed_t string_to_baud PARAMS ((const char *arg));
405 static tcflag_t *mode_type_flag PARAMS ((enum mode_type type,
406 struct termios *mode));
407 static void display_all PARAMS ((struct termios *mode, int fd,
408 const char *device_name));
409 static void display_changed PARAMS ((struct termios *mode));
410 static void display_recoverable PARAMS ((struct termios *mode));
411 static void display_settings PARAMS ((enum output_type output_type,
412 struct termios *mode, int fd,
413 const char *device_name));
414 static void display_speed PARAMS ((struct termios *mode, int fancy));
415 static void display_window_size PARAMS ((int fancy, int fd,
416 const char *device_name));
417 static void sane_mode PARAMS ((struct termios *mode));
418 static void set_control_char PARAMS ((struct control_info *info,
419 const char *arg,
420 struct termios *mode));
421 static void set_speed PARAMS ((enum speed_setting type, const char *arg,
422 struct termios *mode));
423 static void set_window_size PARAMS ((int rows, int cols, int fd,
424 const char *device_name));
426 /* The width of the screen, for output wrapping. */
427 static int max_col;
429 /* Current position, to know when to wrap. */
430 static int current_col;
432 static struct option longopts[] =
434 {"all", no_argument, NULL, 'a'},
435 {"save", no_argument, NULL, 'g'},
436 {"file", required_argument, NULL, 'F'},
437 {NULL, 0, NULL, 0}
440 /* The name this program was run with. */
441 char *program_name;
443 /* Print format string MESSAGE and optional args.
444 Wrap to next line first if it won't fit.
445 Print a space first unless MESSAGE will start a new line. */
447 /* VARARGS */
448 static void
449 #if PROTOTYPES
450 wrapf (const char *message,...)
451 #else
452 wrapf (message, va_alist)
453 const char *message;
454 va_dcl
455 #endif
457 va_list args;
458 char buf[1024]; /* Plenty long for our needs. */
459 int buflen;
461 VA_START (args, message);
462 vsprintf (buf, message, args);
463 va_end (args);
464 buflen = strlen (buf);
465 if (current_col + (current_col > 0) + buflen >= max_col)
467 putchar ('\n');
468 current_col = 0;
470 if (current_col > 0)
472 putchar (' ');
473 current_col++;
475 fputs (buf, stdout);
476 current_col += buflen;
479 static void
480 usage (int status)
482 if (status != 0)
483 fprintf (stderr, _("Try `%s --help' for more information.\n"),
484 program_name);
485 else
487 printf (_("\
488 Usage: %s [-F device] [--file=device] [SETTING]...\n\
489 or: %s [-F device] [--file=device] [-a|--all]\n\
490 or: %s [-F device] [--file=device] [-g|--save]\n\
492 program_name, program_name, program_name);
493 printf (_("\
494 Print or change terminal characteristics.\n\
496 -a, --all print all current settings in human-readable form\n\
497 -g, --save print all current settings in a stty-readable form\n\
498 -F, --file open and use the specified device instead of stdin\n\
499 --help display this help and exit\n\
500 --version output version information and exit\n\
502 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
503 settings. The underlying system defines which settings are available.\n\
504 "));
505 printf (_("\
507 Special characters:\n\
508 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
509 eof CHAR CHAR will send an end of file (terminate the input)\n\
510 eol CHAR CHAR will end the line\n\
511 * eol2 CHAR alternate CHAR for ending the line\n\
512 erase CHAR CHAR will erase the last character typed\n\
513 intr CHAR CHAR will send an interrupt signal\n\
514 kill CHAR CHAR will erase the current line\n\
515 * lnext CHAR CHAR will enter the next character quoted\n\
516 quit CHAR CHAR will send a quit signal\n\
517 * rprnt CHAR CHAR will redraw the current line\n\
518 start CHAR CHAR will restart the output after stopping it\n\
519 stop CHAR CHAR will stop the output\n\
520 susp CHAR CHAR will send a terminal stop signal\n\
521 * swtch CHAR CHAR will switch to a different shell layer\n\
522 * werase CHAR CHAR will erase the last word typed\n\
523 "));
524 printf (_("\
526 Special settings:\n\
527 N set the input and output speeds to N bauds\n\
528 * cols N tell the kernel that the terminal has N columns\n\
529 * columns N same as cols N\n\
530 ispeed N set the input speed to N\n\
531 * line N use line discipline N\n\
532 min N with -icanon, set N characters minimum for a completed read\n\
533 ospeed N set the output speed to N\n\
534 * rows N tell the kernel that the terminal has N rows\n\
535 * size print the number of rows and columns according to the kernel\n\
536 speed print the terminal speed\n\
537 time N with -icanon, set read timeout of N tenths of a second\n\
538 "));
539 printf (_("\
541 Control settings:\n\
542 [-]clocal disable modem control signals\n\
543 [-]cread allow input to be received\n\
544 * [-]crtscts enable RTS/CTS handshaking\n\
545 csN set character size to N bits, N in [5..8]\n\
546 [-]cstopb use two stop bits per character (one with `-')\n\
547 [-]hup send a hangup signal when the last process closes the tty\n\
548 [-]hupcl same as [-]hup\n\
549 [-]parenb generate parity bit in output and expect parity bit in input\n\
550 [-]parodd set odd parity (even with `-')\n\
551 "));
552 printf (_("\
554 Input settings:\n\
555 [-]brkint breaks cause an interrupt signal\n\
556 [-]icrnl translate carriage return to newline\n\
557 [-]ignbrk ignore break characters\n\
558 [-]igncr ignore carriage return\n\
559 [-]ignpar ignore characters with parity errors\n\
560 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
561 [-]inlcr translate newline to carriage return\n\
562 [-]inpck enable input parity checking\n\
563 [-]istrip clear high (8th) bit of input characters\n\
564 * [-]iuclc translate uppercase characters to lowercase\n\
565 * [-]ixany let any character restart output, not only start character\n\
566 [-]ixoff enable sending of start/stop characters\n\
567 [-]ixon enable XON/XOFF flow control\n\
568 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
569 [-]tandem same as [-]ixoff\n\
570 "));
571 printf (_("\
573 Output settings:\n\
574 * bsN backspace delay style, N in [0..1]\n\
575 * crN carriage return delay style, N in [0..3]\n\
576 * ffN form feed delay style, N in [0..1]\n\
577 * nlN newline delay style, N in [0..1]\n\
578 * [-]ocrnl translate carriage return to newline\n\
579 * [-]ofdel use delete characters for fill instead of null characters\n\
580 * [-]ofill use fill (padding) characters instead of timing for delays\n\
581 * [-]olcuc translate lowercase characters to uppercase\n\
582 * [-]onlcr translate newline to carriage return-newline\n\
583 * [-]onlret newline performs a carriage return\n\
584 * [-]onocr do not print carriage returns in the first column\n\
585 [-]opost postprocess output\n\
586 * tabN horizontal tab delay style, N in [0..3]\n\
587 * tabs same as tab0\n\
588 * -tabs same as tab3\n\
589 * vtN vertical tab delay style, N in [0..1]\n\
590 "));
591 printf (_("\
593 Local settings:\n\
594 [-]crterase echo erase characters as backspace-space-backspace\n\
595 * crtkill kill all line by obeying the echoprt and echoe settings\n\
596 * -crtkill kill all line by obeying the echoctl and echok settings\n\
597 * [-]ctlecho echo control characters in hat notation (`^c')\n\
598 [-]echo echo input characters\n\
599 * [-]echoctl same as [-]ctlecho\n\
600 [-]echoe same as [-]crterase\n\
601 [-]echok echo a newline after a kill character\n\
602 * [-]echoke same as [-]crtkill\n\
603 [-]echonl echo newline even if not echoing other characters\n\
604 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
605 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
606 [-]iexten enable non-POSIX special characters\n\
607 [-]isig enable interrupt, quit, and suspend special characters\n\
608 [-]noflsh disable flushing after interrupt and quit special characters\n\
609 * [-]prterase same as [-]echoprt\n\
610 * [-]tostop stop background jobs that try to write to the terminal\n\
611 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
612 "));
613 printf (_("\
615 Combination settings:\n\
616 * [-]LCASE same as [-]lcase\n\
617 cbreak same as -icanon\n\
618 -cbreak same as icanon\n\
619 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
620 icanon, eof and eol characters to their default values\n\
621 -cooked same as raw\n\
622 crt same as echoe echoctl echoke\n\
623 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
624 kill ^u\n\
625 * [-]decctlq same as [-]ixany\n\
626 ek erase and kill characters to their default values\n\
627 evenp same as parenb -parodd cs7\n\
628 -evenp same as -parenb cs8\n\
629 * [-]lcase same as xcase iuclc olcuc\n\
630 litout same as -parenb -istrip -opost cs8\n\
631 -litout same as parenb istrip opost cs7\n\
632 nl same as -icrnl -onlcr\n\
633 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
634 oddp same as parenb parodd cs7\n\
635 -oddp same as -parenb cs8\n\
636 [-]parity same as [-]evenp\n\
637 pass8 same as -parenb -istrip cs8\n\
638 -pass8 same as parenb istrip cs7\n\
639 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
640 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
641 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
642 -raw same as cooked\n\
643 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
644 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
645 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
646 isig icanon iexten echo echoe echok -echonl -noflsh\n\
647 -xcase -tostop -echoprt echoctl echoke, all special\n\
648 characters to their default values.\n\
649 "));
650 printf (_("\
652 Handle the tty line connected to standard input. Without arguments,\n\
653 prints baud rate, line discipline, and deviations from stty sane. In\n\
654 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
655 127; special values ^- or undef used to disable special characters.\n\
656 "));
657 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
659 exit (status);
662 /* Return 1 if the string contains only valid options. */
664 valid_options (char *opt, const char *valid_opts,
665 const char *valid_arg_opts)
667 char ch;
669 if (*opt++ != '-')
670 return 0;
672 while ((ch = *opt))
674 opt++;
675 if (strchr (valid_opts, ch))
676 continue;
677 if (strchr (valid_arg_opts, ch))
678 return 1;
679 return 0;
681 return 1;
685 main (int argc, char **argv)
687 struct termios mode;
688 enum output_type output_type;
689 int optc;
690 int require_set_attr;
691 int speed_was_set;
692 int verbose_output;
693 int recoverable_output;
694 int k;
695 int noargs = 1;
696 char *file_name = NULL;
697 int fd;
698 const char *device_name;
699 const char *posixly_correct = getenv ("POSIXLY_CORRECT");
700 int invalid_long_option = 0;
702 program_name = argv[0];
703 setlocale (LC_ALL, "");
704 bindtextdomain (PACKAGE, LOCALEDIR);
705 textdomain (PACKAGE);
707 parse_long_options (argc, argv, "stty", GNU_PACKAGE, VERSION, usage);
709 output_type = changed;
710 verbose_output = 0;
711 recoverable_output = 0;
713 /* Don't print error messages for unrecognized options. */
714 opterr = 0;
716 while ((optc = getopt_long (argc, argv, "agF:", longopts, NULL)) != -1)
718 int unrecognized_option = 0;
719 switch (optc)
721 case 'a':
722 verbose_output = 1;
723 output_type = all;
724 break;
726 case 'g':
727 recoverable_output = 1;
728 output_type = recoverable;
729 break;
731 case 'F':
732 if (file_name)
733 error (2, 0, _("only one device may be specified"));
734 file_name = optarg;
735 break;
737 default:
738 unrecognized_option = 1;
739 break;
742 if (unrecognized_option)
743 break;
746 /* FIXME: what is this?!? */
747 if (invalid_long_option)
748 usage (1);
750 /* Clear out the options that have been parsed. This is really
751 gross, but it's needed because stty SETTINGS look like options to
752 getopt(), so we need to work around things in a really horrible
753 way. If any new options are ever added to stty, the short option
754 MUST NOT be a letter which is the first letter of one of the
755 possible stty settings. If you change anything about how stty
756 parses options, be sure it still works with combinations of
757 short and long options, --, POSIXLY_CORRECT, etc. */
758 for (k = 1; k < argc; k++)
760 size_t len;
761 char *eq;
763 if (argv[k] == NULL)
764 continue;
766 /* Handle --, and reset noargs if there are arguments following it. */
767 if (STREQ (argv[k], "--"))
769 argv[k] = NULL;
770 if (k < argc - 1)
771 noargs = 0;
772 break;
775 /* Handle "--file device" */
776 len = strlen (argv[k]);
777 if (len >= 3 && strstr ("--file", argv[k]))
779 argv[k] = NULL;
780 argv[k + 1] = NULL;
781 continue;
784 /* Handle "--all" and "--save". */
785 if (len >= 3
786 && (strstr ("--all", argv[k])
787 || strstr ("--save", argv[k])))
789 argv[k] = NULL;
790 continue;
793 /* Handle "--file=device". */
794 eq = strchr (argv[k], '=');
795 if (eq && eq - argv[k] >= 3)
797 *eq = '\0';
798 if (strstr ("--file", argv[k]))
800 argv[k] = NULL;
801 continue;
803 /* Put the equals sign back for the error message. */
804 *eq = '=';
807 /* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc. */
808 if (valid_options (argv[k], "ag", "F"))
810 /* FIXME: this loses when the device name ends in `F'.
811 e.g. `stty -F/dev/BARF nl' would clobber the `nl' argument. */
812 if (argv[k][strlen (argv[k]) - 1] == 'F')
813 argv[k + 1] = NULL;
814 argv[k] = NULL;
816 /* Everything else must be a normal, non-option argument. */
817 else
819 noargs = 0;
820 if (posixly_correct)
821 break;
825 /* Specifying both -a and -g gets an error. */
826 if (verbose_output && recoverable_output)
827 error (2, 0,
828 _("the options for verbose and stty-readable output styles are\n\
829 mutually exclusive"));
831 /* Specifying any other arguments with -a or -g gets an error. */
832 if (!noargs && (verbose_output || recoverable_output))
833 error (2, 0, _("when specifying an output style, modes may not be set"));
835 /* FIXME: it'd be better not to open the file until we've verified
836 that all arguments are valid. Otherwise, we could end up doing
837 only some of the requested operations and then failing, probably
838 leaving things in an undesirable state. */
840 if (file_name)
842 int fdflags;
843 device_name = file_name;
844 fd = open (device_name, O_RDONLY | O_NONBLOCK);
845 if (fd < 0)
846 error (1, errno, "%s", device_name);
847 if ((fdflags = fcntl (fd, F_GETFL)) == -1
848 || fcntl (fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
849 error (1, errno, _("%s: couldn't reset non-blocking mode"),
850 device_name);
852 else
854 fd = 0;
855 device_name = _("standard input");
858 /* Initialize to all zeroes so there is no risk memcmp will report a
859 spurious difference in an uninitialized portion of the structure. */
860 memset (&mode, 0, sizeof (mode));
861 if (tcgetattr (fd, &mode))
862 error (1, errno, "%s", device_name);
864 if (verbose_output || recoverable_output || noargs)
866 max_col = screen_columns ();
867 current_col = 0;
868 display_settings (output_type, &mode, fd, device_name);
869 exit (0);
872 speed_was_set = 0;
873 require_set_attr = 0;
874 k = 1;
875 while (k < argc)
877 int match_found = 0;
878 int reversed = 0;
879 int i;
881 if (argv[k] == 0)
883 k++;
884 continue;
887 if (argv[k][0] == '-')
889 ++argv[k];
890 reversed = 1;
892 for (i = 0; mode_info[i].name != NULL; ++i)
894 if (STREQ (argv[k], mode_info[i].name))
896 match_found = set_mode (&mode_info[i], reversed, &mode);
897 require_set_attr = 1;
898 break;
901 if (match_found == 0 && reversed)
903 error (0, 0, _("invalid argument `%s'"), --argv[k]);
904 usage (1);
906 if (match_found == 0)
908 for (i = 0; control_info[i].name != NULL; ++i)
910 if (STREQ (argv[k], control_info[i].name))
912 if (k == argc - 1)
914 error (0, 0, _("missing argument to `%s'"), argv[k]);
915 usage (1);
917 match_found = 1;
918 ++k;
919 set_control_char (&control_info[i], argv[k], &mode);
920 require_set_attr = 1;
921 break;
925 if (match_found == 0)
927 if (STREQ (argv[k], "ispeed"))
929 if (k == argc - 1)
931 error (0, 0, _("missing argument to `%s'"), argv[k]);
932 usage (1);
934 ++k;
935 set_speed (input_speed, argv[k], &mode);
936 speed_was_set = 1;
937 require_set_attr = 1;
939 else if (STREQ (argv[k], "ospeed"))
941 if (k == argc - 1)
943 error (0, 0, _("missing argument to `%s'"), argv[k]);
944 usage (1);
946 ++k;
947 set_speed (output_speed, argv[k], &mode);
948 speed_was_set = 1;
949 require_set_attr = 1;
951 #ifdef TIOCGWINSZ
952 else if (STREQ (argv[k], "rows"))
954 if (k == argc - 1)
956 error (0, 0, _("missing argument to `%s'"), argv[k]);
957 usage (1);
959 ++k;
960 set_window_size ((int) integer_arg (argv[k]), -1,
961 fd, device_name);
963 else if (STREQ (argv[k], "cols")
964 || STREQ (argv[k], "columns"))
966 if (k == argc - 1)
968 error (0, 0, _("missing argument to `%s'"), argv[k]);
969 usage (1);
971 ++k;
972 set_window_size (-1, (int) integer_arg (argv[k]),
973 fd, device_name);
975 else if (STREQ (argv[k], "size"))
977 max_col = screen_columns ();
978 current_col = 0;
979 display_window_size (0, fd, device_name);
981 #endif
982 #ifdef HAVE_C_LINE
983 else if (STREQ (argv[k], "line"))
985 if (k == argc - 1)
987 error (0, 0, _("missing argument to `%s'"), argv[k]);
988 usage (1);
990 ++k;
991 mode.c_line = integer_arg (argv[k]);
992 require_set_attr = 1;
994 #endif
995 else if (STREQ (argv[k], "speed"))
997 max_col = screen_columns ();
998 display_speed (&mode, 0);
1000 else if (string_to_baud (argv[k]) != (speed_t) -1)
1002 set_speed (both_speeds, argv[k], &mode);
1003 speed_was_set = 1;
1004 require_set_attr = 1;
1006 else
1008 if (recover_mode (argv[k], &mode) == 0)
1010 error (0, 0, _("invalid argument `%s'"), argv[k]);
1011 usage (1);
1013 require_set_attr = 1;
1016 k++;
1019 if (require_set_attr)
1021 struct termios new_mode;
1023 if (tcsetattr (fd, TCSADRAIN, &mode))
1024 error (1, errno, "%s", device_name);
1026 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1027 it performs *any* of the requested operations. This means it
1028 can report `success' when it has actually failed to perform
1029 some proper subset of the requested operations. To detect
1030 this partial failure, get the current terminal attributes and
1031 compare them to the requested ones. */
1033 /* Initialize to all zeroes so there is no risk memcmp will report a
1034 spurious difference in an uninitialized portion of the structure. */
1035 memset (&new_mode, 0, sizeof (new_mode));
1036 if (tcgetattr (fd, &new_mode))
1037 error (1, errno, "%s", device_name);
1039 /* Normally, one shouldn't use memcmp to compare structures that
1040 may have `holes' containing uninitialized data, but we have been
1041 careful to initialize the storage of these two variables to all
1042 zeroes. One might think it more efficient simply to compare the
1043 modified fields, but that would require enumerating those fields --
1044 and not all systems have the same fields in this structure. */
1046 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1048 #ifdef CIBAUD
1049 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1050 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1051 sometimes (m1 != m2). The only difference is in the four bits
1052 of the c_cflag field corresponding to the baud rate. To save
1053 Sun users a little confusion, don't report an error if this
1054 happens. But suppress the error only if we haven't tried to
1055 set the baud rate explicitly -- otherwise we'd never give an
1056 error for a true failure to set the baud rate. */
1058 new_mode.c_cflag &= (~CIBAUD);
1059 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1060 #endif
1062 size_t i;
1063 error (1, 0,
1064 _("%s: unable to perform all requested operations"),
1065 device_name);
1066 printf (_("new_mode: mode\n"));
1067 for (i = 0; i < sizeof (new_mode); i++)
1068 printf ("0x%02x: 0x%02x\n",
1069 *(((unsigned char *) &new_mode) + i),
1070 *(((unsigned char *) &mode) + i));
1075 exit (0);
1078 /* Return 0 if not applied because not reversible; otherwise return 1. */
1080 static int
1081 set_mode (struct mode_info *info, int reversed, struct termios *mode)
1083 tcflag_t *bitsp;
1085 if (reversed && (info->flags & REV) == 0)
1086 return 0;
1088 bitsp = mode_type_flag (info->type, mode);
1090 if (bitsp == NULL)
1092 /* Combination mode. */
1093 if (STREQ (info->name, "evenp") || STREQ (info->name, "parity"))
1095 if (reversed)
1096 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1097 else
1098 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
1100 else if (STREQ (info->name, "oddp"))
1102 if (reversed)
1103 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1104 else
1105 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
1107 else if (STREQ (info->name, "nl"))
1109 if (reversed)
1111 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
1112 mode->c_oflag = (mode->c_oflag
1113 #ifdef ONLCR
1114 | ONLCR
1115 #endif
1117 #ifdef OCRNL
1118 & ~OCRNL
1119 #endif
1120 #ifdef ONLRET
1121 & ~ONLRET
1122 #endif
1125 else
1127 mode->c_iflag = mode->c_iflag & ~ICRNL;
1128 #ifdef ONLCR
1129 mode->c_oflag = mode->c_oflag & ~ONLCR;
1130 #endif
1133 else if (STREQ (info->name, "ek"))
1135 mode->c_cc[VERASE] = CERASE;
1136 mode->c_cc[VKILL] = CKILL;
1138 else if (STREQ (info->name, "sane"))
1139 sane_mode (mode);
1140 else if (STREQ (info->name, "cbreak"))
1142 if (reversed)
1143 mode->c_lflag |= ICANON;
1144 else
1145 mode->c_lflag &= ~ICANON;
1147 else if (STREQ (info->name, "pass8"))
1149 if (reversed)
1151 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1152 mode->c_iflag |= ISTRIP;
1154 else
1156 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1157 mode->c_iflag &= ~ISTRIP;
1160 else if (STREQ (info->name, "litout"))
1162 if (reversed)
1164 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1165 mode->c_iflag |= ISTRIP;
1166 mode->c_oflag |= OPOST;
1168 else
1170 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1171 mode->c_iflag &= ~ISTRIP;
1172 mode->c_oflag &= ~OPOST;
1175 else if (STREQ (info->name, "raw") || STREQ (info->name, "cooked"))
1177 if ((info->name[0] == 'r' && reversed)
1178 || (info->name[0] == 'c' && !reversed))
1180 /* Cooked mode. */
1181 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1182 mode->c_oflag |= OPOST;
1183 mode->c_lflag |= ISIG | ICANON;
1184 #if VMIN == VEOF
1185 mode->c_cc[VEOF] = CEOF;
1186 #endif
1187 #if VTIME == VEOL
1188 mode->c_cc[VEOL] = CEOL;
1189 #endif
1191 else
1193 /* Raw mode. */
1194 mode->c_iflag = 0;
1195 mode->c_oflag &= ~OPOST;
1196 mode->c_lflag &= ~(ISIG | ICANON
1197 #ifdef XCASE
1198 | XCASE
1199 #endif
1201 mode->c_cc[VMIN] = 1;
1202 mode->c_cc[VTIME] = 0;
1205 #ifdef IXANY
1206 else if (STREQ (info->name, "decctlq"))
1208 if (reversed)
1209 mode->c_iflag |= IXANY;
1210 else
1211 mode->c_iflag &= ~IXANY;
1213 #endif
1214 #ifdef TABDLY
1215 else if (STREQ (info->name, "tabs"))
1217 if (reversed)
1218 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1219 else
1220 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1222 #else
1223 # ifdef OXTABS
1224 else if (STREQ (info->name, "tabs"))
1226 if (reversed)
1227 mode->c_oflag = mode->c_oflag | OXTABS;
1228 else
1229 mode->c_oflag = mode->c_oflag & ~OXTABS;
1231 # endif
1232 #endif
1233 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1234 else if (STREQ (info->name, "lcase")
1235 || STREQ (info->name, "LCASE"))
1237 if (reversed)
1239 mode->c_lflag &= ~XCASE;
1240 mode->c_iflag &= ~IUCLC;
1241 mode->c_oflag &= ~OLCUC;
1243 else
1245 mode->c_lflag |= XCASE;
1246 mode->c_iflag |= IUCLC;
1247 mode->c_oflag |= OLCUC;
1250 #endif
1251 else if (STREQ (info->name, "crt"))
1252 mode->c_lflag |= ECHOE
1253 #ifdef ECHOCTL
1254 | ECHOCTL
1255 #endif
1256 #ifdef ECHOKE
1257 | ECHOKE
1258 #endif
1260 else if (STREQ (info->name, "dec"))
1262 mode->c_cc[VINTR] = 3; /* ^C */
1263 mode->c_cc[VERASE] = 127; /* DEL */
1264 mode->c_cc[VKILL] = 21; /* ^U */
1265 mode->c_lflag |= ECHOE
1266 #ifdef ECHOCTL
1267 | ECHOCTL
1268 #endif
1269 #ifdef ECHOKE
1270 | ECHOKE
1271 #endif
1273 #ifdef IXANY
1274 mode->c_iflag &= ~IXANY;
1275 #endif
1278 else if (reversed)
1279 *bitsp = *bitsp & ~info->mask & ~info->bits;
1280 else
1281 *bitsp = (*bitsp & ~info->mask) | info->bits;
1283 return 1;
1286 static void
1287 set_control_char (struct control_info *info, const char *arg,
1288 struct termios *mode)
1290 unsigned char value;
1292 if (STREQ (info->name, "min") || STREQ (info->name, "time"))
1293 value = integer_arg (arg);
1294 else if (arg[0] == '\0' || arg[1] == '\0')
1295 value = arg[0];
1296 else if (STREQ (arg, "^-") || STREQ (arg, "undef"))
1297 value = _POSIX_VDISABLE;
1298 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1300 if (arg[1] == '?')
1301 value = 127;
1302 else
1303 value = arg[1] & ~0140; /* Non-letters get weird results. */
1305 else
1306 value = integer_arg (arg);
1307 mode->c_cc[info->offset] = value;
1310 static void
1311 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1313 speed_t baud;
1315 baud = string_to_baud (arg);
1316 if (type == input_speed || type == both_speeds)
1317 cfsetispeed (mode, baud);
1318 if (type == output_speed || type == both_speeds)
1319 cfsetospeed (mode, baud);
1322 #ifdef TIOCGWINSZ
1324 static int
1325 get_win_size (int fd, struct winsize *win)
1327 int err = ioctl (fd, TIOCGWINSZ, (char *) win);
1328 return err;
1331 static void
1332 set_window_size (int rows, int cols, int fd, const char *device_name)
1334 struct winsize win;
1336 if (get_win_size (fd, &win))
1338 if (errno != EINVAL)
1339 error (1, errno, "%s", device_name);
1340 memset (&win, 0, sizeof (win));
1343 if (rows >= 0)
1344 win.ws_row = rows;
1345 if (cols >= 0)
1346 win.ws_col = cols;
1348 # ifdef TIOCSSIZE
1349 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1350 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1351 This comment from sys/ttold.h describes Sun's twisted logic - a better
1352 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1353 At any rate, the problem is gone in Solaris 2.x.
1355 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1356 but they can be disambiguated by checking whether a "struct ttysize"
1357 structure's "ts_lines" field is greater than 64K or not. If so,
1358 it's almost certainly a "struct winsize" instead.
1360 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1361 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1362 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1363 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1364 "stty cols 0 rows 0" would do the right thing. On a little-endian
1365 machine like the sun386i, the problem is the same, but for ws_col == 0.
1367 The workaround is to do the ioctl once with row and col = 1 to set the
1368 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1370 if (win.ws_row == 0 || win.ws_col == 0)
1372 struct ttysize ttysz;
1374 ttysz.ts_lines = win.ws_row;
1375 ttysz.ts_cols = win.ws_col;
1377 win.ws_row = 1;
1378 win.ws_col = 1;
1380 if (ioctl (fd, TIOCSWINSZ, (char *) &win))
1381 error (1, errno, "%s", device_name);
1383 if (ioctl (fd, TIOCSSIZE, (char *) &ttysz))
1384 error (1, errno, "%s", device_name);
1385 return;
1387 # endif
1389 if (ioctl (fd, TIOCSWINSZ, (char *) &win))
1390 error (1, errno, "%s", device_name);
1393 static void
1394 display_window_size (int fancy, int fd, const char *device_name)
1396 struct winsize win;
1398 if (get_win_size (fd, &win))
1400 if (errno != EINVAL)
1401 error (1, errno, "%s", device_name);
1402 if (!fancy)
1403 error (1, 0, _("%s: no size information for this device"), device_name);
1405 else
1407 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1408 win.ws_row, win.ws_col);
1409 if (!fancy)
1410 current_col = 0;
1413 #endif
1415 static int
1416 screen_columns (void)
1418 #ifdef TIOCGWINSZ
1419 struct winsize win;
1421 /* With Solaris 2.[123], this ioctl fails and errno is set to
1422 EINVAL for telnet (but not rlogin) sessions.
1423 On ISC 3.0, it fails for the console and the serial port
1424 (but it works for ptys).
1425 It can also fail on any system when stdout isn't a tty.
1426 In case of any failure, just use the default. */
1427 if (get_win_size (STDOUT_FILENO, &win) == 0 && win.ws_col > 0)
1428 return win.ws_col;
1429 #endif
1430 /* FIXME: use xstrtol */
1431 if (getenv ("COLUMNS"))
1432 return atoi (getenv ("COLUMNS"));
1433 return 80;
1436 static tcflag_t *
1437 mode_type_flag (enum mode_type type, struct termios *mode)
1439 switch (type)
1441 case control:
1442 return &mode->c_cflag;
1444 case input:
1445 return &mode->c_iflag;
1447 case output:
1448 return &mode->c_oflag;
1450 case local:
1451 return &mode->c_lflag;
1453 case combination:
1454 return NULL;
1456 default:
1457 abort ();
1461 static void
1462 display_settings (enum output_type output_type, struct termios *mode,
1463 int fd, const char *device_name)
1465 switch (output_type)
1467 case changed:
1468 display_changed (mode);
1469 break;
1471 case all:
1472 display_all (mode, fd, device_name);
1473 break;
1475 case recoverable:
1476 display_recoverable (mode);
1477 break;
1481 static void
1482 display_changed (struct termios *mode)
1484 int i;
1485 int empty_line;
1486 tcflag_t *bitsp;
1487 unsigned long mask;
1488 enum mode_type prev_type = control;
1490 display_speed (mode, 1);
1491 #ifdef HAVE_C_LINE
1492 wrapf ("line = %d;", mode->c_line);
1493 #endif
1494 putchar ('\n');
1495 current_col = 0;
1497 empty_line = 1;
1498 for (i = 0; !STREQ (control_info[i].name, "min"); ++i)
1500 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1501 continue;
1502 /* If swtch is the same as susp, don't print both. */
1503 #if VSWTCH == VSUSP
1504 if (STREQ (control_info[i].name, "swtch"))
1505 continue;
1506 #endif
1507 /* If eof uses the same slot as min, only print whichever applies. */
1508 #if VEOF == VMIN
1509 if ((mode->c_lflag & ICANON) == 0
1510 && (STREQ (control_info[i].name, "eof")
1511 || STREQ (control_info[i].name, "eol")))
1512 continue;
1513 #endif
1515 empty_line = 0;
1516 wrapf ("%s = %s;", control_info[i].name,
1517 visible (mode->c_cc[control_info[i].offset]));
1519 if ((mode->c_lflag & ICANON) == 0)
1521 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1522 (int) mode->c_cc[VTIME]);
1524 else if (empty_line == 0)
1525 putchar ('\n');
1526 current_col = 0;
1528 empty_line = 1;
1529 for (i = 0; mode_info[i].name != NULL; ++i)
1531 if (mode_info[i].flags & OMIT)
1532 continue;
1533 if (mode_info[i].type != prev_type)
1535 if (empty_line == 0)
1537 putchar ('\n');
1538 current_col = 0;
1539 empty_line = 1;
1541 prev_type = mode_info[i].type;
1544 bitsp = mode_type_flag (mode_info[i].type, mode);
1545 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1546 if ((*bitsp & mask) == mode_info[i].bits)
1548 if (mode_info[i].flags & SANE_UNSET)
1550 wrapf ("%s", mode_info[i].name);
1551 empty_line = 0;
1554 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1556 wrapf ("-%s", mode_info[i].name);
1557 empty_line = 0;
1560 if (empty_line == 0)
1561 putchar ('\n');
1562 current_col = 0;
1565 static void
1566 display_all (struct termios *mode, int fd, const char *device_name)
1568 int i;
1569 tcflag_t *bitsp;
1570 unsigned long mask;
1571 enum mode_type prev_type = control;
1573 display_speed (mode, 1);
1574 #ifdef TIOCGWINSZ
1575 display_window_size (1, fd, device_name);
1576 #endif
1577 #ifdef HAVE_C_LINE
1578 wrapf ("line = %d;", mode->c_line);
1579 #endif
1580 putchar ('\n');
1581 current_col = 0;
1583 for (i = 0; ! STREQ (control_info[i].name, "min"); ++i)
1585 /* If swtch is the same as susp, don't print both. */
1586 #if VSWTCH == VSUSP
1587 if (STREQ (control_info[i].name, "swtch"))
1588 continue;
1589 #endif
1590 /* If eof uses the same slot as min, only print whichever applies. */
1591 #if VEOF == VMIN
1592 if ((mode->c_lflag & ICANON) == 0
1593 && (STREQ (control_info[i].name, "eof")
1594 || STREQ (control_info[i].name, "eol")))
1595 continue;
1596 #endif
1597 wrapf ("%s = %s;", control_info[i].name,
1598 visible (mode->c_cc[control_info[i].offset]));
1600 #if VEOF == VMIN
1601 if ((mode->c_lflag & ICANON) == 0)
1602 #endif
1603 wrapf ("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1604 if (current_col != 0)
1605 putchar ('\n');
1606 current_col = 0;
1608 for (i = 0; mode_info[i].name != NULL; ++i)
1610 if (mode_info[i].flags & OMIT)
1611 continue;
1612 if (mode_info[i].type != prev_type)
1614 putchar ('\n');
1615 current_col = 0;
1616 prev_type = mode_info[i].type;
1619 bitsp = mode_type_flag (mode_info[i].type, mode);
1620 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1621 if ((*bitsp & mask) == mode_info[i].bits)
1622 wrapf ("%s", mode_info[i].name);
1623 else if (mode_info[i].flags & REV)
1624 wrapf ("-%s", mode_info[i].name);
1626 putchar ('\n');
1627 current_col = 0;
1630 static void
1631 display_speed (struct termios *mode, int fancy)
1633 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1634 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1635 baud_to_value (cfgetospeed (mode)));
1636 else
1637 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1638 baud_to_value (cfgetispeed (mode)),
1639 baud_to_value (cfgetospeed (mode)));
1640 if (!fancy)
1641 current_col = 0;
1644 static void
1645 display_recoverable (struct termios *mode)
1647 int i;
1649 printf ("%lx:%lx:%lx:%lx",
1650 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1651 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1652 for (i = 0; i < NCCS; ++i)
1653 printf (":%x", (unsigned int) mode->c_cc[i]);
1654 putchar ('\n');
1657 static int
1658 recover_mode (char *arg, struct termios *mode)
1660 int i, n;
1661 unsigned int chr;
1662 unsigned long iflag, oflag, cflag, lflag;
1664 /* Scan into temporaries since it is too much trouble to figure out
1665 the right format for `tcflag_t'. */
1666 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1667 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1668 return 0;
1669 mode->c_iflag = iflag;
1670 mode->c_oflag = oflag;
1671 mode->c_cflag = cflag;
1672 mode->c_lflag = lflag;
1673 arg += n;
1674 for (i = 0; i < NCCS; ++i)
1676 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1677 return 0;
1678 mode->c_cc[i] = chr;
1679 arg += n;
1682 /* Fail if there are too many fields. */
1683 if (*arg != '\0')
1684 return 0;
1686 return 1;
1689 struct speed_map
1691 const char *string; /* ASCII representation. */
1692 speed_t speed; /* Internal form. */
1693 unsigned long value; /* Numeric value. */
1696 struct speed_map speeds[] =
1698 {"0", B0, 0},
1699 {"50", B50, 50},
1700 {"75", B75, 75},
1701 {"110", B110, 110},
1702 {"134", B134, 134},
1703 {"134.5", B134, 134},
1704 {"150", B150, 150},
1705 {"200", B200, 200},
1706 {"300", B300, 300},
1707 {"600", B600, 600},
1708 {"1200", B1200, 1200},
1709 {"1800", B1800, 1800},
1710 {"2400", B2400, 2400},
1711 {"4800", B4800, 4800},
1712 {"9600", B9600, 9600},
1713 {"19200", B19200, 19200},
1714 {"38400", B38400, 38400},
1715 {"exta", B19200, 19200},
1716 {"extb", B38400, 38400},
1717 #ifdef B57600
1718 {"57600", B57600, 57600},
1719 #endif
1720 #ifdef B115200
1721 {"115200", B115200, 115200},
1722 #endif
1723 #ifdef B230400
1724 {"230400", B230400, 230400},
1725 #endif
1726 #ifdef B460800
1727 {"460800", B460800, 460800},
1728 #endif
1729 {NULL, 0, 0}
1732 static speed_t
1733 string_to_baud (const char *arg)
1735 int i;
1737 for (i = 0; speeds[i].string != NULL; ++i)
1738 if (STREQ (arg, speeds[i].string))
1739 return speeds[i].speed;
1740 return (speed_t) -1;
1743 static unsigned long
1744 baud_to_value (speed_t speed)
1746 int i;
1748 for (i = 0; speeds[i].string != NULL; ++i)
1749 if (speed == speeds[i].speed)
1750 return speeds[i].value;
1751 return 0;
1754 static void
1755 sane_mode (struct termios *mode)
1757 int i;
1758 tcflag_t *bitsp;
1760 for (i = 0; control_info[i].name; ++i)
1762 #if VMIN == VEOF
1763 if (STREQ (control_info[i].name, "min"))
1764 break;
1765 #endif
1766 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1769 for (i = 0; mode_info[i].name != NULL; ++i)
1771 if (mode_info[i].flags & SANE_SET)
1773 bitsp = mode_type_flag (mode_info[i].type, mode);
1774 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1776 else if (mode_info[i].flags & SANE_UNSET)
1778 bitsp = mode_type_flag (mode_info[i].type, mode);
1779 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1784 /* Return a string that is the printable representation of character CH. */
1785 /* Adapted from `cat' by Torbjorn Granlund. */
1787 static const char *
1788 visible (unsigned int ch)
1790 static char buf[10];
1791 char *bpout = buf;
1793 if (ch == _POSIX_VDISABLE)
1794 return _("<undef>");
1796 if (ch >= 32)
1798 if (ch < 127)
1799 *bpout++ = ch;
1800 else if (ch == 127)
1802 *bpout++ = '^';
1803 *bpout++ = '?';
1805 else
1807 *bpout++ = 'M',
1808 *bpout++ = '-';
1809 if (ch >= 128 + 32)
1811 if (ch < 128 + 127)
1812 *bpout++ = ch - 128;
1813 else
1815 *bpout++ = '^';
1816 *bpout++ = '?';
1819 else
1821 *bpout++ = '^';
1822 *bpout++ = ch - 128 + 64;
1826 else
1828 *bpout++ = '^';
1829 *bpout++ = ch + 64;
1831 *bpout = '\0';
1832 return (const char *) buf;
1835 /* Parse string S as an integer, using decimal radix by default,
1836 but allowing octal and hex numbers as in C. */
1837 /* From `od' by Richard Stallman. */
1839 static long
1840 integer_arg (const char *s)
1842 long value;
1843 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1845 error (0, 0, _("invalid integer argument `%s'"), s);
1846 usage (1);
1848 return value;