1 /* stty -- change and print terminal line settings
2 Copyright (C) 90,91,92,93,94,95,96,1997 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)
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...]
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
28 David MacKenzie <djm@gnu.ai.mit.edu> */
32 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
33 # define _XOPEN_SOURCE
37 #include <sys/types.h>
41 #ifdef GWINSZ_IN_SYS_IOCTL
42 # include <sys/ioctl.h>
44 #ifdef WINSIZE_IN_PTEM
45 # include <sys/stream.h>
46 # include <sys/ptem.h>
48 #ifdef GWINSZ_IN_SYS_PTY
49 # include <sys/ioctl.h>
56 # define VA_START(args, lastarg) va_start(args, lastarg)
59 # define VA_START(args, lastarg) va_start(args)
63 #include "long-options.h"
67 #ifndef _POSIX_VDISABLE
68 # define _POSIX_VDISABLE ((unsigned char) 0)
71 #define Control(c) ((c) & 0x1f)
72 /* Canonical values for control characters. */
74 # define CINTR Control ('c')
83 # define CKILL Control ('u')
86 # define CEOF Control ('d')
89 # define CEOL _POSIX_VDISABLE
92 # define CSTART Control ('q')
95 # define CSTOP Control ('s')
98 # define CSUSP Control ('z')
100 #if defined(VEOL2) && !defined(CEOL2)
101 # define CEOL2 _POSIX_VDISABLE
103 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
104 #if defined(VSUSP) && !defined(VSWTCH)
105 # define VSWTCH VSUSP
106 # define CSWTCH CSUSP
108 #if defined(VSWTCH) && !defined(CSWTCH)
109 # define CSWTCH _POSIX_VDISABLE
112 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
113 So the default is to disable `swtch.' */
114 #if defined (__sparc__) && defined (__svr4__)
116 # define CSWTCH _POSIX_VDISABLE
119 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
120 # define VWERASE VWERSE
122 #if defined(VDSUSP) && !defined (CDSUSP)
123 # define CDSUSP Control ('y')
125 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
126 # define VREPRINT VRPRNT
128 #if defined(VREPRINT) && !defined(CRPRNT)
129 # define CRPRNT Control ('r')
131 #if defined(VWERASE) && !defined(CWERASE)
132 # define CWERASE Control ('w')
134 #if defined(VLNEXT) && !defined(CLNEXT)
135 # define CLNEXT Control ('v')
137 #if defined(VDISCARD) && !defined(VFLUSHO)
138 # define VFLUSHO VDISCARD
140 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
141 # define VFLUSHO VFLUSH
143 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
144 # define ECHOCTL CTLECH
146 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
147 # define ECHOCTL TCTLECH
149 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
150 # define ECHOKE CRTKIL
152 #if defined(VFLUSHO) && !defined(CFLUSHO)
153 # define CFLUSHO Control ('o')
155 #if defined(VSTATUS) && !defined(CSTATUS)
156 # define CSTATUS Control ('t')
159 /* Which speeds to set. */
162 input_speed, output_speed, both_speeds
165 /* What to output and how. */
168 changed, all, recoverable /* Default, -a, -g. */
171 /* Which member(s) of `struct termios' a mode uses. */
174 control, input, output, local, combination
177 /* Flags for `struct mode_info'. */
178 #define SANE_SET 1 /* Set in `sane' mode. */
179 #define SANE_UNSET 2 /* Unset in `sane' mode. */
180 #define REV 4 /* Can be turned off by prepending `-'. */
181 #define OMIT 8 /* Don't display value. */
186 const char *name; /* Name given on command line. */
187 enum mode_type type; /* Which structure element to change. */
188 char flags; /* Setting and display options. */
189 unsigned long bits; /* Bits to set for this mode. */
190 unsigned long mask; /* Other bits to turn off for this mode. */
193 static struct mode_info mode_info[] =
195 {"parenb", control, REV, PARENB, 0},
196 {"parodd", control, REV, PARODD, 0},
197 {"cs5", control, 0, CS5, CSIZE},
198 {"cs6", control, 0, CS6, CSIZE},
199 {"cs7", control, 0, CS7, CSIZE},
200 {"cs8", control, 0, CS8, CSIZE},
201 {"hupcl", control, REV, HUPCL, 0},
202 {"hup", control, REV | OMIT, HUPCL, 0},
203 {"cstopb", control, REV, CSTOPB, 0},
204 {"cread", control, SANE_SET | REV, CREAD, 0},
205 {"clocal", control, REV, CLOCAL, 0},
207 {"crtscts", control, REV, CRTSCTS, 0},
210 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
211 {"brkint", input, SANE_SET | REV, BRKINT, 0},
212 {"ignpar", input, REV, IGNPAR, 0},
213 {"parmrk", input, REV, PARMRK, 0},
214 {"inpck", input, REV, INPCK, 0},
215 {"istrip", input, REV, ISTRIP, 0},
216 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
217 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
218 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
219 {"ixon", input, REV, IXON, 0},
220 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
221 {"tandem", input, REV | OMIT, IXOFF, 0},
223 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
226 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
229 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
232 {"opost", output, SANE_SET | REV, OPOST, 0},
234 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
237 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
240 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
243 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
246 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
249 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
252 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
255 {"nl1", output, SANE_UNSET, NL1, NLDLY},
256 {"nl0", output, SANE_SET, NL0, NLDLY},
259 {"cr3", output, SANE_UNSET, CR3, CRDLY},
260 {"cr2", output, SANE_UNSET, CR2, CRDLY},
261 {"cr1", output, SANE_UNSET, CR1, CRDLY},
262 {"cr0", output, SANE_SET, CR0, CRDLY},
265 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
266 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
267 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
268 {"tab0", output, SANE_SET, TAB0, TABDLY},
271 {"tab3", output, SANE_UNSET, OXTABS, 0},
275 {"bs1", output, SANE_UNSET, BS1, BSDLY},
276 {"bs0", output, SANE_SET, BS0, BSDLY},
279 {"vt1", output, SANE_UNSET, VT1, VTDLY},
280 {"vt0", output, SANE_SET, VT0, VTDLY},
283 {"ff1", output, SANE_UNSET, FF1, FFDLY},
284 {"ff0", output, SANE_SET, FF0, FFDLY},
287 {"isig", local, SANE_SET | REV, ISIG, 0},
288 {"icanon", local, SANE_SET | REV, ICANON, 0},
290 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
292 {"echo", local, SANE_SET | REV, ECHO, 0},
293 {"echoe", local, SANE_SET | REV, ECHOE, 0},
294 {"crterase", local, REV | OMIT, ECHOE, 0},
295 {"echok", local, SANE_SET | REV, ECHOK, 0},
296 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
297 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
299 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
302 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
305 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
306 {"prterase", local, REV | OMIT, ECHOPRT, 0},
309 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
310 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
313 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
314 {"crtkill", local, REV | OMIT, ECHOKE, 0},
317 {"evenp", combination, REV | OMIT, 0, 0},
318 {"parity", combination, REV | OMIT, 0, 0},
319 {"oddp", combination, REV | OMIT, 0, 0},
320 {"nl", combination, REV | OMIT, 0, 0},
321 {"ek", combination, OMIT, 0, 0},
322 {"sane", combination, OMIT, 0, 0},
323 {"cooked", combination, REV | OMIT, 0, 0},
324 {"raw", combination, REV | OMIT, 0, 0},
325 {"pass8", combination, REV | OMIT, 0, 0},
326 {"litout", combination, REV | OMIT, 0, 0},
327 {"cbreak", combination, REV | OMIT, 0, 0},
329 {"decctlq", combination, REV | OMIT, 0, 0},
331 #if defined (TABDLY) || defined (OXTABS)
332 {"tabs", combination, REV | OMIT, 0, 0},
334 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
335 {"lcase", combination, REV | OMIT, 0, 0},
336 {"LCASE", combination, REV | OMIT, 0, 0},
338 {"crt", combination, OMIT, 0, 0},
339 {"dec", combination, OMIT, 0, 0},
341 {NULL, control, 0, 0, 0}
344 /* Control character settings. */
347 const char *name; /* Name given on command line. */
348 unsigned char saneval; /* Value to set for `stty sane'. */
349 int offset; /* Offset in c_cc. */
352 /* Control characters. */
354 static struct control_info control_info[] =
356 {"intr", CINTR, VINTR},
357 {"quit", CQUIT, VQUIT},
358 {"erase", CERASE, VERASE},
359 {"kill", CKILL, VKILL},
363 {"eol2", CEOL2, VEOL2},
366 {"swtch", CSWTCH, VSWTCH},
368 {"start", CSTART, VSTART},
369 {"stop", CSTOP, VSTOP},
370 {"susp", CSUSP, VSUSP},
372 {"dsusp", CDSUSP, VDSUSP},
375 {"rprnt", CRPRNT, VREPRINT},
378 {"werase", CWERASE, VWERASE},
381 {"lnext", CLNEXT, VLNEXT},
384 {"flush", CFLUSHO, VFLUSHO},
387 {"status", CSTATUS, VSTATUS},
390 /* These must be last because of the display routines. */
396 static const char *visible __P ((unsigned int ch));
397 static unsigned long baud_to_value __P ((speed_t speed));
398 static int recover_mode __P ((char *arg, struct termios *mode));
399 static int screen_columns __P ((void));
400 static int set_mode __P ((struct mode_info *info, int reversed,
401 struct termios *mode));
402 static long integer_arg __P ((const char *s));
403 static speed_t string_to_baud __P ((const char *arg));
404 static tcflag_t *mode_type_flag __P ((enum mode_type type,
405 struct termios *mode));
406 static void display_all __P ((struct termios *mode));
407 static void display_changed __P ((struct termios *mode));
408 static void display_recoverable __P ((struct termios *mode));
409 static void display_settings __P ((enum output_type output_type,
410 struct termios *mode));
411 static void display_speed __P ((struct termios *mode, int fancy));
412 static void display_window_size __P ((int fancy));
413 static void sane_mode __P ((struct termios *mode));
414 static void set_control_char __P ((struct control_info *info, const char *arg,
415 struct termios *mode));
416 static void set_speed __P ((enum speed_setting type, const char *arg,
417 struct termios *mode));
418 static void set_window_size __P ((int rows, int cols));
420 /* The width of the screen, for output wrapping. */
423 /* Current position, to know when to wrap. */
424 static int current_col;
426 static struct option longopts[] =
428 {"all", no_argument, NULL, 'a'},
429 {"save", no_argument, NULL, 'g'},
433 /* The name this program was run with. */
436 /* Print format string MESSAGE and optional args.
437 Wrap to next line first if it won't fit.
438 Print a space first unless MESSAGE will start a new line. */
443 wrapf (const char *message,...)
445 wrapf (message, va_alist)
451 char buf[1024]; /* Plenty long for our needs. */
454 VA_START (args, message);
455 vsprintf (buf, message, args);
457 buflen = strlen (buf);
458 if (current_col + (current_col > 0) + buflen >= max_col)
469 current_col += buflen;
476 fprintf (stderr, _("Try `%s --help' for more information.\n"),
481 Usage: %s [SETTING]...\n\
484 program_name, program_name);
486 Print or change terminal characteristics.\n\
488 -a, --all print all current settings in human-readable form\n\
489 -g, --save print all current settings in a stty-readable form\n\
490 --help display this help and exit\n\
491 --version output version information and exit\n\
493 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
494 settings. The underlying system defines which settings are available.\n\
498 Special characters:\n\
499 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
500 eof CHAR CHAR will send an end of file (terminate the input)\n\
501 eol CHAR CHAR will end the line\n\
502 * eol2 CHAR alternate CHAR for ending the line\n\
503 erase CHAR CHAR will erase the last character typed\n\
504 intr CHAR CHAR will send an interrupt signal\n\
505 kill CHAR CHAR will erase the current line\n\
506 * lnext CHAR CHAR will enter the next character quoted\n\
507 quit CHAR CHAR will send a quit signal\n\
508 * rprnt CHAR CHAR will redraw the current line\n\
509 start CHAR CHAR will restart the output after stopping it\n\
510 stop CHAR CHAR will stop the output\n\
511 susp CHAR CHAR will send a terminal stop signal\n\
512 * swtch CHAR CHAR will switch to a different shell layer\n\
513 * werase CHAR CHAR will erase the last word typed\n\
518 N set the input and output speeds to N bauds\n\
519 * cols N tell the kernel that the terminal has N columns\n\
520 * columns N same as cols N\n\
521 ispeed N set the input speed to N\n\
522 * line N use line discipline N\n\
523 min N with -icanon, set N characters minimum for a completed read\n\
524 ospeed N set the output speed to N\n\
525 * rows N tell the kernel that the terminal has N rows\n\
526 * size print the number of rows and columns according to the kernel\n\
527 speed print the terminal speed\n\
528 time N with -icanon, set read timeout of N tenths of a second\n\
533 [-]clocal disable modem control signals\n\
534 [-]cread allow input to be received\n\
535 * [-]crtscts enable RTS/CTS handshaking\n\
536 csN set character size to N bits, N in [5..8]\n\
537 [-]cstopb use two stop bits per character (one with `-')\n\
538 [-]hup send a hangup signal when the last process closes the tty\n\
539 [-]hupcl same as [-]hup\n\
540 [-]parenb generate parity bit in output and expect parity bit in input\n\
541 [-]parodd set odd parity (even with `-')\n\
546 [-]brkint breaks cause an interrupt signal\n\
547 [-]icrnl translate carriage return to newline\n\
548 [-]ignbrk ignore break characters\n\
549 [-]igncr ignore carriage return\n\
550 [-]ignpar ignore characters with parity errors\n\
551 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
552 [-]inlcr translate newline to carriage return\n\
553 [-]inpck enable input parity checking\n\
554 [-]istrip clear high (8th) bit of input characters\n\
555 * [-]iuclc translate uppercase characters to lowercase\n\
556 * [-]ixany let any character restart output, not only start character\n\
557 [-]ixoff enable sending of start/stop characters\n\
558 [-]ixon enable XON/XOFF flow control\n\
559 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
560 [-]tandem same as [-]ixoff\n\
565 * bsN backspace delay style, N in [0..1]\n\
566 * crN carriage return delay style, N in [0..3]\n\
567 * ffN form feed delay style, N in [0..1]\n\
568 * nlN newline delay style, N in [0..1]\n\
569 * [-]ocrnl translate carriage return to newline\n\
570 * [-]ofdel use delete characters for fill instead of null characters\n\
571 * [-]ofill use fill (padding) characters instead of timing for delays\n\
572 * [-]olcuc translate lowercase characters to uppercase\n\
573 * [-]onlcr translate newline to carriage return-newline\n\
574 * [-]onlret newline performs a carriage return\n\
575 * [-]onocr do not print carriage returns in the first column\n\
576 [-]opost postprocess output\n\
577 * tabN horizontal tab delay style, N in [0..3]\n\
578 * tabs same as tab0\n\
579 * -tabs same as tab3\n\
580 * vtN vertical tab delay style, N in [0..1]\n\
585 [-]crterase echo erase characters as backspace-space-backspace\n\
586 * crtkill kill all line by obeying the echoprt and echoe settings\n\
587 * -crtkill kill all line by obeying the echoctl and echok settings\n\
588 * [-]ctlecho echo control characters in hat notation (`^c')\n\
589 [-]echo echo input characters\n\
590 * [-]echoctl same as [-]ctlecho\n\
591 [-]echoe same as [-]crterase\n\
592 [-]echok echo a newline after a kill character\n\
593 * [-]echoke same as [-]crtkill\n\
594 [-]echonl echo newline even if not echoing other characters\n\
595 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
596 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
597 [-]iexten enable non-POSIX special characters\n\
598 [-]isig enable interrupt, quit, and suspend special characters\n\
599 [-]noflsh disable flushing after interrupt and quit special characters\n\
600 * [-]prterase same as [-]echoprt\n\
601 * [-]tostop stop background jobs that try to write to the terminal\n\
602 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
606 Combination settings:\n\
607 * [-]LCASE same as [-]lcase\n\
608 cbreak same as -icanon\n\
609 -cbreak same as icanon\n\
610 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
611 icanon, eof and eol characters to their default values\n\
612 -cooked same as raw\n\
613 crt same as echoe echoctl echoke\n\
614 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
616 * [-]decctlq same as [-]ixany\n\
617 ek erase and kill characters to their default values\n\
618 evenp same as parenb -parodd cs7\n\
619 -evenp same as -parenb cs8\n\
620 * [-]lcase same as xcase iuclc olcuc\n\
621 litout same as -parenb -istrip -opost cs8\n\
622 -litout same as parenb istrip opost cs7\n\
623 nl same as -icrnl -onlcr\n\
624 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
625 oddp same as parenb parodd cs7\n\
626 -oddp same as -parenb cs8\n\
627 [-]parity same as [-]evenp\n\
628 pass8 same as -parenb -istrip cs8\n\
629 -pass8 same as parenb istrip cs7\n\
630 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
631 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
632 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
633 -raw same as cooked\n\
634 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
635 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
636 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
637 isig icanon iexten echo echoe echok -echonl -noflsh\n\
638 -xcase -tostop -echoprt echoctl echoke, all special\n\
639 characters to their default values.\n\
643 Handle the tty line connected to standard input. Without arguments,\n\
644 prints baud rate, line discipline, and deviations from stty sane. In\n\
645 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
646 127; special values ^- or undef used to disable special characters.\n\
648 puts (_("\nReport bugs to <sh-utils-bugs@gnu.ai.mit.edu>."));
654 main (int argc, char **argv)
657 enum output_type output_type;
659 int require_set_attr;
662 int recoverable_output;
665 program_name = argv[0];
666 setlocale (LC_ALL, "");
667 bindtextdomain (PACKAGE, LOCALEDIR);
668 textdomain (PACKAGE);
670 parse_long_options (argc, argv, "stty", GNU_PACKAGE, VERSION, usage);
672 output_type = changed;
674 recoverable_output = 0;
676 /* Recognize the long options only. */
678 while ((optc = getopt_long_only (argc, argv, "ag", longopts, NULL)) != -1)
688 recoverable_output = 1;
689 output_type = recoverable;
697 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
698 They need not precede non-options. We cannot use GNU getopt because
699 it would treat -tabs and -ixany as uses of the -a option. */
700 for (k = optind; k < argc; k++)
702 if (argv[k][0] == '-')
704 if (argv[k][1] == 'a'
705 && argv[k][2] == '\0')
710 else if (argv[k][1] == 'g'
711 && argv[k][2] == '\0')
714 recoverable_output = 1;
716 else if ((argv[k][1] == 'g'
718 && argv[k][3] == '\0')
719 || (argv[k][1] == 'a'
721 && argv[k][3] == '\0'))
725 recoverable_output = 1;
730 /* Specifying both -a and -g gets an error. */
731 if (verbose_output && recoverable_output)
733 _("the options for verbose and stty-readable output styles are\n\
734 mutually exclusive"));
736 /* Specifying any other arguments with -a or -g gets an error. */
737 if (argc - optind > 0 && (verbose_output || recoverable_output))
738 error (2, 0, _("when specifying an output style, modes may not be set"));
740 /* Initialize to all zeroes so there is no risk memcmp will report a
741 spurious difference in an uninitialized portion of the structure. */
742 memset (&mode, 0, sizeof (mode));
743 if (tcgetattr (0, &mode))
744 error (1, errno, _("standard input"));
746 if (verbose_output || recoverable_output || argc == 1)
748 max_col = screen_columns ();
750 display_settings (output_type, &mode);
755 require_set_attr = 0;
763 if (argv[k][0] == '-')
768 for (i = 0; mode_info[i].name != NULL; ++i)
770 if (!strcmp (argv[k], mode_info[i].name))
772 match_found = set_mode (&mode_info[i], reversed, &mode);
773 require_set_attr = 1;
777 if (match_found == 0 && reversed)
779 error (0, 0, _("invalid argument `%s'"), --argv[k]);
782 if (match_found == 0)
784 for (i = 0; control_info[i].name != NULL; ++i)
786 if (!strcmp (argv[k], control_info[i].name))
790 error (0, 0, _("missing argument to `%s'"), argv[k]);
795 set_control_char (&control_info[i], argv[k], &mode);
796 require_set_attr = 1;
801 if (match_found == 0)
803 if (!strcmp (argv[k], "ispeed"))
807 error (0, 0, _("missing argument to `%s'"), argv[k]);
811 set_speed (input_speed, argv[k], &mode);
813 require_set_attr = 1;
815 else if (!strcmp (argv[k], "ospeed"))
819 error (0, 0, _("missing argument to `%s'"), argv[k]);
823 set_speed (output_speed, argv[k], &mode);
825 require_set_attr = 1;
828 else if (!strcmp (argv[k], "rows"))
832 error (0, 0, _("missing argument to `%s'"), argv[k]);
836 set_window_size ((int) integer_arg (argv[k]), -1);
838 else if (!strcmp (argv[k], "cols")
839 || !strcmp (argv[k], "columns"))
843 error (0, 0, _("missing argument to `%s'"), argv[k]);
847 set_window_size (-1, (int) integer_arg (argv[k]));
849 else if (!strcmp (argv[k], "size"))
851 max_col = screen_columns ();
853 display_window_size (0);
857 else if (!strcmp (argv[k], "line"))
861 error (0, 0, _("missing argument to `%s'"), argv[k]);
865 mode.c_line = integer_arg (argv[k]);
866 require_set_attr = 1;
869 else if (!strcmp (argv[k], "speed"))
871 max_col = screen_columns ();
872 display_speed (&mode, 0);
874 else if (string_to_baud (argv[k]) != (speed_t) -1)
876 set_speed (both_speeds, argv[k], &mode);
878 require_set_attr = 1;
882 if (recover_mode (argv[k], &mode) == 0)
884 error (0, 0, _("invalid argument `%s'"), argv[k]);
887 require_set_attr = 1;
893 if (require_set_attr)
895 struct termios new_mode;
897 if (tcsetattr (0, TCSADRAIN, &mode))
898 error (1, errno, _("standard input"));
900 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
901 it performs *any* of the requested operations. This means it
902 can report `success' when it has actually failed to perform
903 some proper subset of the requested operations. To detect
904 this partial failure, get the current terminal attributes and
905 compare them to the requested ones. */
907 /* Initialize to all zeroes so there is no risk memcmp will report a
908 spurious difference in an uninitialized portion of the structure. */
909 memset (&new_mode, 0, sizeof (new_mode));
910 if (tcgetattr (0, &new_mode))
911 error (1, errno, _("standard input"));
913 /* Normally, one shouldn't use memcmp to compare structures that
914 may have `holes' containing uninitialized data, but we have been
915 careful to initialize the storage of these two variables to all
916 zeroes. One might think it more efficient simply to compare the
917 modified fields, but that would require enumerating those fields --
918 and not all systems have the same fields in this structure. */
920 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
923 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
924 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
925 sometimes (m1 != m2). The only difference is in the four bits
926 of the c_cflag field corresponding to the baud rate. To save
927 Sun users a little confusion, don't report an error if this
928 happens. But suppress the error only if we haven't tried to
929 set the baud rate explicitly -- otherwise we'd never give an
930 error for a true failure to set the baud rate. */
932 new_mode.c_cflag &= (~CIBAUD);
933 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
938 _("standard input: unable to perform all requested operations"));
939 printf (_("new_mode: mode\n"));
940 for (i = 0; i < sizeof (new_mode); i++)
941 printf ("0x%02x: 0x%02x\n",
942 *(((unsigned char *) &new_mode) + i),
943 *(((unsigned char *) &mode) + i));
951 /* Return 0 if not applied because not reversible; otherwise return 1. */
954 set_mode (struct mode_info *info, int reversed, struct termios *mode)
958 if (reversed && (info->flags & REV) == 0)
961 bitsp = mode_type_flag (info->type, mode);
965 /* Combination mode. */
966 if (!strcmp (info->name, "evenp") || !strcmp (info->name, "parity"))
969 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
971 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
973 else if (!strcmp (info->name, "oddp"))
976 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
978 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
980 else if (!strcmp (info->name, "nl"))
984 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
985 mode->c_oflag = (mode->c_oflag
1000 mode->c_iflag = mode->c_iflag & ~ICRNL;
1002 mode->c_oflag = mode->c_oflag & ~ONLCR;
1006 else if (!strcmp (info->name, "ek"))
1008 mode->c_cc[VERASE] = CERASE;
1009 mode->c_cc[VKILL] = CKILL;
1011 else if (!strcmp (info->name, "sane"))
1013 else if (!strcmp (info->name, "cbreak"))
1016 mode->c_lflag |= ICANON;
1018 mode->c_lflag &= ~ICANON;
1020 else if (!strcmp (info->name, "pass8"))
1024 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1025 mode->c_iflag |= ISTRIP;
1029 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1030 mode->c_iflag &= ~ISTRIP;
1033 else if (!strcmp (info->name, "litout"))
1037 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1038 mode->c_iflag |= ISTRIP;
1039 mode->c_oflag |= OPOST;
1043 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1044 mode->c_iflag &= ~ISTRIP;
1045 mode->c_oflag &= ~OPOST;
1048 else if (!strcmp (info->name, "raw") || !strcmp (info->name, "cooked"))
1050 if ((info->name[0] == 'r' && reversed)
1051 || (info->name[0] == 'c' && !reversed))
1054 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1055 mode->c_oflag |= OPOST;
1056 mode->c_lflag |= ISIG | ICANON;
1058 mode->c_cc[VEOF] = CEOF;
1061 mode->c_cc[VEOL] = CEOL;
1068 mode->c_oflag &= ~OPOST;
1069 mode->c_lflag &= ~(ISIG | ICANON
1074 mode->c_cc[VMIN] = 1;
1075 mode->c_cc[VTIME] = 0;
1079 else if (!strcmp (info->name, "decctlq"))
1082 mode->c_iflag |= IXANY;
1084 mode->c_iflag &= ~IXANY;
1088 else if (!strcmp (info->name, "tabs"))
1091 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1093 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1097 else if (!strcmp (info->name, "tabs"))
1100 mode->c_oflag = mode->c_oflag | OXTABS;
1102 mode->c_oflag = mode->c_oflag & ~OXTABS;
1106 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1107 else if (!strcmp (info->name, "lcase")
1108 || !strcmp (info->name, "LCASE"))
1112 mode->c_lflag &= ~XCASE;
1113 mode->c_iflag &= ~IUCLC;
1114 mode->c_oflag &= ~OLCUC;
1118 mode->c_lflag |= XCASE;
1119 mode->c_iflag |= IUCLC;
1120 mode->c_oflag |= OLCUC;
1124 else if (!strcmp (info->name, "crt"))
1125 mode->c_lflag |= ECHOE
1133 else if (!strcmp (info->name, "dec"))
1135 mode->c_cc[VINTR] = 3; /* ^C */
1136 mode->c_cc[VERASE] = 127; /* DEL */
1137 mode->c_cc[VKILL] = 21; /* ^U */
1138 mode->c_lflag |= ECHOE
1147 mode->c_iflag &= ~IXANY;
1152 *bitsp = *bitsp & ~info->mask & ~info->bits;
1154 *bitsp = (*bitsp & ~info->mask) | info->bits;
1160 set_control_char (struct control_info *info, const char *arg,
1161 struct termios *mode)
1163 unsigned char value;
1165 if (!strcmp (info->name, "min") || !strcmp (info->name, "time"))
1166 value = integer_arg (arg);
1167 else if (arg[0] == '\0' || arg[1] == '\0')
1169 else if (!strcmp (arg, "^-") || !strcmp (arg, "undef"))
1170 value = _POSIX_VDISABLE;
1171 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1176 value = arg[1] & ~0140; /* Non-letters get weird results. */
1179 value = integer_arg (arg);
1180 mode->c_cc[info->offset] = value;
1184 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1188 baud = string_to_baud (arg);
1189 if (type == input_speed || type == both_speeds)
1190 cfsetispeed (mode, baud);
1191 if (type == output_speed || type == both_speeds)
1192 cfsetospeed (mode, baud);
1198 get_win_size (int fd, struct winsize *win)
1200 int err = ioctl (fd, TIOCGWINSZ, (char *) win);
1205 set_window_size (int rows, int cols)
1209 if (get_win_size (STDIN_FILENO, &win))
1211 if (errno != EINVAL)
1212 error (1, errno, _("standard input"));
1213 memset (&win, 0, sizeof (win));
1222 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1223 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1224 This comment from sys/ttold.h describes Sun's twisted logic - a better
1225 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1226 At any rate, the problem is gone in Solaris 2.x.
1228 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1229 but they can be disambiguated by checking whether a "struct ttysize"
1230 structure's "ts_lines" field is greater than 64K or not. If so,
1231 it's almost certainly a "struct winsize" instead.
1233 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1234 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1235 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1236 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1237 "stty cols 0 rows 0" would do the right thing. On a little-endian
1238 machine like the sun386i, the problem is the same, but for ws_col == 0.
1240 The workaround is to do the ioctl once with row and col = 1 to set the
1241 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1243 if (win.ws_row == 0 || win.ws_col == 0)
1245 struct ttysize ttysz;
1247 ttysz.ts_lines = win.ws_row;
1248 ttysz.ts_cols = win.ws_col;
1253 if (ioctl (STDIN_FILENO, TIOCSWINSZ, (char *) &win))
1254 error (1, errno, _("standard input"));
1256 if (ioctl (STDIN_FILENO, TIOCSSIZE, (char *) &ttysz))
1257 error (1, errno, _("standard input"));
1262 if (ioctl (STDIN_FILENO, TIOCSWINSZ, (char *) &win))
1263 error (1, errno, _("standard input"));
1267 display_window_size (int fancy)
1271 if (get_win_size (STDIN_FILENO, &win))
1273 if (errno != EINVAL)
1274 error (1, errno, _("standard input"));
1276 error (1, 0, _("no size information for this device"));
1280 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1281 win.ws_row, win.ws_col);
1289 screen_columns (void)
1294 /* With Solaris 2.[123], this ioctl fails and errno is set to
1295 EINVAL for telnet (but not rlogin) sessions.
1296 On ISC 3.0, it fails for the console and the serial port
1297 (but it works for ptys).
1298 It can also fail on any system when stdout isn't a tty.
1299 In case of any failure, just use the default. */
1300 if (get_win_size (STDOUT_FILENO, &win) == 0 && win.ws_col > 0)
1303 /* FIXME: use xstrtol */
1304 if (getenv ("COLUMNS"))
1305 return atoi (getenv ("COLUMNS"));
1310 mode_type_flag (enum mode_type type, struct termios *mode)
1315 return &mode->c_cflag;
1318 return &mode->c_iflag;
1321 return &mode->c_oflag;
1324 return &mode->c_lflag;
1335 display_settings (enum output_type output_type, struct termios *mode)
1337 switch (output_type)
1340 display_changed (mode);
1348 display_recoverable (mode);
1354 display_changed (struct termios *mode)
1360 enum mode_type prev_type = control;
1362 display_speed (mode, 1);
1364 wrapf ("line = %d;", mode->c_line);
1370 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1372 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1374 /* If swtch is the same as susp, don't print both. */
1376 if (strcmp (control_info[i].name, "swtch") == 0)
1379 /* If eof uses the same slot as min, only print whichever applies. */
1381 if ((mode->c_lflag & ICANON) == 0
1382 && (strcmp (control_info[i].name, "eof") == 0
1383 || strcmp(control_info[i].name, "eol") == 0))
1388 wrapf ("%s = %s;", control_info[i].name,
1389 visible (mode->c_cc[control_info[i].offset]));
1391 if ((mode->c_lflag & ICANON) == 0)
1393 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1394 (int) mode->c_cc[VTIME]);
1396 else if (empty_line == 0)
1401 for (i = 0; mode_info[i].name != NULL; ++i)
1403 if (mode_info[i].flags & OMIT)
1405 if (mode_info[i].type != prev_type)
1407 if (empty_line == 0)
1413 prev_type = mode_info[i].type;
1416 bitsp = mode_type_flag (mode_info[i].type, mode);
1417 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1418 if ((*bitsp & mask) == mode_info[i].bits)
1420 if (mode_info[i].flags & SANE_UNSET)
1422 wrapf ("%s", mode_info[i].name);
1426 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1428 wrapf ("-%s", mode_info[i].name);
1432 if (empty_line == 0)
1438 display_all (struct termios *mode)
1443 enum mode_type prev_type = control;
1445 display_speed (mode, 1);
1447 display_window_size (1);
1450 wrapf ("line = %d;", mode->c_line);
1455 for (i = 0; strcmp (control_info[i].name, "min"); ++i)
1457 /* If swtch is the same as susp, don't print both. */
1459 if (strcmp (control_info[i].name, "swtch") == 0)
1462 /* If eof uses the same slot as min, only print whichever applies. */
1464 if ((mode->c_lflag & ICANON) == 0
1465 && (strcmp (control_info[i].name, "eof") == 0
1466 || strcmp(control_info[i].name, "eol") == 0))
1469 wrapf ("%s = %s;", control_info[i].name,
1470 visible (mode->c_cc[control_info[i].offset]));
1473 if ((mode->c_lflag & ICANON) == 0)
1475 wrapf ("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1476 if (current_col != 0)
1480 for (i = 0; mode_info[i].name != NULL; ++i)
1482 if (mode_info[i].flags & OMIT)
1484 if (mode_info[i].type != prev_type)
1488 prev_type = mode_info[i].type;
1491 bitsp = mode_type_flag (mode_info[i].type, mode);
1492 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1493 if ((*bitsp & mask) == mode_info[i].bits)
1494 wrapf ("%s", mode_info[i].name);
1495 else if (mode_info[i].flags & REV)
1496 wrapf ("-%s", mode_info[i].name);
1503 display_speed (struct termios *mode, int fancy)
1505 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1506 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1507 baud_to_value (cfgetospeed (mode)));
1509 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1510 baud_to_value (cfgetispeed (mode)),
1511 baud_to_value (cfgetospeed (mode)));
1517 display_recoverable (struct termios *mode)
1521 printf ("%lx:%lx:%lx:%lx",
1522 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1523 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1524 for (i = 0; i < NCCS; ++i)
1525 printf (":%x", (unsigned int) mode->c_cc[i]);
1530 recover_mode (char *arg, struct termios *mode)
1534 unsigned long iflag, oflag, cflag, lflag;
1536 /* Scan into temporaries since it is too much trouble to figure out
1537 the right format for `tcflag_t'. */
1538 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1539 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1541 mode->c_iflag = iflag;
1542 mode->c_oflag = oflag;
1543 mode->c_cflag = cflag;
1544 mode->c_lflag = lflag;
1546 for (i = 0; i < NCCS; ++i)
1548 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1550 mode->c_cc[i] = chr;
1554 /* Fail if there are too many fields. */
1563 const char *string; /* ASCII representation. */
1564 speed_t speed; /* Internal form. */
1565 unsigned long value; /* Numeric value. */
1568 struct speed_map speeds[] =
1575 {"134.5", B134, 134},
1580 {"1200", B1200, 1200},
1581 {"1800", B1800, 1800},
1582 {"2400", B2400, 2400},
1583 {"4800", B4800, 4800},
1584 {"9600", B9600, 9600},
1585 {"19200", B19200, 19200},
1586 {"38400", B38400, 38400},
1587 {"exta", B19200, 19200},
1588 {"extb", B38400, 38400},
1590 {"57600", B57600, 57600},
1593 {"115200", B115200, 115200},
1599 string_to_baud (const char *arg)
1603 for (i = 0; speeds[i].string != NULL; ++i)
1604 if (!strcmp (arg, speeds[i].string))
1605 return speeds[i].speed;
1606 return (speed_t) -1;
1609 static unsigned long
1610 baud_to_value (speed_t speed)
1614 for (i = 0; speeds[i].string != NULL; ++i)
1615 if (speed == speeds[i].speed)
1616 return speeds[i].value;
1621 sane_mode (struct termios *mode)
1626 for (i = 0; control_info[i].name; ++i)
1629 if (!strcmp (control_info[i].name, "min"))
1632 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1635 for (i = 0; mode_info[i].name != NULL; ++i)
1637 if (mode_info[i].flags & SANE_SET)
1639 bitsp = mode_type_flag (mode_info[i].type, mode);
1640 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1642 else if (mode_info[i].flags & SANE_UNSET)
1644 bitsp = mode_type_flag (mode_info[i].type, mode);
1645 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1650 /* Return a string that is the printable representation of character CH. */
1651 /* Adapted from `cat' by Torbjorn Granlund. */
1654 visible (unsigned int ch)
1656 static char buf[10];
1659 if (ch == _POSIX_VDISABLE)
1660 return _("<undef>");
1678 *bpout++ = ch - 128;
1688 *bpout++ = ch - 128 + 64;
1698 return (const char *) buf;
1701 /* Parse string S as an integer, using decimal radix by default,
1702 but allowing octal and hex numbers as in C. */
1703 /* From `od' by Richard Stallman. */
1706 integer_arg (const char *s)
1709 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1711 error (0, 0, _("invalid integer argument `%s'"), s);