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)
52 #include "long-options.h"
56 #if defined(GWINSZ_BROKEN) /* Such as for SCO UNIX 3.2.2. */
60 #ifndef _POSIX_VDISABLE
61 # define _POSIX_VDISABLE ((unsigned char) 0)
64 #define Control(c) ((c) & 0x1f)
65 /* Canonical values for control characters. */
67 # define CINTR Control ('c')
76 # define CKILL Control ('u')
79 # define CEOF Control ('d')
82 # define CEOL _POSIX_VDISABLE
85 # define CSTART Control ('q')
88 # define CSTOP Control ('s')
91 # define CSUSP Control ('z')
93 #if defined(VEOL2) && !defined(CEOL2)
94 # define CEOL2 _POSIX_VDISABLE
96 #if defined(VSWTCH) && !defined(CSWTCH)
97 # define CSWTCH _POSIX_VDISABLE
100 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
101 So the default is to disable `swtch.' */
102 #if defined (__sparc__) && defined (__svr4__)
104 # define CSWTCH _POSIX_VDISABLE
107 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
108 # define VWERASE VWERSE
110 #if defined(VDSUSP) && !defined (CDSUSP)
111 # define CDSUSP Control ('y')
113 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
114 # define VREPRINT VRPRNT
116 #if defined(VREPRINT) && !defined(CRPRNT)
117 # define CRPRNT Control ('r')
119 #if defined(VWERASE) && !defined(CWERASE)
120 # define CWERASE Control ('w')
122 #if defined(VLNEXT) && !defined(CLNEXT)
123 # define CLNEXT Control ('v')
125 #if defined(VDISCARD) && !defined(VFLUSHO)
126 # define VFLUSHO VDISCARD
128 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
129 # define VFLUSHO VFLUSH
131 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
132 # define ECHOCTL CTLECH
134 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
135 # define ECHOCTL TCTLECH
137 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
138 # define ECHOKE CRTKIL
140 #if defined(VFLUSHO) && !defined(CFLUSHO)
141 # define CFLUSHO Control ('o')
143 #if defined(VSTATUS) && !defined(CSTATUS)
144 # define CSTATUS Control ('t')
147 /* Which speeds to set. */
150 input_speed
, output_speed
, both_speeds
153 /* What to output and how. */
156 changed
, all
, recoverable
/* Default, -a, -g. */
159 /* Which member(s) of `struct termios' a mode uses. */
162 control
, input
, output
, local
, combination
165 /* Flags for `struct mode_info'. */
166 #define SANE_SET 1 /* Set in `sane' mode. */
167 #define SANE_UNSET 2 /* Unset in `sane' mode. */
168 #define REV 4 /* Can be turned off by prepending `-'. */
169 #define OMIT 8 /* Don't display value. */
174 const char *name
; /* Name given on command line. */
175 enum mode_type type
; /* Which structure element to change. */
176 char flags
; /* Setting and display options. */
177 unsigned long bits
; /* Bits to set for this mode. */
178 unsigned long mask
; /* Other bits to turn off for this mode. */
181 static struct mode_info mode_info
[] =
183 {"parenb", control
, REV
, PARENB
, 0},
184 {"parodd", control
, REV
, PARODD
, 0},
185 {"cs5", control
, 0, CS5
, CSIZE
},
186 {"cs6", control
, 0, CS6
, CSIZE
},
187 {"cs7", control
, 0, CS7
, CSIZE
},
188 {"cs8", control
, 0, CS8
, CSIZE
},
189 {"hupcl", control
, REV
, HUPCL
, 0},
190 {"hup", control
, REV
| OMIT
, HUPCL
, 0},
191 {"cstopb", control
, REV
, CSTOPB
, 0},
192 {"cread", control
, SANE_SET
| REV
, CREAD
, 0},
193 {"clocal", control
, REV
, CLOCAL
, 0},
195 {"crtscts", control
, REV
, CRTSCTS
, 0},
198 {"ignbrk", input
, SANE_UNSET
| REV
, IGNBRK
, 0},
199 {"brkint", input
, SANE_SET
| REV
, BRKINT
, 0},
200 {"ignpar", input
, REV
, IGNPAR
, 0},
201 {"parmrk", input
, REV
, PARMRK
, 0},
202 {"inpck", input
, REV
, INPCK
, 0},
203 {"istrip", input
, REV
, ISTRIP
, 0},
204 {"inlcr", input
, SANE_UNSET
| REV
, INLCR
, 0},
205 {"igncr", input
, SANE_UNSET
| REV
, IGNCR
, 0},
206 {"icrnl", input
, SANE_SET
| REV
, ICRNL
, 0},
207 {"ixon", input
, REV
, IXON
, 0},
208 {"ixoff", input
, SANE_UNSET
| REV
, IXOFF
, 0},
209 {"tandem", input
, REV
| OMIT
, IXOFF
, 0},
211 {"iuclc", input
, SANE_UNSET
| REV
, IUCLC
, 0},
214 {"ixany", input
, SANE_UNSET
| REV
, IXANY
, 0},
217 {"imaxbel", input
, SANE_SET
| REV
, IMAXBEL
, 0},
220 {"opost", output
, SANE_SET
| REV
, OPOST
, 0},
222 {"olcuc", output
, SANE_UNSET
| REV
, OLCUC
, 0},
225 {"ocrnl", output
, SANE_UNSET
| REV
, OCRNL
, 0},
228 {"onlcr", output
, SANE_SET
| REV
, ONLCR
, 0},
231 {"onocr", output
, SANE_UNSET
| REV
, ONOCR
, 0},
234 {"onlret", output
, SANE_UNSET
| REV
, ONLRET
, 0},
237 {"ofill", output
, SANE_UNSET
| REV
, OFILL
, 0},
240 {"ofdel", output
, SANE_UNSET
| REV
, OFDEL
, 0},
243 {"nl1", output
, SANE_UNSET
, NL1
, NLDLY
},
244 {"nl0", output
, SANE_SET
, NL0
, NLDLY
},
247 {"cr3", output
, SANE_UNSET
, CR3
, CRDLY
},
248 {"cr2", output
, SANE_UNSET
, CR2
, CRDLY
},
249 {"cr1", output
, SANE_UNSET
, CR1
, CRDLY
},
250 {"cr0", output
, SANE_SET
, CR0
, CRDLY
},
253 {"tab3", output
, SANE_UNSET
, TAB3
, TABDLY
},
254 {"tab2", output
, SANE_UNSET
, TAB2
, TABDLY
},
255 {"tab1", output
, SANE_UNSET
, TAB1
, TABDLY
},
256 {"tab0", output
, SANE_SET
, TAB0
, TABDLY
},
259 {"tab3", output
, SANE_UNSET
, OXTABS
, 0},
263 {"bs1", output
, SANE_UNSET
, BS1
, BSDLY
},
264 {"bs0", output
, SANE_SET
, BS0
, BSDLY
},
267 {"vt1", output
, SANE_UNSET
, VT1
, VTDLY
},
268 {"vt0", output
, SANE_SET
, VT0
, VTDLY
},
271 {"ff1", output
, SANE_UNSET
, FF1
, FFDLY
},
272 {"ff0", output
, SANE_SET
, FF0
, FFDLY
},
275 {"isig", local
, SANE_SET
| REV
, ISIG
, 0},
276 {"icanon", local
, SANE_SET
| REV
, ICANON
, 0},
278 {"iexten", local
, SANE_SET
| REV
, IEXTEN
, 0},
280 {"echo", local
, SANE_SET
| REV
, ECHO
, 0},
281 {"echoe", local
, SANE_SET
| REV
, ECHOE
, 0},
282 {"crterase", local
, REV
| OMIT
, ECHOE
, 0},
283 {"echok", local
, SANE_SET
| REV
, ECHOK
, 0},
284 {"echonl", local
, SANE_UNSET
| REV
, ECHONL
, 0},
285 {"noflsh", local
, SANE_UNSET
| REV
, NOFLSH
, 0},
287 {"xcase", local
, SANE_UNSET
| REV
, XCASE
, 0},
290 {"tostop", local
, SANE_UNSET
| REV
, TOSTOP
, 0},
293 {"echoprt", local
, SANE_UNSET
| REV
, ECHOPRT
, 0},
294 {"prterase", local
, REV
| OMIT
, ECHOPRT
, 0},
297 {"echoctl", local
, SANE_SET
| REV
, ECHOCTL
, 0},
298 {"ctlecho", local
, REV
| OMIT
, ECHOCTL
, 0},
301 {"echoke", local
, SANE_SET
| REV
, ECHOKE
, 0},
302 {"crtkill", local
, REV
| OMIT
, ECHOKE
, 0},
305 {"evenp", combination
, REV
| OMIT
, 0, 0},
306 {"parity", combination
, REV
| OMIT
, 0, 0},
307 {"oddp", combination
, REV
| OMIT
, 0, 0},
308 {"nl", combination
, REV
| OMIT
, 0, 0},
309 {"ek", combination
, OMIT
, 0, 0},
310 {"sane", combination
, OMIT
, 0, 0},
311 {"cooked", combination
, REV
| OMIT
, 0, 0},
312 {"raw", combination
, REV
| OMIT
, 0, 0},
313 {"pass8", combination
, REV
| OMIT
, 0, 0},
314 {"litout", combination
, REV
| OMIT
, 0, 0},
315 {"cbreak", combination
, REV
| OMIT
, 0, 0},
317 {"decctlq", combination
, REV
| OMIT
, 0, 0},
319 #if defined (TABDLY) || defined (OXTABS)
320 {"tabs", combination
, REV
| OMIT
, 0, 0},
322 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
323 {"lcase", combination
, REV
| OMIT
, 0, 0},
324 {"LCASE", combination
, REV
| OMIT
, 0, 0},
326 {"crt", combination
, OMIT
, 0, 0},
327 {"dec", combination
, OMIT
, 0, 0},
329 {NULL
, control
, 0, 0, 0}
332 /* Control character settings. */
335 const char *name
; /* Name given on command line. */
336 unsigned char saneval
; /* Value to set for `stty sane'. */
337 int offset
; /* Offset in c_cc. */
340 /* Control characters. */
342 static struct control_info control_info
[] =
344 {"intr", CINTR
, VINTR
},
345 {"quit", CQUIT
, VQUIT
},
346 {"erase", CERASE
, VERASE
},
347 {"kill", CKILL
, VKILL
},
351 {"eol2", CEOL2
, VEOL2
},
354 {"swtch", CSWTCH
, VSWTCH
},
356 {"start", CSTART
, VSTART
},
357 {"stop", CSTOP
, VSTOP
},
358 {"susp", CSUSP
, VSUSP
},
360 {"dsusp", CDSUSP
, VDSUSP
},
363 {"rprnt", CRPRNT
, VREPRINT
},
366 {"werase", CWERASE
, VWERASE
},
369 {"lnext", CLNEXT
, VLNEXT
},
372 {"flush", CFLUSHO
, VFLUSHO
},
375 {"status", CSTATUS
, VSTATUS
},
378 /* These must be last because of the display routines. */
384 static const char *visible
__P ((unsigned int ch
));
385 static unsigned long baud_to_value
__P ((speed_t speed
));
386 static int recover_mode
__P ((char *arg
, struct termios
*mode
));
387 static int screen_columns
__P ((void));
388 static int set_mode
__P ((struct mode_info
*info
, int reversed
,
389 struct termios
*mode
));
390 static long integer_arg
__P ((const char *s
));
391 static speed_t string_to_baud
__P ((const char *arg
));
392 static tcflag_t
*mode_type_flag
__P ((enum mode_type type
,
393 struct termios
*mode
));
394 static void display_all
__P ((struct termios
*mode
));
395 static void display_changed
__P ((struct termios
*mode
));
396 static void display_recoverable
__P ((struct termios
*mode
));
397 static void display_settings
__P ((enum output_type output_type
,
398 struct termios
*mode
));
399 static void display_speed
__P ((struct termios
*mode
, int fancy
));
400 static void display_window_size
__P ((int fancy
));
401 static void sane_mode
__P ((struct termios
*mode
));
402 static void set_control_char
__P ((struct control_info
*info
, const char *arg
,
403 struct termios
*mode
));
404 static void set_speed
__P ((enum speed_setting type
, const char *arg
,
405 struct termios
*mode
));
406 static void set_window_size
__P ((int rows
, int cols
));
408 /* The width of the screen, for output wrapping. */
411 /* Current position, to know when to wrap. */
412 static int current_col
;
414 static struct option longopts
[] =
416 {"all", no_argument
, NULL
, 'a'},
417 {"save", no_argument
, NULL
, 'g'},
421 /* The name this program was run with. */
424 /* Print format string MESSAGE and optional args.
425 Wrap to next line first if it won't fit.
426 Print a space first unless MESSAGE will start a new line. */
431 wrapf (const char *message
,...)
433 wrapf (message
, va_alist
)
439 char buf
[1024]; /* Plenty long for our needs. */
442 VA_START (args
, message
);
443 vsprintf (buf
, message
, args
);
445 buflen
= strlen (buf
);
446 if (current_col
+ (current_col
> 0) + buflen
>= max_col
)
457 current_col
+= buflen
;
464 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
469 Usage: %s [SETTING]...\n\
472 program_name
, program_name
);
474 Print or change terminal characteristics.\n\
476 -a, --all print all current settings in human-readable form\n\
477 -g, --save print all current settings in a stty-readable form\n\
478 --help display this help and exit\n\
479 --version output version information and exit\n\
481 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
482 settings. The underlying system defines which settings are available.\n\
486 Special characters:\n\
487 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
488 eof CHAR CHAR will send an end of file (terminate the input)\n\
489 eol CHAR CHAR will end the line\n\
490 * eol2 CHAR alternate CHAR for ending the line\n\
491 erase CHAR CHAR will erase the last character typed\n\
492 intr CHAR CHAR will send an interrupt signal\n\
493 kill CHAR CHAR will erase the current line\n\
494 * lnext CHAR CHAR will enter the next character quoted\n\
495 quit CHAR CHAR will send a quit signal\n\
496 * rprnt CHAR CHAR will redraw the current line\n\
497 start CHAR CHAR will restart the output after stopping it\n\
498 stop CHAR CHAR will stop the output\n\
499 susp CHAR CHAR will send a terminal stop signal\n\
500 * swtch CHAR CHAR will switch to a different shell layer\n\
501 * werase CHAR CHAR will erase the last word typed\n\
506 N set the input and output speeds to N bauds\n\
507 * cols N tell the kernel that the terminal has N columns\n\
508 * columns N same as cols N\n\
509 ispeed N set the input speed to N\n\
510 * line N use line discipline N\n\
511 min N with -icanon, set N characters minimum for a completed read\n\
512 ospeed N set the output speed to N\n\
513 * rows N tell the kernel that the terminal has N rows\n\
514 * size print the number of rows and columns according to the kernel\n\
515 speed print the terminal speed\n\
516 time N with -icanon, set read timeout of N tenths of a second\n\
521 [-]clocal disable modem control signals\n\
522 [-]cread allow input to be received\n\
523 * [-]crtscts enable RTS/CTS handshaking\n\
524 csN set character size to N bits, N in [5..8]\n\
525 [-]cstopb use two stop bits per character (one with `-')\n\
526 [-]hup send a hangup signal when the last process closes the tty\n\
527 [-]hupcl same as [-]hup\n\
528 [-]parenb generate parity bit in output and expect parity bit in input\n\
529 [-]parodd set odd parity (even with `-')\n\
534 [-]brkint breaks cause an interrupt signal\n\
535 [-]icrnl translate carriage return to newline\n\
536 [-]ignbrk ignore break characters\n\
537 [-]igncr ignore carriage return\n\
538 [-]ignpar ignore characters with parity errors\n\
539 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
540 [-]inlcr translate newline to carriage return\n\
541 [-]inpck enable input parity checking\n\
542 [-]istrip clear high (8th) bit of input characters\n\
543 * [-]iuclc translate uppercase characters to lowercase\n\
544 * [-]ixany let any character restart output, not only start character\n\
545 [-]ixoff enable sending of start/stop characters\n\
546 [-]ixon enable XON/XOFF flow control\n\
547 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
548 [-]tandem same as [-]ixoff\n\
553 * bsN backspace delay style, N in [0..1]\n\
554 * crN carriage return delay style, N in [0..3]\n\
555 * ffN form feed delay style, N in [0..1]\n\
556 * nlN newline delay style, N in [0..1]\n\
557 * [-]ocrnl translate carriage return to newline\n\
558 * [-]ofdel use delete characters for fill instead of null characters\n\
559 * [-]ofill use fill (padding) characters instead of timing for delays\n\
560 * [-]olcuc translate lowercase characters to uppercase\n\
561 * [-]onlcr translate newline to carriage return-newline\n\
562 * [-]onlret newline performs a carriage return\n\
563 * [-]onocr do not print carriage returns in the first column\n\
564 [-]opost postprocess output\n\
565 * tabN horizontal tab delay style, N in [0..3]\n\
566 * tabs same as tab0\n\
567 * -tabs same as tab3\n\
568 * vtN vertical tab delay style, N in [0..1]\n\
573 [-]crterase echo erase characters as backspace-space-backspace\n\
574 * crtkill kill all line by obeying the echoprt and echoe settings\n\
575 * -crtkill kill all line by obeying the echoctl and echok settings\n\
576 * [-]ctlecho echo control characters in hat notation (`^c')\n\
577 [-]echo echo input characters\n\
578 * [-]echoctl same as [-]ctlecho\n\
579 [-]echoe same as [-]crterase\n\
580 [-]echok echo a newline after a kill character\n\
581 * [-]echoke same as [-]crtkill\n\
582 [-]echonl echo newline even if not echoing other characters\n\
583 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
584 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
585 [-]iexten enable non-POSIX special characters\n\
586 [-]isig enable interrupt, quit, and suspend special characters\n\
587 [-]noflsh disable flushing after interrupt and quit special characters\n\
588 * [-]prterase same as [-]echoprt\n\
589 * [-]tostop stop background jobs that try to write to the terminal\n\
590 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
594 Combination settings:\n\
595 * [-]LCASE same as [-]lcase\n\
596 cbreak same as -icanon\n\
597 -cbreak same as icanon\n\
598 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
599 icanon, eof and eol characters to their default values\n\
600 -cooked same as raw\n\
601 crt same as echoe echoctl echoke\n\
602 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
604 * [-]decctlq same as [-]ixany\n\
605 ek erase and kill characters to their default values\n\
606 evenp same as parenb -parodd cs7\n\
607 -evenp same as -parenb cs8\n\
608 * [-]lcase same as xcase iuclc olcuc\n\
609 litout same as -parenb -istrip -opost cs8\n\
610 -litout same as parenb istrip opost cs7\n\
611 nl same as -icrnl -onlcr\n\
612 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
613 oddp same as parenb parodd cs7\n\
614 -oddp same as -parenb cs8\n\
615 [-]parity same as [-]evenp\n\
616 pass8 same as -parenb -istrip cs8\n\
617 -pass8 same as parenb istrip cs7\n\
618 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
619 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
620 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
621 -raw same as cooked\n\
622 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
623 -ixoff -iucl -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
624 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
625 isig icanon iexten echo echoe echok -echonl -noflsh\n\
626 -xcase -tostop -echoprt echoctl echoke, all special\n\
627 characters to their default values.\n\
631 Handle the tty line connected to standard input. Without arguments,\n\
632 prints baud rate, line discipline, and deviations from stty sane. In\n\
633 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
634 127; special values ^- or undef used to disable special characters.\n\
641 main (int argc
, char **argv
)
644 enum output_type output_type
;
646 int require_set_attr
;
649 int recoverable_output
;
652 program_name
= argv
[0];
654 parse_long_options (argc
, argv
, "stty", version_string
, usage
);
656 output_type
= changed
;
658 recoverable_output
= 0;
660 /* Recognize the long options only. */
662 while ((optc
= getopt_long_only (argc
, argv
, "ag", longopts
, (int *) 0))
673 recoverable_output
= 1;
674 output_type
= recoverable
;
682 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
683 They need not precede non-options. We cannot use GNU getopt because
684 it would treat -tabs and -ixany as uses of the -a option. */
685 for (k
= optind
; k
< argc
; k
++)
687 if (argv
[k
][0] == '-')
689 if (argv
[k
][1] == 'a'
690 && argv
[k
][2] == '\0')
695 else if (argv
[k
][1] == 'g'
696 && argv
[k
][2] == '\0')
699 recoverable_output
= 1;
701 else if ((argv
[k
][1] == 'g'
703 && argv
[k
][3] == '\0')
704 || (argv
[k
][1] == 'a'
706 && argv
[k
][3] == '\0'))
710 recoverable_output
= 1;
715 /* Specifying both -a and -g gets an error. */
716 if (verbose_output
&& recoverable_output
)
718 _("the options for verbose and stty-readable output styles are\n\
719 \tmutually exclusive"));
721 /* Specifying any other arguments with -a or -g gets an error. */
722 if (argc
- optind
> 0 && (verbose_output
|| recoverable_output
))
723 error (2, 0, _("when specifying an output style, modes may not be set"));
725 /* Initialize to all zeroes so there is no risk memcmp will report a
726 spurious difference in an uninitialized portion of the structure. */
727 memset (&mode
, 0, sizeof (mode
));
728 if (tcgetattr (0, &mode
))
729 error (1, errno
, _("standard input"));
731 if (verbose_output
|| recoverable_output
|| argc
== 1)
733 max_col
= screen_columns ();
735 display_settings (output_type
, &mode
);
740 require_set_attr
= 0;
748 if (argv
[k
][0] == '-')
753 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
755 if (!strcmp (argv
[k
], mode_info
[i
].name
))
757 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
758 require_set_attr
= 1;
762 if (match_found
== 0 && reversed
)
764 error (0, 0, _("invalid argument `%s'"), --argv
[k
]);
767 if (match_found
== 0)
769 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
771 if (!strcmp (argv
[k
], control_info
[i
].name
))
775 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
780 set_control_char (&control_info
[i
], argv
[k
], &mode
);
781 require_set_attr
= 1;
786 if (match_found
== 0)
788 if (!strcmp (argv
[k
], "ispeed"))
792 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
796 set_speed (input_speed
, argv
[k
], &mode
);
798 require_set_attr
= 1;
800 else if (!strcmp (argv
[k
], "ospeed"))
804 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
808 set_speed (output_speed
, argv
[k
], &mode
);
810 require_set_attr
= 1;
813 else if (!strcmp (argv
[k
], "rows"))
817 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
821 set_window_size ((int) integer_arg (argv
[k
]), -1);
823 else if (!strcmp (argv
[k
], "cols")
824 || !strcmp (argv
[k
], "columns"))
828 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
832 set_window_size (-1, (int) integer_arg (argv
[k
]));
834 else if (!strcmp (argv
[k
], "size"))
836 max_col
= screen_columns ();
838 display_window_size (0);
842 else if (!strcmp (argv
[k
], "line"))
846 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
850 mode
.c_line
= integer_arg (argv
[k
]);
851 require_set_attr
= 1;
854 else if (!strcmp (argv
[k
], "speed"))
856 max_col
= screen_columns ();
857 display_speed (&mode
, 0);
859 else if (string_to_baud (argv
[k
]) != (speed_t
) -1)
861 set_speed (both_speeds
, argv
[k
], &mode
);
863 require_set_attr
= 1;
867 if (recover_mode (argv
[k
], &mode
) == 0)
869 error (0, 0, _("invalid argument `%s'"), argv
[k
]);
872 require_set_attr
= 1;
878 if (require_set_attr
)
880 struct termios new_mode
;
882 if (tcsetattr (0, TCSADRAIN
, &mode
))
883 error (1, errno
, _("standard input"));
885 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
886 it performs *any* of the requested operations. This means it
887 can report `success' when it has actually failed to perform
888 some proper subset of the requested operations. To detect
889 this partial failure, get the current terminal attributes and
890 compare them to the requested ones. */
892 /* Initialize to all zeroes so there is no risk memcmp will report a
893 spurious difference in an uninitialized portion of the structure. */
894 memset (&new_mode
, 0, sizeof (new_mode
));
895 if (tcgetattr (0, &new_mode
))
896 error (1, errno
, _("standard input"));
898 /* Normally, one shouldn't use memcmp to compare structures that
899 may have `holes' containing uninitialized data, but we have been
900 careful to initialize the storage of these two variables to all
901 zeroes. One might think it more efficient simply to compare the
902 modified fields, but that would require enumerating those fields --
903 and not all systems have the same fields in this structure. */
905 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
908 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
909 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
910 sometimes (m1 != m2). The only difference is in the four bits
911 of the c_cflag field corresponding to the baud rate. To save
912 Sun users a little confusion, don't report an error if this
913 happens. But suppress the error only if we haven't tried to
914 set the baud rate explicitly -- otherwise we'd never give an
915 error for a true failure to set the baud rate. */
917 new_mode
.c_cflag
&= (~CIBAUD
);
918 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
923 _("standard input: unable to perform all requested operations"));
924 printf (_("new_mode: mode\n"));
925 for (i
=0; i
<sizeof(new_mode
); i
++)
926 printf ("0x%02x: 0x%02x\n",
927 *(((unsigned char *) &new_mode
) + i
),
928 *(((unsigned char *) &mode
) + i
));
936 /* Return 0 if not applied because not reversible; otherwise return 1. */
939 set_mode (struct mode_info
*info
, int reversed
, struct termios
*mode
)
943 if (reversed
&& (info
->flags
& REV
) == 0)
946 bitsp
= mode_type_flag (info
->type
, mode
);
950 /* Combination mode. */
951 if (!strcmp (info
->name
, "evenp") || !strcmp (info
->name
, "parity"))
954 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
956 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
958 else if (!strcmp (info
->name
, "oddp"))
961 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
963 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
965 else if (!strcmp (info
->name
, "nl"))
969 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
970 mode
->c_oflag
= (mode
->c_oflag
985 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
987 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
991 else if (!strcmp (info
->name
, "ek"))
993 mode
->c_cc
[VERASE
] = CERASE
;
994 mode
->c_cc
[VKILL
] = CKILL
;
996 else if (!strcmp (info
->name
, "sane"))
998 else if (!strcmp (info
->name
, "cbreak"))
1001 mode
->c_lflag
|= ICANON
;
1003 mode
->c_lflag
&= ~ICANON
;
1005 else if (!strcmp (info
->name
, "pass8"))
1009 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1010 mode
->c_iflag
|= ISTRIP
;
1014 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1015 mode
->c_iflag
&= ~ISTRIP
;
1018 else if (!strcmp (info
->name
, "litout"))
1022 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1023 mode
->c_iflag
|= ISTRIP
;
1024 mode
->c_oflag
|= OPOST
;
1028 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1029 mode
->c_iflag
&= ~ISTRIP
;
1030 mode
->c_oflag
&= ~OPOST
;
1033 else if (!strcmp (info
->name
, "raw") || !strcmp (info
->name
, "cooked"))
1035 if ((info
->name
[0] == 'r' && reversed
)
1036 || (info
->name
[0] == 'c' && !reversed
))
1039 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1040 mode
->c_oflag
|= OPOST
;
1041 mode
->c_lflag
|= ISIG
| ICANON
;
1043 mode
->c_cc
[VEOF
] = CEOF
;
1046 mode
->c_cc
[VEOL
] = CEOL
;
1053 mode
->c_oflag
&= ~OPOST
;
1054 mode
->c_lflag
&= ~(ISIG
| ICANON
1059 mode
->c_cc
[VMIN
] = 1;
1060 mode
->c_cc
[VTIME
] = 0;
1064 else if (!strcmp (info
->name
, "decctlq"))
1067 mode
->c_iflag
|= IXANY
;
1069 mode
->c_iflag
&= ~IXANY
;
1073 else if (!strcmp (info
->name
, "tabs"))
1076 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1078 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1082 else if (!strcmp (info
->name
, "tabs"))
1085 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1087 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1091 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1092 else if (!strcmp (info
->name
, "lcase")
1093 || !strcmp (info
->name
, "LCASE"))
1097 mode
->c_lflag
&= ~XCASE
;
1098 mode
->c_iflag
&= ~IUCLC
;
1099 mode
->c_oflag
&= ~OLCUC
;
1103 mode
->c_lflag
|= XCASE
;
1104 mode
->c_iflag
|= IUCLC
;
1105 mode
->c_oflag
|= OLCUC
;
1109 else if (!strcmp (info
->name
, "crt"))
1110 mode
->c_lflag
|= ECHOE
1118 else if (!strcmp (info
->name
, "dec"))
1120 mode
->c_cc
[VINTR
] = 3; /* ^C */
1121 mode
->c_cc
[VERASE
] = 127; /* DEL */
1122 mode
->c_cc
[VKILL
] = 21; /* ^U */
1123 mode
->c_lflag
|= ECHOE
1132 mode
->c_iflag
&= ~IXANY
;
1137 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1139 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1145 set_control_char (struct control_info
*info
, const char *arg
,
1146 struct termios
*mode
)
1148 unsigned char value
;
1150 if (!strcmp (info
->name
, "min") || !strcmp (info
->name
, "time"))
1151 value
= integer_arg (arg
);
1152 else if (arg
[0] == '\0' || arg
[1] == '\0')
1154 else if (!strcmp (arg
, "^-") || !strcmp (arg
, "undef"))
1155 value
= _POSIX_VDISABLE
;
1156 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1161 value
= arg
[1] & ~0140; /* Non-letters get weird results. */
1164 value
= integer_arg (arg
);
1165 mode
->c_cc
[info
->offset
] = value
;
1169 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1173 baud
= string_to_baud (arg
);
1174 if (type
== input_speed
|| type
== both_speeds
)
1175 cfsetispeed (mode
, baud
);
1176 if (type
== output_speed
|| type
== both_speeds
)
1177 cfsetospeed (mode
, baud
);
1182 /* Get window size information. First try getting the information
1183 associated with standard output and if that fails, try standard input.
1184 Return zero for success, nonzero if both ioctl's failed. */
1187 get_win_size (struct winsize
*win
)
1191 err
= ioctl (1, TIOCGWINSZ
, (char *) win
);
1193 err
= ioctl (0, TIOCGWINSZ
, (char *) win
);
1198 set_window_size (int rows
, int cols
)
1202 if (get_win_size (&win
))
1204 if (errno
!= EINVAL
)
1205 error (1, errno
, _("standard input"));
1206 memset (&win
, 0, sizeof (win
));
1215 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1216 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1217 This comment from sys/ttold.h describes Sun's twisted logic - a better
1218 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1219 At any rate, the problem is gone in Solaris 2.x.
1221 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1222 but they can be disambiguated by checking whether a "struct ttysize"
1223 structure's "ts_lines" field is greater than 64K or not. If so,
1224 it's almost certainly a "struct winsize" instead.
1226 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1227 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1228 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1229 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1230 "stty cols 0 rows 0" would do the right thing. On a little-endian
1231 machine like the sun386i, the problem is the same, but for ws_col == 0.
1233 The workaround is to do the ioctl once with row and col = 1 to set the
1234 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1236 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1238 struct ttysize ttysz
;
1240 ttysz
.ts_lines
= win
.ws_row
;
1241 ttysz
.ts_cols
= win
.ws_col
;
1246 if (ioctl (0, TIOCSWINSZ
, (char *) &win
))
1247 error (1, errno
, _("standard input"));
1249 if (ioctl (0, TIOCSSIZE
, (char *) &ttysz
))
1250 error (1, errno
, _("standard input"));
1255 if (ioctl (0, TIOCSWINSZ
, (char *) &win
))
1256 error (1, errno
, _("standard input"));
1260 display_window_size (int fancy
)
1264 if (get_win_size (&win
))
1266 if (errno
!= EINVAL
)
1267 error (1, errno
, _("standard input"));
1271 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1272 win
.ws_row
, win
.ws_col
);
1280 screen_columns (void)
1285 if (get_win_size (&win
))
1287 /* With Solaris 2.[123], this ioctl fails and errno is set to
1288 EINVAL for telnet (but not rlogin) sessions. */
1289 if (errno
!= EINVAL
)
1290 error (1, errno
, _("standard input"));
1292 else if (win
.ws_col
> 0)
1295 if (getenv ("COLUMNS"))
1296 return atoi (getenv ("COLUMNS"));
1301 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1306 return &mode
->c_cflag
;
1309 return &mode
->c_iflag
;
1312 return &mode
->c_oflag
;
1315 return &mode
->c_lflag
;
1326 display_settings (enum output_type output_type
, struct termios
*mode
)
1328 switch (output_type
)
1331 display_changed (mode
);
1339 display_recoverable (mode
);
1345 display_changed (struct termios
*mode
)
1351 enum mode_type prev_type
= control
;
1353 display_speed (mode
, 1);
1355 wrapf ("line = %d;", mode
->c_line
);
1361 for (i
= 0; strcmp (control_info
[i
].name
, "min"); ++i
)
1363 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1366 wrapf ("%s = %s;", control_info
[i
].name
,
1367 visible (mode
->c_cc
[control_info
[i
].offset
]));
1369 if ((mode
->c_lflag
& ICANON
) == 0)
1371 wrapf ("min = %d; time = %d;\n", (int) mode
->c_cc
[VMIN
],
1372 (int) mode
->c_cc
[VTIME
]);
1374 else if (empty_line
== 0)
1379 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1381 if (mode_info
[i
].flags
& OMIT
)
1383 if (mode_info
[i
].type
!= prev_type
)
1385 if (empty_line
== 0)
1391 prev_type
= mode_info
[i
].type
;
1394 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1395 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1396 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1398 if (mode_info
[i
].flags
& SANE_UNSET
)
1400 wrapf ("%s", mode_info
[i
].name
);
1404 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1406 wrapf ("-%s", mode_info
[i
].name
);
1410 if (empty_line
== 0)
1416 display_all (struct termios
*mode
)
1421 enum mode_type prev_type
= control
;
1423 display_speed (mode
, 1);
1425 display_window_size (1);
1428 wrapf ("line = %d;", mode
->c_line
);
1433 for (i
= 0; strcmp (control_info
[i
].name
, "min"); ++i
)
1435 wrapf ("%s = %s;", control_info
[i
].name
,
1436 visible (mode
->c_cc
[control_info
[i
].offset
]));
1438 wrapf ("min = %d; time = %d;\n", mode
->c_cc
[VMIN
], mode
->c_cc
[VTIME
]);
1441 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1443 if (mode_info
[i
].flags
& OMIT
)
1445 if (mode_info
[i
].type
!= prev_type
)
1449 prev_type
= mode_info
[i
].type
;
1452 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1453 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1454 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1455 wrapf ("%s", mode_info
[i
].name
);
1456 else if (mode_info
[i
].flags
& REV
)
1457 wrapf ("-%s", mode_info
[i
].name
);
1464 display_speed (struct termios
*mode
, int fancy
)
1466 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1467 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1468 baud_to_value (cfgetospeed (mode
)));
1470 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1471 baud_to_value (cfgetispeed (mode
)),
1472 baud_to_value (cfgetospeed (mode
)));
1478 display_recoverable (struct termios
*mode
)
1482 printf ("%lx:%lx:%lx:%lx",
1483 (unsigned long) mode
->c_iflag
, (unsigned long) mode
->c_oflag
,
1484 (unsigned long) mode
->c_cflag
, (unsigned long) mode
->c_lflag
);
1485 for (i
= 0; i
< NCCS
; ++i
)
1486 printf (":%x", (unsigned int) mode
->c_cc
[i
]);
1491 recover_mode (char *arg
, struct termios
*mode
)
1495 unsigned long iflag
, oflag
, cflag
, lflag
;
1497 /* Scan into temporaries since it is too much trouble to figure out
1498 the right format for `tcflag_t'. */
1499 if (sscanf (arg
, "%lx:%lx:%lx:%lx%n",
1500 &iflag
, &oflag
, &cflag
, &lflag
, &n
) != 4)
1502 mode
->c_iflag
= iflag
;
1503 mode
->c_oflag
= oflag
;
1504 mode
->c_cflag
= cflag
;
1505 mode
->c_lflag
= lflag
;
1507 for (i
= 0; i
< NCCS
; ++i
)
1509 if (sscanf (arg
, ":%x%n", &chr
, &n
) != 1)
1511 mode
->c_cc
[i
] = chr
;
1519 const char *string
; /* ASCII representation. */
1520 speed_t speed
; /* Internal form. */
1521 unsigned long value
; /* Numeric value. */
1524 struct speed_map speeds
[] =
1531 {"134.5", B134
, 134},
1536 {"1200", B1200
, 1200},
1537 {"1800", B1800
, 1800},
1538 {"2400", B2400
, 2400},
1539 {"4800", B4800
, 4800},
1540 {"9600", B9600
, 9600},
1541 {"19200", B19200
, 19200},
1542 {"38400", B38400
, 38400},
1543 {"exta", B19200
, 19200},
1544 {"extb", B38400
, 38400},
1546 {"57600", B57600
, 57600},
1549 {"115200", B115200
, 115200},
1555 string_to_baud (const char *arg
)
1559 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1560 if (!strcmp (arg
, speeds
[i
].string
))
1561 return speeds
[i
].speed
;
1562 return (speed_t
) -1;
1565 static unsigned long
1566 baud_to_value (speed_t speed
)
1570 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1571 if (speed
== speeds
[i
].speed
)
1572 return speeds
[i
].value
;
1577 sane_mode (struct termios
*mode
)
1582 for (i
= 0; control_info
[i
].name
; ++i
)
1585 if (!strcmp (control_info
[i
].name
, "min"))
1588 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1591 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1593 if (mode_info
[i
].flags
& SANE_SET
)
1595 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1596 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1598 else if (mode_info
[i
].flags
& SANE_UNSET
)
1600 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1601 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1606 /* Return a string that is the printable representation of character CH. */
1607 /* Adapted from `cat' by Torbjorn Granlund. */
1610 visible (unsigned int ch
)
1612 static char buf
[10];
1615 if (ch
== _POSIX_VDISABLE
)
1616 return _("<undef>");
1634 *bpout
++ = ch
- 128;
1644 *bpout
++ = ch
- 128 + 64;
1654 return (const char *) buf
;
1657 /* Parse string S as an integer, using decimal radix by default,
1658 but allowing octal and hex numbers as in C. */
1659 /* From `od' by Richard Stallman. */
1662 integer_arg (const char *s
)
1665 if (xstrtol (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
)
1667 error (0, 0, _("invalid integer argument `%s'"), s
);