1 /* stty -- change and print terminal line settings
2 Copyright (C) 1990-2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Usage: stty [-ag] [--all] [--save] [-F device] [--file=device] [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.
23 -F, --file Open and use the specified device instead of stdin
25 If no args are given, write to stdout the baud rate and settings that
26 have been changed from their defaults. Mode reading and changes
27 are done on the specified device, or stdin if none was specified.
29 David MacKenzie <djm@gnu.ai.mit.edu> */
33 #ifdef TERMIOS_NEEDS_XOPEN_SOURCE
34 # define _XOPEN_SOURCE
38 #include <sys/types.h>
42 #ifdef GWINSZ_IN_SYS_IOCTL
43 # include <sys/ioctl.h>
45 #ifdef WINSIZE_IN_PTEM
46 # include <sys/stream.h>
47 # include <sys/ptem.h>
49 #ifdef GWINSZ_IN_SYS_PTY
50 # include <sys/ioctl.h>
56 #define VA_START(args, lastarg) va_start(args, lastarg)
59 #include "long-options.h"
63 /* The official name of this program (e.g., no `g' prefix). */
64 #define PROGRAM_NAME "stty"
66 #define WRITTEN_BY _("Written by David MacKenzie.")
68 #ifndef _POSIX_VDISABLE
69 # define _POSIX_VDISABLE ((unsigned char) 0)
72 #define Control(c) ((c) & 0x1f)
73 /* Canonical values for control characters. */
75 # define CINTR Control ('c')
84 # define CKILL Control ('u')
87 # define CEOF Control ('d')
90 # define CEOL _POSIX_VDISABLE
93 # define CSTART Control ('q')
96 # define CSTOP Control ('s')
99 # define CSUSP Control ('z')
101 #if defined(VEOL2) && !defined(CEOL2)
102 # define CEOL2 _POSIX_VDISABLE
104 /* ISC renamed swtch to susp for termios, but we'll accept either name. */
105 #if defined(VSUSP) && !defined(VSWTCH)
106 # define VSWTCH VSUSP
107 # define CSWTCH CSUSP
109 #if defined(VSWTCH) && !defined(CSWTCH)
110 # define CSWTCH _POSIX_VDISABLE
113 /* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'.
114 So the default is to disable `swtch.' */
115 #if defined (__sparc__) && defined (__svr4__)
117 # define CSWTCH _POSIX_VDISABLE
120 #if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */
121 # define VWERASE VWERSE
123 #if defined(VDSUSP) && !defined (CDSUSP)
124 # define CDSUSP Control ('y')
126 #if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */
127 # define VREPRINT VRPRNT
129 #if defined(VREPRINT) && !defined(CRPRNT)
130 # define CRPRNT Control ('r')
132 #if defined(CREPRINT) && !defined(CRPRNT)
133 # define CRPRNT Control ('r')
135 #if defined(VWERASE) && !defined(CWERASE)
136 # define CWERASE Control ('w')
138 #if defined(VLNEXT) && !defined(CLNEXT)
139 # define CLNEXT Control ('v')
141 #if defined(VDISCARD) && !defined(VFLUSHO)
142 # define VFLUSHO VDISCARD
144 #if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */
145 # define VFLUSHO VFLUSH
147 #if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */
148 # define ECHOCTL CTLECH
150 #if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */
151 # define ECHOCTL TCTLECH
153 #if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */
154 # define ECHOKE CRTKIL
156 #if defined(VFLUSHO) && !defined(CFLUSHO)
157 # define CFLUSHO Control ('o')
159 #if defined(VSTATUS) && !defined(CSTATUS)
160 # define CSTATUS Control ('t')
163 /* Which speeds to set. */
166 input_speed, output_speed, both_speeds
169 /* What to output and how. */
172 changed, all, recoverable /* Default, -a, -g. */
175 /* Which member(s) of `struct termios' a mode uses. */
178 control, input, output, local, combination
181 /* Flags for `struct mode_info'. */
182 #define SANE_SET 1 /* Set in `sane' mode. */
183 #define SANE_UNSET 2 /* Unset in `sane' mode. */
184 #define REV 4 /* Can be turned off by prepending `-'. */
185 #define OMIT 8 /* Don't display value. */
190 const char *name; /* Name given on command line. */
191 enum mode_type type; /* Which structure element to change. */
192 char flags; /* Setting and display options. */
193 unsigned long bits; /* Bits to set for this mode. */
194 unsigned long mask; /* Other bits to turn off for this mode. */
197 static struct mode_info mode_info[] =
199 {"parenb", control, REV, PARENB, 0},
200 {"parodd", control, REV, PARODD, 0},
201 {"cs5", control, 0, CS5, CSIZE},
202 {"cs6", control, 0, CS6, CSIZE},
203 {"cs7", control, 0, CS7, CSIZE},
204 {"cs8", control, 0, CS8, CSIZE},
205 {"hupcl", control, REV, HUPCL, 0},
206 {"hup", control, REV | OMIT, HUPCL, 0},
207 {"cstopb", control, REV, CSTOPB, 0},
208 {"cread", control, SANE_SET | REV, CREAD, 0},
209 {"clocal", control, REV, CLOCAL, 0},
211 {"crtscts", control, REV, CRTSCTS, 0},
214 {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0},
215 {"brkint", input, SANE_SET | REV, BRKINT, 0},
216 {"ignpar", input, REV, IGNPAR, 0},
217 {"parmrk", input, REV, PARMRK, 0},
218 {"inpck", input, REV, INPCK, 0},
219 {"istrip", input, REV, ISTRIP, 0},
220 {"inlcr", input, SANE_UNSET | REV, INLCR, 0},
221 {"igncr", input, SANE_UNSET | REV, IGNCR, 0},
222 {"icrnl", input, SANE_SET | REV, ICRNL, 0},
223 {"ixon", input, REV, IXON, 0},
224 {"ixoff", input, SANE_UNSET | REV, IXOFF, 0},
225 {"tandem", input, REV | OMIT, IXOFF, 0},
227 {"iuclc", input, SANE_UNSET | REV, IUCLC, 0},
230 {"ixany", input, SANE_UNSET | REV, IXANY, 0},
233 {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0},
236 {"opost", output, SANE_SET | REV, OPOST, 0},
238 {"olcuc", output, SANE_UNSET | REV, OLCUC, 0},
241 {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0},
244 {"onlcr", output, SANE_SET | REV, ONLCR, 0},
247 {"onocr", output, SANE_UNSET | REV, ONOCR, 0},
250 {"onlret", output, SANE_UNSET | REV, ONLRET, 0},
253 {"ofill", output, SANE_UNSET | REV, OFILL, 0},
256 {"ofdel", output, SANE_UNSET | REV, OFDEL, 0},
259 {"nl1", output, SANE_UNSET, NL1, NLDLY},
260 {"nl0", output, SANE_SET, NL0, NLDLY},
263 {"cr3", output, SANE_UNSET, CR3, CRDLY},
264 {"cr2", output, SANE_UNSET, CR2, CRDLY},
265 {"cr1", output, SANE_UNSET, CR1, CRDLY},
266 {"cr0", output, SANE_SET, CR0, CRDLY},
269 {"tab3", output, SANE_UNSET, TAB3, TABDLY},
270 {"tab2", output, SANE_UNSET, TAB2, TABDLY},
271 {"tab1", output, SANE_UNSET, TAB1, TABDLY},
272 {"tab0", output, SANE_SET, TAB0, TABDLY},
275 {"tab3", output, SANE_UNSET, OXTABS, 0},
279 {"bs1", output, SANE_UNSET, BS1, BSDLY},
280 {"bs0", output, SANE_SET, BS0, BSDLY},
283 {"vt1", output, SANE_UNSET, VT1, VTDLY},
284 {"vt0", output, SANE_SET, VT0, VTDLY},
287 {"ff1", output, SANE_UNSET, FF1, FFDLY},
288 {"ff0", output, SANE_SET, FF0, FFDLY},
291 {"isig", local, SANE_SET | REV, ISIG, 0},
292 {"icanon", local, SANE_SET | REV, ICANON, 0},
294 {"iexten", local, SANE_SET | REV, IEXTEN, 0},
296 {"echo", local, SANE_SET | REV, ECHO, 0},
297 {"echoe", local, SANE_SET | REV, ECHOE, 0},
298 {"crterase", local, REV | OMIT, ECHOE, 0},
299 {"echok", local, SANE_SET | REV, ECHOK, 0},
300 {"echonl", local, SANE_UNSET | REV, ECHONL, 0},
301 {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0},
303 {"xcase", local, SANE_UNSET | REV, XCASE, 0},
306 {"tostop", local, SANE_UNSET | REV, TOSTOP, 0},
309 {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0},
310 {"prterase", local, REV | OMIT, ECHOPRT, 0},
313 {"echoctl", local, SANE_SET | REV, ECHOCTL, 0},
314 {"ctlecho", local, REV | OMIT, ECHOCTL, 0},
317 {"echoke", local, SANE_SET | REV, ECHOKE, 0},
318 {"crtkill", local, REV | OMIT, ECHOKE, 0},
321 {"evenp", combination, REV | OMIT, 0, 0},
322 {"parity", combination, REV | OMIT, 0, 0},
323 {"oddp", combination, REV | OMIT, 0, 0},
324 {"nl", combination, REV | OMIT, 0, 0},
325 {"ek", combination, OMIT, 0, 0},
326 {"sane", combination, OMIT, 0, 0},
327 {"cooked", combination, REV | OMIT, 0, 0},
328 {"raw", combination, REV | OMIT, 0, 0},
329 {"pass8", combination, REV | OMIT, 0, 0},
330 {"litout", combination, REV | OMIT, 0, 0},
331 {"cbreak", combination, REV | OMIT, 0, 0},
333 {"decctlq", combination, REV | OMIT, 0, 0},
335 #if defined (TABDLY) || defined (OXTABS)
336 {"tabs", combination, REV | OMIT, 0, 0},
338 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
339 {"lcase", combination, REV | OMIT, 0, 0},
340 {"LCASE", combination, REV | OMIT, 0, 0},
342 {"crt", combination, OMIT, 0, 0},
343 {"dec", combination, OMIT, 0, 0},
345 {NULL, control, 0, 0, 0}
348 /* Control character settings. */
351 const char *name; /* Name given on command line. */
352 unsigned char saneval; /* Value to set for `stty sane'. */
353 int offset; /* Offset in c_cc. */
356 /* Control characters. */
358 static struct control_info control_info[] =
360 {"intr", CINTR, VINTR},
361 {"quit", CQUIT, VQUIT},
362 {"erase", CERASE, VERASE},
363 {"kill", CKILL, VKILL},
367 {"eol2", CEOL2, VEOL2},
370 {"swtch", CSWTCH, VSWTCH},
372 {"start", CSTART, VSTART},
373 {"stop", CSTOP, VSTOP},
374 {"susp", CSUSP, VSUSP},
376 {"dsusp", CDSUSP, VDSUSP},
379 {"rprnt", CRPRNT, VREPRINT},
381 # ifdef CREPRINT /* HPUX 10.20 needs this */
382 {"rprnt", CRPRNT, CREPRINT},
386 {"werase", CWERASE, VWERASE},
389 {"lnext", CLNEXT, VLNEXT},
392 {"flush", CFLUSHO, VFLUSHO},
395 {"status", CSTATUS, VSTATUS},
398 /* These must be last because of the display routines. */
404 static const char *visible (unsigned int ch);
405 static unsigned long baud_to_value (speed_t speed);
406 static int recover_mode (char *arg, struct termios *mode);
407 static int screen_columns (void);
408 static int set_mode (struct mode_info *info, int reversed,
409 struct termios *mode);
410 static long integer_arg (const char *s);
411 static speed_t string_to_baud (const char *arg);
412 static tcflag_t *mode_type_flag (enum mode_type type, struct termios *mode);
413 static void display_all (struct termios *mode, int fd, const char *device_name);
414 static void display_changed (struct termios *mode);
415 static void display_recoverable (struct termios *mode);
416 static void display_settings (enum output_type output_type,
417 struct termios *mode, int fd,
418 const char *device_name);
419 static void display_speed (struct termios *mode, int fancy);
420 static void display_window_size (int fancy, int fd, const char *device_name);
421 static void sane_mode (struct termios *mode);
422 static void set_control_char (struct control_info *info,
424 struct termios *mode);
425 static void set_speed (enum speed_setting type, const char *arg,
426 struct termios *mode);
427 static void set_window_size (int rows, int cols, int fd,
428 const char *device_name);
430 /* The width of the screen, for output wrapping. */
433 /* Current position, to know when to wrap. */
434 static int current_col;
436 static struct option longopts[] =
438 {"all", no_argument, NULL, 'a'},
439 {"save", no_argument, NULL, 'g'},
440 {"file", required_argument, NULL, 'F'},
444 /* The name this program was run with. */
447 static void wrapf (const char *message, ...)
448 __attribute__ ((__format__ (__printf__, 1, 2)));
450 /* Print format string MESSAGE and optional args.
451 Wrap to next line first if it won't fit.
452 Print a space first unless MESSAGE will start a new line. */
456 wrapf (const char *message,...)
459 char buf[1024]; /* Plenty long for our needs. */
462 VA_START (args, message);
463 vsprintf (buf, message, args);
465 buflen = strlen (buf);
467 && max_col <= current_col + (0 < current_col) + buflen)
478 current_col += buflen;
485 fprintf (stderr, _("Try `%s --help' for more information.\n"),
490 Usage: %s [-F DEVICE] [--file=DEVICE] [SETTING]...\n\
491 or: %s [-F DEVICE] [--file=DEVICE] [-a|--all]\n\
492 or: %s [-F DEVICE] [--file=DEVICE] [-g|--save]\n\
494 program_name, program_name, program_name);
496 Print or change terminal characteristics.\n\
498 -a, --all print all current settings in human-readable form\n\
499 -g, --save print all current settings in a stty-readable form\n\
500 -F, --file=DEVICE open and use the specified DEVICE instead of stdin\n\
502 fputs (HELP_OPTION_DESCRIPTION, stdout);
503 fputs (VERSION_OPTION_DESCRIPTION, stdout);
506 Optional - before SETTING indicates negation. An * marks non-POSIX\n\
507 settings. The underlying system defines which settings are available.\n\
511 Special characters:\n\
512 * dsusp CHAR CHAR will send a terminal stop signal once input flushed\n\
513 eof CHAR CHAR will send an end of file (terminate the input)\n\
514 eol CHAR CHAR will end the line\n\
517 * eol2 CHAR alternate CHAR for ending the line\n\
518 erase CHAR CHAR will erase the last character typed\n\
519 intr CHAR CHAR will send an interrupt signal\n\
520 kill CHAR CHAR will erase the current line\n\
523 * lnext CHAR CHAR will enter the next character quoted\n\
524 quit CHAR CHAR will send a quit signal\n\
525 * rprnt CHAR CHAR will redraw the current line\n\
526 start CHAR CHAR will restart the output after stopping it\n\
529 stop CHAR CHAR will stop the output\n\
530 susp CHAR CHAR will send a terminal stop signal\n\
531 * swtch CHAR CHAR will switch to a different shell layer\n\
532 * werase CHAR CHAR will erase the last word typed\n\
537 N set the input and output speeds to N bauds\n\
538 * cols N tell the kernel that the terminal has N columns\n\
539 * columns N same as cols N\n\
542 ispeed N set the input speed to N\n\
543 * line N use line discipline N\n\
544 min N with -icanon, set N characters minimum for a completed read\n\
545 ospeed N set the output speed to N\n\
548 * rows N tell the kernel that the terminal has N rows\n\
549 * size print the number of rows and columns according to the kernel\n\
550 speed print the terminal speed\n\
551 time N with -icanon, set read timeout of N tenths of a second\n\
556 [-]clocal disable modem control signals\n\
557 [-]cread allow input to be received\n\
558 * [-]crtscts enable RTS/CTS handshaking\n\
559 csN set character size to N bits, N in [5..8]\n\
562 [-]cstopb use two stop bits per character (one with `-')\n\
563 [-]hup send a hangup signal when the last process closes the tty\n\
564 [-]hupcl same as [-]hup\n\
565 [-]parenb generate parity bit in output and expect parity bit in input\n\
566 [-]parodd set odd parity (even with `-')\n\
571 [-]brkint breaks cause an interrupt signal\n\
572 [-]icrnl translate carriage return to newline\n\
573 [-]ignbrk ignore break characters\n\
574 [-]igncr ignore carriage return\n\
577 [-]ignpar ignore characters with parity errors\n\
578 * [-]imaxbel beep and do not flush a full input buffer on a character\n\
579 [-]inlcr translate newline to carriage return\n\
580 [-]inpck enable input parity checking\n\
581 [-]istrip clear high (8th) bit of input characters\n\
584 * [-]iuclc translate uppercase characters to lowercase\n\
585 * [-]ixany let any character restart output, not only start character\n\
586 [-]ixoff enable sending of start/stop characters\n\
587 [-]ixon enable XON/XOFF flow control\n\
588 [-]parmrk mark parity errors (with a 255-0-character sequence)\n\
589 [-]tandem same as [-]ixoff\n\
594 * bsN backspace delay style, N in [0..1]\n\
595 * crN carriage return delay style, N in [0..3]\n\
596 * ffN form feed delay style, N in [0..1]\n\
597 * nlN newline delay style, N in [0..1]\n\
600 * [-]ocrnl translate carriage return to newline\n\
601 * [-]ofdel use delete characters for fill instead of null characters\n\
602 * [-]ofill use fill (padding) characters instead of timing for delays\n\
603 * [-]olcuc translate lowercase characters to uppercase\n\
604 * [-]onlcr translate newline to carriage return-newline\n\
605 * [-]onlret newline performs a carriage return\n\
608 * [-]onocr do not print carriage returns in the first column\n\
609 [-]opost postprocess output\n\
610 * tabN horizontal tab delay style, N in [0..3]\n\
611 * tabs same as tab0\n\
612 * -tabs same as tab3\n\
613 * vtN vertical tab delay style, N in [0..1]\n\
618 [-]crterase echo erase characters as backspace-space-backspace\n\
619 * crtkill kill all line by obeying the echoprt and echoe settings\n\
620 * -crtkill kill all line by obeying the echoctl and echok settings\n\
623 * [-]ctlecho echo control characters in hat notation (`^c')\n\
624 [-]echo echo input characters\n\
625 * [-]echoctl same as [-]ctlecho\n\
626 [-]echoe same as [-]crterase\n\
627 [-]echok echo a newline after a kill character\n\
630 * [-]echoke same as [-]crtkill\n\
631 [-]echonl echo newline even if not echoing other characters\n\
632 * [-]echoprt echo erased characters backward, between `\\' and '/'\n\
633 [-]icanon enable erase, kill, werase, and rprnt special characters\n\
634 [-]iexten enable non-POSIX special characters\n\
637 [-]isig enable interrupt, quit, and suspend special characters\n\
638 [-]noflsh disable flushing after interrupt and quit special characters\n\
639 * [-]prterase same as [-]echoprt\n\
640 * [-]tostop stop background jobs that try to write to the terminal\n\
641 * [-]xcase with icanon, escape with `\\' for uppercase characters\n\
645 Combination settings:\n\
646 * [-]LCASE same as [-]lcase\n\
647 cbreak same as -icanon\n\
648 -cbreak same as icanon\n\
651 cooked same as brkint ignpar istrip icrnl ixon opost isig\n\
652 icanon, eof and eol characters to their default values\n\
653 -cooked same as raw\n\
654 crt same as echoe echoctl echoke\n\
657 dec same as echoe echoctl echoke -ixany intr ^c erase 0177\n\
659 * [-]decctlq same as [-]ixany\n\
660 ek erase and kill characters to their default values\n\
661 evenp same as parenb -parodd cs7\n\
664 -evenp same as -parenb cs8\n\
665 * [-]lcase same as xcase iuclc olcuc\n\
666 litout same as -parenb -istrip -opost cs8\n\
667 -litout same as parenb istrip opost cs7\n\
668 nl same as -icrnl -onlcr\n\
669 -nl same as icrnl -inlcr -igncr onlcr -ocrnl -onlret\n\
672 oddp same as parenb parodd cs7\n\
673 -oddp same as -parenb cs8\n\
674 [-]parity same as [-]evenp\n\
675 pass8 same as -parenb -istrip cs8\n\
676 -pass8 same as parenb istrip cs7\n\
679 raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip\n\
680 -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany\n\
681 -imaxbel -opost -isig -icanon -xcase min 1 time 0\n\
682 -raw same as cooked\n\
685 sane same as cread -ignbrk brkint -inlcr -igncr icrnl\n\
686 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl onlcr\n\
687 -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0\n\
688 isig icanon iexten echo echoe echok -echonl -noflsh\n\
689 -xcase -tostop -echoprt echoctl echoke, all special\n\
690 characters to their default values.\n\
694 Handle the tty line connected to standard input. Without arguments,\n\
695 prints baud rate, line discipline, and deviations from stty sane. In\n\
696 settings, CHAR is taken literally, or coded as in ^c, 0x37, 0177 or\n\
697 127; special values ^- or undef used to disable special characters.\n\
699 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
704 /* Return 1 if the string contains only valid options. */
706 valid_options (char *opt, const char *valid_opts,
707 const char *valid_arg_opts)
711 if (*opt++ != '-' || *opt == 0)
717 if (strchr (valid_opts, ch))
719 if (strchr (valid_arg_opts, ch))
727 main (int argc, char **argv)
730 enum output_type output_type;
732 int require_set_attr;
735 int recoverable_output;
738 char *file_name = NULL;
740 const char *device_name;
741 const char *posixly_correct = getenv ("POSIXLY_CORRECT");
742 int invalid_long_option = 0;
744 initialize_main (&argc, &argv);
745 program_name = argv[0];
746 setlocale (LC_ALL, "");
747 bindtextdomain (PACKAGE, LOCALEDIR);
748 textdomain (PACKAGE);
750 atexit (close_stdout);
752 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
755 output_type = changed;
757 recoverable_output = 0;
759 /* Don't print error messages for unrecognized options. */
762 while ((optc = getopt_long (argc, argv, "agF:", longopts, NULL)) != -1)
764 int unrecognized_option = 0;
773 recoverable_output = 1;
774 output_type = recoverable;
779 error (2, 0, _("only one device may be specified"));
784 unrecognized_option = 1;
788 if (unrecognized_option)
792 /* FIXME: what is this?!? */
793 if (invalid_long_option)
794 usage (EXIT_FAILURE);
796 /* Clear out the options that have been parsed. This is really
797 gross, but it's needed because stty SETTINGS look like options to
798 getopt(), so we need to work around things in a really horrible
799 way. If any new options are ever added to stty, the short option
800 MUST NOT be a letter which is the first letter of one of the
801 possible stty settings. If you change anything about how stty
802 parses options, be sure it still works with combinations of
803 short and long options, --, POSIXLY_CORRECT, etc. */
804 for (k = 1; k < argc; k++)
812 /* Handle --, and reset noargs if there are arguments following it. */
813 if (STREQ (argv[k], "--"))
821 /* Handle "--file device" */
822 len = strlen (argv[k]);
823 if (len >= 3 && strstr ("--file", argv[k]))
830 /* Handle "--all" and "--save". */
832 && (strstr ("--all", argv[k])
833 || strstr ("--save", argv[k])))
839 /* Handle "--file=device". */
840 eq = strchr (argv[k], '=');
841 if (eq && eq - argv[k] >= 3)
844 if (strstr ("--file", argv[k]))
849 /* Put the equals sign back for the error message. */
853 /* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc. */
854 if (valid_options (argv[k], "ag", "F"))
856 /* FIXME: this loses when the device name ends in `F'.
857 e.g. `stty -F/dev/BARF nl' would clobber the `nl' argument. */
858 if (argv[k][strlen (argv[k]) - 1] == 'F')
862 /* Everything else must be a normal, non-option argument. */
871 /* Specifying both -a and -g gets an error. */
872 if (verbose_output && recoverable_output)
874 _("the options for verbose and stty-readable output styles are\n\
875 mutually exclusive"));
877 /* Specifying any other arguments with -a or -g gets an error. */
878 if (!noargs && (verbose_output || recoverable_output))
879 error (2, 0, _("when specifying an output style, modes may not be set"));
881 /* FIXME: it'd be better not to open the file until we've verified
882 that all arguments are valid. Otherwise, we could end up doing
883 only some of the requested operations and then failing, probably
884 leaving things in an undesirable state. */
889 device_name = file_name;
890 fd = open (device_name, O_RDONLY | O_NONBLOCK);
892 error (EXIT_FAILURE, errno, "%s", device_name);
893 if ((fdflags = fcntl (fd, F_GETFL)) == -1
894 || fcntl (fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
895 error (EXIT_FAILURE, errno, _("%s: couldn't reset non-blocking mode"),
901 device_name = _("standard input");
904 /* Initialize to all zeroes so there is no risk memcmp will report a
905 spurious difference in an uninitialized portion of the structure. */
906 memset (&mode, 0, sizeof (mode));
907 if (tcgetattr (fd, &mode))
908 error (EXIT_FAILURE, errno, "%s", device_name);
910 if (verbose_output || recoverable_output || noargs)
912 max_col = screen_columns ();
914 display_settings (output_type, &mode, fd, device_name);
919 require_set_attr = 0;
933 if (argv[k][0] == '-')
938 for (i = 0; mode_info[i].name != NULL; ++i)
940 if (STREQ (argv[k], mode_info[i].name))
942 match_found = set_mode (&mode_info[i], reversed, &mode);
943 require_set_attr = 1;
947 if (match_found == 0 && reversed)
949 error (0, 0, _("invalid argument `%s'"), --argv[k]);
950 usage (EXIT_FAILURE);
952 if (match_found == 0)
954 for (i = 0; control_info[i].name != NULL; ++i)
956 if (STREQ (argv[k], control_info[i].name))
960 error (0, 0, _("missing argument to `%s'"), argv[k]);
961 usage (EXIT_FAILURE);
965 set_control_char (&control_info[i], argv[k], &mode);
966 require_set_attr = 1;
971 if (match_found == 0)
973 if (STREQ (argv[k], "ispeed"))
977 error (0, 0, _("missing argument to `%s'"), argv[k]);
978 usage (EXIT_FAILURE);
981 set_speed (input_speed, argv[k], &mode);
983 require_set_attr = 1;
985 else if (STREQ (argv[k], "ospeed"))
989 error (0, 0, _("missing argument to `%s'"), argv[k]);
990 usage (EXIT_FAILURE);
993 set_speed (output_speed, argv[k], &mode);
995 require_set_attr = 1;
998 else if (STREQ (argv[k], "rows"))
1002 error (0, 0, _("missing argument to `%s'"), argv[k]);
1003 usage (EXIT_FAILURE);
1006 set_window_size ((int) integer_arg (argv[k]), -1,
1009 else if (STREQ (argv[k], "cols")
1010 || STREQ (argv[k], "columns"))
1014 error (0, 0, _("missing argument to `%s'"), argv[k]);
1015 usage (EXIT_FAILURE);
1018 set_window_size (-1, (int) integer_arg (argv[k]),
1021 else if (STREQ (argv[k], "size"))
1023 max_col = screen_columns ();
1025 display_window_size (0, fd, device_name);
1029 else if (STREQ (argv[k], "line"))
1033 error (0, 0, _("missing argument to `%s'"), argv[k]);
1034 usage (EXIT_FAILURE);
1037 mode.c_line = integer_arg (argv[k]);
1038 require_set_attr = 1;
1041 else if (STREQ (argv[k], "speed"))
1043 max_col = screen_columns ();
1044 display_speed (&mode, 0);
1046 else if (string_to_baud (argv[k]) != (speed_t) -1)
1048 set_speed (both_speeds, argv[k], &mode);
1050 require_set_attr = 1;
1054 if (recover_mode (argv[k], &mode) == 0)
1056 error (0, 0, _("invalid argument `%s'"), argv[k]);
1057 usage (EXIT_FAILURE);
1059 require_set_attr = 1;
1065 if (require_set_attr)
1067 struct termios new_mode;
1069 if (tcsetattr (fd, TCSADRAIN, &mode))
1070 error (EXIT_FAILURE, errno, "%s", device_name);
1072 /* POSIX (according to Zlotnick's book) tcsetattr returns zero if
1073 it performs *any* of the requested operations. This means it
1074 can report `success' when it has actually failed to perform
1075 some proper subset of the requested operations. To detect
1076 this partial failure, get the current terminal attributes and
1077 compare them to the requested ones. */
1079 /* Initialize to all zeroes so there is no risk memcmp will report a
1080 spurious difference in an uninitialized portion of the structure. */
1081 memset (&new_mode, 0, sizeof (new_mode));
1082 if (tcgetattr (fd, &new_mode))
1083 error (EXIT_FAILURE, errno, "%s", device_name);
1085 /* Normally, one shouldn't use memcmp to compare structures that
1086 may have `holes' containing uninitialized data, but we have been
1087 careful to initialize the storage of these two variables to all
1088 zeroes. One might think it more efficient simply to compare the
1089 modified fields, but that would require enumerating those fields --
1090 and not all systems have the same fields in this structure. */
1092 if (memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1095 /* SunOS 4.1.3 (at least) has the problem that after this sequence,
1096 tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2);
1097 sometimes (m1 != m2). The only difference is in the four bits
1098 of the c_cflag field corresponding to the baud rate. To save
1099 Sun users a little confusion, don't report an error if this
1100 happens. But suppress the error only if we haven't tried to
1101 set the baud rate explicitly -- otherwise we'd never give an
1102 error for a true failure to set the baud rate. */
1104 new_mode.c_cflag &= (~CIBAUD);
1105 if (speed_was_set || memcmp (&mode, &new_mode, sizeof (mode)) != 0)
1108 error (EXIT_FAILURE, 0,
1109 _("%s: unable to perform all requested operations"),
1114 printf (_("new_mode: mode\n"));
1115 for (i = 0; i < sizeof (new_mode); i++)
1116 printf ("0x%02x: 0x%02x\n",
1117 *(((unsigned char *) &new_mode) + i),
1118 *(((unsigned char *) &mode) + i));
1125 exit (EXIT_SUCCESS);
1128 /* Return 0 if not applied because not reversible; otherwise return 1. */
1131 set_mode (struct mode_info *info, int reversed, struct termios *mode)
1135 if (reversed && (info->flags & REV) == 0)
1138 bitsp = mode_type_flag (info->type, mode);
1142 /* Combination mode. */
1143 if (STREQ (info->name, "evenp") || STREQ (info->name, "parity"))
1146 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1148 mode->c_cflag = (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7;
1150 else if (STREQ (info->name, "oddp"))
1153 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1155 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB;
1157 else if (STREQ (info->name, "nl"))
1161 mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR;
1162 mode->c_oflag = (mode->c_oflag
1177 mode->c_iflag = mode->c_iflag & ~ICRNL;
1179 mode->c_oflag = mode->c_oflag & ~ONLCR;
1183 else if (STREQ (info->name, "ek"))
1185 mode->c_cc[VERASE] = CERASE;
1186 mode->c_cc[VKILL] = CKILL;
1188 else if (STREQ (info->name, "sane"))
1190 else if (STREQ (info->name, "cbreak"))
1193 mode->c_lflag |= ICANON;
1195 mode->c_lflag &= ~ICANON;
1197 else if (STREQ (info->name, "pass8"))
1201 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1202 mode->c_iflag |= ISTRIP;
1206 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1207 mode->c_iflag &= ~ISTRIP;
1210 else if (STREQ (info->name, "litout"))
1214 mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB;
1215 mode->c_iflag |= ISTRIP;
1216 mode->c_oflag |= OPOST;
1220 mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8;
1221 mode->c_iflag &= ~ISTRIP;
1222 mode->c_oflag &= ~OPOST;
1225 else if (STREQ (info->name, "raw") || STREQ (info->name, "cooked"))
1227 if ((info->name[0] == 'r' && reversed)
1228 || (info->name[0] == 'c' && !reversed))
1231 mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;
1232 mode->c_oflag |= OPOST;
1233 mode->c_lflag |= ISIG | ICANON;
1235 mode->c_cc[VEOF] = CEOF;
1238 mode->c_cc[VEOL] = CEOL;
1245 mode->c_oflag &= ~OPOST;
1246 mode->c_lflag &= ~(ISIG | ICANON
1251 mode->c_cc[VMIN] = 1;
1252 mode->c_cc[VTIME] = 0;
1256 else if (STREQ (info->name, "decctlq"))
1259 mode->c_iflag |= IXANY;
1261 mode->c_iflag &= ~IXANY;
1265 else if (STREQ (info->name, "tabs"))
1268 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3;
1270 mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0;
1274 else if (STREQ (info->name, "tabs"))
1277 mode->c_oflag = mode->c_oflag | OXTABS;
1279 mode->c_oflag = mode->c_oflag & ~OXTABS;
1283 #if defined(XCASE) && defined(IUCLC) && defined(OLCUC)
1284 else if (STREQ (info->name, "lcase")
1285 || STREQ (info->name, "LCASE"))
1289 mode->c_lflag &= ~XCASE;
1290 mode->c_iflag &= ~IUCLC;
1291 mode->c_oflag &= ~OLCUC;
1295 mode->c_lflag |= XCASE;
1296 mode->c_iflag |= IUCLC;
1297 mode->c_oflag |= OLCUC;
1301 else if (STREQ (info->name, "crt"))
1302 mode->c_lflag |= ECHOE
1310 else if (STREQ (info->name, "dec"))
1312 mode->c_cc[VINTR] = 3; /* ^C */
1313 mode->c_cc[VERASE] = 127; /* DEL */
1314 mode->c_cc[VKILL] = 21; /* ^U */
1315 mode->c_lflag |= ECHOE
1324 mode->c_iflag &= ~IXANY;
1329 *bitsp = *bitsp & ~info->mask & ~info->bits;
1331 *bitsp = (*bitsp & ~info->mask) | info->bits;
1337 set_control_char (struct control_info *info, const char *arg,
1338 struct termios *mode)
1340 unsigned char value;
1342 if (STREQ (info->name, "min") || STREQ (info->name, "time"))
1343 value = integer_arg (arg);
1344 else if (arg[0] == '\0' || arg[1] == '\0')
1346 else if (STREQ (arg, "^-") || STREQ (arg, "undef"))
1347 value = _POSIX_VDISABLE;
1348 else if (arg[0] == '^' && arg[1] != '\0') /* Ignore any trailing junk. */
1353 value = arg[1] & ~0140; /* Non-letters get weird results. */
1356 value = integer_arg (arg);
1357 mode->c_cc[info->offset] = value;
1361 set_speed (enum speed_setting type, const char *arg, struct termios *mode)
1365 baud = string_to_baud (arg);
1366 if (type == input_speed || type == both_speeds)
1367 cfsetispeed (mode, baud);
1368 if (type == output_speed || type == both_speeds)
1369 cfsetospeed (mode, baud);
1375 get_win_size (int fd, struct winsize *win)
1377 int err = ioctl (fd, TIOCGWINSZ, (char *) win);
1382 set_window_size (int rows, int cols, int fd, const char *device_name)
1386 if (get_win_size (fd, &win))
1388 if (errno != EINVAL)
1389 error (EXIT_FAILURE, errno, "%s", device_name);
1390 memset (&win, 0, sizeof (win));
1399 /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote:
1400 The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel.
1401 This comment from sys/ttold.h describes Sun's twisted logic - a better
1402 test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0).
1403 At any rate, the problem is gone in Solaris 2.x.
1405 Unfortunately, the old TIOCSSIZE code does collide with TIOCSWINSZ,
1406 but they can be disambiguated by checking whether a "struct ttysize"
1407 structure's "ts_lines" field is greater than 64K or not. If so,
1408 it's almost certainly a "struct winsize" instead.
1410 At any rate, the bug manifests itself when ws_row == 0; the symptom is
1411 that ws_row is set to ws_col, and ws_col is set to (ws_xpixel<<16) +
1412 ws_ypixel. Since GNU stty sets rows and columns separately, this bug
1413 caused "stty rows 0 cols 0" to set rows to cols and cols to 0, while
1414 "stty cols 0 rows 0" would do the right thing. On a little-endian
1415 machine like the sun386i, the problem is the same, but for ws_col == 0.
1417 The workaround is to do the ioctl once with row and col = 1 to set the
1418 pixel info, and then do it again using a TIOCSSIZE to set rows/cols. */
1420 if (win.ws_row == 0 || win.ws_col == 0)
1422 struct ttysize ttysz;
1424 ttysz.ts_lines = win.ws_row;
1425 ttysz.ts_cols = win.ws_col;
1430 if (ioctl (fd, TIOCSWINSZ, (char *) &win))
1431 error (EXIT_FAILURE, errno, "%s", device_name);
1433 if (ioctl (fd, TIOCSSIZE, (char *) &ttysz))
1434 error (EXIT_FAILURE, errno, "%s", device_name);
1439 if (ioctl (fd, TIOCSWINSZ, (char *) &win))
1440 error (EXIT_FAILURE, errno, "%s", device_name);
1444 display_window_size (int fancy, int fd, const char *device_name)
1448 if (get_win_size (fd, &win))
1450 if (errno != EINVAL)
1451 error (EXIT_FAILURE, errno, "%s", device_name);
1453 error (EXIT_FAILURE, 0,
1454 _("%s: no size information for this device"), device_name);
1458 wrapf (fancy ? "rows %d; columns %d;" : "%d %d\n",
1459 win.ws_row, win.ws_col);
1467 screen_columns (void)
1472 /* With Solaris 2.[123], this ioctl fails and errno is set to
1473 EINVAL for telnet (but not rlogin) sessions.
1474 On ISC 3.0, it fails for the console and the serial port
1475 (but it works for ptys).
1476 It can also fail on any system when stdout isn't a tty.
1477 In case of any failure, just use the default. */
1478 if (get_win_size (STDOUT_FILENO, &win) == 0 && 0 < win.ws_col)
1482 /* Use $COLUMNS if it's in [1..INT_MAX-1]. */
1483 char *col_string = getenv ("COLUMNS");
1485 if (!(col_string != NULL
1486 && xstrtol (col_string, NULL, 0, &n_columns, "") == LONGINT_OK
1488 && n_columns < INT_MAX))
1495 mode_type_flag (enum mode_type type, struct termios *mode)
1500 return &mode->c_cflag;
1503 return &mode->c_iflag;
1506 return &mode->c_oflag;
1509 return &mode->c_lflag;
1520 display_settings (enum output_type output_type, struct termios *mode,
1521 int fd, const char *device_name)
1523 switch (output_type)
1526 display_changed (mode);
1530 display_all (mode, fd, device_name);
1534 display_recoverable (mode);
1540 display_changed (struct termios *mode)
1546 enum mode_type prev_type = control;
1548 display_speed (mode, 1);
1550 wrapf ("line = %d;", mode->c_line);
1556 for (i = 0; !STREQ (control_info[i].name, "min"); ++i)
1558 if (mode->c_cc[control_info[i].offset] == control_info[i].saneval)
1560 /* If swtch is the same as susp, don't print both. */
1562 if (STREQ (control_info[i].name, "swtch"))
1565 /* If eof uses the same slot as min, only print whichever applies. */
1567 if ((mode->c_lflag & ICANON) == 0
1568 && (STREQ (control_info[i].name, "eof")
1569 || STREQ (control_info[i].name, "eol")))
1574 wrapf ("%s = %s;", control_info[i].name,
1575 visible (mode->c_cc[control_info[i].offset]));
1577 if ((mode->c_lflag & ICANON) == 0)
1579 wrapf ("min = %d; time = %d;\n", (int) mode->c_cc[VMIN],
1580 (int) mode->c_cc[VTIME]);
1582 else if (empty_line == 0)
1587 for (i = 0; mode_info[i].name != NULL; ++i)
1589 if (mode_info[i].flags & OMIT)
1591 if (mode_info[i].type != prev_type)
1593 if (empty_line == 0)
1599 prev_type = mode_info[i].type;
1602 bitsp = mode_type_flag (mode_info[i].type, mode);
1603 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1604 if ((*bitsp & mask) == mode_info[i].bits)
1606 if (mode_info[i].flags & SANE_UNSET)
1608 wrapf ("%s", mode_info[i].name);
1612 else if ((mode_info[i].flags & (SANE_SET | REV)) == (SANE_SET | REV))
1614 wrapf ("-%s", mode_info[i].name);
1618 if (empty_line == 0)
1624 display_all (struct termios *mode, int fd, const char *device_name)
1629 enum mode_type prev_type = control;
1631 display_speed (mode, 1);
1633 display_window_size (1, fd, device_name);
1636 wrapf ("line = %d;", mode->c_line);
1641 for (i = 0; ! STREQ (control_info[i].name, "min"); ++i)
1643 /* If swtch is the same as susp, don't print both. */
1645 if (STREQ (control_info[i].name, "swtch"))
1648 /* If eof uses the same slot as min, only print whichever applies. */
1650 if ((mode->c_lflag & ICANON) == 0
1651 && (STREQ (control_info[i].name, "eof")
1652 || STREQ (control_info[i].name, "eol")))
1655 wrapf ("%s = %s;", control_info[i].name,
1656 visible (mode->c_cc[control_info[i].offset]));
1659 if ((mode->c_lflag & ICANON) == 0)
1661 wrapf ("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]);
1662 if (current_col != 0)
1666 for (i = 0; mode_info[i].name != NULL; ++i)
1668 if (mode_info[i].flags & OMIT)
1670 if (mode_info[i].type != prev_type)
1674 prev_type = mode_info[i].type;
1677 bitsp = mode_type_flag (mode_info[i].type, mode);
1678 mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits;
1679 if ((*bitsp & mask) == mode_info[i].bits)
1680 wrapf ("%s", mode_info[i].name);
1681 else if (mode_info[i].flags & REV)
1682 wrapf ("-%s", mode_info[i].name);
1689 display_speed (struct termios *mode, int fancy)
1691 if (cfgetispeed (mode) == 0 || cfgetispeed (mode) == cfgetospeed (mode))
1692 wrapf (fancy ? "speed %lu baud;" : "%lu\n",
1693 baud_to_value (cfgetospeed (mode)));
1695 wrapf (fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n",
1696 baud_to_value (cfgetispeed (mode)),
1697 baud_to_value (cfgetospeed (mode)));
1703 display_recoverable (struct termios *mode)
1707 printf ("%lx:%lx:%lx:%lx",
1708 (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag,
1709 (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag);
1710 for (i = 0; i < NCCS; ++i)
1711 printf (":%x", (unsigned int) mode->c_cc[i]);
1716 recover_mode (char *arg, struct termios *mode)
1720 unsigned long iflag, oflag, cflag, lflag;
1722 /* Scan into temporaries since it is too much trouble to figure out
1723 the right format for `tcflag_t'. */
1724 if (sscanf (arg, "%lx:%lx:%lx:%lx%n",
1725 &iflag, &oflag, &cflag, &lflag, &n) != 4)
1727 mode->c_iflag = iflag;
1728 mode->c_oflag = oflag;
1729 mode->c_cflag = cflag;
1730 mode->c_lflag = lflag;
1732 for (i = 0; i < NCCS; ++i)
1734 if (sscanf (arg, ":%x%n", &chr, &n) != 1)
1736 mode->c_cc[i] = chr;
1740 /* Fail if there are too many fields. */
1749 const char *string; /* ASCII representation. */
1750 speed_t speed; /* Internal form. */
1751 unsigned long value; /* Numeric value. */
1754 struct speed_map speeds[] =
1761 {"134.5", B134, 134},
1766 {"1200", B1200, 1200},
1767 {"1800", B1800, 1800},
1768 {"2400", B2400, 2400},
1769 {"4800", B4800, 4800},
1770 {"9600", B9600, 9600},
1771 {"19200", B19200, 19200},
1772 {"38400", B38400, 38400},
1773 {"exta", B19200, 19200},
1774 {"extb", B38400, 38400},
1776 {"57600", B57600, 57600},
1779 {"115200", B115200, 115200},
1782 {"230400", B230400, 230400},
1785 {"460800", B460800, 460800},
1788 {"500000", B500000, 500000},
1791 {"576000", B576000, 576000},
1794 {"921600", B921600, 921600},
1797 {"1000000", B1000000, 1000000},
1800 {"1152000", B1152000, 1152000},
1803 {"1500000", B1500000, 1500000},
1806 {"2000000", B2000000, 2000000},
1809 {"2500000", B2500000, 2500000},
1812 {"3000000", B3000000, 3000000},
1815 {"3500000", B3500000, 3500000},
1818 {"4000000", B4000000, 4000000},
1824 string_to_baud (const char *arg)
1828 for (i = 0; speeds[i].string != NULL; ++i)
1829 if (STREQ (arg, speeds[i].string))
1830 return speeds[i].speed;
1831 return (speed_t) -1;
1834 static unsigned long
1835 baud_to_value (speed_t speed)
1839 for (i = 0; speeds[i].string != NULL; ++i)
1840 if (speed == speeds[i].speed)
1841 return speeds[i].value;
1846 sane_mode (struct termios *mode)
1851 for (i = 0; control_info[i].name; ++i)
1854 if (STREQ (control_info[i].name, "min"))
1857 mode->c_cc[control_info[i].offset] = control_info[i].saneval;
1860 for (i = 0; mode_info[i].name != NULL; ++i)
1862 if (mode_info[i].flags & SANE_SET)
1864 bitsp = mode_type_flag (mode_info[i].type, mode);
1865 *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits;
1867 else if (mode_info[i].flags & SANE_UNSET)
1869 bitsp = mode_type_flag (mode_info[i].type, mode);
1870 *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits;
1875 /* Return a string that is the printable representation of character CH. */
1876 /* Adapted from `cat' by Torbjorn Granlund. */
1879 visible (unsigned int ch)
1881 static char buf[10];
1884 if (ch == _POSIX_VDISABLE)
1903 *bpout++ = ch - 128;
1913 *bpout++ = ch - 128 + 64;
1923 return (const char *) buf;
1926 /* Parse string S as an integer, using decimal radix by default,
1927 but allowing octal and hex numbers as in C. */
1928 /* From `od' by Richard Stallman. */
1931 integer_arg (const char *s)
1934 if (xstrtol (s, NULL, 0, &value, "bB") != LONGINT_OK)
1936 error (0, 0, _("invalid integer argument `%s'"), s);
1937 usage (EXIT_FAILURE);