xref: /illumos-gate/usr/src/ucbcmd/stty/stty.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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 	1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000,
763 	4000000
764 };
765 
766 void
767 prspeed(char *c, int s)
768 {
769 	(void) fprintf(output, "%s%d baud; ", c, speed[s]);
770 }
771 
772 /*
773  * print current settings for use with
774  * another stty cmd, used for -g option
775  */
776 void
777 prencode(void)
778 {
779 	int i, last;
780 
781 	/* Since the -g option is mostly used for redirecting to a file */
782 	/* We must print to stdout here, not stderr */
783 
784 	(void) printf("%x:%x:%x:%x:", cb.c_iflag, cb.c_oflag,
785 	    cb.c_cflag, cb.c_lflag);
786 
787 	if (term & TERMIOS)
788 	/* last control slot is unused */
789 		last = NCCS - 2;
790 	else
791 		last = NCC - 1;
792 	for (i = 0; i < last; i++)
793 		(void) printf("%x:", cb.c_cc[i]);
794 	(void) printf("%x\n", cb.c_cc[last]);
795 }
796