1 /* stty -- change and print terminal line settings
2 Copyright (C) 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Usage: stty [-ag] [--all] [--save] [setting...]
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 #include <sys/types.h>
34 #ifdef GWINSZ_IN_SYS_IOCTL
35 # include <sys/ioctl.h>
37 #ifdef WINSIZE_IN_PTEM
38 # include <sys/stream.h>
39 # include <sys/ptem.h>
44 # define VA_START(args, lastarg) va_start(args, lastarg)
47 # define VA_START(args, lastarg) va_start(args)
51 #include "long-options.h"
55 #if defined(GWINSZ_BROKEN) /* Such as for SCO UNIX 3.2.2. */
59 #ifndef _POSIX_VDISABLE
60 # define _POSIX_VDISABLE ((unsigned char) 0)
63 #define Control(c) ((c) & 0x1f)
64 /* Canonical values for control characters. */
66 # define CINTR Control ('c')
75 # define CKILL Control ('u')
78 # define CEOF Control ('d')
81 # define CEOL _POSIX_VDISABLE
84 # define CSTART Control ('q')
87 # define CSTOP Control ('s')
90 # define CSUSP Control ('z')
92 #if defined(VEOL2) && !defined(CEOL2)
93 # define CEOL2 _POSIX_VDISABLE
95 #if defined(VSWTCH) && !defined(CSWTCH)
96 # define CSWTCH _POSIX_VDISABLE
99 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
100 So the default is to disable `swtch.' */
101 #if defined (__sparc__) && defined (__svr4__)
103 # define CSWTCH _POSIX_VDISABLE
106 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
107 # define VWERASE VWERSE
109 #if defined(VDSUSP) && !defined (CDSUSP)
110 # define CDSUSP Control ('y')
112 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
113 # define VREPRINT VRPRNT
115 #if defined(VREPRINT) && !defined(CRPRNT)
116 # define CRPRNT Control ('r')
118 #if defined(VWERASE) && !defined(CWERASE)
119 # define CWERASE Control ('w')
121 #if defined(VLNEXT) && !defined(CLNEXT)
122 # define CLNEXT Control ('v')
124 #if defined(VDISCARD) && !defined(VFLUSHO)
125 # define VFLUSHO VDISCARD
127 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
128 # define VFLUSHO VFLUSH
130 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
131 # define ECHOCTL CTLECH
133 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
134 # define ECHOCTL TCTLECH
136 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
137 # define ECHOKE CRTKIL
139 #if defined(VFLUSHO) && !defined(CFLUSHO)
140 # define CFLUSHO Control ('o')
142 #if defined(VSTATUS) && !defined(CSTATUS)
143 # define CSTATUS Control ('t')
146 /* Which speeds to set. */
149 input_speed
, output_speed
, both_speeds
152 /* What to output and how. */
155 changed
, all
, recoverable
/* Default, -a, -g. */
158 /* Which member(s) of `struct termios' a mode uses. */
161 control
, input
, output
, local
, combination
164 /* Flags for `struct mode_info'. */
165 #define SANE_SET 1 /* Set in `sane' mode. */
166 #define SANE_UNSET 2 /* Unset in `sane' mode. */
167 #define REV 4 /* Can be turned off by prepending `-'. */
168 #define OMIT 8 /* Don't display value. */
173 const char *name
; /* Name given on command line. */
174 enum mode_type type
; /* Which structure element to change. */
175 char flags
; /* Setting and display options. */
176 unsigned long bits
; /* Bits to set for this mode. */
177 unsigned long mask
; /* Other bits to turn off for this mode. */
180 static struct mode_info mode_info
[] =
182 {"parenb", control
, REV
, PARENB
, 0},
183 {"parodd", control
, REV
, PARODD
, 0},
184 {"cs5", control
, 0, CS5
, CSIZE
},
185 {"cs6", control
, 0, CS6
, CSIZE
},
186 {"cs7", control
, 0, CS7
, CSIZE
},
187 {"cs8", control
, 0, CS8
, CSIZE
},
188 {"hupcl", control
, REV
, HUPCL
, 0},
189 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
190 {"cstopb", control
, REV
, CSTOPB
, 0},
191 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
192 {"clocal", control
, REV
, CLOCAL
, 0},
194 {"crtscts", control
, REV
, CRTSCTS
, 0},
197 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
198 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
199 {"ignpar", input
, REV
, IGNPAR
, 0},
200 {"parmrk", input
, REV
, PARMRK
, 0},
201 {"inpck", input
, REV
, INPCK
, 0},
202 {"istrip", input
, REV
, ISTRIP
, 0},
203 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
204 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
205 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
206 {"ixon", input
, REV
, IXON
, 0},
207 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
208 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
210 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
213 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
216 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
219 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
221 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
224 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
227 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
230 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
233 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
236 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
239 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
242 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
243 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
246 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
247 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
248 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
249 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
252 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
253 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
254 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
255 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
258 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
262 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
263 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
266 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
267 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
270 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
271 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
274 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
275 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
277 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
279 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
280 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
281 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
282 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
283 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
284 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
286 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
289 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
292 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
293 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
296 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
297 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
300 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
301 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
304 {"evenp", combination
, REV
| OMIT
, 0, 0},
305 {"parity", combination
, REV
| OMIT
, 0, 0},
306 {"oddp", combination
, REV
| OMIT
, 0, 0},
307 {"nl", combination
, REV
| OMIT
, 0, 0},
308 {"ek", combination
, OMIT
, 0, 0},
309 {"sane", combination
, OMIT
, 0, 0},
310 {"cooked", combination
, REV
| OMIT
, 0, 0},
311 {"raw", combination
, REV
| OMIT
, 0, 0},
312 {"pass8", combination
, REV
| OMIT
, 0, 0},
313 {"litout", combination
, REV
| OMIT
, 0, 0},
314 {"cbreak", combination
, REV
| OMIT
, 0, 0},
316 {"decctlq", combination
, REV
| OMIT
, 0, 0},
318 #if defined (TABDLY) || defined (OXTABS)
319 {"tabs", combination
, REV
| OMIT
, 0, 0},
321 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
322 {"lcase", combination
, REV
| OMIT
, 0, 0},
323 {"LCASE", combination
, REV
| OMIT
, 0, 0},
325 {"crt", combination
, OMIT
, 0, 0},
326 {"dec", combination
, OMIT
, 0, 0},
328 {NULL
, control
, 0, 0, 0}
331 /* Control character settings. */
334 const char *name
; /* Name given on command line. */
335 unsigned char saneval
; /* Value to set for `stty sane'. */
336 int offset
; /* Offset in c_cc. */
339 /* Control characters. */
341 static struct control_info control_info
[] =
343 {"intr", CINTR
, VINTR
},
344 {"quit", CQUIT
, VQUIT
},
345 {"erase", CERASE
, VERASE
},
346 {"kill", CKILL
, VKILL
},
350 {"eol2", CEOL2
, VEOL2
},
353 {"swtch", CSWTCH
, VSWTCH
},
355 {"start", CSTART
, VSTART
},
356 {"stop", CSTOP
, VSTOP
},
357 {"susp", CSUSP
, VSUSP
},
359 {"dsusp", CDSUSP
, VDSUSP
},
362 {"rprnt", CRPRNT
, VREPRINT
},
365 {"werase", CWERASE
, VWERASE
},
368 {"lnext", CLNEXT
, VLNEXT
},
371 {"flush", CFLUSHO
, VFLUSHO
},
374 {"status", CSTATUS
, VSTATUS
},
377 /* These must be last because of the display routines. */
383 static const char *visible
__P ((unsigned int ch
));
384 static unsigned long baud_to_value
__P ((speed_t speed
));
385 static int recover_mode
__P ((char *arg
, struct termios
*mode
));
386 static int screen_columns
__P ((void));
387 static int set_mode
__P ((struct mode_info
*info
, int reversed
,
388 struct termios
*mode
));
389 static long integer_arg
__P ((const char *s
));
390 static speed_t string_to_baud
__P ((const char *arg
));
391 static tcflag_t
*mode_type_flag
__P ((enum mode_type type
,
392 struct termios
*mode
));
393 static void display_all
__P ((struct termios
*mode
));
394 static void display_changed
__P ((struct termios
*mode
));
395 static void display_recoverable
__P ((struct termios
*mode
));
396 static void display_settings
__P ((enum output_type output_type
,
397 struct termios
*mode
));
398 static void display_speed
__P ((struct termios
*mode
, int fancy
));
399 static void display_window_size
__P ((int fancy
));
400 static void sane_mode
__P ((struct termios
*mode
));
401 static void set_control_char
__P ((struct control_info
*info
, const char *arg
,
402 struct termios
*mode
));
403 static void set_speed
__P ((enum speed_setting type
, const char *arg
,
404 struct termios
*mode
));
405 static void set_window_size
__P ((int rows
, int cols
));
407 /* The width of the screen, for output wrapping. */
410 /* Current position, to know when to wrap. */
411 static int current_col
;
413 static struct option longopts
[] =
415 {"all", no_argument
, NULL
, 'a'},
416 {"save", no_argument
, NULL
, 'g'},
420 /* The name this program was run with. */
423 /* Print format string MESSAGE and optional args.
424 Wrap to next line first if it won't fit.
425 Print a space first unless MESSAGE will start a new line. */
430 wrapf (const char *message
,...)
432 wrapf (message
, va_alist
)
438 char buf
[1024]; /* Plenty long for our needs. */
441 VA_START (args
, message
);
442 vsprintf (buf
, message
, args
);
444 buflen
= strlen (buf
);
445 if (current_col
+ (current_col
> 0) + buflen
>= max_col
)
456 current_col
+= buflen
;
463 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
468 Usage: %s [SETTING]...\n\
471 program_name
, program_name
);
473 Print or change terminal characteristics.\n\
475 -a, --all print all current settings in human-readable form\n\
476 -g, --save print all current settings in a stty-readable form\n\
477 --help display this help and exit\n\
478 --version output version information and exit\n\
480 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
481 settings. The underlying system defines which settings are available.\n\
485 Special characters:\n\
486 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
487 eof CHAR CHAR will send an end of file (terminate the input)\n\
488 eol CHAR CHAR will end the line\n\
489 * eol2 CHAR alternate CHAR for ending the line\n\
490 erase CHAR CHAR will erase the last character typed\n\
491 intr CHAR CHAR will send an interrupt signal\n\
492 kill CHAR CHAR will erase the current line\n\
493 * lnext CHAR CHAR will enter the next character quoted\n\
494 quit CHAR CHAR will send a quit signal\n\
495 * rprnt CHAR CHAR will redraw the current line\n\
496 start CHAR CHAR will restart the output after stopping it\n\
497 stop CHAR CHAR will stop the output\n\
498 susp CHAR CHAR will send a terminal stop signal\n\
499 * swtch CHAR CHAR will switch to a different shell layer\n\
500 * werase CHAR CHAR will erase the last word typed\n\
505 N set the input and output speeds to N bauds\n\
506 * cols N tell the kernel that the terminal has N columns\n\
507 * columns N same as cols N\n\
508 ispeed N set the input speed to N\n\
509 * line N use line discipline N\n\
510 min N with -icanon, set N characters minimum for a completed read\n\
511 ospeed N set the output speed to N\n\
512 * rows N tell the kernel that the terminal has N rows\n\
513 * size print the number of rows and columns according to the kernel\n\
514 speed print the terminal speed\n\
515 time N with -icanon, set read timeout of N tenths of a second\n\
520 [-]clocal disable modem control signals\n\
521 [-]cread allow input to be received\n\
522 * [-]crtscts enable RTS/CTS handshaking\n\
523 csN set character size to N bits, N in [5..8]\n\
524 [-]cstopb use two stop bits per character (one with `-')\n\
525 [-]hup send a hangup signal when the last process closes the tty\n\
526 [-]hupcl same as [-]hup\n\
527 [-]parenb generate parity bit in output and expect parity bit in input\n\
528 [-]parodd set odd parity (even with `-')\n\
533 [-]brkint breaks cause an interrupt signal\n\
534 [-]icrnl translate carriage return to newline\n\
535 [-]ignbrk ignore break characters\n\
536 [-]igncr ignore carriage return\n\
537 [-]ignpar ignore characters with parity errors\n\
538 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
539 [-]inlcr translate newline to carriage return\n\
540 [-]inpck enable input parity checking\n\
541 [-]istrip clear high (8th) bit of input characters\n\
542 * [-]iuclc translate uppercase characters to lowercase\n\
543 * [-]ixany let any character restart output, not only start character\n\
544 [-]ixoff enable sending of start/stop characters\n\
545 [-]ixon enable XON/XOFF flow control\n\
546 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
547 [-]tandem same as [-]ixoff\n\
552 * bsN backspace delay style, N in [0..1]\n\
553 * crN carriage return delay style, N in [0..3]\n\
554 * ffN form feed delay style, N in [0..1]\n\
555 * nlN newline delay style, N in [0..1]\n\
556 * [-]ocrnl translate carriage return to newline\n\
557 * [-]ofdel use delete characters for fill instead of null characters\n\
558 * [-]ofill use fill (padding) characters instead of timing for delays\n\
559 * [-]olcuc translate lowercase characters to uppercase\n\
560 * [-]onlcr translate newline to carriage return-newline\n\
561 * [-]onlret newline performs a carriage return\n\
562 * [-]onocr do not print carriage returns in the first column\n\
563 [-]opost postprocess output\n\
564 * tabN horizontal tab delay style, N in [0..3]\n\
565 * tabs same as tab0\n\
566 * -tabs same as tab3\n\
567 * vtN vertical tab delay style, N in [0..1]\n\
572 [-]crterase echo erase characters as backspace-space-backspace\n\
573 * crtkill kill all line by obeying the echoprt and echoe settings\n\
574 * -crtkill kill all line by obeying the echoctl and echok settings\n\
575 * [-]ctlecho echo control characters in hat notation (`^c')\n\
576 [-]echo echo input characters\n\
577 * [-]echoctl same as [-]ctlecho\n\
578 [-]echoe same as [-]crterase\n\
579 [-]echok echo a newline after a kill character\n\
580 * [-]echoke same as [-]crtkill\n\
581 [-]echonl echo newline even if not echoing other characters\n\
582 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
583 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
584 [-]iexten enable non-POSIX special characters\n\
585 [-]isig enable interrupt, quit, and suspend special characters\n\
586 [-]noflsh disable flushing after interrupt and quit special characters\n\
587 * [-]prterase same as [-]echoprt\n\
588 * [-]tostop stop background jobs that try to write to the terminal\n\
589 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
593 Combination settings:\n\
594 * [-]LCASE same as [-]lcase\n\
595 cbreak same as -icanon\n\
596 -cbreak same as icanon\n\
597 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
598 icanon, eof and eol characters to their default values\n\
599 -cooked same as raw\n\
600 crt same as echoe echoctl echoke\n\
601 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
603 * [-]decctlq same as [-]ixany\n\
604 ek erase and kill characters to their default values\n\
605 evenp same as parenb -parodd cs7\n\
606 -evenp same as -parenb cs8\n\
607 * [-]lcase same as xcase iuclc olcuc\n\
608 litout same as -parenb -istrip -opost cs8\n\
609 -litout same as parenb istrip opost cs7\n\
610 nl same as -icrnl -onlcr\n\
611 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
612 oddp same as parenb parodd cs7\n\
613 -oddp same as -parenb cs8\n\
614 [-]parity same as [-]evenp\n\
615 pass8 same as -parenb -istrip cs8\n\
616 -pass8 same as parenb istrip cs7\n\
617 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
618 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
619 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
620 -raw same as cooked\n\
621 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
622 -ixoff -iucl -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
623 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
624 isig icanon iexten echo echoe echok -echonl -noflsh\n\
625 -xcase -tostop -echoprt echoctl echoke, all special\n\
626 characters to their default values.\n\
630 Handle the tty line connected to standard input. Without arguments,\n\
631 prints baud rate, line discipline, and deviations from stty sane. In\n\
632 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
633 127; special values ^- or undef used to disable special characters.\n\
640 main (int argc
, char **argv
)
643 enum output_type output_type
;
645 int require_set_attr
;
648 int recoverable_output
;
651 program_name
= argv
[0];
652 setlocale (LC_ALL
, "");
653 bindtextdomain (PACKAGE
, LOCALEDIR
);
654 textdomain (PACKAGE
);
656 parse_long_options (argc
, argv
, "stty", PACKAGE_VERSION
, usage
);
658 output_type
= changed
;
660 recoverable_output
= 0;
662 /* Recognize the long options only. */
664 while ((optc
= getopt_long_only (argc
, argv
, "ag", longopts
, (int *) 0))
675 recoverable_output
= 1;
676 output_type
= recoverable
;
684 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
685 They need not precede non-options. We cannot use GNU getopt because
686 it would treat -tabs and -ixany as uses of the -a option. */
687 for (k
= optind
; k
< argc
; k
++)
689 if (argv
[k
][0] == '-')
691 if (argv
[k
][1] == 'a'
692 && argv
[k
][2] == '\0')
697 else if (argv
[k
][1] == 'g'
698 && argv
[k
][2] == '\0')
701 recoverable_output
= 1;
703 else if ((argv
[k
][1] == 'g'
705 && argv
[k
][3] == '\0')
706 || (argv
[k
][1] == 'a'
708 && argv
[k
][3] == '\0'))
712 recoverable_output
= 1;
717 /* Specifying both -a and -g gets an error. */
718 if (verbose_output
&& recoverable_output
)
720 _("the options for verbose and stty-readable output styles are\n\
721 \tmutually exclusive"));
723 /* Specifying any other arguments with -a or -g gets an error. */
724 if (argc
- optind
> 0 && (verbose_output
|| recoverable_output
))
725 error (2, 0, _("when specifying an output style, modes may not be set"));
727 /* Initialize to all zeroes so there is no risk memcmp will report a
728 spurious difference in an uninitialized portion of the structure. */
729 memset (&mode
, 0, sizeof (mode
));
730 if (tcgetattr (0, &mode
))
731 error (1, errno
, _("standard input"));
733 if (verbose_output
|| recoverable_output
|| argc
== 1)
735 max_col
= screen_columns ();
737 display_settings (output_type
, &mode
);
742 require_set_attr
= 0;
750 if (argv
[k
][0] == '-')
755 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
757 if (!strcmp (argv
[k
], mode_info
[i
].name
))
759 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
760 require_set_attr
= 1;
764 if (match_found
== 0 && reversed
)
766 error (0, 0, _("invalid argument `%s'"), --argv
[k
]);
769 if (match_found
== 0)
771 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
773 if (!strcmp (argv
[k
], control_info
[i
].name
))
777 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
782 set_control_char (&control_info
[i
], argv
[k
], &mode
);
783 require_set_attr
= 1;
788 if (match_found
== 0)
790 if (!strcmp (argv
[k
], "ispeed"))
794 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
798 set_speed (input_speed
, argv
[k
], &mode
);
800 require_set_attr
= 1;
802 else if (!strcmp (argv
[k
], "ospeed"))
806 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
810 set_speed (output_speed
, argv
[k
], &mode
);
812 require_set_attr
= 1;
815 else if (!strcmp (argv
[k
], "rows"))
819 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
823 set_window_size ((int) integer_arg (argv
[k
]), -1);
825 else if (!strcmp (argv
[k
], "cols")
826 || !strcmp (argv
[k
], "columns"))
830 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
834 set_window_size (-1, (int) integer_arg (argv
[k
]));
836 else if (!strcmp (argv
[k
], "size"))
838 max_col
= screen_columns ();
840 display_window_size (0);
844 else if (!strcmp (argv
[k
], "line"))
848 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
852 mode
.c_line
= integer_arg (argv
[k
]);
853 require_set_attr
= 1;
856 else if (!strcmp (argv
[k
], "speed"))
858 max_col
= screen_columns ();
859 display_speed (&mode
, 0);
861 else if (string_to_baud (argv
[k
]) != (speed_t
) -1)
863 set_speed (both_speeds
, argv
[k
], &mode
);
865 require_set_attr
= 1;
869 if (recover_mode (argv
[k
], &mode
) == 0)
871 error (0, 0, _("invalid argument `%s'"), argv
[k
]);
874 require_set_attr
= 1;
880 if (require_set_attr
)
882 struct termios new_mode
;
884 if (tcsetattr (0, TCSADRAIN
, &mode
))
885 error (1, errno
, _("standard input"));
887 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
888 it performs *any* of the requested operations. This means it
889 can report `success' when it has actually failed to perform
890 some proper subset of the requested operations. To detect
891 this partial failure, get the current terminal attributes and
892 compare them to the requested ones. */
894 /* Initialize to all zeroes so there is no risk memcmp will report a
895 spurious difference in an uninitialized portion of the structure. */
896 memset (&new_mode
, 0, sizeof (new_mode
));
897 if (tcgetattr (0, &new_mode
))
898 error (1, errno
, _("standard input"));
900 /* Normally, one shouldn't use memcmp to compare structures that
901 may have `holes' containing uninitialized data, but we have been
902 careful to initialize the storage of these two variables to all
903 zeroes. One might think it more efficient simply to compare the
904 modified fields, but that would require enumerating those fields --
905 and not all systems have the same fields in this structure. */
907 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
910 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
911 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
912 sometimes (m1 != m2). The only difference is in the four bits
913 of the c_cflag field corresponding to the baud rate. To save
914 Sun users a little confusion, don't report an error if this
915 happens. But suppress the error only if we haven't tried to
916 set the baud rate explicitly -- otherwise we'd never give an
917 error for a true failure to set the baud rate. */
919 new_mode
.c_cflag
&= (~CIBAUD
);
920 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
925 _("standard input: unable to perform all requested operations"));
926 printf (_("new_mode: mode\n"));
927 for (i
=0; i
<sizeof(new_mode
); i
++)
928 printf ("0x%02x: 0x%02x\n",
929 *(((unsigned char *) &new_mode
) + i
),
930 *(((unsigned char *) &mode
) + i
));
938 /* Return 0 if not applied because not reversible; otherwise return 1. */
941 set_mode (struct mode_info
*info
, int reversed
, struct termios
*mode
)
945 if (reversed
&& (info
->flags
& REV
) == 0)
948 bitsp
= mode_type_flag (info
->type
, mode
);
952 /* Combination mode. */
953 if (!strcmp (info
->name
, "evenp") || !strcmp (info
->name
, "parity"))
956 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
958 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
960 else if (!strcmp (info
->name
, "oddp"))
963 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
965 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
967 else if (!strcmp (info
->name
, "nl"))
971 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
972 mode
->c_oflag
= (mode
->c_oflag
987 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
989 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
993 else if (!strcmp (info
->name
, "ek"))
995 mode
->c_cc
[VERASE
] = CERASE
;
996 mode
->c_cc
[VKILL
] = CKILL
;
998 else if (!strcmp (info
->name
, "sane"))
1000 else if (!strcmp (info
->name
, "cbreak"))
1003 mode
->c_lflag
|= ICANON
;
1005 mode
->c_lflag
&= ~ICANON
;
1007 else if (!strcmp (info
->name
, "pass8"))
1011 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1012 mode
->c_iflag
|= ISTRIP
;
1016 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1017 mode
->c_iflag
&= ~ISTRIP
;
1020 else if (!strcmp (info
->name
, "litout"))
1024 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1025 mode
->c_iflag
|= ISTRIP
;
1026 mode
->c_oflag
|= OPOST
;
1030 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1031 mode
->c_iflag
&= ~ISTRIP
;
1032 mode
->c_oflag
&= ~OPOST
;
1035 else if (!strcmp (info
->name
, "raw") || !strcmp (info
->name
, "cooked"))
1037 if ((info
->name
[0] == 'r' && reversed
)
1038 || (info
->name
[0] == 'c' && !reversed
))
1041 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1042 mode
->c_oflag
|= OPOST
;
1043 mode
->c_lflag
|= ISIG
| ICANON
;
1045 mode
->c_cc
[VEOF
] = CEOF
;
1048 mode
->c_cc
[VEOL
] = CEOL
;
1055 mode
->c_oflag
&= ~OPOST
;
1056 mode
->c_lflag
&= ~(ISIG
| ICANON
1061 mode
->c_cc
[VMIN
] = 1;
1062 mode
->c_cc
[VTIME
] = 0;
1066 else if (!strcmp (info
->name
, "decctlq"))
1069 mode
->c_iflag
|= IXANY
;
1071 mode
->c_iflag
&= ~IXANY
;
1075 else if (!strcmp (info
->name
, "tabs"))
1078 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1080 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1084 else if (!strcmp (info
->name
, "tabs"))
1087 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1089 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1093 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1094 else if (!strcmp (info
->name
, "lcase")
1095 || !strcmp (info
->name
, "LCASE"))
1099 mode
->c_lflag
&= ~XCASE
;
1100 mode
->c_iflag
&= ~IUCLC
;
1101 mode
->c_oflag
&= ~OLCUC
;
1105 mode
->c_lflag
|= XCASE
;
1106 mode
->c_iflag
|= IUCLC
;
1107 mode
->c_oflag
|= OLCUC
;
1111 else if (!strcmp (info
->name
, "crt"))
1112 mode
->c_lflag
|= ECHOE
1120 else if (!strcmp (info
->name
, "dec"))
1122 mode
->c_cc
[VINTR
] = 3; /* ^C */
1123 mode
->c_cc
[VERASE
] = 127; /* DEL */
1124 mode
->c_cc
[VKILL
] = 21; /* ^U */
1125 mode
->c_lflag
|= ECHOE
1134 mode
->c_iflag
&= ~IXANY
;
1139 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1141 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1147 set_control_char (struct control_info
*info
, const char *arg
,
1148 struct termios
*mode
)
1150 unsigned char value
;
1152 if (!strcmp (info
->name
, "min") || !strcmp (info
->name
, "time"))
1153 value
= integer_arg (arg
);
1154 else if (arg
[0] == '\0' || arg
[1] == '\0')
1156 else if (!strcmp (arg
, "^-") || !strcmp (arg
, "undef"))
1157 value
= _POSIX_VDISABLE
;
1158 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1163 value
= arg
[1] & ~0140; /* Non-letters get weird results. */
1166 value
= integer_arg (arg
);
1167 mode
->c_cc
[info
->offset
] = value
;
1171 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1175 baud
= string_to_baud (arg
);
1176 if (type
== input_speed
|| type
== both_speeds
)
1177 cfsetispeed (mode
, baud
);
1178 if (type
== output_speed
|| type
== both_speeds
)
1179 cfsetospeed (mode
, baud
);
1184 /* Get window size information. First try getting the information
1185 associated with standard output and if that fails, try standard input.
1186 Return zero for success, nonzero if both ioctl's failed. */
1189 get_win_size (struct winsize
*win
)
1193 err
= ioctl (1, TIOCGWINSZ
, (char *) win
);
1195 err
= ioctl (0, TIOCGWINSZ
, (char *) win
);
1200 set_window_size (int rows
, int cols
)
1204 if (get_win_size (&win
))
1206 if (errno
!= EINVAL
)
1207 error (1, errno
, _("standard input"));
1208 memset (&win
, 0, sizeof (win
));
1217 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1218 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1219 This comment from sys/ttold.h describes Sun's twisted logic - a better
1220 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1221 At any rate, the problem is gone in Solaris 2.x.
1223 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1224 but they can be disambiguated by checking whether a "struct ttysize"
1225 structure's "ts_lines" field is greater than 64K or not. If so,
1226 it's almost certainly a "struct winsize" instead.
1228 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1229 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1230 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1231 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1232 "stty cols 0 rows 0" would do the right thing. On a little-endian
1233 machine like the sun386i, the problem is the same, but for ws_col == 0.
1235 The workaround is to do the ioctl once with row and col = 1 to set the
1236 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1238 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1240 struct ttysize ttysz
;
1242 ttysz
.ts_lines
= win
.ws_row
;
1243 ttysz
.ts_cols
= win
.ws_col
;
1248 if (ioctl (0, TIOCSWINSZ
, (char *) &win
))
1249 error (1, errno
, _("standard input"));
1251 if (ioctl (0, TIOCSSIZE
, (char *) &ttysz
))
1252 error (1, errno
, _("standard input"));
1257 if (ioctl (0, TIOCSWINSZ
, (char *) &win
))
1258 error (1, errno
, _("standard input"));
1262 display_window_size (int fancy
)
1266 if (get_win_size (&win
))
1268 if (errno
!= EINVAL
)
1269 error (1, errno
, _("standard input"));
1273 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1274 win
.ws_row
, win
.ws_col
);
1282 screen_columns (void)
1287 if (get_win_size (&win
))
1289 /* With Solaris 2.[123], this ioctl fails and errno is set to
1290 EINVAL for telnet (but not rlogin) sessions. */
1291 if (errno
!= EINVAL
)
1292 error (1, errno
, _("standard input"));
1294 else if (win
.ws_col
> 0)
1297 if (getenv ("COLUMNS"))
1298 return atoi (getenv ("COLUMNS"));
1303 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1308 return &mode
->c_cflag
;
1311 return &mode
->c_iflag
;
1314 return &mode
->c_oflag
;
1317 return &mode
->c_lflag
;
1328 display_settings (enum output_type output_type
, struct termios
*mode
)
1330 switch (output_type
)
1333 display_changed (mode
);
1341 display_recoverable (mode
);
1347 display_changed (struct termios
*mode
)
1353 enum mode_type prev_type
= control
;
1355 display_speed (mode
, 1);
1357 wrapf ("line = %d;", mode
->c_line
);
1363 for (i
= 0; strcmp (control_info
[i
].name
, "min"); ++i
)
1365 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1368 wrapf ("%s = %s;", control_info
[i
].name
,
1369 visible (mode
->c_cc
[control_info
[i
].offset
]));
1371 if ((mode
->c_lflag
& ICANON
) == 0)
1373 wrapf ("min = %d; time = %d;\n", (int) mode
->c_cc
[VMIN
],
1374 (int) mode
->c_cc
[VTIME
]);
1376 else if (empty_line
== 0)
1381 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1383 if (mode_info
[i
].flags
& OMIT
)
1385 if (mode_info
[i
].type
!= prev_type
)
1387 if (empty_line
== 0)
1393 prev_type
= mode_info
[i
].type
;
1396 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1397 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1398 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1400 if (mode_info
[i
].flags
& SANE_UNSET
)
1402 wrapf ("%s", mode_info
[i
].name
);
1406 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1408 wrapf ("-%s", mode_info
[i
].name
);
1412 if (empty_line
== 0)
1418 display_all (struct termios
*mode
)
1423 enum mode_type prev_type
= control
;
1425 display_speed (mode
, 1);
1427 display_window_size (1);
1430 wrapf ("line = %d;", mode
->c_line
);
1435 for (i
= 0; strcmp (control_info
[i
].name
, "min"); ++i
)
1437 wrapf ("%s = %s;", control_info
[i
].name
,
1438 visible (mode
->c_cc
[control_info
[i
].offset
]));
1440 wrapf ("min = %d; time = %d;\n", mode
->c_cc
[VMIN
], mode
->c_cc
[VTIME
]);
1443 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1445 if (mode_info
[i
].flags
& OMIT
)
1447 if (mode_info
[i
].type
!= prev_type
)
1451 prev_type
= mode_info
[i
].type
;
1454 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1455 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1456 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1457 wrapf ("%s", mode_info
[i
].name
);
1458 else if (mode_info
[i
].flags
& REV
)
1459 wrapf ("-%s", mode_info
[i
].name
);
1466 display_speed (struct termios
*mode
, int fancy
)
1468 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1469 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1470 baud_to_value (cfgetospeed (mode
)));
1472 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1473 baud_to_value (cfgetispeed (mode
)),
1474 baud_to_value (cfgetospeed (mode
)));
1480 display_recoverable (struct termios
*mode
)
1484 printf ("%lx:%lx:%lx:%lx",
1485 (unsigned long) mode
->c_iflag
, (unsigned long) mode
->c_oflag
,
1486 (unsigned long) mode
->c_cflag
, (unsigned long) mode
->c_lflag
);
1487 for (i
= 0; i
< NCCS
; ++i
)
1488 printf (":%x", (unsigned int) mode
->c_cc
[i
]);
1493 recover_mode (char *arg
, struct termios
*mode
)
1497 unsigned long iflag
, oflag
, cflag
, lflag
;
1499 /* Scan into temporaries since it is too much trouble to figure out
1500 the right format for `tcflag_t'. */
1501 if (sscanf (arg
, "%lx:%lx:%lx:%lx%n",
1502 &iflag
, &oflag
, &cflag
, &lflag
, &n
) != 4)
1504 mode
->c_iflag
= iflag
;
1505 mode
->c_oflag
= oflag
;
1506 mode
->c_cflag
= cflag
;
1507 mode
->c_lflag
= lflag
;
1509 for (i
= 0; i
< NCCS
; ++i
)
1511 if (sscanf (arg
, ":%x%n", &chr
, &n
) != 1)
1513 mode
->c_cc
[i
] = chr
;
1521 const char *string
; /* ASCII representation. */
1522 speed_t speed
; /* Internal form. */
1523 unsigned long value
; /* Numeric value. */
1526 struct speed_map speeds
[] =
1533 {"134.5", B134
, 134},
1538 {"1200", B1200
, 1200},
1539 {"1800", B1800
, 1800},
1540 {"2400", B2400
, 2400},
1541 {"4800", B4800
, 4800},
1542 {"9600", B9600
, 9600},
1543 {"19200", B19200
, 19200},
1544 {"38400", B38400
, 38400},
1545 {"exta", B19200
, 19200},
1546 {"extb", B38400
, 38400},
1548 {"57600", B57600
, 57600},
1551 {"115200", B115200
, 115200},
1557 string_to_baud (const char *arg
)
1561 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1562 if (!strcmp (arg
, speeds
[i
].string
))
1563 return speeds
[i
].speed
;
1564 return (speed_t
) -1;
1567 static unsigned long
1568 baud_to_value (speed_t speed
)
1572 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1573 if (speed
== speeds
[i
].speed
)
1574 return speeds
[i
].value
;
1579 sane_mode (struct termios
*mode
)
1584 for (i
= 0; control_info
[i
].name
; ++i
)
1587 if (!strcmp (control_info
[i
].name
, "min"))
1590 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1593 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1595 if (mode_info
[i
].flags
& SANE_SET
)
1597 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1598 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1600 else if (mode_info
[i
].flags
& SANE_UNSET
)
1602 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1603 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1608 /* Return a string that is the printable representation of character CH. */
1609 /* Adapted from `cat' by Torbjorn Granlund. */
1612 visible (unsigned int ch
)
1614 static char buf
[10];
1617 if (ch
== _POSIX_VDISABLE
)
1618 return _("<undef>");
1636 *bpout
++ = ch
- 128;
1646 *bpout
++ = ch
- 128 + 64;
1656 return (const char *) buf
;
1659 /* Parse string S as an integer, using decimal radix by default,
1660 but allowing octal and hex numbers as in C. */
1661 /* From `od' by Richard Stallman. */
1664 integer_arg (const char *s
)
1667 if (xstrtol (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
)
1669 error (0, 0, _("invalid integer argument `%s'"), s
);