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