xref: /csrg-svn/bin/stty/stty.c (revision 48945)
147843Sbostic /*-
2*48945Sbostic  * Copyright (c) 1989, 1991 The Regents of the University of California.
347843Sbostic  * All rights reserved.
447843Sbostic  *
547843Sbostic  * %sccs.include.proprietary.c%
619907Sdist  */
719907Sdist 
813073Ssam #ifndef lint
919907Sdist char copyright[] =
10*48945Sbostic "@(#) Copyright (c) 1989, 1991 The Regents of the University of California.\n\
1119907Sdist  All rights reserved.\n";
1247843Sbostic #endif /* not lint */
1319907Sdist 
1419907Sdist #ifndef lint
15*48945Sbostic static char sccsid[] = "@(#)stty.c	5.21 (Berkeley) 05/02/91";
1647843Sbostic #endif /* not lint */
1719907Sdist 
1838674Smarc #include <sys/types.h>
1937609Sbostic #include <sys/ioctl.h>
20*48945Sbostic #include <termios.h>
21*48945Sbostic #include <fcntl.h>
2238674Smarc #include <errno.h>
23*48945Sbostic #include <unistd.h>
24*48945Sbostic #include <stdio.h>
2538674Smarc #include <ctype.h>
26*48945Sbostic #include <stdlib.h>
27*48945Sbostic #include <string.h>
28*48945Sbostic #include "stty.h"
29*48945Sbostic #include "extern.h"
301179Sbill 
31*48945Sbostic static void usage __P((void));
3238674Smarc 
3338674Smarc main(argc, argv)
34*48945Sbostic 	int argc;
35*48945Sbostic 	char **argv;
361179Sbill {
3738674Smarc 	extern char *optarg;
3838674Smarc 	extern int optind;
39*48945Sbostic 	extern struct cchar cchars1[], cchars2[];
40*48945Sbostic 	extern struct modes cmodes[], imodes[], lmodes[], omodes[];
41*48945Sbostic 	register struct modes *mp;
42*48945Sbostic 	register struct cchar *cp;
43*48945Sbostic 	struct winsize win;
44*48945Sbostic 	struct termios t;
45*48945Sbostic 	enum FMT fmt;
46*48945Sbostic 	int ch, ctl, ldisc, tmp;
471179Sbill 
48*48945Sbostic 	ctl = STDIN_FILENO;
49*48945Sbostic 	fmt = NOTSET;
50*48945Sbostic 	while ((ch = getopt(argc, argv, "aef:g")) != EOF)
51*48945Sbostic 		switch(ch) {
52*48945Sbostic 		case 'a':		/* undocumented: POSIX compatibility */
53*48945Sbostic 			fmt = POSIX;
54*48945Sbostic 			break;
55*48945Sbostic 		case 'e':
56*48945Sbostic 			fmt = BSD;
57*48945Sbostic 			break;
58*48945Sbostic 		case 'f':
59*48945Sbostic 			if ((ctl = open(optarg, O_RDONLY | O_NONBLOCK)) < 0)
60*48945Sbostic 				err(optarg);
61*48945Sbostic 			break;
62*48945Sbostic 		case 'g':
63*48945Sbostic 			fmt = GFLAG;
64*48945Sbostic 			break;
65*48945Sbostic 		case '?':
66*48945Sbostic 			usage();
67*48945Sbostic 		default:
68*48945Sbostic 			--optind;
69*48945Sbostic 			goto args;
70*48945Sbostic 		}
71*48945Sbostic 
72*48945Sbostic args:	argc -= optind;
73*48945Sbostic 	argv += optind;
74*48945Sbostic 
7538674Smarc 	if (ioctl(ctl, TIOCGETD, &ldisc) < 0)
76*48945Sbostic 		err("TIOCGETD: %s", strerror(errno));
7738674Smarc 	if (tcgetattr(ctl, &t) < 0)
78*48945Sbostic 		err("tcgetattr: %s", strerror(errno));
7938674Smarc 	if (ioctl(ctl, TIOCGWINSZ, &win) < 0)
80*48945Sbostic 		warn("TIOCGWINSZ: %s\n", strerror(errno));
8138674Smarc 
82*48945Sbostic 	checkredirect();			/* conversion aid */
83*48945Sbostic 
84*48945Sbostic 	switch(fmt) {
85*48945Sbostic 	case NOTSET:
86*48945Sbostic 		if (*argv)
87*48945Sbostic 			break;
88*48945Sbostic 		/* FALLTHROUGH */
89*48945Sbostic 	case BSD:
90*48945Sbostic 	case POSIX:
91*48945Sbostic 		print(&t, &win, ldisc, fmt);
92*48945Sbostic 		break;
93*48945Sbostic 	case GFLAG:
94*48945Sbostic 		gprint(&t, &win, ldisc);
95*48945Sbostic 		break;
961179Sbill 	}
9738674Smarc 
98*48945Sbostic #define	CHK(s)	(**argv == s[0] && !strcmp(*argv, s))
99*48945Sbostic 
100*48945Sbostic 	for (; *argv; ++argv) {
101*48945Sbostic 		if (CHK("-nl")) {
102*48945Sbostic 			t.c_iflag |= ICRNL;
103*48945Sbostic 			t.c_oflag |= ONLCR;
104*48945Sbostic 			continue;
1051179Sbill 		}
106*48945Sbostic 		if (CHK("all")) {
107*48945Sbostic 			print(&t, &win, ldisc, BSD);
108*48945Sbostic 			continue;
1091179Sbill 		}
110*48945Sbostic 		if (CHK("-cbreak"))
111*48945Sbostic 			goto reset;
112*48945Sbostic 		if (CHK("cbreak")) {
113*48945Sbostic 			t.c_iflag | BRKINT|IXON|IMAXBEL;
114*48945Sbostic 			t.c_oflag |= OPOST;
115*48945Sbostic 			t.c_lflag |= ISIG|IEXTEN;
116*48945Sbostic 			t.c_lflag &= ~ICANON;
117*48945Sbostic 			continue;
1181179Sbill 		}
119*48945Sbostic 		if (CHK("cols")) {
120*48945Sbostic 			if (!*++argv)
121*48945Sbostic 				err("option requires an argument -- cols");
122*48945Sbostic 			goto columns;
1231179Sbill 		}
124*48945Sbostic 		if (CHK("columns")) {
125*48945Sbostic 			if (!*++argv)
126*48945Sbostic 				err("option requires an argument -- columns");
127*48945Sbostic columns:		win.ws_col = atoi(*argv);
128*48945Sbostic 			continue;
1293797Sroot 		}
130*48945Sbostic 		if (CHK("cooked"))
131*48945Sbostic 			goto reset;
132*48945Sbostic 		if (CHK("dec")) {
13338674Smarc 			t.c_cc[VERASE] = (u_char)0177;
13438674Smarc 			t.c_cc[VKILL] = CTRL('u');
13538674Smarc 			t.c_cc[VINTR] = CTRL('c');
13638674Smarc 			t.c_lflag &= ~ECHOPRT;
13738674Smarc 			t.c_lflag |= ECHOE|ECHOKE|ECHOCTL;
13838674Smarc 			t.c_iflag &= ~IXANY;
139*48945Sbostic 			continue;
1401179Sbill 		}
141*48945Sbostic 		if (CHK("everything")) {
142*48945Sbostic 			print(&t, &win, ldisc, BSD);
143*48945Sbostic 			continue;
144*48945Sbostic 		}
145*48945Sbostic 		if (CHK("-extproc")) {
146*48945Sbostic 			tmp = 0;
147*48945Sbostic 			ioctl(ctl, TIOCEXT, &tmp);
148*48945Sbostic 			continue;
149*48945Sbostic 		}
150*48945Sbostic 		if (CHK("extrpc")) {
151*48945Sbostic 			tmp = 1;
152*48945Sbostic 			ioctl(ctl, TIOCEXT, &tmp);
153*48945Sbostic 			continue;
154*48945Sbostic 		}
155*48945Sbostic 		if (CHK("ispeed")) {
156*48945Sbostic 			if (!*++argv)
157*48945Sbostic 				err("option requires an argument -- ispeed");
158*48945Sbostic 			cfsetispeed(&t, atoi(*argv));
159*48945Sbostic 			continue;
160*48945Sbostic 		}
161*48945Sbostic 		if (CHK("new"))
162*48945Sbostic 			goto tty;
163*48945Sbostic 		if (CHK("nl")) {
164*48945Sbostic 			t.c_iflag &= ~ICRNL;
165*48945Sbostic 			t.c_oflag &= ~ONLCR;
166*48945Sbostic 			continue;
167*48945Sbostic 		}
168*48945Sbostic 		if (CHK("old"))
169*48945Sbostic 			goto tty;
170*48945Sbostic 		if (CHK("ospeed")) {
171*48945Sbostic 			if (!*++argv)
172*48945Sbostic 				err("option requires an argument -- ospeed");
173*48945Sbostic 			cfsetospeed(&t, atoi(*argv));
174*48945Sbostic 			continue;
175*48945Sbostic 		}
176*48945Sbostic 		if (CHK("-raw"))
177*48945Sbostic 			goto reset;
178*48945Sbostic 		if (CHK("raw")) {
17940169Skarels 			cfmakeraw(&t);
18040169Skarels 			t.c_cflag &= ~(CSIZE|PARENB);
18140169Skarels 			t.c_cflag |= CS8;
182*48945Sbostic 			continue;
18340169Skarels 		}
184*48945Sbostic 		if (CHK("rows")) {
185*48945Sbostic 			if (!*++argv)
186*48945Sbostic 				err("option requires an argument -- rows");
187*48945Sbostic 			win.ws_row = atoi(*argv);
188*48945Sbostic 			continue;
18945029Smarc 		}
190*48945Sbostic 		if (CHK("sane")) {
191*48945Sbostic reset:			t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL);
19240169Skarels 			t.c_iflag = TTYDEF_IFLAG;
19340169Skarels 			t.c_iflag |= ICRNL;
19440169Skarels 			/* preserve user-preference flags in lflag */
19540169Skarels #define	LKEEP	(ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH)
19640169Skarels 			t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP);
19740169Skarels 			t.c_oflag = TTYDEF_OFLAG;
198*48945Sbostic 			continue;
19940169Skarels 		}
200*48945Sbostic 		if (CHK("size")) {
201*48945Sbostic 			(void)printf("%d %d\n", win.ws_row, win.ws_col);
202*48945Sbostic 			continue;
20318023Sbloom 		}
204*48945Sbostic 		if (CHK("speed")) {
205*48945Sbostic 			(void)printf("%d\n", cfgetospeed(&t));
206*48945Sbostic 			continue;
20738674Smarc 		}
208*48945Sbostic 		if (CHK("tty")) {
209*48945Sbostic tty:			tmp = TTYDISC;
210*48945Sbostic 			if (ioctl(0, TIOCSETD, &tmp) < 0)
211*48945Sbostic 				err("TIOCSETD: %s", strerror(errno));
212*48945Sbostic 			continue;
21338674Smarc 		}
214*48945Sbostic 
215*48945Sbostic 		for (mp = cmodes; mp->name; ++mp)
216*48945Sbostic 			if (CHK(mp->name)) {
217*48945Sbostic 				t.c_cflag &= ~mp->unset;
218*48945Sbostic 				t.c_cflag |= mp->set;
21938674Smarc 				goto next;
2201179Sbill 			}
221*48945Sbostic 		for (mp = imodes; mp->name; ++mp)
222*48945Sbostic 			if (CHK(mp->name)) {
223*48945Sbostic 				t.c_iflag &= ~mp->unset;
224*48945Sbostic 				t.c_iflag |= mp->set;
22538674Smarc 				goto next;
22638674Smarc 			}
227*48945Sbostic 		for (mp = lmodes; mp->name; ++mp)
228*48945Sbostic 			if (CHK(mp->name)) {
229*48945Sbostic 				t.c_lflag &= ~mp->unset;
230*48945Sbostic 				t.c_lflag |= mp->set;
23138674Smarc 				goto next;
23238674Smarc 			}
233*48945Sbostic 		for (mp = omodes; mp->name; ++mp)
234*48945Sbostic 			if (CHK(mp->name)) {
235*48945Sbostic 				t.c_oflag &= ~mp->unset;
236*48945Sbostic 				t.c_oflag |= mp->set;
23738674Smarc 				goto next;
23838674Smarc 			}
239*48945Sbostic 		for (cp = cchars1; cp->name; ++cp) {
240*48945Sbostic 			if (!CHK(cp->name))
241*48945Sbostic 				continue;
242*48945Sbostic 			goto ccfound;
2431179Sbill 		}
244*48945Sbostic 		for (cp = cchars2; cp->name; ++cp) {
245*48945Sbostic 			if (!CHK(cp->name))
246*48945Sbostic 				continue;
247*48945Sbostic ccfound:		if (!*++argv)
248*48945Sbostic 				err("option requires an argument -- %s",
249*48945Sbostic 				    cp->name);
250*48945Sbostic 			if (CHK("undef") || CHK("disable"))
251*48945Sbostic 				t.c_cc[cp->sub] = _POSIX_VDISABLE;
252*48945Sbostic 			else if (**argv == '^')
253*48945Sbostic 				t.c_cc[cp->sub] =
254*48945Sbostic 				    ((*argv)[1] == '?') ? 0177 :
255*48945Sbostic 				    ((*argv)[1] == '-') ? _POSIX_VDISABLE :
256*48945Sbostic 				    (*argv)[1] & 037;
257*48945Sbostic 			else
258*48945Sbostic 				t.c_cc[cp->sub] = **argv;
259*48945Sbostic 			goto next;
260*48945Sbostic 		}
261*48945Sbostic 
26238674Smarc 		if (isdigit(**argv)) {
26338674Smarc 			cfsetospeed(&t, atoi(*argv));
26438674Smarc 			cfsetispeed(&t, atoi(*argv));
26538674Smarc 			goto next;
26638674Smarc 		}
267*48945Sbostic 		if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) {
268*48945Sbostic 			gread(&t, *argv + sizeof("gfmt1") - 1);
26943323Smarc 			goto next;
27043323Smarc 		}
271*48945Sbostic 
272*48945Sbostic 		err("illegal option -- %s", *argv);
273*48945Sbostic next:		continue;
2741179Sbill 	}
275*48945Sbostic 
27638674Smarc 	if (tcsetattr(ctl, 0, &t) < 0)
277*48945Sbostic 		err("tcsetattr: %s", strerror(errno));
27838674Smarc 	if (ioctl(ctl, TIOCSWINSZ, &win) < 0)
279*48945Sbostic 		warn("TIOCSWINSZ: %s", strerror(errno));
28038674Smarc 	exit(0);
2811179Sbill }
2821179Sbill 
283*48945Sbostic static void
284*48945Sbostic usage()
28543323Smarc {
286*48945Sbostic 	(void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n");
28738674Smarc 	exit(1);
28838674Smarc }
289