1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
20 ***********************************************************************/
24 * Written by David Korn
25 * Tue Apr 4 10:46:00 EDT 1995
28 static const char usage
[] =
29 "[-?@(#)$Id: stty (AT&T Research) 2008-11-10 $\n]"
31 "[+NAME?stty - set or get terminal modes]"
32 "[+DESCRIPTION?\bstty\b sets certain terminal I/O modes for the device "
33 "that is the current standard input; without arguments, it writes "
34 "the settings of certain modes to standard output.]"
36 "[a:all?Writes to standard output all of the mode settings.]"
37 "[g:save?Writes the current settings to standard output in a form that can "
38 "be used as an argument to another \bstty\b command. The \brows\b "
39 "and \bcolumns\b values are not included.]"
40 "[t:terminal-group?Print the terminal group id of the device, -1 if unknown.]"
44 "[+EXTENDED DESCRIPTION?Modes are specified either as a single name or "
45 "as a name followed by a value. As indicated below, many of the "
46 "mode names can be preceded by a \b-\b to negate its meaning. "
47 "Modes are listed by group corresponding to field in the "
48 "\btermios\b structure defined in \b<termios.h>\b. Modes "
49 "in the last group are implemented using options in the previous "
50 "groups. Note that many combinations of modes make no sense, but "
51 "no sanity checking is performed. The modes are selected from the "
52 "following:]{\fabc\f}"
55 "[+0?All modes reported or set successfully.]"
56 "[+>0?Standard input not a terminaol or one or more modes failed.]"
58 "[+SEE ALSO?\btegetattr\b(2), \btcsetattr\b(2), \bioctl\b(2)]"
66 #include <sys/ioctl.h>
69 #define C(x) ERROR_catalog(x)
71 #ifndef _POSIX_VDISABLE
72 # define _POSIX_VDISABLE 0
79 # define NCCS elementsof(((struct termio*)0)->c_cc)
111 #undef SS /* who co-opted this namespace? */
113 #define IG 0x0001 /* ignore display */
114 #define NL 0x0002 /* entry ends line of display */
115 #define SS 0x0004 /* set in sane mode */
116 #define US 0x0010 /* unset in sane mode */
126 const char description
[76];
129 static const Tty_t Ttable
[] =
132 { "ispeed", NUM
, C_SPEED
,0, CBAUD
, 0, C("\an\a is the input baud rate") },
133 { "ospeed", NUM
, C_SPEED
,0, CBAUD
, 0, C("\an\a is the output baud rate") },
134 { "speed", NUM
, C_SPEED
,IG
, CBAUD
},
136 { "0", SPEED
, C_FLAG
, 0, B0
},
137 { "50", SPEED
, C_FLAG
, 0, B50
},
138 { "75", SPEED
, C_FLAG
, 0, B75
},
139 { "110", SPEED
, C_FLAG
, 0, B110
},
140 { "134", SPEED
, C_FLAG
, 0, B134
},
141 { "150", SPEED
, C_FLAG
, 0, B150
},
142 { "200", SPEED
, C_FLAG
, 0, B200
},
143 { "300", SPEED
, C_FLAG
, 0, B300
},
144 { "600", SPEED
, C_FLAG
, 0, B600
},
145 { "1200", SPEED
, C_FLAG
, 0, B1200
},
146 { "1800", SPEED
, C_FLAG
, 0, B1800
},
147 { "2400", SPEED
, C_FLAG
, 0, B2400
},
148 { "4800", SPEED
, C_FLAG
, 0, B4800
},
149 { "9600", SPEED
, C_FLAG
, 0, B9600
},
150 { "19200", SPEED
, C_FLAG
, 0, B19200
},
151 { "38400", SPEED
, C_FLAG
, 0, B38400
},
154 { "rows", WIND
, W_SIZE
, IG
, 0, 24, C("\an\a is the number of lines for display") },
155 { "cols", WIND
, W_SIZE
, IG
, 1, 80, C("\an\a is the number of columns for display") },
156 { "columns", WIND
, W_SIZE
, IG
, 1, 80, C("Same as \bcols\b") },
158 { "intr", CHAR
, T_CHAR
, SS
, VINTR
, 'C', C("Send an interrupt signal") },
159 { "quit", CHAR
, T_CHAR
, SS
, VQUIT
, '|', C("Send a quit signal") },
160 { "erase", CHAR
, T_CHAR
, SS
, VERASE
, 'H', C("Erase the last character entered") },
161 { "kill", CHAR
, T_CHAR
, NL
|SS
, VKILL
, 'U', C("Erase the current line") },
162 { "eof", CHAR
, T_CHAR
, SS
, VEOF
, 'D', C("Send an end of file") },
164 { "eol2", CHAR
, T_CHAR
, US
, VEOL2
, _POSIX_VDISABLE
, C("Alternate character to end the line") },
167 { "swtch", CHAR
, T_CHAR
, US
, VSWTCH
, _POSIX_VDISABLE
, C("Switch to a different shell layer") },
169 { "eol", CHAR
, T_CHAR
, NL
|US
, VEOL
, _POSIX_VDISABLE
, C("End the line") },
171 { "start", CHAR
, T_CHAR
, SS
, VSTART
, 'Q', C("Restart the output after stopping it") },
174 { "stop", CHAR
, T_CHAR
, SS
, VSTOP
, 'S', C("Stop the output") },
177 { "dsusp", CHAR
, T_CHAR
, SS
, VDSUSP
, 'Y', C("Send a terminal stop signal after flushing the input") },
180 { "susp", CHAR
, T_CHAR
, NL
|SS
, VSUSP
, 'Z', C("Send a terminal stop signal") },
183 { "rprnt", CHAR
, T_CHAR
, SS
, VREPRINT
, 'R', C("Redraw the current line") },
184 #endif /* VREPRINT */
186 { "flush", CHAR
, T_CHAR
, SS
, VDISCARD
, 'O', C("Discard output") },
187 #endif /* VDISCARD */
189 { "werase", CHAR
, T_CHAR
, SS
, VWERASE
, 'W', C("Erase the last word entered") },
192 { "lnext", CHAR
, T_CHAR
, NL
|SS
, VLNEXT
, 'V', C("Enter the next input character literally") },
195 #if _mem_c_line_termios
196 { "line", NUM
, C_LINE
, 0, 0, 0, C("Line discipline number") },
198 { "min", NUM
, T_CHAR
, 0, VMIN
, 0, C("Mininmum number of characters to read in raw mode") },
199 { "time", NUM
, T_CHAR
, 0, VTIME
, 0, C("Number of .1 second intervals with raw mode") },
201 { "parenb", BIT
, C_FLAG
, 0, PARENB
, PARENB
, C("Enable (disable) parity generation and detection") },
202 { "parodd", BIT
, C_FLAG
, 0, PARODD
, PARODD
, C("Use odd (even) parity") },
204 { "parext", BIT
, C_FLAG
, 0, PAREXT
, PAREXT
},
207 { "cread", BIT
, C_FLAG
, SS
, CREAD
, CREAD
, C("Enable (disable) input") },
209 { "cs5", SIZE
, C_FLAG
, 0, CSIZE
, CS5
, C("Char size 5") },
210 { "cs6", SIZE
, C_FLAG
, 0, CSIZE
, CS6
, C("Char size 6") },
211 { "cs7", SIZE
, C_FLAG
, 0, CSIZE
, CS7
, C("Char size 7") },
212 { "cs8", SIZE
, C_FLAG
, 0, CSIZE
, CS8
, C("Char size 8") },
213 { "hupcl", BIT
, C_FLAG
, 0, HUPCL
, HUPCL
, C("Hangup (do not hangup) connection on last close") },
214 { "hup", BIT
, C_FLAG
, IG
, HUPCL
, HUPCL
, C("Same as \bhupcl\b") },
215 { "cstopb", BIT
, C_FLAG
, 0, CSTOPB
, CSTOPB
, C("Use two (one) stop bits") },
217 { "crtscts", BIT
, C_FLAG
, 0, CRTSCTS
, CRTSCTS
, C("Enable (disable) RTS/CTS handshaking") },
219 { "clocal", BIT
, C_FLAG
, NL
, CLOCAL
, CLOCAL
, C("Disable (enable) modem control signals") },
221 { "ignbrk", BIT
, I_FLAG
, US
, IGNBRK
, IGNBRK
, C("Ignore (do not ignore) break characters") },
222 { "brkint", BIT
, I_FLAG
, SS
, BRKINT
, BRKINT
, C("Generate (do not generate) INTR signal on break") },
223 { "ignpar", BIT
, I_FLAG
, 0, IGNPAR
, IGNPAR
, C("Ignore (do not ignore) characters with parity errors") },
224 { "parmrk", BIT
, I_FLAG
, 0, PARMRK
, PARMRK
, C("Mark (do not mark) parity errors") },
225 { "inpck", BIT
, I_FLAG
, 0, INPCK
, INPCK
, C("Enable (disable) input parity checking") },
226 { "istrip", BIT
, I_FLAG
, 0, ISTRIP
, ISTRIP
, C("Clear (do not clear) high bit of input characters") },
227 { "inlcr", BIT
, I_FLAG
, US
, INLCR
, INLCR
, C("Translate (do not translate) carriage return to newline") },
228 { "igncr", BIT
, I_FLAG
, US
, IGNCR
, IGNCR
, C("Ignore (do not ignore) carriage return") },
230 { "iuclc", BIT
, I_FLAG
, US
, IUCLC
, IUCLC
, C("Map (do not map) upper-case to lower case") },
232 { "ixon", BIT
, I_FLAG
, 0, IXON
, IXON
, C("Enable (disable) XON/XOFF flow control. \bstop\b character stops output") },
234 { "ixany", BIT
, I_FLAG
, US
, IXANY
, IXANY
, C("Any character (only start character) can restart output.") },
235 { "decctlq", BIT
, I_FLAG
, IG
, IXANY
, 0, C("Same as \b-ixany\b") },
237 { "ixoff", BIT
, I_FLAG
, US
, IXOFF
, IXOFF
, C("Disable (enable) XON/XOFF flow control") },
239 { "imaxbel", BIT
, I_FLAG
, SS
, IMAXBEL
, IMAXBEL
, C("Beep (do not beep) if a character arrives with full input buffer") },
241 { "icrnl", BIT
, I_FLAG
, NL
|SS
, ICRNL
, ICRNL
, C("Translate (do not translate) carriage return to newline") },
243 { "isig", BIT
, L_FLAG
, SS
, ISIG
, ISIG
, C("Enable (disable) \bintr\b, \bquit\b, and \bsusp\b special characters") },
244 { "icanon", BIT
, L_FLAG
, SS
, ICANON
, ICANON
, C("Enable (disable) \berase\b, \bkill\b, \bwerase\b, and \brprnt\b special characters") },
245 { "icannon", BIT
, L_FLAG
, SS
, ICANON
, ICANON
},
247 { "iexten", BIT
, L_FLAG
, SS
, IEXTEN
, IEXTEN
, C("Enable (disable) non-POSIX special characters") },
249 { "echo", BIT
, L_FLAG
, SS
, ECHO
|ECHONL
, ECHO
|ECHONL
, C("Echo (do not echo) input characters") },
250 { "echoe", BIT
, L_FLAG
, SS
, ECHOE
, ECHOE
, C("Echo (do not echo) erase characters as backspace-space-backspace") },
251 { "echok", BIT
, L_FLAG
, SS
, ECHOK
, ECHOK
, C("Echo (do not echo) a newline after a kill character") },
253 { "echoke", BIT
, L_FLAG
, SS
, ECHOKE
, ECHOKE
, C("Echo (do not echo) a newline after a kill character") },
255 { "lfkc", BIT
, L_FLAG
, IG
, ECHOK
, ECHOK
, C("Same as \bechok\b (\b-echok\b); obsolete") },
256 { "echonl", BIT
, L_FLAG
, SS
, ECHONL
, ECHONL
,"Echo (do not echo) newline even if not echoing other character" },
258 { "echoctl", BIT
, L_FLAG
, SS
, ECHOCTL
, ECHOCTL
, C("Echo (do not echo) control characters as \b^\b\ac\a") },
263 { "echoprt", BIT
, L_FLAG
, US
, ECHOPRT
, ECHOPRT
, C("Echo (do not echo) erased characters backward, between '\\' and '/'") },
268 { "xcase", BIT
, L_FLAG
, US
, XCASE
, XCASE
, C("Enable (disable) \bicanon\b uppercase as lowercase with '\\' prefix") },
271 { "defecho", BIT
, L_FLAG
, 0, DEFECHO
, DEFECHO
},
274 { "flusho", BIT
, L_FLAG
, 0, FLUSHO
, FLUSHO
, C("Discard (do not discard) written data. Cleared by subsequent input") },
277 { "pendin", BIT
, L_FLAG
, 0, PENDIN
, PENDIN
, C("Redisplay pending input at next read and then automatically clear \bpendin\b") },
279 { "noflsh", BIT
, L_FLAG
, US
, NOFLSH
, NOFLSH
, C("Disable (enable) flushing after \bintr\b and \bquit\b special characters") },
281 { "tostop", BIT
, L_FLAG
, NL
|US
, TOSTOP
, TOSTOP
, C("Stop (do not stop) background jobs that try to write to the terminal") },
284 { "olcuc", BIT
, O_FLAG
, US
, OLCUC
, OLCUC
, C("Translate (do not translate) lowercase characters to uppercase") },
287 { "onlcr", BIT
, O_FLAG
, SS
, ONLCR
, ONLCR
, C("Translate (do not translate) newline to carriage return-newline") },
290 { "onlret", BIT
, O_FLAG
, US
, ONLRET
, ONLRET
, C("Newline performs (does not perform) a carriage return") },
293 { "ocrnl", BIT
, O_FLAG
, US
, OCRNL
, OCRNL
, C("Translate (do not translate) carriage return to newline") },
296 { "onocr", BIT
, O_FLAG
, US
, ONOCR
, ONOCR
, C("Do not (do) print carriage returns in the first column") },
299 { "ofill", BIT
, O_FLAG
, US
, OFILL
, OFILL
, C("Use fill characters (use timing) for delays") },
302 { "ofdel", BIT
, O_FLAG
, US
, OFDEL
, OFDEL
, C("Use DEL (NUL) as fill characters for delays") },
304 { "opost", BIT
, O_FLAG
, SS
, OPOST
, OPOST
, C(" Postprocess (do not postprocess) output") },
306 { "cr0", BITS
, O_FLAG
, IG
|SS
, CRDLY
, CR0
},
307 { "cr1", BITS
, O_FLAG
, US
, CRDLY
, CR1
},
308 { "cr2", BITS
, O_FLAG
, US
, CRDLY
, CR2
},
309 { "cr3", BITS
, O_FLAG
, US
, CRDLY
, CR3
},
312 { "nl0", BITS
, O_FLAG
, IG
|US
, NLDLY
, NL0
},
313 { "nl1", BITS
, O_FLAG
, US
, NLDLY
, NL1
},
316 { "tabs", TABS
, O_FLAG
, IG
, TABDLY
, TAB3
, C("Preserve (expand to spaces) tabs") },
318 { "tab0", BITS
, O_FLAG
, IG
|SS
, TABDLY
, TAB0
},
321 { "tab1", BITS
, O_FLAG
, US
, TABDLY
, TAB1
},
324 { "tab2", BITS
, O_FLAG
, US
, TABDLY
, TAB2
},
326 { "tab3", BITS
, O_FLAG
, US
, TABDLY
, TAB3
},
329 { "bs0", BITS
, O_FLAG
, IG
|SS
, BSDLY
, BS0
},
330 { "bs1", BITS
, O_FLAG
, US
, BSDLY
, BS1
},
333 { "vt0", BITS
, O_FLAG
, IG
|SS
, VTDLY
, VT0
},
334 { "vt1", BITS
, O_FLAG
, US
, VTDLY
, VT1
},
337 { "ff0", BITS
, O_FLAG
, IG
|SS
, FFDLY
, FF0
},
338 { "ff1", BITS
, O_FLAG
, US
, FFDLY
, FF1
},
340 { "", MIXED
, O_FLAG
, NL
|IG
},
342 { "evenp", MIXED
, C_FLAG
, IG
, PARENB
, 0, C("Same as \bparenb -parodd cs7\b") },
343 { "oddp", MIXED
, C_FLAG
, IG
, PARODD
, 0, C("Same as \bparenb parodd cs7\b") },
344 { "parity", MIXED
, C_FLAG
, IG
, 0, 0, C("Same as parenb \b-parodd cs7\b") },
345 { "ek", MIXED
, C_FLAG
, IG
, 0, 0, C("Reset the \berase\b and \bkill\b special characters to their default values") },
346 { "sane", SANE
, C_FLAG
, IG
, 0, 0, C("Reset all modes to some reasonable values") },
347 { "cooked", COOKED
, C_FLAG
, IG
, 0, 0, C("Disable raw input and output") },
348 { "raw", COOKED
, C_FLAG
, IG
, 0, 0, C("Enable raw input and output") },
349 { "lcase", CASE
, C_FLAG
, IG
, 0 , 0, C("Set \bxcase\b, \biuclc\b, and \bolcuc\b") },
350 { "LCASE", CASE
, C_FLAG
, IG
, 0 , 0, C("Same as \blcase\b") }
353 #if CC_NATIVE == CC_ASCII
354 #define cntl(x) (((x)=='?')?0177:((x)&037))
356 #define cntl(x) (((x)=='?')?ccmapc(0177,CC_ASCII,CC_NATIVE):ccmapc(ccmapc(x,CC_NATIVE,CC_ASCII)&037,CC_ASCII,CC_NATIVE))
359 static void sane(register struct termios
*sp
)
361 register const Tty_t
* tp
;
363 for (tp
= Ttable
; tp
< &Ttable
[elementsof(Ttable
)]; tp
++)
364 if (tp
->flags
& (SS
|US
))
373 sp
->c_cflag
|= tp
->mask
;
375 sp
->c_cflag
&= ~tp
->mask
;
379 sp
->c_iflag
|= tp
->mask
;
381 sp
->c_iflag
&= ~tp
->mask
;
385 sp
->c_oflag
|= tp
->mask
;
387 sp
->c_oflag
&= ~tp
->mask
;
391 sp
->c_lflag
|= tp
->mask
;
393 sp
->c_lflag
&= ~tp
->mask
;
398 sp
->c_cc
[tp
->mask
] = cntl(tp
->val
);
403 static int gin(char *arg
,struct termios
*sp
)
408 sp
->c_iflag
= strtol(arg
,&arg
,16);
411 sp
->c_oflag
= strtol(arg
,&arg
,16);
414 sp
->c_cflag
= strtol(arg
,&arg
,16);
417 sp
->c_lflag
= strtol(arg
,&arg
,16);
420 for(i
=0;i
< NCCS
; i
++)
422 sp
->c_cc
[i
] = strtol(arg
,&arg
,16);
426 #if _mem_c_line_termios
432 i
= strtol(arg
,&arg
,16);
436 i
= strtol(arg
,&arg
,16);
445 static void gout(struct termios
*sp
)
448 sfprintf(sfstdout
,":%x",sp
->c_iflag
);
449 sfprintf(sfstdout
,":%x",sp
->c_oflag
);
450 sfprintf(sfstdout
,":%x",sp
->c_cflag
);
451 sfprintf(sfstdout
,":%x",sp
->c_lflag
);
452 for(i
=0;i
< NCCS
; i
++)
453 sfprintf(sfstdout
,":%x",sp
->c_cc
[i
]);
454 #if _mem_c_line_termios
455 sfprintf(sfstdout
,":%x", sp
->c_line
);
457 sfprintf(sfstdout
,":%x", 0);
459 sfprintf(sfstdout
,":%x",cfgetispeed(sp
));
460 sfprintf(sfstdout
,":%x",cfgetospeed(sp
));
461 sfprintf(sfstdout
,":\n");
464 static void output(struct termios
*sp
, int flags
)
468 register int delim
= ' ';
469 register int i
,off
,off2
;
471 unsigned int ispeed
= cfgetispeed(sp
);
472 unsigned int ospeed
= cfgetospeed(sp
);
480 for(i
=0; i
< elementsof(Ttable
); i
++)
486 sfputc(sfstdout
,'\n');
497 if(sp
->c_cflag
&tp
->mask
)
499 if(tty
.c_cflag
&tp
->mask
)
503 if(sp
->c_iflag
&tp
->mask
)
505 if(tty
.c_iflag
&tp
->mask
)
509 if((sp
->c_oflag
&tp
->mask
)==tp
->val
)
511 if(tty
.c_oflag
&tp
->mask
)
515 if(sp
->c_lflag
&tp
->mask
)
517 if(tty
.c_lflag
&tp
->mask
)
522 if(!flags
&& off
==off2
)
525 sfprintf(sfstdout
,"%s%c",tp
->name
,delim
);
526 else if(tp
->type
==BIT
)
527 sfprintf(sfstdout
,"-%s%c",tp
->name
,delim
);
532 off
= sp
->c_cc
[tp
->mask
];
535 if(!flags
&& off
==(unsigned char)tty
.c_cc
[tp
->mask
])
537 if(off
==_POSIX_VDISABLE
)
538 sfprintf(sfstdout
,"%s = <undef>;%c",tp
->name
,delim
);
539 else if(isprint(off
&0xff))
540 sfprintf(sfstdout
,"%s = %c;%c",tp
->name
,off
,delim
);
542 #if CC_NATIVE == CC_ASCII
543 sfprintf(sfstdout
,"%s = ^%c;%c",tp
->name
,off
==0177?'?':(off
^0100),delim
);
546 off
= ccmapc(off
, CC_NATIVE
, CC_ASCII
);
547 sfprintf(sfstdout
,"%s = ^%c;%c",tp
->name
,off
==0177?'?':ccmapc(off
^0100,CC_ASCII
,CC_NATIVE
),delim
);
553 if((sp
->c_cflag
&CSIZE
)!=tp
->mask
)
555 if(flags
|| (sp
->c_cflag
&CSIZE
) != (tty
.c_cflag
&CSIZE
))
556 sfprintf(sfstdout
,"%s ",tp
->name
);
566 else if(tp
->mask
==ospeed
)
574 off
= ioctl(0,TIOCGWINSZ
,&win
);
576 sfprintf(sfstdout
,"%sspeed %s baud; rows %d; columns %d;\n",schar
,tp
->name
,win
.ws_row
,win
.ws_col
);
580 sfprintf(sfstdout
,"%sspeed %s baud;\n",schar
,tp
->name
);
584 sfputc(sfstdout
,'\n');
587 static const Tty_t
*lookup(const char *name
)
590 for(i
=0; i
< elementsof(Ttable
); i
++)
592 if(strcmp(Ttable
[i
].name
,name
)==0)
599 static const Tty_t
*getspeed(unsigned long val
)
602 for(i
=0; i
< elementsof(Ttable
); i
++)
604 if(Ttable
[i
].type
==SPEED
&& Ttable
[i
].mask
==val
)
610 static int gettchar(register const char *cp
)
615 return((unsigned)cp
[0]);
616 if(*cp
=='^' && cp
[1] && cp
[2]==0)
626 if(streq(cp
,"undef") || streq(cp
,"<undef>"))
628 return(*((unsigned char*)cp
));
631 static void set(char *argv
[], struct termios
*sp
)
645 if(!(tp
=lookup(cp
)) || (off
&& (tp
->type
!=BIT
) && (tp
->type
!=TABS
)))
646 error(ERROR_exit(1),"%s: unknown mode",cp
);
651 error(ERROR_exit(1),"%s: unknown mode",cp
);
653 error(ERROR_exit(1),"missing argument to %s",cp
);
654 c
= gettchar(*argv
++);
656 sp
->c_cc
[tp
->mask
] = c
;
658 sp
->c_cc
[tp
->mask
] = _POSIX_VDISABLE
;
665 sp
->c_cflag
&= ~tp
->mask
;
667 sp
->c_cflag
|= tp
->mask
;
671 sp
->c_iflag
&= ~tp
->mask
;
673 sp
->c_iflag
|= tp
->mask
;
676 sp
->c_oflag
&= ~tp
->mask
;
677 sp
->c_oflag
|= tp
->val
;
681 sp
->c_lflag
&= ~tp
->mask
;
683 sp
->c_lflag
|= tp
->mask
;
688 sp
->c_oflag
&= ~tp
->mask
;
690 sp
->c_oflag
|= tp
->val
;
697 if(ioctl(0,TIOCGWINSZ
,&win
)<0)
698 error(ERROR_system(1),"cannot set %s",tp
->name
);
701 sfprintf(sfstdout
,"%d\n",tp
->mask
?win
.ws_col
:win
.ws_row
);
707 error(ERROR_system(1),"%d: invalid number of %s",argv
[-1],tp
->name
);
712 if(ioctl(0,TIOCSWINSZ
,&win
)<0)
713 error(ERROR_system(1),"cannot set %s",tp
->name
);
721 if (tp
->field
== C_SPEED
)
723 if (tp
= getspeed(*tp
->name
== 'i' ? cfgetispeed(sp
) : cfgetospeed(sp
)))
724 sfprintf(sfstdout
, "%s\n", tp
->name
);
727 error(ERROR_exit(1), "%s: missing numeric argument", tp
->name
);
730 c
= (int)strtol(cp
, &ep
, 10);
732 error(ERROR_exit(1), "%s: %s: numeric argument expected", tp
->name
, cp
);
735 #if _mem_c_line_termios
743 if (*tp
->name
!= 'o')
745 if (*tp
->name
!= 'i')
749 error(ERROR_exit(1), "%s: %s: invalid speed", tp
->name
, cp
);
752 sp
->c_cc
[tp
->mask
] = c
;
757 cfsetospeed(sp
, tp
->mask
);
758 cfsetispeed(sp
, tp
->mask
);
761 sp
->c_cflag
&= ~CSIZE
;
762 sp
->c_cflag
|= tp
->mask
;
767 #if defined(OLCUC) && defined(IUCLC)
771 sp
->c_iflag
|= IUCLC
;
772 sp
->c_oflag
|= OLCUC
;
776 sp
->c_iflag
&= ~IUCLC
;
777 sp
->c_oflag
&= ~OLCUC
;
780 #endif /* OLCUC && IUCLC */
786 static void listchars(Sfio_t
*sp
,int type
)
789 c
= (type
==CHAR
?'c':'n');
790 for(i
=0; i
< elementsof(Ttable
); i
++)
792 if(Ttable
[i
].type
==type
&& *Ttable
[i
].description
)
793 sfprintf(sp
,"[+%s \a%c\a?%s.]",Ttable
[i
].name
,c
,Ttable
[i
].description
);
797 static void listgroup(Sfio_t
*sp
,int type
, const char *description
)
801 for(i
=0; i
< elementsof(Ttable
); i
++)
803 if(Ttable
[i
].type
==type
)
804 sfprintf(sp
,"%s ",Ttable
[i
].name
);
806 sfprintf(sp
,"?%s.]",description
);
809 static void listmask(Sfio_t
*sp
,unsigned int mask
,const char *description
)
813 for(i
=0; i
< elementsof(Ttable
); i
++)
815 if(Ttable
[i
].mask
==mask
&& Ttable
[i
].type
==BITS
)
816 sfprintf(sp
,"%s ",Ttable
[i
].name
);
818 sfprintf(sp
,"?%s.]",description
);
821 static void listfields(Sfio_t
*sp
,int field
)
824 for(i
=0; i
< elementsof(Ttable
); i
++)
826 if(Ttable
[i
].field
==field
&& Ttable
[i
].type
==BIT
&& *Ttable
[i
].description
)
827 sfprintf(sp
,"[+%s (-%s)?%s.]",Ttable
[i
].name
,Ttable
[i
].name
,Ttable
[i
].description
);
831 static void listmode(Sfio_t
*sp
,const char *name
)
833 sfprintf(sp
,"[+%s?%s.]",name
,lookup(name
)->description
);
836 static int infof(Opt_t
* op
, Sfio_t
* sp
, const char* s
, Optdisc_t
* dp
)
841 sfprintf(sp
,"[+Control Modes.]{");
842 listfields(sp
,C_FLAG
);
843 listgroup(sp
,SPEED
,"Attempt to set input and output baud rate to number given. A value of \b0\b causes immediate hangup");
845 listgroup(sp
,SIZE
,"Number of bits in a character");
846 sfprintf(sp
,"}[+Input Modes.]{");
847 listfields(sp
,I_FLAG
);
848 sfprintf(sp
,"}[+Output Modes.]{");
849 listfields(sp
,O_FLAG
);
851 listmask(sp
,CRDLY
,"Carriage return delay style");
854 listmask(sp
,NLDLY
,"Newline delay style");
857 listmask(sp
,TABDLY
,"Horizontal tab delay style");
860 listmask(sp
,BSDLY
,"Backspace delay style");
863 listmask(sp
,FFDLY
,"Form feed delay style");
866 listmask(sp
,VTDLY
,"Vertical tab delay style");
868 sfprintf(sp
,"}[+Local Modes.]{");
869 listfields(sp
,L_FLAG
);
870 sfprintf(sp
,"}[+Control Assignments.?If \ac\a is \bundef\b or an empty "
871 "string then the control assignment is disabled.]{");
874 sfprintf(sp
,"}[+Combination Modes.]{");
876 listmode(sp
,"evenp");
877 listmode(sp
,"lcase");
879 listmode(sp
,"parity");
882 listmode(sp
,"LCASE");
887 #ifndef _lib_tcgetpgrp
890 # define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
892 # define tcgetpgrp(a) (-1)
893 # endif /* TIOCGPGRP */
894 #endif /* _lib_tcgetpgrp */
897 b_stty(int argc
, char** argv
, void* context
)
901 register int flags
= 0;
905 cmdinit(argc
, argv
, context
, ERROR_CATALOG
, ERROR_INTERACTIVE
);
906 if (tcgetattr(0, &tty
) < 0)
907 error(ERROR_system(1),"not a tty");
908 memset(&disc
, 0, sizeof(disc
));
909 disc
.version
= OPT_VERSION
;
911 opt_info
.disc
= &disc
;
914 switch (n
= optget(argv
, usage
))
919 if (!opt_info
.offset
|| !argv
[opt_info
.index
][opt_info
.offset
])
937 if (!opt_info
.offset
)
938 error(2, "%s", opt_info
.arg
);
939 else if (!(tp
= lookup(argv
[opt_info
.index
]+1)) || (tp
->type
!= BIT
&& tp
->type
!= TABS
))
940 error(ERROR_exit(1), "%s: unknown mode", argv
[opt_info
.index
]);
943 error(ERROR_usage(2), "%s", opt_info
.arg
);
948 argv
+= opt_info
.index
;
949 if (error_info
.errors
|| (flags
&& *argv
) || (flags
&(flags
-1)))
950 error(ERROR_usage(2), "%s", optusage(NiL
));
952 sfprintf(sfstdout
, "%d\n", tcgetpgrp(0));
955 if (!argv
[1] && **argv
== ':')
959 if (tcsetattr(0, TCSANOW
, &tty
) < 0)
960 error(ERROR_system(1), "cannot set tty");
964 return error_info
.errors
;