xref: /illumos-gate/usr/src/ucbcmd/stty/stty.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <termio.h>
35 #include <sys/stermio.h>
36 #include <sys/termiox.h>
37 #include "stty.h"
38 
39 extern char *getenv();
40 extern void exit();
41 extern void perror();
42 
43 static char *STTY = "stty: ";
44 static char *USAGE = "usage: stty [-agh] [modes]\n";
45 static int	pitt = 0;
46 static struct termios cb;
47 static struct termio ocb; /* for non-streams devices */
48 static struct stio stio;
49 static struct termiox termiox;
50 static struct winsize winsize, owinsize;
51 static int term;
52 
53 void prmodes(int);
54 void pramodes(int);
55 void prachars(void);
56 void pcol(int, int);
57 void pit(unsigned char, char *, char *);
58 void delay(int, char *s);
59 void prspeed(char *, int);
60 void prencode(void);
61 
62 #define	ioctl_desc	1
63 #define	output		stderr
64 
65 int
66 main(int argc, char *argv[])
67 {
68 
69 	int i;
70 	char	*s_arg, *sttyparse();	/* s_arg: ptr to mode to be set */
71 	extern const struct	speeds	speeds[];
72 
73 	if (argc == 2) {
74 		/*
75 		 * "stty size", "stty speed" and "stty -g" are intended for
76 		 * use within backquotes; thus, they do the "fetch" "ioctl"
77 		 * from "/dev/tty" and always print their result on the
78 		 * standard output.
79 		 * Since their standard output is likely to be a pipe, they
80 		 * should not try to read the modes from the standard output.
81 		 */
82 		if (strcmp(argv[1], "size") == 0) {
83 			if ((i = open("/dev/tty", 0)) < 0) {
84 				perror("stty: Cannot open /dev/tty");
85 				exit(2);
86 			}
87 			if (ioctl(i, TIOCGWINSZ, &winsize) < 0) {
88 				perror("stty: TIOCGWINSZ");
89 				exit(2);
90 			}
91 			(void) printf("%d %d\n",
92 			    winsize.ws_row, winsize.ws_col);
93 			exit(0);
94 		} else if (strcmp(argv[1], "speed") == 0) {
95 			if ((i = open("/dev/tty", 0)) < 0) {
96 				perror("stty: Cannot open /dev/tty");
97 				exit(2);
98 			}
99 			if ((term = get_ttymode(i,
100 			    &ocb, &cb, &stio, &termiox, &winsize)) < 0) {
101 				perror(STTY);
102 				exit(2);
103 			}
104 			if (term & TERMIOS) {
105 				for (i = 0; speeds[i].string; i++)
106 					if (cfgetospeed(&cb) ==
107 					    speeds[i].speed) {
108 						(void) printf("%s\n",
109 						    speeds[i].string);
110 						exit(0);
111 					}
112 			} else {
113 				for (i = 0; speeds[i].string; i++)
114 					if ((cb.c_cflag&CBAUD) ==
115 					    speeds[i].speed) {
116 						(void) printf("%s\n",
117 						    speeds[i].string);
118 						exit(0);
119 					}
120 			}
121 			(void) printf("unknown\n");
122 			exit(1);
123 		} else if (strcmp(argv[1], "-g") == 0) {
124 			if ((i = open("/dev/tty", 0)) < 0) {
125 				perror("stty: Cannot open /dev/tty");
126 				exit(2);
127 			}
128 			if ((term = get_ttymode(i,
129 			    &ocb, &cb, &stio, &termiox, &winsize)) < 0) {
130 				perror(STTY);
131 				exit(2);
132 			}
133 			prencode();
134 			exit(0);
135 		}
136 	}
137 
138 	if ((term = get_ttymode(ioctl_desc,
139 	    &ocb, &cb, &stio, &termiox, &winsize)) < 0) {
140 		perror(STTY);
141 		exit(2);
142 	}
143 	owinsize = winsize;
144 	if (argc == 1) {
145 		prmodes(0);
146 		exit(0);
147 	}
148 	if ((argc == 2) && strcmp(argv[1], "all") == 0) {
149 		prmodes(1);
150 		exit(0);
151 	}
152 	if ((argc == 2) && strcmp(argv[1], "everything") == 0) {
153 		pramodes(1);
154 		exit(0);
155 	}
156 	if ((argc == 2) && (argv[1][0] == '-') && (argv[1][2] == '\0'))
157 		switch (argv[1][1]) {
158 		case 'a':
159 			pramodes(0);
160 			exit(0);
161 		case 'h':
162 			pramodes(1);
163 			exit(0);
164 		default:
165 			(void) fprintf(stderr, "%s", USAGE);
166 			exit(2);
167 		}
168 	if (s_arg = sttyparse(argc, argv,
169 	    term, &ocb, &cb, &termiox, &winsize)) {
170 		(void) fprintf(stderr, "unknown mode: %s\n", s_arg);
171 		exit(2);
172 	}
173 
174 	if (set_ttymode(ioctl_desc,
175 	    term, &ocb, &cb, &stio, &termiox, &winsize, &owinsize) == -1) {
176 		perror(STTY);
177 		exit(2);
178 	}
179 	return (0);	/*NOTREACHED*/
180 }
181 
182 void
183 prmodes(int moremodes)
184 /* print modes, no options, argc is 1 */
185 {
186 	int m;
187 
188 	if (!(term & ASYNC)) {
189 		m = stio.imode;
190 		if (m & IUCLC)
191 			(void) fprintf(output, "iuclc ");
192 		else
193 			(void) fprintf(output, "-iuclc ");
194 		m = stio.omode;
195 		if (m & OLCUC)
196 			(void) fprintf(output, "olcuc ");
197 		else
198 			(void) fprintf(output, "-olcuc ");
199 		if (m & TAB3)
200 			(void) fprintf(output, "tab3 ");
201 		m = stio.lmode;
202 		if (m & XCASE)
203 			(void) fprintf(output, "xcase ");
204 		else
205 			(void) fprintf(output, "-xcase ");
206 		if (m & STFLUSH)
207 			(void) fprintf(output, "stflush ");
208 		else
209 			(void) fprintf(output, "-stflush ");
210 		if (m & STWRAP)
211 			(void) fprintf(output, "stwrap ");
212 		else
213 			(void) fprintf(output, "-stwrap ");
214 		if (m & STAPPL)
215 			(void) fprintf(output, "stappl ");
216 		else
217 			(void) fprintf(output, "-stappl ");
218 		(void) fprintf(output, "\n");
219 	}
220 	if (term & ASYNC) {
221 		m = cb.c_cflag;
222 		if ((term & TERMIOS) && cfgetispeed(&cb) != 0 &&
223 		    cfgetispeed(&cb) != cfgetospeed(&cb)) {
224 			prspeed("ispeed ", cfgetispeed(&cb));
225 			prspeed("ospeed ", cfgetospeed(&cb));
226 		} else
227 			prspeed("speed ", cfgetospeed(&cb));
228 		if (m & PARENB) {
229 			if ((m & PAREXT) && (term & TERMIOS)) {
230 				if (m & PARODD)
231 					(void) fprintf(output, "markp ");
232 				else
233 					(void) fprintf(output, "spacep ");
234 			} else {
235 				if (m & PARODD)
236 					(void) fprintf(output, "oddp ");
237 				else
238 					(void) fprintf(output, "evenp ");
239 			}
240 		} else
241 			(void) fprintf(output, "-parity ");
242 		if (((m & PARENB) && !(m & CS7)) ||
243 		    (!(m & PARENB) && !(m & CS8)))
244 			(void) fprintf(output, "cs%c ", '5' + (m & CSIZE)/CS6);
245 		if (m & CSTOPB)
246 			(void) fprintf(output, "cstopb ");
247 		if (m & HUPCL)
248 			(void) fprintf(output, "hupcl ");
249 		if (!(m & CREAD))
250 			(void) fprintf(output, "-cread ");
251 		if (m & CLOCAL)
252 			(void) fprintf(output, "clocal ");
253 		if (m & LOBLK)
254 			(void) fprintf(output, "loblk ");
255 		(void) fprintf(output, "\n");
256 		if (ocb.c_line != 0)
257 			(void) fprintf(output, "line = %d; ", ocb.c_line);
258 		if (term & WINDOW) {
259 			(void) fprintf(output, "rows = %d; columns = %d;",
260 			    winsize.ws_row, winsize.ws_col);
261 			(void) fprintf(output, " ypixels = %d; xpixels = %d;\n",
262 			    winsize.ws_ypixel, winsize.ws_xpixel);
263 		}
264 		if ((cb.c_lflag & ICANON) == 0)
265 			(void) fprintf(output, "min = %d; time = %d;\n",
266 			    cb.c_cc[VMIN], cb.c_cc[VTIME]);
267 		if (!moremodes) {
268 			if (cb.c_cc[VINTR] != CINTR)
269 				pit(cb.c_cc[VINTR], "intr", "; ");
270 			if (cb.c_cc[VQUIT] != CQUIT)
271 				pit(cb.c_cc[VQUIT], "quit", "; ");
272 			if (cb.c_cc[VERASE] != CERASE)
273 				pit(cb.c_cc[VERASE], "erase", "; ");
274 			if (cb.c_cc[VKILL] != CKILL)
275 				pit(cb.c_cc[VKILL], "kill", "; ");
276 			if (cb.c_cc[VEOF] != CEOF)
277 				pit(cb.c_cc[VEOF], "eof", "; ");
278 			if (cb.c_cc[VEOL] != CNUL)
279 				pit(cb.c_cc[VEOL], "eol", "; ");
280 			if (cb.c_cc[VEOL2] != CNUL)
281 				pit(cb.c_cc[VEOL2], "eol2", "; ");
282 			if (cb.c_cc[VSWTCH] != CSWTCH)
283 				pit(cb.c_cc[VSWTCH], "swtch", "; ");
284 			if (term & TERMIOS) {
285 				if (cb.c_cc[VSTART] != CSTART)
286 					pit(cb.c_cc[VSTART], "start", "; ");
287 				if (cb.c_cc[VSTOP] != CSTOP)
288 					pit(cb.c_cc[VSTOP], "stop", "; ");
289 				if (cb.c_cc[VSUSP] != CSUSP)
290 					pit(cb.c_cc[VSUSP], "susp", "; ");
291 				if (cb.c_cc[VDSUSP] != CDSUSP)
292 					pit(cb.c_cc[VDSUSP], "dsusp", "; ");
293 				if (cb.c_cc[VREPRINT] != CRPRNT)
294 					pit(cb.c_cc[VREPRINT], "rprnt", "; ");
295 				if (cb.c_cc[VDISCARD] != CFLUSH)
296 					pit(cb.c_cc[VDISCARD], "flush", "; ");
297 				if (cb.c_cc[VWERASE] != CWERASE)
298 					pit(cb.c_cc[VWERASE], "werase", "; ");
299 				if (cb.c_cc[VLNEXT] != CLNEXT)
300 					pit(cb.c_cc[VLNEXT], "lnext", "; ");
301 			}
302 		}
303 		if (pitt)
304 			(void) fprintf(output, "\n");
305 		m = cb.c_iflag;
306 		if (m & IGNBRK)
307 			(void) fprintf(output, "ignbrk ");
308 		else if (!(m & BRKINT))
309 			(void) fprintf(output, "-brkint ");
310 		if (!(m & INPCK))
311 			(void) fprintf(output, "-inpck ");
312 		else if (!(m & IGNPAR))
313 			(void) fprintf(output, "-ignpar ");
314 		if (m & PARMRK)
315 			(void) fprintf(output, "parmrk ");
316 		if (!(m & ISTRIP))
317 			(void) fprintf(output, "-istrip ");
318 		if (m & INLCR)
319 			(void) fprintf(output, "inlcr ");
320 		if (m & IGNCR)
321 			(void) fprintf(output, "igncr ");
322 		if (!(m & ICRNL))
323 			(void) fprintf(output, "-icrnl ");
324 		if (m & IUCLC)
325 			(void) fprintf(output, "iuclc ");
326 		if (!(m & IXON))
327 			(void) fprintf(output, "-ixon ");
328 		else if (m & IXANY)
329 			(void) fprintf(output, "ixany ");
330 		if (m & IXOFF)
331 			(void) fprintf(output, "ixoff ");
332 		if ((term & TERMIOS) && (m & IMAXBEL))
333 			(void) fprintf(output, "imaxbel ");
334 		m = cb.c_oflag;
335 		if (!(m & OPOST))
336 			(void) fprintf(output, "-opost ");
337 		else {
338 			if (m & OLCUC)
339 				(void) fprintf(output, "olcuc ");
340 			if (!(m & ONLCR))
341 				(void) fprintf(output, "-onlcr ");
342 			if (m & OCRNL)
343 				(void) fprintf(output, "ocrnl ");
344 			if (m & ONOCR)
345 				(void) fprintf(output, "onocr ");
346 			if (m & ONLRET)
347 				(void) fprintf(output, "onlret ");
348 			if (m & OFILL)
349 				if (m & OFDEL)
350 					(void) fprintf(output, "del-fill ");
351 				else
352 					(void) fprintf(output, "nul-fill ");
353 			delay((m & CRDLY)/CR1, "cr");
354 			delay((m & NLDLY)/NL1, "nl");
355 			if ((m & TABDLY) == XTABS)
356 				(void) fprintf(output, "-tabs ");
357 			else
358 				delay((m & TABDLY)/TAB1, "tab");
359 			delay((m & BSDLY)/BS1, "bs");
360 			delay((m & VTDLY)/VT1, "vt");
361 			delay((m & FFDLY)/FF1, "ff");
362 		}
363 		(void) fprintf(output, "\n");
364 		m = cb.c_lflag;
365 		if (!(m & ISIG))
366 			(void) fprintf(output, "-isig ");
367 		if (!(m & ICANON))
368 			(void) fprintf(output, "-icanon ");
369 		if (m & XCASE)
370 			(void) fprintf(output, "xcase ");
371 		if (!(m & ECHO))
372 			(void) fprintf(output, "-echo ");
373 		if (m & ECHOE) {
374 			if (m & ECHOKE)
375 				(void) fprintf(output, "crt ");
376 			else
377 				(void) fprintf(output, "echoe -echoke ");
378 		} else {
379 			if (!(m & ECHOPRT))
380 				(void) fprintf(output, "-echoprt ");
381 		}
382 		if (!(m & ECHOK))
383 			(void) fprintf(output, "-echok ");
384 		if (m & ECHONL)
385 			(void) fprintf(output, "echonl ");
386 		if (m & NOFLSH)
387 			(void) fprintf(output, "noflsh ");
388 		if (m & TOSTOP)
389 			(void) fprintf(output, "tostop ");
390 		if (!(m & ECHOCTL))
391 			(void) fprintf(output, "-echoctl ");
392 		if (m & DEFECHO)
393 			(void) fprintf(output, "defecho ");
394 		if (m & FLUSHO)
395 			(void) fprintf(output, "flusho ");
396 		if (m & PENDIN)
397 			(void) fprintf(output, "pendin ");
398 		if (m & IEXTEN)
399 			(void) fprintf(output, "iexten ");
400 		(void) fprintf(output, "\n");
401 	}
402 	if (term & FLOW) {
403 		m = termiox.x_hflag;
404 		if (m & RTSXOFF)
405 			(void) fprintf(output, "rtsxoff ");
406 		if (m & CTSXON)
407 			(void) fprintf(output, "ctsxon ");
408 		if (m & DTRXOFF)
409 			(void) fprintf(output, "dterxoff ");
410 		if (m & CDXON)
411 			(void) fprintf(output, "rlsdxon ");
412 		if (m & ISXOFF)
413 			(void) fprintf(output, "isxoff ");
414 		m = termiox.x_cflag;
415 		switch (m & XMTCLK) {
416 		case XCIBRG:
417 			(void) fprintf(output, "xcibrg ");
418 			break;
419 		case XCTSET:
420 			(void) fprintf(output, "xctset ");
421 			break;
422 		case XCRSET:
423 			(void) fprintf(output, "xcrset ");
424 			break;
425 		}
426 
427 		switch (m & RCVCLK) {
428 		case RCIBRG:
429 			(void) fprintf(output, "rcibrg ");
430 			break;
431 		case RCTSET:
432 			(void) fprintf(output, "rctset ");
433 			break;
434 		case RCRSET:
435 			(void) fprintf(output, "rcrset ");
436 			break;
437 		}
438 
439 		switch (m & TSETCLK) {
440 		case TSETCOFF:
441 			(void) fprintf(output, "tsetcoff ");
442 			break;
443 		case TSETCRBRG:
444 			(void) fprintf(output, "tsetcrc ");
445 			break;
446 		case TSETCTBRG:
447 			(void) fprintf(output, "tsetcxc ");
448 			break;
449 		}
450 
451 		switch (m & RSETCLK) {
452 		case RSETCOFF:
453 			(void) fprintf(output, "rsetcoff ");
454 			break;
455 		case RSETCRBRG:
456 			(void) fprintf(output, "rsetcrc ");
457 			break;
458 		case RSETCTBRG:
459 			(void) fprintf(output, "rsetcxc ");
460 		}
461 		(void) fprintf(output, "\n");
462 	}
463 	if (moremodes)
464 		prachars();
465 }
466 
467 void
468 pramodes(int tabform)
469 /* print all modes, -a option */
470 {
471 	int m;
472 
473 	m = cb.c_cflag;
474 	if (term & ASYNC) {
475 		if ((term & TERMIOS) && cfgetispeed(&cb) != 0 &&
476 		    cfgetispeed(&cb) != cfgetospeed(&cb)) {
477 			prspeed("ispeed ", cfgetispeed(&cb));
478 			prspeed("ospeed ", cfgetospeed(&cb));
479 		} else
480 			prspeed("speed ", cfgetospeed(&cb));
481 		if (!(term & TERMIOS))
482 			(void) fprintf(output, "line = %d; ", ocb.c_line);
483 		(void) fprintf(output, "\n");
484 		if (term & WINDOW) {
485 			(void) fprintf(output, "rows = %d columns = %d; ",
486 			    winsize.ws_row, winsize.ws_col);
487 			(void) fprintf(output, "ypixels = %d xpixels = %d\n",
488 			    winsize.ws_ypixel, winsize.ws_xpixel);
489 		}
490 		if ((cb.c_lflag & ICANON) == 0)
491 			(void) fprintf(output, "min = %d; time = %d;\n",
492 			    cb.c_cc[VMIN], cb.c_cc[VTIME]);
493 		if (!tabform) {
494 			pit(cb.c_cc[VINTR], "intr", "; ");
495 			pit(cb.c_cc[VQUIT], "quit", "; ");
496 			pit(cb.c_cc[VERASE], "erase", "; ");
497 			pit(cb.c_cc[VKILL], "kill", ";\n");
498 			pit(cb.c_cc[VEOF], "eof", "; ");
499 			pit(cb.c_cc[VEOL], "eol", "; ");
500 			pit(cb.c_cc[VEOL2], "eol2", "; ");
501 			pit(cb.c_cc[VSWTCH], "swtch", ";\n");
502 			if (term & TERMIOS) {
503 				pit(cb.c_cc[VSTART], "start", "; ");
504 				pit(cb.c_cc[VSTOP], "stop", "; ");
505 				pit(cb.c_cc[VSUSP], "susp", "; ");
506 				pit(cb.c_cc[VDSUSP], "dsusp", ";\n");
507 				pit(cb.c_cc[VREPRINT], "rprnt", "; ");
508 				pit(cb.c_cc[VDISCARD], "flush", "; ");
509 				pit(cb.c_cc[VWERASE], "werase", "; ");
510 				pit(cb.c_cc[VLNEXT], "lnext", ";\n");
511 			}
512 		}
513 	} else
514 		pit((unsigned)stio.tab, "ctab", "\n");
515 	m = cb.c_cflag;
516 	(void) fprintf(output, "-parenb " + ((m & PARENB) != 0));
517 	(void) fprintf(output, "-parodd " + ((m & PARODD) != 0));
518 	(void) fprintf(output, "cs%c ", '5'+ (m & CSIZE)/CS6);
519 	(void) fprintf(output, "-cstopb " + ((m & CSTOPB) != 0));
520 	(void) fprintf(output, "-hupcl " + ((m & HUPCL) != 0));
521 	(void) fprintf(output, "-cread " + ((m & CREAD) != 0));
522 	(void) fprintf(output, "-clocal " + ((m & CLOCAL) != 0));
523 
524 	(void) fprintf(output, "-loblk " + ((m & LOBLK) != 0));
525 	if (term & TERMIOS)
526 		(void) fprintf(output, "-parext " + ((m & PAREXT) != 0));
527 
528 	(void) fprintf(output, "\n");
529 	m = cb.c_iflag;
530 	(void) fprintf(output, "-ignbrk " + ((m & IGNBRK) != 0));
531 	(void) fprintf(output, "-brkint " + ((m & BRKINT) != 0));
532 	(void) fprintf(output, "-ignpar " + ((m & IGNPAR) != 0));
533 	(void) fprintf(output, "-parmrk " + ((m & PARMRK) != 0));
534 	(void) fprintf(output, "-inpck " + ((m & INPCK) != 0));
535 	(void) fprintf(output, "-istrip " + ((m & ISTRIP) != 0));
536 	(void) fprintf(output, "-inlcr " + ((m & INLCR) != 0));
537 	(void) fprintf(output, "-igncr " + ((m & IGNCR) != 0));
538 	(void) fprintf(output, "-icrnl " + ((m & ICRNL) != 0));
539 	(void) fprintf(output, "-iuclc " + ((m & IUCLC) != 0));
540 	(void) fprintf(output, "\n");
541 	(void) fprintf(output, "-ixon " + ((m & IXON) != 0));
542 	(void) fprintf(output, "-ixany " + ((m & IXANY) != 0));
543 	(void) fprintf(output, "-ixoff " + ((m & IXOFF) != 0));
544 	if (term & TERMIOS)
545 		(void) fprintf(output, "-imaxbel " + ((m & IMAXBEL) != 0));
546 	(void) fprintf(output, "\n");
547 	m = cb.c_lflag;
548 	(void) fprintf(output, "-isig " + ((m & ISIG) != 0));
549 	(void) fprintf(output, "-icanon " + ((m & ICANON) != 0));
550 	(void) fprintf(output, "-xcase " + ((m & XCASE) != 0));
551 	(void) fprintf(output, "-echo " + ((m & ECHO) != 0));
552 	(void) fprintf(output, "-echoe " + ((m & ECHOE) != 0));
553 	(void) fprintf(output, "-echok " + ((m & ECHOK) != 0));
554 	(void) fprintf(output, "-echonl " + ((m & ECHONL) != 0));
555 	(void) fprintf(output, "-noflsh " + ((m & NOFLSH) != 0));
556 	if (term & TERMIOS) {
557 		(void) fprintf(output, "\n");
558 		(void) fprintf(output, "-tostop " + ((m & TOSTOP) != 0));
559 		(void) fprintf(output, "-echoctl " + ((m & ECHOCTL) != 0));
560 		(void) fprintf(output, "-echoprt " + ((m & ECHOPRT) != 0));
561 		(void) fprintf(output, "-echoke " + ((m & ECHOKE) != 0));
562 		(void) fprintf(output, "-defecho " + ((m & DEFECHO) != 0));
563 		(void) fprintf(output, "-flusho " + ((m & FLUSHO) != 0));
564 		(void) fprintf(output, "-pendin " + ((m & PENDIN) != 0));
565 		(void) fprintf(output, "-iexten " + ((m & IEXTEN) != 0));
566 	}
567 	if (!(term & ASYNC)) {
568 		(void) fprintf(output, "-stflush " + ((m & STFLUSH) != 0));
569 		(void) fprintf(output, "-stwrap " + ((m & STWRAP) != 0));
570 		(void) fprintf(output, "-stappl " + ((m & STAPPL) != 0));
571 	}
572 	(void) fprintf(output, "\n");
573 	m = cb.c_oflag;
574 	(void) fprintf(output, "-opost " + ((m & OPOST) != 0));
575 	(void) fprintf(output, "-olcuc " + ((m & OLCUC) != 0));
576 	(void) fprintf(output, "-onlcr " + ((m & ONLCR) != 0));
577 	(void) fprintf(output, "-ocrnl " + ((m & OCRNL) != 0));
578 	(void) fprintf(output, "-onocr " + ((m & ONOCR) != 0));
579 	(void) fprintf(output, "-onlret " + ((m & ONLRET) != 0));
580 	(void) fprintf(output, "-ofill " + ((m & OFILL) != 0));
581 	(void) fprintf(output, "-ofdel " + ((m & OFDEL) != 0));
582 	delay((m & CRDLY)/CR1, "cr");
583 	delay((m & NLDLY)/NL1, "nl");
584 	if ((m & TABDLY) == XTABS)
585 		(void) fprintf(output, "-tabs ");
586 	else
587 		delay((m & TABDLY)/TAB1, "tab");
588 	delay((m & BSDLY)/BS1, "bs");
589 	delay((m & VTDLY)/VT1, "vt");
590 	delay((m & FFDLY)/FF1, "ff");
591 	(void) fprintf(output, "\n");
592 	if (term & FLOW) {
593 		m = termiox.x_hflag;
594 		(void) fprintf(output, "-rtsxoff " + ((m & RTSXOFF) != 0));
595 		(void) fprintf(output, "-ctsxon " + ((m & CTSXON) != 0));
596 		(void) fprintf(output, "-dterxoff " + ((m & DTRXOFF) != 0));
597 		(void) fprintf(output, "-rlsdxon " + ((m & CDXON) != 0));
598 		(void) fprintf(output, "-isxoff " + ((m & ISXOFF) != 0));
599 		m = termiox.x_cflag;
600 		switch (m & XMTCLK) {
601 		case XCIBRG:
602 			(void) fprintf(output, "xcibrg ");
603 			break;
604 		case XCTSET:
605 			(void) fprintf(output, "xctset ");
606 			break;
607 		case XCRSET:
608 			(void) fprintf(output, "xcrset ");
609 			break;
610 		}
611 
612 		switch (m & RCVCLK) {
613 		case RCIBRG:
614 			(void) fprintf(output, "rcibrg ");
615 			break;
616 		case RCTSET:
617 			(void) fprintf(output, "rctset ");
618 			break;
619 		case RCRSET:
620 			(void) fprintf(output, "rcrset ");
621 			break;
622 		}
623 
624 		switch (m & TSETCLK) {
625 		case TSETCOFF:
626 			(void) fprintf(output, "tsetcoff ");
627 			break;
628 		case TSETCRBRG:
629 			(void) fprintf(output, "tsetcrc ");
630 			break;
631 		case TSETCTBRG:
632 			(void) fprintf(output, "tsetcxc ");
633 			break;
634 		}
635 
636 		switch (m & RSETCLK) {
637 		case RSETCOFF:
638 			(void) fprintf(output, "rsetcoff ");
639 			break;
640 		case RSETCRBRG:
641 			(void) fprintf(output, "rsetcrc ");
642 			break;
643 		case RSETCTBRG:
644 			(void) fprintf(output, "rsetcxc ");
645 			break;
646 		}
647 		(void) fprintf(output, "\n");
648 	}
649 	if (tabform)
650 		prachars();
651 }
652 
653 void
654 prachars(void)
655 {
656 	if ((cb.c_lflag & ICANON) == 0)
657 		(void) fprintf(output, "min %d, time %d\n", cb.c_cc[VMIN],
658 		    cb.c_cc[VTIME]);
659 	(void) fprintf(output, "\
660 erase  kill   werase rprnt  flush  lnext  susp   intr   quit   stop   eof\
661 \n");
662 	pcol(cb.c_cc[VERASE], 0);
663 	pcol(cb.c_cc[VKILL], 0);
664 	pcol(cb.c_cc[VWERASE], 0);
665 	pcol(cb.c_cc[VREPRINT], 0);
666 	pcol(cb.c_cc[VDISCARD], 0);
667 	pcol(cb.c_cc[VLNEXT], 0);
668 	pcol(cb.c_cc[VSUSP], cb.c_cc[VDSUSP]);
669 	pcol(cb.c_cc[VINTR], 0);
670 	pcol(cb.c_cc[VQUIT], 0);
671 	pcol(cb.c_cc[VSTOP], cb.c_cc[VSTART]);
672 	if (cb.c_lflag&ICANON)
673 		pcol(cb.c_cc[VEOF], cb.c_cc[VEOL]);
674 	(void) fprintf(output, "\n");
675 	if (cb.c_cc[VEOL2] != 0 || cb.c_cc[VSWTCH] != 0) {
676 		(void) fprintf(output, "\
677 eol2  swtch\
678 \n");
679 		pcol(cb.c_cc[VEOL2], 0);
680 		pcol(cb.c_cc[VSWTCH], 0);
681 		(void) fprintf(output, "\n");
682 	}
683 }
684 
685 void
686 pcol(int ch1, int ch2)
687 {
688 	int nout = 0;
689 
690 	ch1 &= 0377;
691 	ch2 &= 0377;
692 	if (ch1 == ch2)
693 		ch2 = 0;
694 	for (; ch1 != 0 || ch2 != 0; ch1 = ch2, ch2 = 0) {
695 		if (ch1 == 0)
696 			continue;
697 		if (ch1 & 0200 && !isprint(ch1)) {
698 			(void) fprintf(output, "M-");
699 			nout += 2;
700 			ch1 &= ~ 0200;
701 		}
702 		if (ch1 == 0177) {
703 			(void) fprintf(output, "^");
704 			nout++;
705 			ch1 = '?';
706 		} else if (ch1 < ' ') {
707 			(void) fprintf(output, "^");
708 			nout++;
709 			ch1 += '@';
710 		}
711 		(void) fprintf(output, "%c", ch1);
712 		nout++;
713 		if (ch2 != 0) {
714 			(void) fprintf(output, "/");
715 			nout++;
716 		}
717 	}
718 	while (nout < 7) {
719 		(void) fprintf(output, " ");
720 		nout++;
721 	}
722 }
723 
724 void
725 pit(unsigned char what, char *itsname, char *sep)
726 /* print function for prmodes() and pramodes() */
727 {
728 
729 	pitt++;
730 	(void) fprintf(output, "%s", itsname);
731 	if ((term & TERMIOS) && what == _POSIX_VDISABLE ||
732 	    !(term & TERMIOS) && what == 0200) {
733 		(void) fprintf(output, " = <undef>%s", sep);
734 		return;
735 	}
736 	(void) fprintf(output, " = ");
737 	if (what & 0200 && !isprint(what)) {
738 		(void) fprintf(output, "-");
739 		what &= ~ 0200;
740 	}
741 	if (what == 0177) {
742 		(void) fprintf(output, "^?%s", sep);
743 		return;
744 	} else if (what < ' ') {
745 		(void) fprintf(output, "^");
746 		what += '`';
747 	}
748 	(void) fprintf(output, "%c%s", what, sep);
749 }
750 
751 void
752 delay(int m, char *s)
753 {
754 	if (m)
755 		(void) fprintf(output, "%s%d ", s, m);
756 }
757 
758 long	speed[] = {
759 	0, 50, 75, 110, 134, 150, 200, 300,
760 	600, 1200, 1800, 2400, 4800, 9600, 19200, 38400,
761 	57600, 76800, 115200, 153600, 230400, 307200, 460800, 921600
762 };
763 
764 void
765 prspeed(char *c, int s)
766 {
767 	(void) fprintf(output, "%s%d baud; ", c, speed[s]);
768 }
769 
770 /*
771  * print current settings for use with
772  * another stty cmd, used for -g option
773  */
774 void
775 prencode(void)
776 {
777 	int i, last;
778 
779 	/* Since the -g option is mostly used for redirecting to a file */
780 	/* We must print to stdout here, not stderr */
781 
782 	(void) printf("%x:%x:%x:%x:", cb.c_iflag, cb.c_oflag,
783 	    cb.c_cflag, cb.c_lflag);
784 
785 	if (term & TERMIOS)
786 	/* last control slot is unused */
787 		last = NCCS - 2;
788 	else
789 		last = NCC - 1;
790 	for (i = 0; i < last; i++)
791 		(void) printf("%x:", cb.c_cc[i]);
792 	(void) printf("%x\n", cb.c_cc[last]);
793 }
794