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