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
38extern char *getenv();
39extern void exit();
40extern void perror();
41
42static char *STTY = "stty: ";
43static char *USAGE = "usage: stty [-agh] [modes]\n";
44static int	pitt = 0;
45static struct termios cb;
46static struct termio ocb; /* for non-streams devices */
47static struct stio stio;
48static struct termiox termiox;
49static struct winsize winsize, owinsize;
50static int term;
51
52void prmodes(int);
53void pramodes(int);
54void prachars(void);
55void pcol(int, int);
56void pit(unsigned char, char *, char *);
57void delay(int, char *s);
58void prspeed(char *, int);
59void prencode(void);
60
61#define	ioctl_desc	1
62#define	output		stderr
63
64int
65main(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
181void
182prmodes(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
466void
467pramodes(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
652void
653prachars(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, "\
659erase  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, "\
676eol2  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
684void
685pcol(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
723void
724pit(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
750void
751delay(int m, char *s)
752{
753	if (m)
754		(void) fprintf(output, "%s%d ", s, m);
755}
756
757long	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
763void
764prspeed(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 */
773void
774prencode(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