xref: /csrg-svn/bin/stty/stty.c (revision 38674)
119907Sdist /*
219907Sdist  * Copyright (c) 1980 Regents of the University of California.
319907Sdist  * All rights reserved.  The Berkeley software License Agreement
419907Sdist  * specifies the terms and conditions for redistribution.
519907Sdist  */
619907Sdist 
713073Ssam #ifndef lint
819907Sdist char copyright[] =
919907Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1019907Sdist  All rights reserved.\n";
1119907Sdist #endif not lint
1219907Sdist 
1319907Sdist #ifndef lint
14*38674Smarc static char sccsid[] = "@(#)stty.c	5.7 (Berkeley) 08/19/89";
1519907Sdist #endif not lint
1619907Sdist 
171179Sbill /*
181179Sbill  * set teletype modes
191179Sbill  */
201179Sbill 
21*38674Smarc #include <sys/types.h>
22*38674Smarc #include <sys/stat.h>
2337609Sbostic #include <sys/ioctl.h>
24*38674Smarc #include <sys/syslog.h>
25*38674Smarc #define KERNEL
26*38674Smarc #include <sys/tty.h>
27*38674Smarc #undef KERNEL
28*38674Smarc #include <sys/termios.h>
29*38674Smarc #include <sys/file.h>
30*38674Smarc #include <errno.h>
31*38674Smarc #include <ctype.h>
321179Sbill #include <stdio.h>
331179Sbill 
34*38674Smarc #ifndef STATIC
35*38674Smarc #define STATIC
369853Ssam #endif
37*38674Smarc 
38*38674Smarc #define eq(s1, s2)	(strcmp(s1, s2) == 0)
39*38674Smarc #define WRAPCOL 65
40*38674Smarc #define COMPAT_43
41*38674Smarc 
42*38674Smarc STATIC struct modes {
43*38674Smarc 	char *name;
44*38674Smarc 	long set;
45*38674Smarc 	long unset;
461179Sbill };
471179Sbill 
48*38674Smarc STATIC struct modes imodes[] = {
49*38674Smarc 	"ignbrk",	IGNBRK, 0,
50*38674Smarc 	"-ignbrk",	0, IGNBRK,
51*38674Smarc 	"brkint",	BRKINT, 0,
52*38674Smarc 	"-brkint",	0, BRKINT,
53*38674Smarc 	"ignpar",	IGNPAR, 0,
54*38674Smarc 	"-ignpar",	0, IGNPAR,
55*38674Smarc 	"parmrk",	PARMRK, 0,
56*38674Smarc 	"-parmrk",	0, PARMRK,
57*38674Smarc 	"inpck",	INPCK, 0,
58*38674Smarc 	"-inpck",	0, INPCK,
59*38674Smarc 	"istrip",	ISTRIP, 0,
60*38674Smarc 	"-istrip",	0, ISTRIP,
61*38674Smarc 	"inlcr",	INLCR, 0,
62*38674Smarc 	"-inlcr",	0, INLCR,
63*38674Smarc 	"igncr",	IGNCR, 0,
64*38674Smarc 	"-igncr",	0, IGNCR,
65*38674Smarc 	"icrnl",	ICRNL, 0,
66*38674Smarc 	"-icrnl",	0, ICRNL,
67*38674Smarc 	"ixon",		IXON, 0,
68*38674Smarc 	"-ixon",	0, IXON,
69*38674Smarc 	"flow",		IXON, 0,
70*38674Smarc 	"-flow",	0, IXON,
71*38674Smarc 	"ixoff",	IXOFF, 0,
72*38674Smarc 	"-ixoff",	0, IXOFF,
73*38674Smarc 	"tandem",	IXOFF, 0,
74*38674Smarc 	"-tandem",	0, IXOFF,
75*38674Smarc 	"ixany",	IXANY, 0,
76*38674Smarc 	"-ixany",	0, IXANY,
77*38674Smarc 	"decctlq",	0, IXANY,
78*38674Smarc 	"-decctlq",	IXANY, 0,
79*38674Smarc 	"imaxbel",	IMAXBEL, 0,
80*38674Smarc 	"-imaxbel",	0, IMAXBEL,
81*38674Smarc 	0
82*38674Smarc };
831179Sbill 
84*38674Smarc STATIC struct modes omodes[] = {
85*38674Smarc 	"opost",	OPOST, 0,
86*38674Smarc 	"-opost",	0, OPOST,
87*38674Smarc 	"-litout",	OPOST, 0,
88*38674Smarc 	"litout",	0, OPOST,
89*38674Smarc 	"onlcr",	ONLCR, 0,
90*38674Smarc 	"-onlcr",	0, ONLCR,
91*38674Smarc 	"tabs",		0, OXTABS,	/* "preserve" tabs */
92*38674Smarc 	"-tabs",	OXTABS, 0,
93*38674Smarc 	"xtabs",	OXTABS, 0,
94*38674Smarc 	"-xtabs",	0, OXTABS,
95*38674Smarc 	"oxtabs",	OXTABS, 0,
96*38674Smarc 	"-oxtabs",	0, OXTABS,
971179Sbill 	0
981179Sbill };
991179Sbill 
100*38674Smarc STATIC struct modes cmodes[] = {
101*38674Smarc 	"cs5",		CS5, CSIZE,
102*38674Smarc 	"cs6",		CS6, CSIZE,
103*38674Smarc 	"cs7",		CS7, CSIZE,
104*38674Smarc 	"cs8",		CS8, CSIZE,
105*38674Smarc 	"cstopb",	CSTOPB, 0,
106*38674Smarc 	"-cstopb",	0, CSTOPB,
107*38674Smarc 	"cread",	CREAD, 0,
108*38674Smarc 	"-cread",	0, CREAD,
109*38674Smarc 	"parenb",	PARENB, 0,
110*38674Smarc 	"-parenb",	0, PARENB,
111*38674Smarc 	"parodd",	PARODD, 0,
112*38674Smarc 	"-parodd",	0, PARODD,
113*38674Smarc 	"parity",	PARENB | CS7, PARODD | CSIZE,
114*38674Smarc 	"evenp",	PARENB | CS7, PARODD | CSIZE,
115*38674Smarc 	"oddp",		PARENB | CS7 | PARODD, CSIZE,
116*38674Smarc 	"-parity",	CS8, PARODD | PARENB | CSIZE,
117*38674Smarc 	"-evenp",	CS8, PARODD | PARENB | CSIZE,
118*38674Smarc 	"-oddp",	CS8, PARODD | PARENB | CSIZE,
119*38674Smarc 	"hupcl",	HUPCL, 0,
120*38674Smarc 	"-hupcl",	0, HUPCL,
121*38674Smarc 	"hup",		HUPCL, 0,
122*38674Smarc 	"-hup",		0, HUPCL,
123*38674Smarc 	"clocal",	CLOCAL, 0,
124*38674Smarc 	"-clocal",	0, CLOCAL,
125*38674Smarc 	"crtscts",	CRTSCTS, 0,
126*38674Smarc 	"-crtscts",	0, CRTSCTS,
127*38674Smarc 	0
128*38674Smarc };
129*38674Smarc 
130*38674Smarc STATIC struct modes lmodes[] = {
131*38674Smarc 	"echo",		ECHO, 0,
132*38674Smarc 	"-echo",	0, ECHO,
133*38674Smarc 	"echoe",	ECHOE, 0,
134*38674Smarc 	"-echoe",	0, ECHOE,
135*38674Smarc 	"crterase",	ECHOE, 0,
136*38674Smarc 	"-crterase",	0, ECHOE,
137*38674Smarc 	"crtbs",	ECHOE, 0,   /* crtbs not supported, close enough */
138*38674Smarc 	"-crtbs",	0, ECHOE,
139*38674Smarc 	"echok",	ECHOK, 0,
140*38674Smarc 	"-echok",	0, ECHOK,
141*38674Smarc 	"echoke",	ECHOKE, 0,
142*38674Smarc 	"-echoke",	0, ECHOKE,
143*38674Smarc 	"crtkill",	ECHOKE, 0,
144*38674Smarc 	"-crtkill",	0, ECHOKE,
145*38674Smarc 	"altwerase",	ALTWERASE, 0,
146*38674Smarc 	"-altwerase",	0, ALTWERASE,
147*38674Smarc 	"iexten",	IEXTEN, 0,
148*38674Smarc 	"-iexten",	0, IEXTEN,
149*38674Smarc 	"echonl",	ECHONL, 0,
150*38674Smarc 	"-echonl",	0, ECHONL,
151*38674Smarc 	"echoctl",	ECHOCTL, 0,
152*38674Smarc 	"-echoctl",	0, ECHOCTL,
153*38674Smarc 	"ctlecho",	ECHOCTL, 0,
154*38674Smarc 	"-ctlecho",	0, ECHOCTL,
155*38674Smarc 	"echoprt",	ECHOPRT, 0,
156*38674Smarc 	"-echoprt",	0, ECHOPRT,
157*38674Smarc 	"prterase",	ECHOPRT, 0,
158*38674Smarc 	"-prterase",	0, ECHOPRT,
159*38674Smarc 	"isig",		ISIG, 0,
160*38674Smarc 	"-isig",	0, ISIG,
161*38674Smarc 	"icanon",	ICANON, 0,
162*38674Smarc 	"-icanon",	0, ICANON,
163*38674Smarc 	"noflsh",	NOFLSH, 0,
164*38674Smarc 	"-noflsh",	0, NOFLSH,
165*38674Smarc 	"tostop",	TOSTOP, 0,
166*38674Smarc 	"-tostop",	0, TOSTOP,
167*38674Smarc 	"mdmbuf",	MDMBUF, 0,
168*38674Smarc 	"-mdmbuf",	0, MDMBUF,
169*38674Smarc 	"nohang",	NOHANG, 0,
170*38674Smarc 	"-nohang",	0, NOHANG,
171*38674Smarc 	"flusho",	FLUSHO, 0,
172*38674Smarc 	"-flusho",	0, FLUSHO,
173*38674Smarc 	"pendin",	PENDIN, 0,
174*38674Smarc 	"-pendin",	0, PENDIN,
175*38674Smarc 	"crt",		ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT,
176*38674Smarc 	"-crt",		ECHOK, ECHOE|ECHOKE|ECHOCTL,
177*38674Smarc 	"newcrt",	ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT,
178*38674Smarc 	"-newcrt",	ECHOK, ECHOE|ECHOKE|ECHOCTL,
179*38674Smarc 	0
180*38674Smarc };
181*38674Smarc 
182*38674Smarc /*
183*38674Smarc  * Special control characters.
184*38674Smarc  *
185*38674Smarc  * Each entry has a list of names.  The first is the primary name
186*38674Smarc  * and is used when printing the control character in the "name = val;"
187*38674Smarc  * form.  The second is an abbreviation which is guaranteed to be less
188*38674Smarc  * than or equal to four characters in length and is primarily used
189*38674Smarc  * when printing the values in columunar form (guarantees all will
190*38674Smarc  * fit within 80 cols).  The rest are optional aliases.
191*38674Smarc  * All names are recognized on the command line.
192*38674Smarc  */
193*38674Smarc #define MAXNAMES 5
194*38674Smarc STATIC struct {
195*38674Smarc 	char	*names[MAXNAMES+1];
196*38674Smarc 	int	sub;
197*38674Smarc 	u_char	def;
198*38674Smarc } cchars[] = {
199*38674Smarc 	{ "erase", "era" },		VERASE,	CERASE,
200*38674Smarc 	{ "werase", "wera" },		VWERASE, CWERASE,
201*38674Smarc 	{ "kill", "kill" },		VKILL,	CKILL,
202*38674Smarc 	{ "intr", "int" },		VINTR,	CINTR,
203*38674Smarc 	{ "quit", "quit" },		VQUIT,	CQUIT,
204*38674Smarc 	{ "susp", "susp" },		VSUSP,	CSUSP,
205*38674Smarc 	{ "dsusp", "dsus" },		VDSUSP,	CDSUSP,
206*38674Smarc 	{ "eof", "eof" },		VEOF,	CEOF,
207*38674Smarc 	{ "eol", "eol", "brk" },	VEOL,	CEOL,
208*38674Smarc 	{ "eol2", "eol2" },		VEOL2,	CEOL,
209*38674Smarc 	{ "stop", "stop", "xoff" },	VSTOP,	CSTOP,
210*38674Smarc 	{ "start", "star", "xon" },	VSTART,	CSTART,
211*38674Smarc 	{ "lnext", "lnxt" },		VLNEXT,	CLNEXT,
212*38674Smarc 	{ "flusho", "fls", "flush" },	VFLUSHO, CFLUSHO,
213*38674Smarc 	{ "reprint", "rpnt", "rprnt" },	VREPRINT, CREPRINT,
214*38674Smarc 	0
215*38674Smarc };
216*38674Smarc 
217*38674Smarc STATIC struct winsize win;
218*38674Smarc STATIC int ldisc;
219*38674Smarc STATIC int dodisc;
220*38674Smarc STATIC int debug = 0;
221*38674Smarc STATIC int trace, dotrace;
222*38674Smarc 
223*38674Smarc #define OUT	stdout		/* informational output stream */
224*38674Smarc #define ERR	stderr		/* error message stream */
225*38674Smarc #define CTL	0		/* default control descriptor */
226*38674Smarc STATIC int ctl = CTL;
227*38674Smarc 
228*38674Smarc extern errno;
229*38674Smarc extern char *sys_errlist[];
230*38674Smarc 
231*38674Smarc #define NORMAL	0	/* only print modes differing from defaults */
232*38674Smarc #define ALL	1	/* print all modes - POSIX standard format */
233*38674Smarc #define ALL_BSD	2	/* print all modes - using BSD shorthand for cc's */
234*38674Smarc #define GFMT	3	/* print modes in a form that can be re-input to stty */
235*38674Smarc 
236*38674Smarc STATIC
237*38674Smarc main(argc, argv)
238*38674Smarc 	char *argv[];
2391179Sbill {
240*38674Smarc 	struct termios t;
241*38674Smarc 	int i, fmt = NORMAL;
242*38674Smarc 	extern char *optarg;
243*38674Smarc 	extern int optind;
244*38674Smarc 	int ch;
2451179Sbill 
246*38674Smarc 	argc--, argv++;
247*38674Smarc 	if (argc > 0 && eq(argv[0], "-a")) {
248*38674Smarc 		fmt = ALL;
249*38674Smarc 		argc--, argv++;
2501179Sbill 	}
251*38674Smarc 	if (argc > 0 && eq(argv[0], "-f")) {
252*38674Smarc 		argc--, argv++;
253*38674Smarc 		if ((ctl = open(argv[0], O_RDONLY | O_NONBLOCK)) < 0)
254*38674Smarc 			syserrexit(*argv);
255*38674Smarc 		argc--, argv++;
2561179Sbill 	}
257*38674Smarc #ifdef notyet
258*38674Smarc 	while ((ch = getopt(argc, argv, "f:ga")) != EOF)
259*38674Smarc 		switch((char)ch) {
260*38674Smarc 		case 'f':
261*38674Smarc 			if ((ctl = open(*optarg, O_RDONLY | O_NONBLOCK)) < 0)
262*38674Smarc 				syserrexit(*argv);
263*38674Smarc 			break;
264*38674Smarc 		case 'a':
265*38674Smarc 			fmt = ALL;
266*38674Smarc 			break;
267*38674Smarc 		case 'g':
268*38674Smarc 			fmt = GFMT;
269*38674Smarc 			break;
270*38674Smarc 		case '?':
271*38674Smarc 		default:
272*38674Smarc 			fprintf(stderr, "usage: %s", *argv);
273*38674Smarc 			exit(1);
274*38674Smarc 		}
275*38674Smarc 	argc -= optind;
276*38674Smarc 	argv += optind;
277*38674Smarc #endif
278*38674Smarc 
279*38674Smarc 	if (ioctl(ctl, TIOCGETD, &ldisc) < 0)
280*38674Smarc 		syserrexit("TIOCGETD");
281*38674Smarc 	if (tcgetattr(ctl, &t) < 0)
282*38674Smarc 		syserrexit("tcgetattr");
283*38674Smarc 	if (ioctl(ctl, TIOCGWINSZ, &win) < 0)
284*38674Smarc 		warning("TIOCGWINSZ: %s", sys_errlist[errno]);
285*38674Smarc 
286*38674Smarc #ifdef COMPAT_43
287*38674Smarc 	checkredirect();	/* conversion aid */
288*38674Smarc #endif
289*38674Smarc 
290*38674Smarc 	if (argc == 0 || fmt) {
291*38674Smarc 		prmode(&t, ldisc, fmt);
2921179Sbill 		exit(0);
293*38674Smarc 	} else if (argc == 1 && strlen(argv[0]) > 2 && *(argv[0]+2) == ':') {
294*38674Smarc 		gfmtset(argv[0]);
295*38674Smarc 		goto setit;
2961179Sbill 	}
297*38674Smarc 
298*38674Smarc 	while (*argv) {
299*38674Smarc 		if (eq("everything", *argv)) {
300*38674Smarc 			prmode(&t, ldisc, ALL_BSD);
301*38674Smarc 			exit(0);
3021179Sbill 		}
303*38674Smarc 		if (eq("all", *argv)) {
304*38674Smarc 			prmode(&t, ldisc, ALL);
305*38674Smarc 			exit(0);
3061179Sbill 		}
307*38674Smarc 		if (eq("old", *argv)) {
308*38674Smarc 			goto next;
3091179Sbill 		}
310*38674Smarc 		if (eq("new", *argv)) {
311*38674Smarc 			goto next;
3121179Sbill 		}
313*38674Smarc 		if (eq("nl", *argv)) {
314*38674Smarc 			t.c_iflag &= ~ICRNL;
315*38674Smarc 			t.c_oflag &= ~ONLCR;
316*38674Smarc 			goto next;
3171179Sbill 		}
318*38674Smarc 		if (eq("-nl", *argv)) {
319*38674Smarc 			t.c_iflag |= ICRNL;
320*38674Smarc 			t.c_oflag |= ONLCR;
321*38674Smarc 			goto next;
3223797Sroot 		}
323*38674Smarc 		if (eq("dec", *argv)){
324*38674Smarc 			t.c_cc[VERASE] = (u_char)0177;
325*38674Smarc 			t.c_cc[VKILL] = CTRL('u');
326*38674Smarc 			t.c_cc[VINTR] = CTRL('c');
327*38674Smarc 			t.c_lflag &= ~ECHOPRT;
328*38674Smarc 			t.c_lflag |= ECHOE|ECHOKE|ECHOCTL;
329*38674Smarc 			t.c_iflag &= ~IXANY;
330*38674Smarc 			goto next;
3311179Sbill 		}
332*38674Smarc 		if (eq("rows", *argv)) {
333*38674Smarc 			if (*(argv+1) == 0)
334*38674Smarc 				goto setit;
33518023Sbloom 			win.ws_row = atoi(*++argv);
336*38674Smarc 			goto next;
33718023Sbloom 		}
338*38674Smarc 		if (eq("ispeed", *argv)) {
339*38674Smarc 			int code;
340*38674Smarc 			if (*(argv+1) == 0)
341*38674Smarc 				errexit("missing ispeed");
342*38674Smarc 			cfsetispeed(&t, atoi(*++argv));
343*38674Smarc 			goto next;
344*38674Smarc 		}
345*38674Smarc 		if (eq("ospeed", *argv)) {
346*38674Smarc 			int code;
347*38674Smarc 			if (*(argv+1) == 0)
348*38674Smarc 				errexit("missing ospeed");
349*38674Smarc 			cfsetospeed(&t, atoi(*++argv));
350*38674Smarc 			goto next;
351*38674Smarc 		}
352*38674Smarc 		if (eq("cols", *argv) || eq("columns", *argv)) {
353*38674Smarc 			if (*(argv+1) == 0)
354*38674Smarc 				goto setit;
35518023Sbloom 			win.ws_col = atoi(*++argv);
356*38674Smarc 			goto next;
35718023Sbloom 		}
358*38674Smarc 		if (eq("size", *argv)) {
359*38674Smarc 			put("%d %d\n", win.ws_row, win.ws_col);
36025791Skarels 			exit(0);
36125791Skarels 		}
362*38674Smarc 		if (eq("speed", *argv)) {
363*38674Smarc 			put("%d\n", cfgetospeed(&t));
364*38674Smarc 			exit(0);
365*38674Smarc 		}
366*38674Smarc 		for (i=0; imodes[i].name; i++)
367*38674Smarc 			if (eq(imodes[i].name, *argv)) {
368*38674Smarc 				t.c_iflag &= ~imodes[i].unset;
369*38674Smarc 				t.c_iflag |= imodes[i].set;
370*38674Smarc 				goto next;
3711179Sbill 			}
372*38674Smarc 		for (i=0; omodes[i].name; i++)
373*38674Smarc 			if (eq(omodes[i].name, *argv)) {
374*38674Smarc 				t.c_oflag &= ~omodes[i].unset;
375*38674Smarc 				t.c_oflag |= omodes[i].set;
376*38674Smarc 				goto next;
377*38674Smarc 			}
378*38674Smarc 		for (i=0; cmodes[i].name; i++)
379*38674Smarc 			if (eq(cmodes[i].name, *argv)) {
380*38674Smarc 				t.c_cflag &= ~cmodes[i].unset;
381*38674Smarc 				t.c_cflag |= cmodes[i].set;
382*38674Smarc 				goto next;
383*38674Smarc 			}
384*38674Smarc 		for (i=0; lmodes[i].name; i++)
385*38674Smarc 			if (eq(lmodes[i].name, *argv)) {
386*38674Smarc 				t.c_lflag &= ~lmodes[i].unset;
387*38674Smarc 				t.c_lflag |= lmodes[i].set;
388*38674Smarc 				goto next;
389*38674Smarc 			}
390*38674Smarc 		for (i=0; *cchars[i].names; i++) {
391*38674Smarc 			char **cp = cchars[i].names;
392*38674Smarc 			while (*cp) {
393*38674Smarc 				if (eq(*cp, *argv)) {
394*38674Smarc 					if (*++argv == 0)
395*38674Smarc 						goto setit;
396*38674Smarc 					if (eq(*argv, "undef") ||
397*38674Smarc 					    eq(*argv, "disable"))
398*38674Smarc 						t.c_cc[cchars[i].sub] =
399*38674Smarc 						   _POSIX_VDISABLE;
400*38674Smarc 					else if (**argv == '^')
401*38674Smarc 						t.c_cc[cchars[i].sub] =
402*38674Smarc 						    ((*argv)[1] == '?') ? 0177 :
403*38674Smarc 						    ((*argv)[1] == '-') ?
404*38674Smarc 						     _POSIX_VDISABLE :
405*38674Smarc 						     (*argv)[1] & 037;
406*38674Smarc 					else
407*38674Smarc 						t.c_cc[cchars[i].sub] = **argv;
408*38674Smarc 					goto next;
4091179Sbill 				}
410*38674Smarc 				cp++;
411*38674Smarc 			}
4121179Sbill 		}
413*38674Smarc 		if (isdigit(**argv)) {
414*38674Smarc 			cfsetospeed(&t, atoi(*argv));
415*38674Smarc 			cfsetispeed(&t, atoi(*argv));
416*38674Smarc 			goto next;
417*38674Smarc 		}
418*38674Smarc 		/* didn't match anything */
419*38674Smarc 		errexit("unknown option: %s", *argv);
420*38674Smarc 		exit(1);
421*38674Smarc next:
422*38674Smarc 		argv++;
4231179Sbill 	}
424*38674Smarc setit:
425*38674Smarc 	if (tcsetattr(ctl, 0, &t) < 0)
426*38674Smarc 		syserrexit("tcsetattr");
427*38674Smarc 	if (ioctl(ctl, TIOCSWINSZ, &win) < 0)
428*38674Smarc 		warning("can't set window size");
429*38674Smarc 
430*38674Smarc 	exit(0);
4311179Sbill }
4321179Sbill 
433*38674Smarc gfmtset() {
4341179Sbill }
4351179Sbill 
436*38674Smarc prmode(tp, ldisc, fmt)
437*38674Smarc 	struct termios *tp;
4381179Sbill {
439*38674Smarc 	long	i = tp->c_iflag,
440*38674Smarc 		o = tp->c_oflag,
441*38674Smarc 		c = tp->c_cflag,
442*38674Smarc 		l = tp->c_lflag;
443*38674Smarc 	u_char	*cc = tp->c_cc;
444*38674Smarc 	int	ispeed = cfgetispeed(tp),
445*38674Smarc 		ospeed = cfgetospeed(tp);
446*38674Smarc 	char	unknown[32],
447*38674Smarc 		*ld;
448*38674Smarc 	char *ccval();
449*38674Smarc 
4501179Sbill 
451*38674Smarc 	/*
452*38674Smarc 	 * line discipline
453*38674Smarc 	 */
454*38674Smarc 	if (ldisc != TTYDISC) {
455*38674Smarc 		switch(ldisc) {
456*38674Smarc 		case TABLDISC:
457*38674Smarc 			ld = "tablet";
4581179Sbill 			break;
459*38674Smarc 		case SLIPDISC:
460*38674Smarc 			ld = "slip(ed)";
4611179Sbill 			break;
462*38674Smarc 		default:
463*38674Smarc 			sprintf(unknown, "#%d", ldisc);
464*38674Smarc 			ld = unknown;
4651179Sbill 		}
466*38674Smarc 		put("%s disc; ", ld);
467*38674Smarc 	}
468*38674Smarc 	/*
469*38674Smarc 	 * line speed
470*38674Smarc 	 */
471*38674Smarc 	if (ispeed != ospeed)
472*38674Smarc 		put("ispeed %d baud; ospeed %d baud;",
473*38674Smarc 		     ispeed, ospeed);
474*38674Smarc 	else
475*38674Smarc 		put("speed %d baud;", ispeed);
476*38674Smarc 	if (fmt)
477*38674Smarc 		put(" %d rows; %d columns;", win.ws_row, win.ws_col);
478*38674Smarc 	put("\n");
47913817Ssam 
480*38674Smarc #define lput(n, f, d) if (fmt || on(f) != d) mdput(n+on(f))
481*38674Smarc 	/*
482*38674Smarc 	 * "local" flags
483*38674Smarc 	 */
484*38674Smarc #define on(f)	((l&f) != 0)
485*38674Smarc 	if (debug) mdput("LFLAG: ");
486*38674Smarc 	lput("-icanon ",ICANON, 1);
487*38674Smarc 	lput("-isig ", ISIG, 1);
488*38674Smarc 	lput("-iexten ", IEXTEN, 1);
489*38674Smarc 	lput("-echo ",ECHO, 1);
490*38674Smarc 	lput("-echoe ",ECHOE, 0);
491*38674Smarc 	lput("-echok ",ECHOK, 0);
492*38674Smarc 	lput("-echoke ",ECHOKE, 0);
493*38674Smarc 	lput("-echonl ",ECHONL, 0);
494*38674Smarc 	lput("-echoctl ",ECHOCTL, 0);
495*38674Smarc 	lput("-echoprt ",ECHOPRT, 0);
496*38674Smarc 	lput("-altwerase ",ALTWERASE, 0);
497*38674Smarc 	lput("-noflsh ",NOFLSH, 0);
498*38674Smarc 	lput("-tostop ",TOSTOP, 0);
499*38674Smarc 	lput("-mdmbuf ",MDMBUF, 0);
500*38674Smarc 	lput("-nohang ",NOHANG, 0);
501*38674Smarc 	lput("-flusho ",FLUSHO, 0);
502*38674Smarc 	lput("-pendin ",PENDIN, 0);
503*38674Smarc 	/*
504*38674Smarc 	 * input flags
505*38674Smarc 	 */
506*38674Smarc #undef on
507*38674Smarc #define on(f)	((i&f) != 0)
508*38674Smarc 	mdput(0);
509*38674Smarc 	if (debug) mdput("IFLAG: ");
510*38674Smarc 	lput("-istrip ", ISTRIP, 0);
511*38674Smarc 	lput("-icrnl ", ICRNL, 1);
512*38674Smarc 	lput("-inlcr ", INLCR, 0);
513*38674Smarc 	lput("-igncr ", IGNCR, 0);
514*38674Smarc 	lput("-ixon ", IXON, 1);
515*38674Smarc 	lput("-ixoff ", IXOFF, 0);
516*38674Smarc 	lput("-ixany ", IXANY, 1);
517*38674Smarc 	lput("-imaxbel ", IMAXBEL, 1);
518*38674Smarc 	lput("-ignbrk ", IGNBRK, 0);
519*38674Smarc 	lput("-brkint ", BRKINT, 1);
520*38674Smarc 	lput("-inpck ", INPCK, 0);
521*38674Smarc 	lput("-ignpar ", IGNPAR, 0);
522*38674Smarc 	lput("-parmrk ", PARMRK, 0);
523*38674Smarc #undef on
524*38674Smarc 	/*
525*38674Smarc 	 * output flags
526*38674Smarc 	 */
527*38674Smarc #define on(f)	((o&f) != 0)
528*38674Smarc 	mdput(0);
529*38674Smarc 	if (debug) mdput("OFLAG: ");
530*38674Smarc 	lput("-opost ", OPOST, 1);
531*38674Smarc 	lput("-onlcr ", ONLCR, 1);
532*38674Smarc 	lput("-oxtabs ", OXTABS, 1);
533*38674Smarc #undef on
534*38674Smarc 	/*
535*38674Smarc 	 * control flags (hardware state)
536*38674Smarc 	 */
537*38674Smarc #define on(f)	((c&f) != 0)
538*38674Smarc 	mdput(0);
539*38674Smarc 	if (debug) mdput("CFLAG: ");
540*38674Smarc 	lput("-cread ", CREAD, 1);
541*38674Smarc 	switch(c&CSIZE) {
542*38674Smarc 	case CS5: mdput("cs5 "); break;
543*38674Smarc 	case CS6: mdput("cs6 "); break;
544*38674Smarc 	case CS7: mdput("cs7 "); break;
545*38674Smarc 	case CS8: mdput("cs8 "); break;
546*38674Smarc 	}
547*38674Smarc 	mdput("-parenb "+on(PARENB));
548*38674Smarc 	lput("-parodd ", PARODD, 0);
549*38674Smarc 	lput("-hupcl ", HUPCL, 1);
550*38674Smarc 	lput("-clocal ", CLOCAL, 0);
551*38674Smarc 	lput("-cstopb ", CSTOPB, 0);
552*38674Smarc 	lput("-crtscts ", CRTSCTS, 0);
553*38674Smarc 	mdput(0);
554*38674Smarc #undef on
555*38674Smarc 	/*
556*38674Smarc 	 * special control characters
557*38674Smarc 	 */
558*38674Smarc 	if (debug) mdput("CCHARS: ");
559*38674Smarc 	if (fmt != 2) {
560*38674Smarc 		for (i=0; *cchars[i].names; i++) {
561*38674Smarc 			char temp[64];
562*38674Smarc 
563*38674Smarc 			if (fmt || cc[cchars[i].sub] != cchars[i].def) {
564*38674Smarc 				sprintf(temp, "%s = %s; ", *cchars[i].names,
565*38674Smarc 					ccval(cc[cchars[i].sub]), fmt);
566*38674Smarc 				mdput(temp);
567*38674Smarc 			}
5681179Sbill 		}
569*38674Smarc 		mdput(0);
570*38674Smarc 	} else {
571*38674Smarc 		for (i=0; *cchars[i].names; i++)
572*38674Smarc 			put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0),
573*38674Smarc 				*(cchars[i].names+1));
574*38674Smarc 		printf("\n");
575*38674Smarc 		for (i=0; *cchars[i].names; i++)
576*38674Smarc 			put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0),
577*38674Smarc 				ccval(cc[cchars[i].sub], fmt));
578*38674Smarc 		printf("\n");
5791179Sbill 	}
5801179Sbill }
5811179Sbill 
582*38674Smarc #ifdef COMPAT_43
583*38674Smarc /*
584*38674Smarc  * gross, but since we're changing the control descriptor
585*38674Smarc  * from 1 to 0, most users will be probably be doing
586*38674Smarc  * "stty > /dev/sometty" by accident. If 1 and 2 are both ttys,
587*38674Smarc  * but not the same, assume that 1 was incorrectly redirected.
588*38674Smarc  */
589*38674Smarc checkredirect() {
590*38674Smarc 	struct stat st1, st2;
591*38674Smarc 
592*38674Smarc 	if (isatty(1) && isatty(2) && fstat(1, &st1) != -1 &&
593*38674Smarc 	    fstat(2, &st2) != -1 && (st1.st_rdev != st2.st_rdev))
594*38674Smarc warning("stdout appears redirected, but stdin is the control descriptor");
595*38674Smarc }
596*38674Smarc #endif
597*38674Smarc 
598*38674Smarc STATIC char *
599*38674Smarc ccval(c, fmt)
600*38674Smarc 	unsigned char c;
6011179Sbill {
602*38674Smarc 	static char buf[128];
603*38674Smarc 	char *bp;
6041179Sbill 
605*38674Smarc 	*buf = 0, bp = buf;
606*38674Smarc 	if (c == _POSIX_VDISABLE)
607*38674Smarc 		if (fmt == 2)
608*38674Smarc 			return("<u>");
609*38674Smarc 		else
610*38674Smarc 			return("<undef>");
611*38674Smarc 	if (c & 0200) {
612*38674Smarc 		strcat(buf, "M-");
613*38674Smarc 		*bp++ = 'M';
614*38674Smarc 		*bp++ = '-';
615*38674Smarc 		c &= 0177;
6161179Sbill 	}
617*38674Smarc 	if (c == 0177) {
618*38674Smarc 		*bp++ = '^';
619*38674Smarc 		*bp++ = '?';
6201179Sbill 	}
621*38674Smarc 	else if (c < 040) {
622*38674Smarc 		*bp++ = '^';
623*38674Smarc 		*bp++ = c + '@';
624*38674Smarc 	}
625*38674Smarc 	else
626*38674Smarc 		*bp++ = c;
627*38674Smarc 	*bp = 0;
628*38674Smarc 	return(buf);
6291179Sbill }
6301179Sbill 
631*38674Smarc STATIC
632*38674Smarc mdput(s)
633*38674Smarc 	char *s;
6341179Sbill {
635*38674Smarc 	static int col = 0;
6361179Sbill 
637*38674Smarc 	if (s == (char *)0) {
638*38674Smarc 		if (col) {
639*38674Smarc 			put("\n");
640*38674Smarc 			col = 0;
641*38674Smarc 		}
6421179Sbill 		return;
6431179Sbill 	}
644*38674Smarc 	if ((col += strlen(s)) > WRAPCOL) {
645*38674Smarc 		put("\n");
646*38674Smarc 		col = strlen(s);
6471179Sbill 	}
648*38674Smarc 	put(s);
6491179Sbill }
6501179Sbill 
651*38674Smarc STATIC
652*38674Smarc put(f, a)
653*38674Smarc 	char *f;
6541179Sbill {
655*38674Smarc 	_doprnt(f, &a, OUT);
656*38674Smarc }
6571179Sbill 
658*38674Smarc STATIC
659*38674Smarc warning(s, a)
660*38674Smarc 	char *s;
661*38674Smarc {
662*38674Smarc 	fprintf(ERR, "stty: warning: ");
663*38674Smarc 	_doprnt(s, &a, ERR);
664*38674Smarc 	fprintf(ERR, "\n");
6651179Sbill }
6661179Sbill 
667*38674Smarc STATIC
668*38674Smarc errexit(s, a)
669*38674Smarc 	char *s;
670*38674Smarc {
671*38674Smarc 	fprintf(ERR, "stty: ");
672*38674Smarc 	_doprnt(s, &a, ERR);
673*38674Smarc 	fprintf(ERR, "\n");
674*38674Smarc 	exit(1);
675*38674Smarc }
6761179Sbill 
677*38674Smarc STATIC
678*38674Smarc syserrexit(s, a)
679*38674Smarc 	char *s;
6801179Sbill {
681*38674Smarc 	fprintf(ERR, "stty: ");
682*38674Smarc 	_doprnt(s, &a, ERR);
683*38674Smarc 	fprintf(ERR, ": %s\n", sys_errlist[errno]);
684*38674Smarc 	exit(1);
6851179Sbill }
686