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];
653 setlocale (LC_ALL
, "");
654 bindtextdomain (PACKAGE
, LOCALEDIR
);
655 textdomain (PACKAGE
);
657 parse_long_options (argc
, argv
, "stty", version_string
, usage
);
659 output_type
= changed
;
661 recoverable_output
= 0;
663 /* Recognize the long options only. */
665 while ((optc
= getopt_long_only (argc
, argv
, "ag", longopts
, (int *) 0))
676 recoverable_output
= 1;
677 output_type
= recoverable
;
685 /* Recognize short options and combinations: -a, -g, -ag, and -ga.
686 They need not precede non-options. We cannot use GNU getopt because
687 it would treat -tabs and -ixany as uses of the -a option. */
688 for (k
= optind
; k
< argc
; k
++)
690 if (argv
[k
][0] == '-')
692 if (argv
[k
][1] == 'a'
693 && argv
[k
][2] == '\0')
698 else if (argv
[k
][1] == 'g'
699 && argv
[k
][2] == '\0')
702 recoverable_output
= 1;
704 else if ((argv
[k
][1] == 'g'
706 && argv
[k
][3] == '\0')
707 || (argv
[k
][1] == 'a'
709 && argv
[k
][3] == '\0'))
713 recoverable_output
= 1;
718 /* Specifying both -a and -g gets an error. */
719 if (verbose_output
&& recoverable_output
)
721 _("the options for verbose and stty-readable output styles are\n\
722 \tmutually exclusive"));
724 /* Specifying any other arguments with -a or -g gets an error. */
725 if (argc
- optind
> 0 && (verbose_output
|| recoverable_output
))
726 error (2, 0, _("when specifying an output style, modes may not be set"));
728 /* Initialize to all zeroes so there is no risk memcmp will report a
729 spurious difference in an uninitialized portion of the structure. */
730 memset (&mode
, 0, sizeof (mode
));
731 if (tcgetattr (0, &mode
))
732 error (1, errno
, _("standard input"));
734 if (verbose_output
|| recoverable_output
|| argc
== 1)
736 max_col
= screen_columns ();
738 display_settings (output_type
, &mode
);
743 require_set_attr
= 0;
751 if (argv
[k
][0] == '-')
756 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
758 if (!strcmp (argv
[k
], mode_info
[i
].name
))
760 match_found
= set_mode (&mode_info
[i
], reversed
, &mode
);
761 require_set_attr
= 1;
765 if (match_found
== 0 && reversed
)
767 error (0, 0, _("invalid argument `%s'"), --argv
[k
]);
770 if (match_found
== 0)
772 for (i
= 0; control_info
[i
].name
!= NULL
; ++i
)
774 if (!strcmp (argv
[k
], control_info
[i
].name
))
778 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
783 set_control_char (&control_info
[i
], argv
[k
], &mode
);
784 require_set_attr
= 1;
789 if (match_found
== 0)
791 if (!strcmp (argv
[k
], "ispeed"))
795 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
799 set_speed (input_speed
, argv
[k
], &mode
);
801 require_set_attr
= 1;
803 else if (!strcmp (argv
[k
], "ospeed"))
807 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
811 set_speed (output_speed
, argv
[k
], &mode
);
813 require_set_attr
= 1;
816 else if (!strcmp (argv
[k
], "rows"))
820 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
824 set_window_size ((int) integer_arg (argv
[k
]), -1);
826 else if (!strcmp (argv
[k
], "cols")
827 || !strcmp (argv
[k
], "columns"))
831 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
835 set_window_size (-1, (int) integer_arg (argv
[k
]));
837 else if (!strcmp (argv
[k
], "size"))
839 max_col
= screen_columns ();
841 display_window_size (0);
845 else if (!strcmp (argv
[k
], "line"))
849 error (0, 0, _("missing argument to `%s'"), argv
[k
]);
853 mode
.c_line
= integer_arg (argv
[k
]);
854 require_set_attr
= 1;
857 else if (!strcmp (argv
[k
], "speed"))
859 max_col
= screen_columns ();
860 display_speed (&mode
, 0);
862 else if (string_to_baud (argv
[k
]) != (speed_t
) -1)
864 set_speed (both_speeds
, argv
[k
], &mode
);
866 require_set_attr
= 1;
870 if (recover_mode (argv
[k
], &mode
) == 0)
872 error (0, 0, _("invalid argument `%s'"), argv
[k
]);
875 require_set_attr
= 1;
881 if (require_set_attr
)
883 struct termios new_mode
;
885 if (tcsetattr (0, TCSADRAIN
, &mode
))
886 error (1, errno
, _("standard input"));
888 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
889 it performs *any* of the requested operations. This means it
890 can report `success' when it has actually failed to perform
891 some proper subset of the requested operations. To detect
892 this partial failure, get the current terminal attributes and
893 compare them to the requested ones. */
895 /* Initialize to all zeroes so there is no risk memcmp will report a
896 spurious difference in an uninitialized portion of the structure. */
897 memset (&new_mode
, 0, sizeof (new_mode
));
898 if (tcgetattr (0, &new_mode
))
899 error (1, errno
, _("standard input"));
901 /* Normally, one shouldn't use memcmp to compare structures that
902 may have `holes' containing uninitialized data, but we have been
903 careful to initialize the storage of these two variables to all
904 zeroes. One might think it more efficient simply to compare the
905 modified fields, but that would require enumerating those fields --
906 and not all systems have the same fields in this structure. */
908 if (memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
911 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
912 tcgetattr(&m1); tcsetattr(&m1); tcgetattr(&m2);
913 sometimes (m1 != m2). The only difference is in the four bits
914 of the c_cflag field corresponding to the baud rate. To save
915 Sun users a little confusion, don't report an error if this
916 happens. But suppress the error only if we haven't tried to
917 set the baud rate explicitly -- otherwise we'd never give an
918 error for a true failure to set the baud rate. */
920 new_mode
.c_cflag
&= (~CIBAUD
);
921 if (speed_was_set
|| memcmp (&mode
, &new_mode
, sizeof (mode
)) != 0)
926 _("standard input: unable to perform all requested operations"));
927 printf (_("new_mode: mode\n"));
928 for (i
=0; i
<sizeof(new_mode
); i
++)
929 printf ("0x%02x: 0x%02x\n",
930 *(((unsigned char *) &new_mode
) + i
),
931 *(((unsigned char *) &mode
) + i
));
939 /* Return 0 if not applied because not reversible; otherwise return 1. */
942 set_mode (struct mode_info
*info
, int reversed
, struct termios
*mode
)
946 if (reversed
&& (info
->flags
& REV
) == 0)
949 bitsp
= mode_type_flag (info
->type
, mode
);
953 /* Combination mode. */
954 if (!strcmp (info
->name
, "evenp") || !strcmp (info
->name
, "parity"))
957 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
959 mode
->c_cflag
= (mode
->c_cflag
& ~PARODD
& ~CSIZE
) | PARENB
| CS7
;
961 else if (!strcmp (info
->name
, "oddp"))
964 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
966 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARODD
| PARENB
;
968 else if (!strcmp (info
->name
, "nl"))
972 mode
->c_iflag
= (mode
->c_iflag
| ICRNL
) & ~INLCR
& ~IGNCR
;
973 mode
->c_oflag
= (mode
->c_oflag
988 mode
->c_iflag
= mode
->c_iflag
& ~ICRNL
;
990 mode
->c_oflag
= mode
->c_oflag
& ~ONLCR
;
994 else if (!strcmp (info
->name
, "ek"))
996 mode
->c_cc
[VERASE
] = CERASE
;
997 mode
->c_cc
[VKILL
] = CKILL
;
999 else if (!strcmp (info
->name
, "sane"))
1001 else if (!strcmp (info
->name
, "cbreak"))
1004 mode
->c_lflag
|= ICANON
;
1006 mode
->c_lflag
&= ~ICANON
;
1008 else if (!strcmp (info
->name
, "pass8"))
1012 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1013 mode
->c_iflag
|= ISTRIP
;
1017 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1018 mode
->c_iflag
&= ~ISTRIP
;
1021 else if (!strcmp (info
->name
, "litout"))
1025 mode
->c_cflag
= (mode
->c_cflag
& ~CSIZE
) | CS7
| PARENB
;
1026 mode
->c_iflag
|= ISTRIP
;
1027 mode
->c_oflag
|= OPOST
;
1031 mode
->c_cflag
= (mode
->c_cflag
& ~PARENB
& ~CSIZE
) | CS8
;
1032 mode
->c_iflag
&= ~ISTRIP
;
1033 mode
->c_oflag
&= ~OPOST
;
1036 else if (!strcmp (info
->name
, "raw") || !strcmp (info
->name
, "cooked"))
1038 if ((info
->name
[0] == 'r' && reversed
)
1039 || (info
->name
[0] == 'c' && !reversed
))
1042 mode
->c_iflag
|= BRKINT
| IGNPAR
| ISTRIP
| ICRNL
| IXON
;
1043 mode
->c_oflag
|= OPOST
;
1044 mode
->c_lflag
|= ISIG
| ICANON
;
1046 mode
->c_cc
[VEOF
] = CEOF
;
1049 mode
->c_cc
[VEOL
] = CEOL
;
1056 mode
->c_oflag
&= ~OPOST
;
1057 mode
->c_lflag
&= ~(ISIG
| ICANON
1062 mode
->c_cc
[VMIN
] = 1;
1063 mode
->c_cc
[VTIME
] = 0;
1067 else if (!strcmp (info
->name
, "decctlq"))
1070 mode
->c_iflag
|= IXANY
;
1072 mode
->c_iflag
&= ~IXANY
;
1076 else if (!strcmp (info
->name
, "tabs"))
1079 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB3
;
1081 mode
->c_oflag
= (mode
->c_oflag
& ~TABDLY
) | TAB0
;
1085 else if (!strcmp (info
->name
, "tabs"))
1088 mode
->c_oflag
= mode
->c_oflag
| OXTABS
;
1090 mode
->c_oflag
= mode
->c_oflag
& ~OXTABS
;
1094 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1095 else if (!strcmp (info
->name
, "lcase")
1096 || !strcmp (info
->name
, "LCASE"))
1100 mode
->c_lflag
&= ~XCASE
;
1101 mode
->c_iflag
&= ~IUCLC
;
1102 mode
->c_oflag
&= ~OLCUC
;
1106 mode
->c_lflag
|= XCASE
;
1107 mode
->c_iflag
|= IUCLC
;
1108 mode
->c_oflag
|= OLCUC
;
1112 else if (!strcmp (info
->name
, "crt"))
1113 mode
->c_lflag
|= ECHOE
1121 else if (!strcmp (info
->name
, "dec"))
1123 mode
->c_cc
[VINTR
] = 3; /* ^C */
1124 mode
->c_cc
[VERASE
] = 127; /* DEL */
1125 mode
->c_cc
[VKILL
] = 21; /* ^U */
1126 mode
->c_lflag
|= ECHOE
1135 mode
->c_iflag
&= ~IXANY
;
1140 *bitsp
= *bitsp
& ~info
->mask
& ~info
->bits
;
1142 *bitsp
= (*bitsp
& ~info
->mask
) | info
->bits
;
1148 set_control_char (struct control_info
*info
, const char *arg
,
1149 struct termios
*mode
)
1151 unsigned char value
;
1153 if (!strcmp (info
->name
, "min") || !strcmp (info
->name
, "time"))
1154 value
= integer_arg (arg
);
1155 else if (arg
[0] == '\0' || arg
[1] == '\0')
1157 else if (!strcmp (arg
, "^-") || !strcmp (arg
, "undef"))
1158 value
= _POSIX_VDISABLE
;
1159 else if (arg
[0] == '^' && arg
[1] != '\0') /* Ignore any trailing junk. */
1164 value
= arg
[1] & ~0140; /* Non-letters get weird results. */
1167 value
= integer_arg (arg
);
1168 mode
->c_cc
[info
->offset
] = value
;
1172 set_speed (enum speed_setting type
, const char *arg
, struct termios
*mode
)
1176 baud
= string_to_baud (arg
);
1177 if (type
== input_speed
|| type
== both_speeds
)
1178 cfsetispeed (mode
, baud
);
1179 if (type
== output_speed
|| type
== both_speeds
)
1180 cfsetospeed (mode
, baud
);
1185 /* Get window size information. First try getting the information
1186 associated with standard output and if that fails, try standard input.
1187 Return zero for success, nonzero if both ioctl's failed. */
1190 get_win_size (struct winsize
*win
)
1194 err
= ioctl (1, TIOCGWINSZ
, (char *) win
);
1196 err
= ioctl (0, TIOCGWINSZ
, (char *) win
);
1201 set_window_size (int rows
, int cols
)
1205 if (get_win_size (&win
))
1207 if (errno
!= EINVAL
)
1208 error (1, errno
, _("standard input"));
1209 memset (&win
, 0, sizeof (win
));
1218 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1219 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1220 This comment from sys/ttold.h describes Sun's twisted logic - a better
1221 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1222 At any rate, the problem is gone in Solaris 2.x.
1224 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1225 but they can be disambiguated by checking whether a "struct ttysize"
1226 structure's "ts_lines" field is greater than 64K or not. If so,
1227 it's almost certainly a "struct winsize" instead.
1229 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1230 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1231 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1232 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1233 "stty cols 0 rows 0" would do the right thing. On a little-endian
1234 machine like the sun386i, the problem is the same, but for ws_col == 0.
1236 The workaround is to do the ioctl once with row and col = 1 to set the
1237 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1239 if (win
.ws_row
== 0 || win
.ws_col
== 0)
1241 struct ttysize ttysz
;
1243 ttysz
.ts_lines
= win
.ws_row
;
1244 ttysz
.ts_cols
= win
.ws_col
;
1249 if (ioctl (0, TIOCSWINSZ
, (char *) &win
))
1250 error (1, errno
, _("standard input"));
1252 if (ioctl (0, TIOCSSIZE
, (char *) &ttysz
))
1253 error (1, errno
, _("standard input"));
1258 if (ioctl (0, TIOCSWINSZ
, (char *) &win
))
1259 error (1, errno
, _("standard input"));
1263 display_window_size (int fancy
)
1267 if (get_win_size (&win
))
1269 if (errno
!= EINVAL
)
1270 error (1, errno
, _("standard input"));
1274 wrapf (fancy
? "rows %d; columns %d;" : "%d %d\n",
1275 win
.ws_row
, win
.ws_col
);
1283 screen_columns (void)
1288 if (get_win_size (&win
))
1290 /* With Solaris 2.[123], this ioctl fails and errno is set to
1291 EINVAL for telnet (but not rlogin) sessions. */
1292 if (errno
!= EINVAL
)
1293 error (1, errno
, _("standard input"));
1295 else if (win
.ws_col
> 0)
1298 if (getenv ("COLUMNS"))
1299 return atoi (getenv ("COLUMNS"));
1304 mode_type_flag (enum mode_type type
, struct termios
*mode
)
1309 return &mode
->c_cflag
;
1312 return &mode
->c_iflag
;
1315 return &mode
->c_oflag
;
1318 return &mode
->c_lflag
;
1329 display_settings (enum output_type output_type
, struct termios
*mode
)
1331 switch (output_type
)
1334 display_changed (mode
);
1342 display_recoverable (mode
);
1348 display_changed (struct termios
*mode
)
1354 enum mode_type prev_type
= control
;
1356 display_speed (mode
, 1);
1358 wrapf ("line = %d;", mode
->c_line
);
1364 for (i
= 0; strcmp (control_info
[i
].name
, "min"); ++i
)
1366 if (mode
->c_cc
[control_info
[i
].offset
] == control_info
[i
].saneval
)
1369 wrapf ("%s = %s;", control_info
[i
].name
,
1370 visible (mode
->c_cc
[control_info
[i
].offset
]));
1372 if ((mode
->c_lflag
& ICANON
) == 0)
1374 wrapf ("min = %d; time = %d;\n", (int) mode
->c_cc
[VMIN
],
1375 (int) mode
->c_cc
[VTIME
]);
1377 else if (empty_line
== 0)
1382 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1384 if (mode_info
[i
].flags
& OMIT
)
1386 if (mode_info
[i
].type
!= prev_type
)
1388 if (empty_line
== 0)
1394 prev_type
= mode_info
[i
].type
;
1397 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1398 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1399 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1401 if (mode_info
[i
].flags
& SANE_UNSET
)
1403 wrapf ("%s", mode_info
[i
].name
);
1407 else if ((mode_info
[i
].flags
& (SANE_SET
| REV
)) == (SANE_SET
| REV
))
1409 wrapf ("-%s", mode_info
[i
].name
);
1413 if (empty_line
== 0)
1419 display_all (struct termios
*mode
)
1424 enum mode_type prev_type
= control
;
1426 display_speed (mode
, 1);
1428 display_window_size (1);
1431 wrapf ("line = %d;", mode
->c_line
);
1436 for (i
= 0; strcmp (control_info
[i
].name
, "min"); ++i
)
1438 wrapf ("%s = %s;", control_info
[i
].name
,
1439 visible (mode
->c_cc
[control_info
[i
].offset
]));
1441 wrapf ("min = %d; time = %d;\n", mode
->c_cc
[VMIN
], mode
->c_cc
[VTIME
]);
1444 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1446 if (mode_info
[i
].flags
& OMIT
)
1448 if (mode_info
[i
].type
!= prev_type
)
1452 prev_type
= mode_info
[i
].type
;
1455 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1456 mask
= mode_info
[i
].mask
? mode_info
[i
].mask
: mode_info
[i
].bits
;
1457 if ((*bitsp
& mask
) == mode_info
[i
].bits
)
1458 wrapf ("%s", mode_info
[i
].name
);
1459 else if (mode_info
[i
].flags
& REV
)
1460 wrapf ("-%s", mode_info
[i
].name
);
1467 display_speed (struct termios
*mode
, int fancy
)
1469 if (cfgetispeed (mode
) == 0 || cfgetispeed (mode
) == cfgetospeed (mode
))
1470 wrapf (fancy
? "speed %lu baud;" : "%lu\n",
1471 baud_to_value (cfgetospeed (mode
)));
1473 wrapf (fancy
? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1474 baud_to_value (cfgetispeed (mode
)),
1475 baud_to_value (cfgetospeed (mode
)));
1481 display_recoverable (struct termios
*mode
)
1485 printf ("%lx:%lx:%lx:%lx",
1486 (unsigned long) mode
->c_iflag
, (unsigned long) mode
->c_oflag
,
1487 (unsigned long) mode
->c_cflag
, (unsigned long) mode
->c_lflag
);
1488 for (i
= 0; i
< NCCS
; ++i
)
1489 printf (":%x", (unsigned int) mode
->c_cc
[i
]);
1494 recover_mode (char *arg
, struct termios
*mode
)
1498 unsigned long iflag
, oflag
, cflag
, lflag
;
1500 /* Scan into temporaries since it is too much trouble to figure out
1501 the right format for `tcflag_t'. */
1502 if (sscanf (arg
, "%lx:%lx:%lx:%lx%n",
1503 &iflag
, &oflag
, &cflag
, &lflag
, &n
) != 4)
1505 mode
->c_iflag
= iflag
;
1506 mode
->c_oflag
= oflag
;
1507 mode
->c_cflag
= cflag
;
1508 mode
->c_lflag
= lflag
;
1510 for (i
= 0; i
< NCCS
; ++i
)
1512 if (sscanf (arg
, ":%x%n", &chr
, &n
) != 1)
1514 mode
->c_cc
[i
] = chr
;
1522 const char *string
; /* ASCII representation. */
1523 speed_t speed
; /* Internal form. */
1524 unsigned long value
; /* Numeric value. */
1527 struct speed_map speeds
[] =
1534 {"134.5", B134
, 134},
1539 {"1200", B1200
, 1200},
1540 {"1800", B1800
, 1800},
1541 {"2400", B2400
, 2400},
1542 {"4800", B4800
, 4800},
1543 {"9600", B9600
, 9600},
1544 {"19200", B19200
, 19200},
1545 {"38400", B38400
, 38400},
1546 {"exta", B19200
, 19200},
1547 {"extb", B38400
, 38400},
1549 {"57600", B57600
, 57600},
1552 {"115200", B115200
, 115200},
1558 string_to_baud (const char *arg
)
1562 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1563 if (!strcmp (arg
, speeds
[i
].string
))
1564 return speeds
[i
].speed
;
1565 return (speed_t
) -1;
1568 static unsigned long
1569 baud_to_value (speed_t speed
)
1573 for (i
= 0; speeds
[i
].string
!= NULL
; ++i
)
1574 if (speed
== speeds
[i
].speed
)
1575 return speeds
[i
].value
;
1580 sane_mode (struct termios
*mode
)
1585 for (i
= 0; control_info
[i
].name
; ++i
)
1588 if (!strcmp (control_info
[i
].name
, "min"))
1591 mode
->c_cc
[control_info
[i
].offset
] = control_info
[i
].saneval
;
1594 for (i
= 0; mode_info
[i
].name
!= NULL
; ++i
)
1596 if (mode_info
[i
].flags
& SANE_SET
)
1598 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1599 *bitsp
= (*bitsp
& ~mode_info
[i
].mask
) | mode_info
[i
].bits
;
1601 else if (mode_info
[i
].flags
& SANE_UNSET
)
1603 bitsp
= mode_type_flag (mode_info
[i
].type
, mode
);
1604 *bitsp
= *bitsp
& ~mode_info
[i
].mask
& ~mode_info
[i
].bits
;
1609 /* Return a string that is the printable representation of character CH. */
1610 /* Adapted from `cat' by Torbjorn Granlund. */
1613 visible (unsigned int ch
)
1615 static char buf
[10];
1618 if (ch
== _POSIX_VDISABLE
)
1619 return _("<undef>");
1637 *bpout
++ = ch
- 128;
1647 *bpout
++ = ch
- 128 + 64;
1657 return (const char *) buf
;
1660 /* Parse string S as an integer, using decimal radix by default,
1661 but allowing octal and hex numbers as in C. */
1662 /* From `od' by Richard Stallman. */
1665 integer_arg (const char *s
)
1668 if (xstrtol (s
, NULL
, 0, &value
, "bB") != LONGINT_OK
)
1670 error (0, 0, _("invalid integer argument `%s'"), s
);