1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*34f9b3eeSRoland Mainz * Copyright (c) 1992-2009 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 77c2fbfb3SApril Chin * by AT&T Intellectual Property * 8da2e3ebdSchin * * 9da2e3ebdSchin * A copy of the License is available at * 10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12da2e3ebdSchin * * 13da2e3ebdSchin * Information and Software Systems Research * 14da2e3ebdSchin * AT&T Research * 15da2e3ebdSchin * Florham Park NJ * 16da2e3ebdSchin * * 17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18da2e3ebdSchin * David Korn <dgk@research.att.com> * 19da2e3ebdSchin * * 20da2e3ebdSchin ***********************************************************************/ 21da2e3ebdSchin #pragma prototyped 22da2e3ebdSchin /* 23da2e3ebdSchin * stty.c 24da2e3ebdSchin * Written by David Korn 25da2e3ebdSchin * Tue Apr 4 10:46:00 EDT 1995 26da2e3ebdSchin */ 27da2e3ebdSchin 28da2e3ebdSchin static const char usage[] = 29*34f9b3eeSRoland Mainz "[-?@(#)$Id: stty (AT&T Research) 2008-11-10 $\n]" 30da2e3ebdSchin USAGE_LICENSE 31da2e3ebdSchin "[+NAME?stty - set or get terminal modes]" 32da2e3ebdSchin "[+DESCRIPTION?\bstty\b sets certain terminal I/O modes for the device " 33da2e3ebdSchin "that is the current standard input; without arguments, it writes " 34da2e3ebdSchin "the settings of certain modes to standard output.]" 35da2e3ebdSchin 36da2e3ebdSchin "[a:all?Writes to standard output all of the mode settings.]" 37da2e3ebdSchin "[g:save?Writes the current settings to standard output in a form that can " 38da2e3ebdSchin "be used as an argument to another \bstty\b command. The \brows\b " 39da2e3ebdSchin "and \bcolumns\b values are not included.]" 407c2fbfb3SApril Chin "[t:terminal-group?Print the terminal group id of the device, -1 if unknown.]" 41da2e3ebdSchin "\n" 42da2e3ebdSchin "\n[mode ...]\n" 43da2e3ebdSchin "\n" 44da2e3ebdSchin "[+EXTENDED DESCRIPTION?Modes are specified either as a single name or " 45da2e3ebdSchin "as a name followed by a value. As indicated below, many of the " 46da2e3ebdSchin "mode names can be preceded by a \b-\b to negate its meaning. " 47da2e3ebdSchin "Modes are listed by group corresponding to field in the " 48da2e3ebdSchin "\btermios\b structure defined in \b<termios.h>\b. Modes " 49da2e3ebdSchin "in the last group are implemented using options in the previous " 50da2e3ebdSchin "groups. Note that many combinations of modes make no sense, but " 51da2e3ebdSchin "no sanity checking is performed. The modes are selected from the " 52da2e3ebdSchin "following:]{\fabc\f}" 53da2e3ebdSchin 54da2e3ebdSchin "[+EXIT STATUS?]{" 55da2e3ebdSchin "[+0?All modes reported or set successfully.]" 56da2e3ebdSchin "[+>0?Standard input not a terminaol or one or more modes failed.]" 57da2e3ebdSchin "}" 58da2e3ebdSchin "[+SEE ALSO?\btegetattr\b(2), \btcsetattr\b(2), \bioctl\b(2)]" 59da2e3ebdSchin ; 60da2e3ebdSchin 61da2e3ebdSchin #include <cmd.h> 62da2e3ebdSchin #include <ccode.h> 63da2e3ebdSchin #include <ctype.h> 64da2e3ebdSchin #include <ast_tty.h> 65da2e3ebdSchin #if _sys_ioctl 66da2e3ebdSchin #include <sys/ioctl.h> 67da2e3ebdSchin #endif 68da2e3ebdSchin 69da2e3ebdSchin #define C(x) ERROR_catalog(x) 70da2e3ebdSchin 71da2e3ebdSchin #ifndef _POSIX_VDISABLE 72da2e3ebdSchin # define _POSIX_VDISABLE 0 73da2e3ebdSchin #endif 74da2e3ebdSchin 75da2e3ebdSchin #ifndef NCCS 76da2e3ebdSchin # ifdef NCC 77da2e3ebdSchin # define NCCS NCC 78da2e3ebdSchin # else 79da2e3ebdSchin # define NCCS elementsof(((struct termio*)0)->c_cc) 80da2e3ebdSchin # endif 81da2e3ebdSchin #endif 82da2e3ebdSchin 83da2e3ebdSchin /* command options */ 84da2e3ebdSchin #define A_FLAG 1 85da2e3ebdSchin #define G_FLAG 2 867c2fbfb3SApril Chin #define T_FLAG 4 87da2e3ebdSchin 88da2e3ebdSchin /* termios fields */ 89da2e3ebdSchin #define C_FLAG 1 90da2e3ebdSchin #define C_LINE 2 91da2e3ebdSchin #define C_SPEED 3 92da2e3ebdSchin #define I_FLAG 4 93da2e3ebdSchin #define O_FLAG 5 94da2e3ebdSchin #define L_FLAG 6 95da2e3ebdSchin #define T_CHAR 7 96da2e3ebdSchin #define W_SIZE 8 97da2e3ebdSchin 98da2e3ebdSchin #define BIT 1 99da2e3ebdSchin #define BITS 2 100da2e3ebdSchin #define NUM 3 101da2e3ebdSchin #define CHAR 4 102da2e3ebdSchin #define SPEED 5 103da2e3ebdSchin #define SIZE 6 104da2e3ebdSchin #define MIXED 7 105da2e3ebdSchin #define SANE 8 106da2e3ebdSchin #define COOKED 9 107da2e3ebdSchin #define CASE 10 108da2e3ebdSchin #define TABS 11 109da2e3ebdSchin #define WIND 12 110da2e3ebdSchin 111da2e3ebdSchin #undef SS /* who co-opted this namespace? */ 112da2e3ebdSchin 113da2e3ebdSchin #define IG 0x0001 /* ignore display */ 114da2e3ebdSchin #define NL 0x0002 /* entry ends line of display */ 115da2e3ebdSchin #define SS 0x0004 /* set in sane mode */ 116da2e3ebdSchin #define US 0x0010 /* unset in sane mode */ 117da2e3ebdSchin 118da2e3ebdSchin typedef struct tty_s 119da2e3ebdSchin { 120da2e3ebdSchin const char name[8]; 121da2e3ebdSchin unsigned char type; 122da2e3ebdSchin unsigned char field; 123da2e3ebdSchin short flags; 124da2e3ebdSchin unsigned long mask; 125da2e3ebdSchin unsigned long val; 126da2e3ebdSchin const char description[76]; 127da2e3ebdSchin } Tty_t; 128da2e3ebdSchin 129da2e3ebdSchin static const Tty_t Ttable[] = 130da2e3ebdSchin { 131da2e3ebdSchin #ifdef CBAUD 132da2e3ebdSchin { "ispeed", NUM, C_SPEED,0, CBAUD, 0, C("\an\a is the input baud rate") }, 133da2e3ebdSchin { "ospeed", NUM, C_SPEED,0, CBAUD, 0, C("\an\a is the output baud rate") }, 134da2e3ebdSchin { "speed", NUM, C_SPEED,IG, CBAUD }, 135da2e3ebdSchin #endif 136da2e3ebdSchin { "0", SPEED, C_FLAG, 0, B0 }, 137da2e3ebdSchin { "50", SPEED, C_FLAG, 0, B50 }, 138da2e3ebdSchin { "75", SPEED, C_FLAG, 0, B75 }, 139da2e3ebdSchin { "110", SPEED, C_FLAG, 0, B110 }, 140da2e3ebdSchin { "134", SPEED, C_FLAG, 0, B134 }, 141da2e3ebdSchin { "150", SPEED, C_FLAG, 0, B150 }, 142da2e3ebdSchin { "200", SPEED, C_FLAG, 0, B200 }, 143da2e3ebdSchin { "300", SPEED, C_FLAG, 0, B300 }, 144da2e3ebdSchin { "600", SPEED, C_FLAG, 0, B600 }, 145da2e3ebdSchin { "1200", SPEED, C_FLAG, 0, B1200 }, 146da2e3ebdSchin { "1800", SPEED, C_FLAG, 0, B1800 }, 147da2e3ebdSchin { "2400", SPEED, C_FLAG, 0, B2400 }, 148da2e3ebdSchin { "4800", SPEED, C_FLAG, 0, B4800 }, 149da2e3ebdSchin { "9600", SPEED, C_FLAG, 0, B9600 }, 150da2e3ebdSchin { "19200", SPEED, C_FLAG, 0, B19200 }, 151da2e3ebdSchin { "38400", SPEED, C_FLAG, 0, B38400 }, 152da2e3ebdSchin 153da2e3ebdSchin #ifdef TIOCSWINSZ 154da2e3ebdSchin { "rows", WIND, W_SIZE, IG, 0, 24, C("\an\a is the number of lines for display") }, 155da2e3ebdSchin { "cols", WIND, W_SIZE, IG, 1, 80, C("\an\a is the number of columns for display") }, 156da2e3ebdSchin { "columns", WIND, W_SIZE, IG, 1, 80, C("Same as \bcols\b") }, 157da2e3ebdSchin #endif 158da2e3ebdSchin { "intr", CHAR, T_CHAR, SS, VINTR, 'C', C("Send an interrupt signal") }, 159da2e3ebdSchin { "quit", CHAR, T_CHAR, SS, VQUIT, '|', C("Send a quit signal") }, 160da2e3ebdSchin { "erase", CHAR, T_CHAR, SS, VERASE, 'H', C("Erase the last character entered") }, 161da2e3ebdSchin { "kill", CHAR, T_CHAR, NL|SS, VKILL, 'U', C("Erase the current line") }, 162da2e3ebdSchin { "eof", CHAR, T_CHAR, SS, VEOF, 'D', C("Send an end of file") }, 163da2e3ebdSchin #ifdef VEOL2 164da2e3ebdSchin { "eol2", CHAR, T_CHAR, US, VEOL2, _POSIX_VDISABLE, C("Alternate character to end the line") }, 165da2e3ebdSchin #endif /* VEOL2 */ 166da2e3ebdSchin #ifdef VSWTCH 167da2e3ebdSchin { "swtch", CHAR, T_CHAR, US, VSWTCH, _POSIX_VDISABLE, C("Switch to a different shell layer") }, 168da2e3ebdSchin #endif /* VSWTCH */ 169da2e3ebdSchin { "eol", CHAR, T_CHAR, NL|US, VEOL, _POSIX_VDISABLE, C("End the line") }, 170da2e3ebdSchin #ifdef VSTART 171da2e3ebdSchin { "start", CHAR, T_CHAR, SS, VSTART, 'Q', C("Restart the output after stopping it") }, 172da2e3ebdSchin #endif /* VSTART */ 173da2e3ebdSchin #ifdef VSTOP 174da2e3ebdSchin { "stop", CHAR, T_CHAR, SS, VSTOP, 'S', C("Stop the output") }, 175da2e3ebdSchin #endif /* VSTOP */ 176da2e3ebdSchin #ifdef VDSUSP 177da2e3ebdSchin { "dsusp", CHAR, T_CHAR, SS, VDSUSP, 'Y', C("Send a terminal stop signal after flushing the input") }, 178da2e3ebdSchin #endif /* VDSUSP */ 179da2e3ebdSchin #ifdef VSUSP 180da2e3ebdSchin { "susp", CHAR, T_CHAR, NL|SS, VSUSP, 'Z', C("Send a terminal stop signal") }, 181da2e3ebdSchin #endif /* VSUSP */ 182da2e3ebdSchin #ifdef VREPRINT 183da2e3ebdSchin { "rprnt", CHAR, T_CHAR, SS, VREPRINT, 'R', C("Redraw the current line") }, 184da2e3ebdSchin #endif /* VREPRINT */ 185da2e3ebdSchin #ifdef VDISCARD 186da2e3ebdSchin { "flush", CHAR, T_CHAR, SS, VDISCARD, 'O', C("Discard output") }, 187da2e3ebdSchin #endif /* VDISCARD */ 188da2e3ebdSchin #ifdef VWERASE 189da2e3ebdSchin { "werase", CHAR, T_CHAR, SS, VWERASE, 'W', C("Erase the last word entered") }, 190da2e3ebdSchin #endif /* VWERASE */ 191da2e3ebdSchin #ifdef VLNEXT 192da2e3ebdSchin { "lnext", CHAR, T_CHAR, NL|SS, VLNEXT, 'V', C("Enter the next input character literally") }, 193da2e3ebdSchin #endif /* VLNEXT */ 194da2e3ebdSchin 195da2e3ebdSchin #if _mem_c_line_termios 196da2e3ebdSchin { "line", NUM, C_LINE, 0, 0, 0, C("Line discipline number") }, 197da2e3ebdSchin #endif 198da2e3ebdSchin { "min", NUM, T_CHAR, 0, VMIN, 0, C("Mininmum number of characters to read in raw mode") }, 199da2e3ebdSchin { "time", NUM, T_CHAR, 0, VTIME, 0, C("Number of .1 second intervals with raw mode") }, 200da2e3ebdSchin 201da2e3ebdSchin { "parenb", BIT, C_FLAG, 0, PARENB, PARENB, C("Enable (disable) parity generation and detection") }, 202da2e3ebdSchin { "parodd", BIT, C_FLAG, 0, PARODD, PARODD, C("Use odd (even) parity") }, 203da2e3ebdSchin #ifdef PAREXT 204da2e3ebdSchin { "parext", BIT, C_FLAG, 0, PAREXT, PAREXT }, 205da2e3ebdSchin #endif /* PAREXT */ 206da2e3ebdSchin #ifdef CREAD 207da2e3ebdSchin { "cread", BIT, C_FLAG, SS, CREAD, CREAD, C("Enable (disable) input") }, 208da2e3ebdSchin #endif /* CREAD */ 209da2e3ebdSchin { "cs5", SIZE, C_FLAG, 0, CSIZE, CS5 , C("Char size 5") }, 210da2e3ebdSchin { "cs6", SIZE, C_FLAG, 0, CSIZE, CS6 , C("Char size 6") }, 211da2e3ebdSchin { "cs7", SIZE, C_FLAG, 0, CSIZE, CS7 , C("Char size 7") }, 212da2e3ebdSchin { "cs8", SIZE, C_FLAG, 0, CSIZE, CS8 , C("Char size 8") }, 213da2e3ebdSchin { "hupcl", BIT, C_FLAG, 0, HUPCL, HUPCL, C("Hangup (do not hangup) connection on last close") }, 214da2e3ebdSchin { "hup", BIT, C_FLAG, IG, HUPCL, HUPCL, C("Same as \bhupcl\b") }, 215da2e3ebdSchin { "cstopb", BIT, C_FLAG, 0, CSTOPB, CSTOPB, C("Use two (one) stop bits") }, 216da2e3ebdSchin #ifdef CRTSCTS 217da2e3ebdSchin { "crtscts", BIT, C_FLAG, 0, CRTSCTS, CRTSCTS, C("Enable (disable) RTS/CTS handshaking") }, 218da2e3ebdSchin #endif /* CRTSCTS */ 219da2e3ebdSchin { "clocal", BIT, C_FLAG, NL, CLOCAL, CLOCAL, C("Disable (enable) modem control signals") }, 220da2e3ebdSchin 221da2e3ebdSchin { "ignbrk", BIT, I_FLAG, US, IGNBRK, IGNBRK, C("Ignore (do not ignore) break characters") }, 222da2e3ebdSchin { "brkint", BIT, I_FLAG, SS, BRKINT, BRKINT, C("Generate (do not generate) INTR signal on break") }, 223da2e3ebdSchin { "ignpar", BIT, I_FLAG, 0, IGNPAR, IGNPAR, C("Ignore (do not ignore) characters with parity errors") }, 224da2e3ebdSchin { "parmrk", BIT, I_FLAG, 0, PARMRK, PARMRK, C("Mark (do not mark) parity errors") }, 225da2e3ebdSchin { "inpck", BIT, I_FLAG, 0, INPCK, INPCK, C("Enable (disable) input parity checking") }, 226da2e3ebdSchin { "istrip", BIT, I_FLAG, 0, ISTRIP, ISTRIP, C("Clear (do not clear) high bit of input characters") }, 227da2e3ebdSchin { "inlcr", BIT, I_FLAG, US, INLCR, INLCR, C("Translate (do not translate) carriage return to newline") }, 228da2e3ebdSchin { "igncr", BIT, I_FLAG, US, IGNCR, IGNCR, C("Ignore (do not ignore) carriage return") }, 229da2e3ebdSchin #ifdef IUCLC 230da2e3ebdSchin { "iuclc", BIT, I_FLAG, US, IUCLC, IUCLC, C("Map (do not map) upper-case to lower case") }, 231da2e3ebdSchin #endif /* IUCLC */ 232da2e3ebdSchin { "ixon", BIT, I_FLAG, 0, IXON, IXON, C("Enable (disable) XON/XOFF flow control. \bstop\b character stops output") }, 233da2e3ebdSchin #ifdef IXANY 234da2e3ebdSchin { "ixany", BIT, I_FLAG, US, IXANY, IXANY, C("Any character (only start character) can restart output.") }, 235da2e3ebdSchin { "decctlq", BIT, I_FLAG, IG, IXANY, 0, C("Same as \b-ixany\b") }, 236da2e3ebdSchin #endif /* IXANY */ 237da2e3ebdSchin { "ixoff", BIT, I_FLAG, US, IXOFF, IXOFF, C("Disable (enable) XON/XOFF flow control") }, 238da2e3ebdSchin #ifdef IMAXBEL 239da2e3ebdSchin { "imaxbel", BIT, I_FLAG, SS, IMAXBEL, IMAXBEL, C("Beep (do not beep) if a character arrives with full input buffer") }, 240da2e3ebdSchin #endif /* IMAXBEL */ 241da2e3ebdSchin { "icrnl", BIT, I_FLAG, NL|SS, ICRNL, ICRNL, C("Translate (do not translate) carriage return to newline") }, 242da2e3ebdSchin 243da2e3ebdSchin { "isig", BIT, L_FLAG, SS, ISIG, ISIG, C("Enable (disable) \bintr\b, \bquit\b, and \bsusp\b special characters") }, 244da2e3ebdSchin { "icanon", BIT, L_FLAG, SS, ICANON, ICANON, C("Enable (disable) \berase\b, \bkill\b, \bwerase\b, and \brprnt\b special characters") }, 245da2e3ebdSchin { "icannon", BIT, L_FLAG, SS, ICANON, ICANON }, 246da2e3ebdSchin #ifdef IEXTEN 247da2e3ebdSchin { "iexten", BIT, L_FLAG, SS, IEXTEN, IEXTEN, C("Enable (disable) non-POSIX special characters") }, 248da2e3ebdSchin #endif /* IEXTEN */ 249da2e3ebdSchin { "echo", BIT, L_FLAG, SS, ECHO|ECHONL, ECHO|ECHONL, C("Echo (do not echo) input characters") }, 250da2e3ebdSchin { "echoe", BIT, L_FLAG, SS, ECHOE, ECHOE, C("Echo (do not echo) erase characters as backspace-space-backspace") }, 251da2e3ebdSchin { "echok", BIT, L_FLAG, SS, ECHOK, ECHOK, C("Echo (do not echo) a newline after a kill character") }, 252da2e3ebdSchin #ifdef ECHOKE 253da2e3ebdSchin { "echoke", BIT, L_FLAG, SS, ECHOKE, ECHOKE, C("Echo (do not echo) a newline after a kill character") }, 254da2e3ebdSchin #endif 255da2e3ebdSchin { "lfkc", BIT, L_FLAG, IG, ECHOK, ECHOK, C("Same as \bechok\b (\b-echok\b); obsolete") }, 256da2e3ebdSchin { "echonl", BIT, L_FLAG, SS, ECHONL, ECHONL,"Echo (do not echo) newline even if not echoing other character" }, 257da2e3ebdSchin #ifdef ECHOCTL 258da2e3ebdSchin { "echoctl", BIT, L_FLAG, SS, ECHOCTL, ECHOCTL, C("Echo (do not echo) control characters as \b^\b\ac\a") }, 259da2e3ebdSchin #else 260da2e3ebdSchin #define ECHOCTL 0 261da2e3ebdSchin #endif /* ECHOCTL */ 262da2e3ebdSchin #ifdef ECHOPRT 263da2e3ebdSchin { "echoprt", BIT, L_FLAG, US, ECHOPRT, ECHOPRT, C("Echo (do not echo) erased characters backward, between '\\' and '/'") }, 264da2e3ebdSchin #else 265da2e3ebdSchin #define ECHOPRT 0 266da2e3ebdSchin #endif /* ECHOPRT */ 267da2e3ebdSchin #ifdef XCASE 268da2e3ebdSchin { "xcase", BIT, L_FLAG, US, XCASE, XCASE, C("Enable (disable) \bicanon\b uppercase as lowercase with '\\' prefix") }, 269da2e3ebdSchin #endif /* XCASE */ 270da2e3ebdSchin #ifdef DEFECHO 271da2e3ebdSchin { "defecho", BIT, L_FLAG, 0, DEFECHO, DEFECHO }, 272da2e3ebdSchin #endif /* DEFECHO */ 273da2e3ebdSchin #ifdef FLUSHO 274da2e3ebdSchin { "flusho", BIT, L_FLAG, 0, FLUSHO, FLUSHO, C("Discard (do not discard) written data. Cleared by subsequent input") }, 275da2e3ebdSchin #endif /* FLUSHO */ 276da2e3ebdSchin #ifdef PENDIN 277da2e3ebdSchin { "pendin", BIT, L_FLAG, 0, PENDIN, PENDIN, C("Redisplay pending input at next read and then automatically clear \bpendin\b") }, 278da2e3ebdSchin #endif /* PENDIN */ 279da2e3ebdSchin { "noflsh", BIT, L_FLAG, US, NOFLSH, NOFLSH, C("Disable (enable) flushing after \bintr\b and \bquit\b special characters") }, 280da2e3ebdSchin #ifdef TOSTOP 281da2e3ebdSchin { "tostop", BIT, L_FLAG, NL|US, TOSTOP, TOSTOP, C("Stop (do not stop) background jobs that try to write to the terminal") }, 282da2e3ebdSchin #endif /* TOSTOP */ 283da2e3ebdSchin #ifdef OLCUC 284da2e3ebdSchin { "olcuc", BIT, O_FLAG, US, OLCUC, OLCUC, C("Translate (do not translate) lowercase characters to uppercase") }, 285da2e3ebdSchin #endif /* OLCUC */ 286da2e3ebdSchin #ifdef ONLCR 287da2e3ebdSchin { "onlcr", BIT, O_FLAG, SS, ONLCR, ONLCR, C("Translate (do not translate) newline to carriage return-newline") }, 288da2e3ebdSchin #endif /* ONLCR */ 289da2e3ebdSchin #ifdef ONLRET 290da2e3ebdSchin { "onlret", BIT, O_FLAG, US, ONLRET, ONLRET, C("Newline performs (does not perform) a carriage return") }, 291da2e3ebdSchin #endif /* ONLRET */ 292da2e3ebdSchin #ifdef OCRNL 293da2e3ebdSchin { "ocrnl", BIT, O_FLAG, US, OCRNL, OCRNL, C("Translate (do not translate) carriage return to newline") }, 294da2e3ebdSchin #endif /* OCRNL */ 295da2e3ebdSchin #ifdef ONOCR 296da2e3ebdSchin { "onocr", BIT, O_FLAG, US, ONOCR, ONOCR, C("Do not (do) print carriage returns in the first column") }, 297da2e3ebdSchin #endif /* ONOCR */ 298da2e3ebdSchin #ifdef OFILL 299da2e3ebdSchin { "ofill", BIT, O_FLAG, US, OFILL, OFILL, C("Use fill characters (use timing) for delays") }, 300da2e3ebdSchin #endif /* OFILL */ 301da2e3ebdSchin #ifdef OFDEL 302da2e3ebdSchin { "ofdel", BIT, O_FLAG, US, OFDEL, OFDEL, C("Use DEL (NUL) as fill characters for delays") }, 303da2e3ebdSchin #endif /* OFDEL */ 304da2e3ebdSchin { "opost", BIT, O_FLAG, SS, OPOST, OPOST, C(" Postprocess (do not postprocess) output") }, 305da2e3ebdSchin #ifdef CRDLY 306da2e3ebdSchin { "cr0", BITS, O_FLAG, IG|SS, CRDLY, CR0 }, 307da2e3ebdSchin { "cr1", BITS, O_FLAG, US, CRDLY, CR1 }, 308da2e3ebdSchin { "cr2", BITS, O_FLAG, US, CRDLY, CR2 }, 309da2e3ebdSchin { "cr3", BITS, O_FLAG, US, CRDLY, CR3 }, 310da2e3ebdSchin #endif 311da2e3ebdSchin #ifdef NLDLY 312da2e3ebdSchin { "nl0", BITS, O_FLAG, IG|US, NLDLY, NL0 }, 313da2e3ebdSchin { "nl1", BITS, O_FLAG, US, NLDLY, NL1 }, 314da2e3ebdSchin #endif 315da2e3ebdSchin #ifdef TABDLY 316da2e3ebdSchin { "tabs", TABS, O_FLAG, IG, TABDLY, TAB3, C("Preserve (expand to spaces) tabs") }, 3177c2fbfb3SApril Chin #ifdef TAB0 318da2e3ebdSchin { "tab0", BITS, O_FLAG, IG|SS, TABDLY, TAB0 }, 3197c2fbfb3SApril Chin #endif 3207c2fbfb3SApril Chin #ifdef TAB1 321da2e3ebdSchin { "tab1", BITS, O_FLAG, US, TABDLY, TAB1 }, 3227c2fbfb3SApril Chin #endif 3237c2fbfb3SApril Chin #ifdef TAB2 324da2e3ebdSchin { "tab2", BITS, O_FLAG, US, TABDLY, TAB2 }, 3257c2fbfb3SApril Chin #endif 326da2e3ebdSchin { "tab3", BITS, O_FLAG, US, TABDLY, TAB3 }, 327da2e3ebdSchin #endif 328da2e3ebdSchin #ifdef BSDLY 329da2e3ebdSchin { "bs0", BITS, O_FLAG, IG|SS, BSDLY, BS0 }, 330da2e3ebdSchin { "bs1", BITS, O_FLAG, US, BSDLY, BS1 }, 331da2e3ebdSchin #endif 332da2e3ebdSchin #ifdef VTDLY 333da2e3ebdSchin { "vt0", BITS, O_FLAG, IG|SS, VTDLY, VT0 }, 334da2e3ebdSchin { "vt1", BITS, O_FLAG, US, VTDLY, VT1 }, 335da2e3ebdSchin #endif 336da2e3ebdSchin #ifdef FFDLY 337da2e3ebdSchin { "ff0", BITS, O_FLAG, IG|SS, FFDLY, FF0 }, 338da2e3ebdSchin { "ff1", BITS, O_FLAG, US, FFDLY, FF1 }, 339da2e3ebdSchin #endif 340da2e3ebdSchin { "", MIXED, O_FLAG, NL|IG }, 341da2e3ebdSchin 342da2e3ebdSchin { "evenp", MIXED, C_FLAG, IG, PARENB, 0, C("Same as \bparenb -parodd cs7\b") }, 343da2e3ebdSchin { "oddp", MIXED, C_FLAG, IG, PARODD, 0, C("Same as \bparenb parodd cs7\b") }, 344da2e3ebdSchin { "parity", MIXED, C_FLAG, IG, 0, 0, C("Same as parenb \b-parodd cs7\b") }, 345da2e3ebdSchin { "ek", MIXED, C_FLAG, IG, 0, 0, C("Reset the \berase\b and \bkill\b special characters to their default values") }, 346da2e3ebdSchin { "sane", SANE, C_FLAG, IG, 0, 0, C("Reset all modes to some reasonable values") }, 347da2e3ebdSchin { "cooked", COOKED, C_FLAG, IG, 0, 0, C("Disable raw input and output") }, 348da2e3ebdSchin { "raw", COOKED, C_FLAG, IG, 0, 0, C("Enable raw input and output") }, 349da2e3ebdSchin { "lcase", CASE, C_FLAG, IG, 0 , 0, C("Set \bxcase\b, \biuclc\b, and \bolcuc\b") }, 350da2e3ebdSchin { "LCASE", CASE, C_FLAG, IG, 0 , 0, C("Same as \blcase\b") } 351da2e3ebdSchin }; 352da2e3ebdSchin 353da2e3ebdSchin #if CC_NATIVE == CC_ASCII 354da2e3ebdSchin #define cntl(x) (((x)=='?')?0177:((x)&037)) 355da2e3ebdSchin #else 356da2e3ebdSchin #define cntl(x) (((x)=='?')?ccmapc(0177,CC_ASCII,CC_NATIVE):ccmapc(ccmapc(x,CC_NATIVE,CC_ASCII)&037,CC_ASCII,CC_NATIVE)) 357da2e3ebdSchin #endif 358da2e3ebdSchin 359da2e3ebdSchin static void sane(register struct termios *sp) 360da2e3ebdSchin { 361da2e3ebdSchin register const Tty_t* tp; 362da2e3ebdSchin 363da2e3ebdSchin for (tp = Ttable; tp < &Ttable[elementsof(Ttable)]; tp++) 364da2e3ebdSchin if (tp->flags & (SS|US)) 365da2e3ebdSchin switch (tp->type) 366da2e3ebdSchin { 367da2e3ebdSchin case BIT: 368da2e3ebdSchin case BITS: 369da2e3ebdSchin switch (tp->field) 370da2e3ebdSchin { 371da2e3ebdSchin case C_FLAG: 372da2e3ebdSchin if (tp->flags & SS) 373da2e3ebdSchin sp->c_cflag |= tp->mask; 374da2e3ebdSchin else 375da2e3ebdSchin sp->c_cflag &= ~tp->mask; 376da2e3ebdSchin break; 377da2e3ebdSchin case I_FLAG: 378da2e3ebdSchin if (tp->flags & SS) 379da2e3ebdSchin sp->c_iflag |= tp->mask; 380da2e3ebdSchin else 381da2e3ebdSchin sp->c_iflag &= ~tp->mask; 382da2e3ebdSchin break; 383da2e3ebdSchin case O_FLAG: 384da2e3ebdSchin if (tp->flags & SS) 385da2e3ebdSchin sp->c_oflag |= tp->mask; 386da2e3ebdSchin else 387da2e3ebdSchin sp->c_oflag &= ~tp->mask; 388da2e3ebdSchin break; 389da2e3ebdSchin case L_FLAG: 390da2e3ebdSchin if (tp->flags & SS) 391da2e3ebdSchin sp->c_lflag |= tp->mask; 392da2e3ebdSchin else 393da2e3ebdSchin sp->c_lflag &= ~tp->mask; 394da2e3ebdSchin break; 395da2e3ebdSchin } 396da2e3ebdSchin break; 397da2e3ebdSchin case CHAR: 398da2e3ebdSchin sp->c_cc[tp->mask] = cntl(tp->val); 399da2e3ebdSchin break; 400da2e3ebdSchin } 401da2e3ebdSchin } 402da2e3ebdSchin 403da2e3ebdSchin static int gin(char *arg,struct termios *sp) 404da2e3ebdSchin { 405da2e3ebdSchin register int i; 406da2e3ebdSchin if(*arg++ != ':') 407da2e3ebdSchin return(0); 408da2e3ebdSchin sp->c_iflag = strtol(arg,&arg,16); 409da2e3ebdSchin if(*arg++ != ':') 410da2e3ebdSchin return(0); 411da2e3ebdSchin sp->c_oflag = strtol(arg,&arg,16); 412da2e3ebdSchin if(*arg++ != ':') 413da2e3ebdSchin return(0); 414da2e3ebdSchin sp->c_cflag = strtol(arg,&arg,16); 415da2e3ebdSchin if(*arg++ != ':') 416da2e3ebdSchin return(0); 417da2e3ebdSchin sp->c_lflag = strtol(arg,&arg,16); 418da2e3ebdSchin if(*arg++ != ':') 419da2e3ebdSchin return(0); 420da2e3ebdSchin for(i=0;i< NCCS; i++) 421da2e3ebdSchin { 422da2e3ebdSchin sp->c_cc[i] = strtol(arg,&arg,16); 423da2e3ebdSchin if(*arg++ != ':') 424da2e3ebdSchin return(0); 425da2e3ebdSchin } 426da2e3ebdSchin #if _mem_c_line_termios 427da2e3ebdSchin sp->c_line = 428da2e3ebdSchin #endif 429da2e3ebdSchin strtol(arg,&arg,16); 430da2e3ebdSchin if(*arg++ != ':') 431da2e3ebdSchin return(0); 432da2e3ebdSchin i = strtol(arg,&arg,16); 433da2e3ebdSchin if(*arg++ != ':') 434da2e3ebdSchin return(0); 435da2e3ebdSchin cfsetispeed(sp, i); 436da2e3ebdSchin i = strtol(arg,&arg,16); 437da2e3ebdSchin if(*arg++ != ':') 438da2e3ebdSchin return(0); 439da2e3ebdSchin cfsetospeed(sp, i); 440da2e3ebdSchin if(*arg) 441da2e3ebdSchin return(0); 442da2e3ebdSchin return(1); 443da2e3ebdSchin } 444da2e3ebdSchin 445da2e3ebdSchin static void gout(struct termios *sp) 446da2e3ebdSchin { 447da2e3ebdSchin register int i; 448da2e3ebdSchin sfprintf(sfstdout,":%x",sp->c_iflag); 449da2e3ebdSchin sfprintf(sfstdout,":%x",sp->c_oflag); 450da2e3ebdSchin sfprintf(sfstdout,":%x",sp->c_cflag); 451da2e3ebdSchin sfprintf(sfstdout,":%x",sp->c_lflag); 452da2e3ebdSchin for(i=0;i< NCCS; i++) 453da2e3ebdSchin sfprintf(sfstdout,":%x",sp->c_cc[i]); 454da2e3ebdSchin #if _mem_c_line_termios 455da2e3ebdSchin sfprintf(sfstdout,":%x", sp->c_line); 456da2e3ebdSchin #else 457da2e3ebdSchin sfprintf(sfstdout,":%x", 0); 458da2e3ebdSchin #endif 459da2e3ebdSchin sfprintf(sfstdout,":%x",cfgetispeed(sp)); 460da2e3ebdSchin sfprintf(sfstdout,":%x",cfgetospeed(sp)); 461da2e3ebdSchin sfprintf(sfstdout,":\n"); 462da2e3ebdSchin } 463da2e3ebdSchin 464da2e3ebdSchin static void output(struct termios *sp, int flags) 465da2e3ebdSchin { 466da2e3ebdSchin const Tty_t *tp; 467da2e3ebdSchin struct termios tty; 468da2e3ebdSchin register int delim = ' '; 469da2e3ebdSchin register int i,off,off2; 470da2e3ebdSchin char schar[2]; 471da2e3ebdSchin unsigned int ispeed = cfgetispeed(sp); 472da2e3ebdSchin unsigned int ospeed = cfgetospeed(sp); 473da2e3ebdSchin if(flags&G_FLAG) 474da2e3ebdSchin { 475da2e3ebdSchin gout(sp); 476da2e3ebdSchin return; 477da2e3ebdSchin } 478da2e3ebdSchin tty = *sp; 479da2e3ebdSchin sane(&tty); 480da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 481da2e3ebdSchin { 482da2e3ebdSchin tp= &Ttable[i]; 483da2e3ebdSchin if(tp->flags&IG) 484da2e3ebdSchin { 485da2e3ebdSchin if(tp->flags&NL) 486da2e3ebdSchin sfputc(sfstdout,'\n'); 487da2e3ebdSchin continue; 488da2e3ebdSchin } 489da2e3ebdSchin switch(tp->type) 490da2e3ebdSchin { 491da2e3ebdSchin case BIT: 492da2e3ebdSchin case BITS: 4937c2fbfb3SApril Chin off = off2 = 1; 494da2e3ebdSchin switch(tp->field) 495da2e3ebdSchin { 496da2e3ebdSchin case C_FLAG: 497da2e3ebdSchin if(sp->c_cflag&tp->mask) 498da2e3ebdSchin off = 0; 499da2e3ebdSchin if(tty.c_cflag&tp->mask) 500da2e3ebdSchin off2 = 0; 501da2e3ebdSchin break; 502da2e3ebdSchin case I_FLAG: 503da2e3ebdSchin if(sp->c_iflag&tp->mask) 504da2e3ebdSchin off = 0; 505da2e3ebdSchin if(tty.c_iflag&tp->mask) 506da2e3ebdSchin off2 = 0; 507da2e3ebdSchin break; 508da2e3ebdSchin case O_FLAG: 509da2e3ebdSchin if((sp->c_oflag&tp->mask)==tp->val) 510da2e3ebdSchin off = 0; 511da2e3ebdSchin if(tty.c_oflag&tp->mask) 512da2e3ebdSchin off2 = 0; 513da2e3ebdSchin break; 514da2e3ebdSchin case L_FLAG: 515da2e3ebdSchin if(sp->c_lflag&tp->mask) 516da2e3ebdSchin off = 0; 517da2e3ebdSchin if(tty.c_lflag&tp->mask) 518da2e3ebdSchin off2 = 0; 519da2e3ebdSchin } 520da2e3ebdSchin if(tp->flags&NL) 521da2e3ebdSchin delim = '\n'; 522da2e3ebdSchin if(!flags && off==off2) 523da2e3ebdSchin continue; 524da2e3ebdSchin if(!off) 525da2e3ebdSchin sfprintf(sfstdout,"%s%c",tp->name,delim); 526da2e3ebdSchin else if(tp->type==BIT) 527da2e3ebdSchin sfprintf(sfstdout,"-%s%c",tp->name,delim); 528da2e3ebdSchin delim = ' '; 529da2e3ebdSchin break; 530da2e3ebdSchin 531da2e3ebdSchin case CHAR: 532da2e3ebdSchin off = sp->c_cc[tp->mask]; 533da2e3ebdSchin if(tp->flags&NL) 534da2e3ebdSchin delim = '\n'; 535da2e3ebdSchin if(!flags && off==(unsigned char)tty.c_cc[tp->mask]) 536da2e3ebdSchin continue; 537da2e3ebdSchin if(off==_POSIX_VDISABLE) 538da2e3ebdSchin sfprintf(sfstdout,"%s = <undef>;%c",tp->name,delim); 539da2e3ebdSchin else if(isprint(off&0xff)) 540da2e3ebdSchin sfprintf(sfstdout,"%s = %c;%c",tp->name,off,delim); 541da2e3ebdSchin else 542da2e3ebdSchin #if CC_NATIVE == CC_ASCII 543da2e3ebdSchin sfprintf(sfstdout,"%s = ^%c;%c",tp->name,off==0177?'?':(off^0100),delim); 544da2e3ebdSchin #else 545da2e3ebdSchin { 546da2e3ebdSchin off = ccmapc(off, CC_NATIVE, CC_ASCII); 547da2e3ebdSchin sfprintf(sfstdout,"%s = ^%c;%c",tp->name,off==0177?'?':ccmapc(off^0100,CC_ASCII,CC_NATIVE),delim); 548da2e3ebdSchin } 549da2e3ebdSchin #endif 550da2e3ebdSchin delim = ' '; 551da2e3ebdSchin break; 552da2e3ebdSchin case SIZE: 553da2e3ebdSchin if((sp->c_cflag&CSIZE)!=tp->mask) 554da2e3ebdSchin continue; 555da2e3ebdSchin if(flags || (sp->c_cflag&CSIZE) != (tty.c_cflag&CSIZE)) 556da2e3ebdSchin sfprintf(sfstdout,"%s ",tp->name); 557da2e3ebdSchin break; 558da2e3ebdSchin case SPEED: 559da2e3ebdSchin if(tp->mask==ispeed) 560da2e3ebdSchin { 561da2e3ebdSchin if(ispeed!=ospeed) 562da2e3ebdSchin schar[0]='i'; 563da2e3ebdSchin else 564da2e3ebdSchin schar[0]=0; 565da2e3ebdSchin } 566da2e3ebdSchin else if(tp->mask==ospeed) 567da2e3ebdSchin schar[0]='o'; 568da2e3ebdSchin else 569da2e3ebdSchin continue; 570da2e3ebdSchin schar[1] = 0; 571da2e3ebdSchin #ifdef TIOCSWINSZ 572da2e3ebdSchin { 573da2e3ebdSchin struct winsize win; 574da2e3ebdSchin off = ioctl(0,TIOCGWINSZ,&win); 575da2e3ebdSchin if(off>=0) 576da2e3ebdSchin sfprintf(sfstdout,"%sspeed %s baud; rows %d; columns %d;\n",schar,tp->name,win.ws_row,win.ws_col); 577da2e3ebdSchin } 578da2e3ebdSchin if(off<0) 579da2e3ebdSchin #endif 580da2e3ebdSchin sfprintf(sfstdout,"%sspeed %s baud;\n",schar,tp->name); 581da2e3ebdSchin } 582da2e3ebdSchin } 583da2e3ebdSchin if(delim=='\n') 584da2e3ebdSchin sfputc(sfstdout,'\n'); 585da2e3ebdSchin } 586da2e3ebdSchin 587da2e3ebdSchin static const Tty_t *lookup(const char *name) 588da2e3ebdSchin { 589da2e3ebdSchin register int i; 590da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 591da2e3ebdSchin { 592da2e3ebdSchin if(strcmp(Ttable[i].name,name)==0) 593da2e3ebdSchin return(&Ttable[i]); 594da2e3ebdSchin } 595da2e3ebdSchin return(0); 596da2e3ebdSchin 597da2e3ebdSchin } 598da2e3ebdSchin 599da2e3ebdSchin static const Tty_t *getspeed(unsigned long val) 600da2e3ebdSchin { 601da2e3ebdSchin register int i; 602da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 603da2e3ebdSchin { 604da2e3ebdSchin if(Ttable[i].type==SPEED && Ttable[i].mask==val) 605da2e3ebdSchin return(&Ttable[i]); 606da2e3ebdSchin } 607da2e3ebdSchin return(0); 608da2e3ebdSchin } 609da2e3ebdSchin 610da2e3ebdSchin static int gettchar(register const char *cp) 611da2e3ebdSchin { 612da2e3ebdSchin if(*cp==0) 613da2e3ebdSchin return(-1); 614da2e3ebdSchin if(cp[1]==0) 615da2e3ebdSchin return((unsigned)cp[0]); 616da2e3ebdSchin if(*cp=='^' && cp[1] && cp[2]==0) 617da2e3ebdSchin { 618da2e3ebdSchin switch(cp[1]) 619da2e3ebdSchin { 620da2e3ebdSchin case '-': 621da2e3ebdSchin return(-1); 622da2e3ebdSchin default: 623da2e3ebdSchin return(cntl(cp[1])); 624da2e3ebdSchin } 625da2e3ebdSchin } 626da2e3ebdSchin if(streq(cp,"undef") || streq(cp,"<undef>")) 627da2e3ebdSchin return(-1); 628da2e3ebdSchin return(*((unsigned char*)cp)); 629da2e3ebdSchin } 630da2e3ebdSchin 631da2e3ebdSchin static void set(char *argv[], struct termios *sp) 632da2e3ebdSchin { 633da2e3ebdSchin const Tty_t *tp; 634da2e3ebdSchin register int c,off; 635da2e3ebdSchin char *cp; 636da2e3ebdSchin char *ep; 637da2e3ebdSchin while(cp = *argv++) 638da2e3ebdSchin { 639da2e3ebdSchin off = 0; 640da2e3ebdSchin if(*cp=='-') 641da2e3ebdSchin { 642da2e3ebdSchin cp++; 643da2e3ebdSchin off=1; 644da2e3ebdSchin } 645da2e3ebdSchin if(!(tp=lookup(cp)) || (off && (tp->type!=BIT) && (tp->type!=TABS))) 646da2e3ebdSchin error(ERROR_exit(1),"%s: unknown mode",cp); 647da2e3ebdSchin switch(tp->type) 648da2e3ebdSchin { 649da2e3ebdSchin case CHAR: 650da2e3ebdSchin if(off) 651da2e3ebdSchin error(ERROR_exit(1),"%s: unknown mode",cp); 652da2e3ebdSchin if(!*argv) 653da2e3ebdSchin error(ERROR_exit(1),"missing argument to %s",cp); 654da2e3ebdSchin c = gettchar(*argv++); 655da2e3ebdSchin if(c>=0) 656da2e3ebdSchin sp->c_cc[tp->mask] = c; 657da2e3ebdSchin else 658da2e3ebdSchin sp->c_cc[tp->mask] = _POSIX_VDISABLE; 659da2e3ebdSchin break; 660da2e3ebdSchin case BIT: case BITS: 661da2e3ebdSchin switch(tp->field) 662da2e3ebdSchin { 663da2e3ebdSchin case C_FLAG: 664da2e3ebdSchin if(off) 665da2e3ebdSchin sp->c_cflag &= ~tp->mask; 666da2e3ebdSchin else 667da2e3ebdSchin sp->c_cflag |= tp->mask; 668da2e3ebdSchin break; 669da2e3ebdSchin case I_FLAG: 670da2e3ebdSchin if(off) 671da2e3ebdSchin sp->c_iflag &= ~tp->mask; 672da2e3ebdSchin else 673da2e3ebdSchin sp->c_iflag |= tp->mask; 674da2e3ebdSchin break; 675da2e3ebdSchin case O_FLAG: 676da2e3ebdSchin sp->c_oflag &= ~tp->mask; 677da2e3ebdSchin sp->c_oflag |= tp->val; 678da2e3ebdSchin break; 679da2e3ebdSchin case L_FLAG: 680da2e3ebdSchin if(off) 681da2e3ebdSchin sp->c_lflag &= ~tp->mask; 682da2e3ebdSchin else 683da2e3ebdSchin sp->c_lflag |= tp->mask; 684da2e3ebdSchin break; 685da2e3ebdSchin } 686da2e3ebdSchin break; 687da2e3ebdSchin case TABS: 688da2e3ebdSchin sp->c_oflag &= ~tp->mask; 689da2e3ebdSchin if(off) 690da2e3ebdSchin sp->c_oflag |= tp->val; 691da2e3ebdSchin break; 692da2e3ebdSchin #ifdef TIOCSWINSZ 693da2e3ebdSchin case WIND: 694da2e3ebdSchin { 695da2e3ebdSchin struct winsize win; 696da2e3ebdSchin int n; 697da2e3ebdSchin if(ioctl(0,TIOCGWINSZ,&win)<0) 698da2e3ebdSchin error(ERROR_system(1),"cannot set %s",tp->name); 699da2e3ebdSchin if(!(cp= *argv)) 700da2e3ebdSchin { 701da2e3ebdSchin sfprintf(sfstdout,"%d\n",tp->mask?win.ws_col:win.ws_row); 702da2e3ebdSchin break; 703da2e3ebdSchin } 704da2e3ebdSchin argv++; 705da2e3ebdSchin n=strtol(cp,&cp,10); 706da2e3ebdSchin if(*cp) 707da2e3ebdSchin error(ERROR_system(1),"%d: invalid number of %s",argv[-1],tp->name); 708da2e3ebdSchin if(tp->mask) 709da2e3ebdSchin win.ws_col = n; 710da2e3ebdSchin else 711da2e3ebdSchin win.ws_row = n; 712da2e3ebdSchin if(ioctl(0,TIOCSWINSZ,&win)<0) 713da2e3ebdSchin error(ERROR_system(1),"cannot set %s",tp->name); 714da2e3ebdSchin break; 715da2e3ebdSchin } 716da2e3ebdSchin #endif 717da2e3ebdSchin case NUM: 718da2e3ebdSchin cp = *argv; 719da2e3ebdSchin if (!cp) 720da2e3ebdSchin { 721da2e3ebdSchin if (tp->field == C_SPEED) 722da2e3ebdSchin { 723da2e3ebdSchin if (tp = getspeed(*tp->name == 'i' ? cfgetispeed(sp) : cfgetospeed(sp))) 724da2e3ebdSchin sfprintf(sfstdout, "%s\n", tp->name); 725da2e3ebdSchin break; 726da2e3ebdSchin } 727da2e3ebdSchin error(ERROR_exit(1), "%s: missing numeric argument", tp->name); 728da2e3ebdSchin } 729da2e3ebdSchin argv++; 730da2e3ebdSchin c = (int)strtol(cp, &ep, 10); 731da2e3ebdSchin if (*ep) 732da2e3ebdSchin error(ERROR_exit(1), "%s: %s: numeric argument expected", tp->name, cp); 733da2e3ebdSchin switch (tp->field) 734da2e3ebdSchin { 735da2e3ebdSchin #if _mem_c_line_termios 736da2e3ebdSchin case C_LINE: 737da2e3ebdSchin sp->c_line = c; 738da2e3ebdSchin break; 739da2e3ebdSchin #endif 740da2e3ebdSchin case C_SPEED: 741da2e3ebdSchin if(getspeed(c)) 742da2e3ebdSchin { 743da2e3ebdSchin if (*tp->name != 'o') 744da2e3ebdSchin cfsetispeed(sp, c); 745da2e3ebdSchin if (*tp->name != 'i') 746da2e3ebdSchin cfsetospeed(sp, c); 747da2e3ebdSchin } 748da2e3ebdSchin else 749da2e3ebdSchin error(ERROR_exit(1), "%s: %s: invalid speed", tp->name, cp); 750da2e3ebdSchin break; 751da2e3ebdSchin case T_CHAR: 752da2e3ebdSchin sp->c_cc[tp->mask] = c; 753da2e3ebdSchin break; 754da2e3ebdSchin } 755da2e3ebdSchin break; 756da2e3ebdSchin case SPEED: 757da2e3ebdSchin cfsetospeed(sp, tp->mask); 758da2e3ebdSchin cfsetispeed(sp, tp->mask); 759da2e3ebdSchin break; 760da2e3ebdSchin case SIZE: 761da2e3ebdSchin sp->c_cflag &= ~CSIZE; 762da2e3ebdSchin sp->c_cflag |= tp->mask; 763da2e3ebdSchin break; 764da2e3ebdSchin case SANE: 765da2e3ebdSchin sane(sp); 766da2e3ebdSchin break; 767da2e3ebdSchin #if defined(OLCUC) && defined(IUCLC) 768da2e3ebdSchin case CASE: 769da2e3ebdSchin if(off) 770da2e3ebdSchin { 771da2e3ebdSchin sp->c_iflag |= IUCLC; 772da2e3ebdSchin sp->c_oflag |= OLCUC; 773da2e3ebdSchin } 774da2e3ebdSchin else 775da2e3ebdSchin { 776da2e3ebdSchin sp->c_iflag &= ~IUCLC; 777da2e3ebdSchin sp->c_oflag &= ~OLCUC; 778da2e3ebdSchin } 779da2e3ebdSchin break; 780da2e3ebdSchin #endif /* OLCUC && IUCLC */ 781da2e3ebdSchin } 782da2e3ebdSchin } 783da2e3ebdSchin } 784da2e3ebdSchin 785da2e3ebdSchin 786da2e3ebdSchin static void listchars(Sfio_t *sp,int type) 787da2e3ebdSchin { 788da2e3ebdSchin int i,c; 789da2e3ebdSchin c = (type==CHAR?'c':'n'); 790da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 791da2e3ebdSchin { 792da2e3ebdSchin if(Ttable[i].type==type && *Ttable[i].description) 793da2e3ebdSchin sfprintf(sp,"[+%s \a%c\a?%s.]",Ttable[i].name,c,Ttable[i].description); 794da2e3ebdSchin } 795da2e3ebdSchin } 796da2e3ebdSchin 797da2e3ebdSchin static void listgroup(Sfio_t *sp,int type, const char *description) 798da2e3ebdSchin { 799da2e3ebdSchin int i; 800da2e3ebdSchin sfprintf(sp,"[+"); 801da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 802da2e3ebdSchin { 803da2e3ebdSchin if(Ttable[i].type==type) 804da2e3ebdSchin sfprintf(sp,"%s ",Ttable[i].name); 805da2e3ebdSchin } 806da2e3ebdSchin sfprintf(sp,"?%s.]",description); 807da2e3ebdSchin } 808da2e3ebdSchin 809da2e3ebdSchin static void listmask(Sfio_t *sp,unsigned int mask,const char *description) 810da2e3ebdSchin { 811da2e3ebdSchin int i; 812da2e3ebdSchin sfprintf(sp,"[+"); 813da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 814da2e3ebdSchin { 815da2e3ebdSchin if(Ttable[i].mask==mask && Ttable[i].type==BITS) 816da2e3ebdSchin sfprintf(sp,"%s ",Ttable[i].name); 817da2e3ebdSchin } 818da2e3ebdSchin sfprintf(sp,"?%s.]",description); 819da2e3ebdSchin } 820da2e3ebdSchin 821da2e3ebdSchin static void listfields(Sfio_t *sp,int field) 822da2e3ebdSchin { 823da2e3ebdSchin int i; 824da2e3ebdSchin for(i=0; i < elementsof(Ttable); i++) 825da2e3ebdSchin { 826da2e3ebdSchin if(Ttable[i].field==field && Ttable[i].type==BIT && *Ttable[i].description) 827da2e3ebdSchin sfprintf(sp,"[+%s (-%s)?%s.]",Ttable[i].name,Ttable[i].name,Ttable[i].description); 828da2e3ebdSchin } 829da2e3ebdSchin } 830da2e3ebdSchin 831da2e3ebdSchin static void listmode(Sfio_t *sp,const char *name) 832da2e3ebdSchin { 833da2e3ebdSchin sfprintf(sp,"[+%s?%s.]",name,lookup(name)->description); 834da2e3ebdSchin } 835da2e3ebdSchin 836da2e3ebdSchin static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp) 837da2e3ebdSchin { 838da2e3ebdSchin NoP(op); 839da2e3ebdSchin NoP(s); 840da2e3ebdSchin NoP(dp); 841da2e3ebdSchin sfprintf(sp,"[+Control Modes.]{"); 842da2e3ebdSchin listfields(sp,C_FLAG); 843da2e3ebdSchin listgroup(sp,SPEED,"Attempt to set input and output baud rate to number given. A value of \b0\b causes immediate hangup"); 844da2e3ebdSchin listchars(sp,NUM); 845da2e3ebdSchin listgroup(sp,SIZE,"Number of bits in a character"); 846da2e3ebdSchin sfprintf(sp,"}[+Input Modes.]{"); 847da2e3ebdSchin listfields(sp,I_FLAG); 848da2e3ebdSchin sfprintf(sp,"}[+Output Modes.]{"); 849da2e3ebdSchin listfields(sp,O_FLAG); 850da2e3ebdSchin #ifdef CRDLY 851da2e3ebdSchin listmask(sp,CRDLY,"Carriage return delay style"); 852da2e3ebdSchin #endif 853da2e3ebdSchin #ifdef NLDLY 854da2e3ebdSchin listmask(sp,NLDLY,"Newline delay style"); 855da2e3ebdSchin #endif 856da2e3ebdSchin #ifdef TABDLY 857da2e3ebdSchin listmask(sp,TABDLY,"Horizontal tab delay style"); 858da2e3ebdSchin #endif 859da2e3ebdSchin #ifdef BSDLY 860da2e3ebdSchin listmask(sp,BSDLY,"Backspace delay style"); 861da2e3ebdSchin #endif 862da2e3ebdSchin #ifdef FFDLY 863da2e3ebdSchin listmask(sp,FFDLY,"Form feed delay style"); 864da2e3ebdSchin #endif 865da2e3ebdSchin #ifdef VTDLY 866da2e3ebdSchin listmask(sp,VTDLY,"Vertical tab delay style"); 867da2e3ebdSchin #endif 868da2e3ebdSchin sfprintf(sp,"}[+Local Modes.]{"); 869da2e3ebdSchin listfields(sp,L_FLAG); 870da2e3ebdSchin sfprintf(sp,"}[+Control Assignments.?If \ac\a is \bundef\b or an empty " 871da2e3ebdSchin "string then the control assignment is disabled.]{"); 872da2e3ebdSchin listchars(sp,WIND); 873da2e3ebdSchin listchars(sp,CHAR); 874da2e3ebdSchin sfprintf(sp,"}[+Combination Modes.]{"); 875da2e3ebdSchin listmode(sp,"ek"); 876da2e3ebdSchin listmode(sp,"evenp"); 877da2e3ebdSchin listmode(sp,"lcase"); 878da2e3ebdSchin listmode(sp,"oddp"); 879da2e3ebdSchin listmode(sp,"parity"); 880da2e3ebdSchin listmode(sp,"sane"); 881da2e3ebdSchin listmode(sp,"tabs"); 882da2e3ebdSchin listmode(sp,"LCASE"); 883da2e3ebdSchin sfputc(sp,'}'); 884da2e3ebdSchin return(1); 885da2e3ebdSchin } 886da2e3ebdSchin 8877c2fbfb3SApril Chin #ifndef _lib_tcgetpgrp 8887c2fbfb3SApril Chin # ifdef TIOCGPGRP 8897c2fbfb3SApril Chin static int _i_; 8907c2fbfb3SApril Chin # define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1) 8917c2fbfb3SApril Chin # else 8927c2fbfb3SApril Chin # define tcgetpgrp(a) (-1) 8937c2fbfb3SApril Chin # endif /* TIOCGPGRP */ 8947c2fbfb3SApril Chin #endif /* _lib_tcgetpgrp */ 8957c2fbfb3SApril Chin 896da2e3ebdSchin int 897da2e3ebdSchin b_stty(int argc, char** argv, void* context) 898da2e3ebdSchin { 899da2e3ebdSchin struct termios tty; 900da2e3ebdSchin register int n; 901da2e3ebdSchin register int flags = 0; 902da2e3ebdSchin const Tty_t* tp; 903da2e3ebdSchin Optdisc_t disc; 904da2e3ebdSchin 905da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_INTERACTIVE); 906da2e3ebdSchin if (tcgetattr(0, &tty) < 0) 907da2e3ebdSchin error(ERROR_system(1),"not a tty"); 908da2e3ebdSchin memset(&disc, 0, sizeof(disc)); 909da2e3ebdSchin disc.version = OPT_VERSION; 910da2e3ebdSchin disc.infof = infof; 911da2e3ebdSchin opt_info.disc = &disc; 912da2e3ebdSchin for (;;) 913da2e3ebdSchin { 914da2e3ebdSchin switch (n = optget(argv, usage)) 915da2e3ebdSchin { 916da2e3ebdSchin case 'a': 917da2e3ebdSchin case 'g': 918*34f9b3eeSRoland Mainz case 't': 919da2e3ebdSchin if (!opt_info.offset || !argv[opt_info.index][opt_info.offset]) 920da2e3ebdSchin { 921da2e3ebdSchin switch (n) 922da2e3ebdSchin { 923da2e3ebdSchin case 'a': 924da2e3ebdSchin flags |= A_FLAG; 925da2e3ebdSchin break; 926da2e3ebdSchin case 'g': 927da2e3ebdSchin flags |= G_FLAG; 928da2e3ebdSchin break; 929*34f9b3eeSRoland Mainz case 't': 930*34f9b3eeSRoland Mainz flags |= T_FLAG; 931*34f9b3eeSRoland Mainz break; 932da2e3ebdSchin } 933da2e3ebdSchin continue; 934da2e3ebdSchin } 935da2e3ebdSchin /*FALLTHROUGH*/ 936da2e3ebdSchin case ':': 937da2e3ebdSchin if (!opt_info.offset) 938da2e3ebdSchin error(2, "%s", opt_info.arg); 939da2e3ebdSchin else if (!(tp = lookup(argv[opt_info.index]+1)) || (tp->type != BIT && tp->type != TABS)) 940da2e3ebdSchin error(ERROR_exit(1), "%s: unknown mode", argv[opt_info.index]); 941da2e3ebdSchin break; 942da2e3ebdSchin case '?': 943da2e3ebdSchin error(ERROR_usage(2), "%s", opt_info.arg); 944da2e3ebdSchin break; 945da2e3ebdSchin } 946da2e3ebdSchin break; 947da2e3ebdSchin } 948da2e3ebdSchin argv += opt_info.index; 9497c2fbfb3SApril Chin if (error_info.errors || (flags && *argv) || (flags&(flags-1))) 950da2e3ebdSchin error(ERROR_usage(2), "%s", optusage(NiL)); 9517c2fbfb3SApril Chin if (flags & T_FLAG) 9527c2fbfb3SApril Chin sfprintf(sfstdout, "%d\n", tcgetpgrp(0)); 9537c2fbfb3SApril Chin else if (*argv) 954da2e3ebdSchin { 955da2e3ebdSchin if (!argv[1] && **argv == ':') 956da2e3ebdSchin gin(*argv, &tty); 957da2e3ebdSchin else 958da2e3ebdSchin set(argv, &tty); 959da2e3ebdSchin if (tcsetattr(0, TCSANOW, &tty) < 0) 960da2e3ebdSchin error(ERROR_system(1), "cannot set tty"); 961da2e3ebdSchin } 962da2e3ebdSchin else 963da2e3ebdSchin output(&tty, flags); 964da2e3ebdSchin return error_info.errors; 965da2e3ebdSchin } 966