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