xref: /csrg-svn/bin/stty/stty.c (revision 49974)
147843Sbostic /*-
248945Sbostic  * Copyright (c) 1989, 1991 The Regents of the University of California.
347843Sbostic  * All rights reserved.
447843Sbostic  *
549269Sbostic  * %sccs.include.redist.c%
619907Sdist  */
719907Sdist 
813073Ssam #ifndef lint
919907Sdist char copyright[] =
1048945Sbostic "@(#) 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*49974Sbostic static char sccsid[] = "@(#)stty.c	5.25 (Berkeley) 06/03/91";
1647843Sbostic #endif /* not lint */
1719907Sdist 
1838674Smarc #include <sys/types.h>
1937609Sbostic #include <sys/ioctl.h>
2048945Sbostic #include <termios.h>
2148945Sbostic #include <fcntl.h>
2238674Smarc #include <errno.h>
2348945Sbostic #include <unistd.h>
2448945Sbostic #include <stdio.h>
2538674Smarc #include <ctype.h>
2648945Sbostic #include <stdlib.h>
2748945Sbostic #include <string.h>
2848945Sbostic #include "stty.h"
2948945Sbostic #include "extern.h"
301179Sbill 
3148945Sbostic static void usage __P((void));
3238674Smarc 
3338674Smarc main(argc, argv)
3448945Sbostic 	int argc;
3548945Sbostic 	char **argv;
361179Sbill {
3738674Smarc 	extern char *optarg;
3848974Sbostic 	extern int opterr, optind;
3948945Sbostic 	extern struct cchar cchars1[], cchars2[];
4048945Sbostic 	extern struct modes cmodes[], imodes[], lmodes[], omodes[];
4148945Sbostic 	register struct modes *mp;
4248945Sbostic 	register struct cchar *cp;
4348945Sbostic 	struct winsize win;
4448945Sbostic 	struct termios t;
4548945Sbostic 	enum FMT fmt;
4648945Sbostic 	int ch, ctl, ldisc, tmp;
471179Sbill 
4848945Sbostic 	ctl = STDIN_FILENO;
4948945Sbostic 	fmt = NOTSET;
5048974Sbostic 	opterr = 0;
51*49974Sbostic 	while (strspn(argv[optind], "-aefg") == strlen(argv[optind]) &&
52*49974Sbostic 	    (ch = getopt(argc, argv, "aef:g")) != EOF)
5348945Sbostic 		switch(ch) {
5448945Sbostic 		case 'a':		/* undocumented: POSIX compatibility */
5548945Sbostic 			fmt = POSIX;
5648945Sbostic 			break;
5748945Sbostic 		case 'e':
5848945Sbostic 			fmt = BSD;
5948945Sbostic 			break;
6048945Sbostic 		case 'f':
6148945Sbostic 			if ((ctl = open(optarg, O_RDONLY | O_NONBLOCK)) < 0)
62*49974Sbostic 				err("%s: %s", optarg, strerror(errno));
6348945Sbostic 			break;
6448945Sbostic 		case 'g':
6548945Sbostic 			fmt = GFLAG;
6648945Sbostic 			break;
6748945Sbostic 		case '?':
6848945Sbostic 		default:
6948945Sbostic 			goto args;
7048945Sbostic 		}
7148945Sbostic 
7248945Sbostic args:	argc -= optind;
7348945Sbostic 	argv += optind;
7448945Sbostic 
7538674Smarc 	if (ioctl(ctl, TIOCGETD, &ldisc) < 0)
7648945Sbostic 		err("TIOCGETD: %s", strerror(errno));
7738674Smarc 	if (tcgetattr(ctl, &t) < 0)
7848945Sbostic 		err("tcgetattr: %s", strerror(errno));
7938674Smarc 	if (ioctl(ctl, TIOCGWINSZ, &win) < 0)
8048945Sbostic 		warn("TIOCGWINSZ: %s\n", strerror(errno));
8138674Smarc 
8248945Sbostic 	checkredirect();			/* conversion aid */
8348945Sbostic 
8448945Sbostic 	switch(fmt) {
8548945Sbostic 	case NOTSET:
8648945Sbostic 		if (*argv)
8748945Sbostic 			break;
8848945Sbostic 		/* FALLTHROUGH */
8948945Sbostic 	case BSD:
9048945Sbostic 	case POSIX:
9148945Sbostic 		print(&t, &win, ldisc, fmt);
9248945Sbostic 		break;
9348945Sbostic 	case GFLAG:
9448945Sbostic 		gprint(&t, &win, ldisc);
9548945Sbostic 		break;
961179Sbill 	}
9738674Smarc 
9848945Sbostic #define	CHK(s)	(**argv == s[0] && !strcmp(*argv, s))
9948945Sbostic 
10048945Sbostic 	for (; *argv; ++argv) {
10148945Sbostic 		if (CHK("-nl")) {
10248945Sbostic 			t.c_iflag |= ICRNL;
10348945Sbostic 			t.c_oflag |= ONLCR;
10448945Sbostic 			continue;
1051179Sbill 		}
10648945Sbostic 		if (CHK("all")) {
10748945Sbostic 			print(&t, &win, ldisc, BSD);
10848945Sbostic 			continue;
1091179Sbill 		}
11048945Sbostic 		if (CHK("-cbreak"))
11148945Sbostic 			goto reset;
11248945Sbostic 		if (CHK("cbreak")) {
11348945Sbostic 			t.c_iflag | BRKINT|IXON|IMAXBEL;
11448945Sbostic 			t.c_oflag |= OPOST;
11548945Sbostic 			t.c_lflag |= ISIG|IEXTEN;
11648945Sbostic 			t.c_lflag &= ~ICANON;
11748945Sbostic 			continue;
1181179Sbill 		}
11948945Sbostic 		if (CHK("cols")) {
12048945Sbostic 			if (!*++argv)
12148945Sbostic 				err("option requires an argument -- cols");
12248945Sbostic 			goto columns;
1231179Sbill 		}
12448945Sbostic 		if (CHK("columns")) {
12548945Sbostic 			if (!*++argv)
12648945Sbostic 				err("option requires an argument -- columns");
12748945Sbostic columns:		win.ws_col = atoi(*argv);
12848945Sbostic 			continue;
1293797Sroot 		}
13048945Sbostic 		if (CHK("cooked"))
13148945Sbostic 			goto reset;
13248945Sbostic 		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;
13948945Sbostic 			continue;
1401179Sbill 		}
14148945Sbostic 		if (CHK("everything")) {
14248945Sbostic 			print(&t, &win, ldisc, BSD);
14348945Sbostic 			continue;
14448945Sbostic 		}
14548945Sbostic 		if (CHK("-extproc")) {
14648945Sbostic 			tmp = 0;
14748945Sbostic 			ioctl(ctl, TIOCEXT, &tmp);
14848945Sbostic 			continue;
14948945Sbostic 		}
15048945Sbostic 		if (CHK("extrpc")) {
15148945Sbostic 			tmp = 1;
15248945Sbostic 			ioctl(ctl, TIOCEXT, &tmp);
15348945Sbostic 			continue;
15448945Sbostic 		}
15548945Sbostic 		if (CHK("ispeed")) {
15648945Sbostic 			if (!*++argv)
15748945Sbostic 				err("option requires an argument -- ispeed");
15848945Sbostic 			cfsetispeed(&t, atoi(*argv));
15948945Sbostic 			continue;
16048945Sbostic 		}
16148945Sbostic 		if (CHK("new"))
16248945Sbostic 			goto tty;
16348945Sbostic 		if (CHK("nl")) {
16448945Sbostic 			t.c_iflag &= ~ICRNL;
16548945Sbostic 			t.c_oflag &= ~ONLCR;
16648945Sbostic 			continue;
16748945Sbostic 		}
16848945Sbostic 		if (CHK("old"))
16948945Sbostic 			goto tty;
17048945Sbostic 		if (CHK("ospeed")) {
17148945Sbostic 			if (!*++argv)
17248945Sbostic 				err("option requires an argument -- ospeed");
17348945Sbostic 			cfsetospeed(&t, atoi(*argv));
17448945Sbostic 			continue;
17548945Sbostic 		}
17648945Sbostic 		if (CHK("-raw"))
17748945Sbostic 			goto reset;
17848945Sbostic 		if (CHK("raw")) {
17940169Skarels 			cfmakeraw(&t);
18040169Skarels 			t.c_cflag &= ~(CSIZE|PARENB);
18140169Skarels 			t.c_cflag |= CS8;
18248945Sbostic 			continue;
18340169Skarels 		}
18448945Sbostic 		if (CHK("rows")) {
18548945Sbostic 			if (!*++argv)
18648945Sbostic 				err("option requires an argument -- rows");
18748945Sbostic 			win.ws_row = atoi(*argv);
18848945Sbostic 			continue;
18945029Smarc 		}
19048945Sbostic 		if (CHK("sane")) {
19148945Sbostic 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;
19848945Sbostic 			continue;
19940169Skarels 		}
20048945Sbostic 		if (CHK("size")) {
20148945Sbostic 			(void)printf("%d %d\n", win.ws_row, win.ws_col);
20248945Sbostic 			continue;
20318023Sbloom 		}
20448945Sbostic 		if (CHK("speed")) {
20548945Sbostic 			(void)printf("%d\n", cfgetospeed(&t));
20648945Sbostic 			continue;
20738674Smarc 		}
20848945Sbostic 		if (CHK("tty")) {
20948945Sbostic tty:			tmp = TTYDISC;
21048945Sbostic 			if (ioctl(0, TIOCSETD, &tmp) < 0)
21148945Sbostic 				err("TIOCSETD: %s", strerror(errno));
21248945Sbostic 			continue;
21338674Smarc 		}
21448945Sbostic 
21548945Sbostic 		for (mp = cmodes; mp->name; ++mp)
21648945Sbostic 			if (CHK(mp->name)) {
21748945Sbostic 				t.c_cflag &= ~mp->unset;
21848945Sbostic 				t.c_cflag |= mp->set;
21938674Smarc 				goto next;
2201179Sbill 			}
22148945Sbostic 		for (mp = imodes; mp->name; ++mp)
22248945Sbostic 			if (CHK(mp->name)) {
22348945Sbostic 				t.c_iflag &= ~mp->unset;
22448945Sbostic 				t.c_iflag |= mp->set;
22538674Smarc 				goto next;
22638674Smarc 			}
22748945Sbostic 		for (mp = lmodes; mp->name; ++mp)
22848945Sbostic 			if (CHK(mp->name)) {
22948945Sbostic 				t.c_lflag &= ~mp->unset;
23048945Sbostic 				t.c_lflag |= mp->set;
23138674Smarc 				goto next;
23238674Smarc 			}
23348945Sbostic 		for (mp = omodes; mp->name; ++mp)
23448945Sbostic 			if (CHK(mp->name)) {
23548945Sbostic 				t.c_oflag &= ~mp->unset;
23648945Sbostic 				t.c_oflag |= mp->set;
23738674Smarc 				goto next;
23838674Smarc 			}
23948945Sbostic 		for (cp = cchars1; cp->name; ++cp) {
24048945Sbostic 			if (!CHK(cp->name))
24148945Sbostic 				continue;
24248945Sbostic 			goto ccfound;
2431179Sbill 		}
24448945Sbostic 		for (cp = cchars2; cp->name; ++cp) {
24548945Sbostic 			if (!CHK(cp->name))
24648945Sbostic 				continue;
24748945Sbostic ccfound:		if (!*++argv)
24848945Sbostic 				err("option requires an argument -- %s",
24948945Sbostic 				    cp->name);
25049847Sbostic 			if (CHK("undef") || CHK("<undef>"))
25148945Sbostic 				t.c_cc[cp->sub] = _POSIX_VDISABLE;
25248945Sbostic 			else if (**argv == '^')
25348945Sbostic 				t.c_cc[cp->sub] =
25448945Sbostic 				    ((*argv)[1] == '?') ? 0177 :
25548945Sbostic 				    ((*argv)[1] == '-') ? _POSIX_VDISABLE :
25648945Sbostic 				    (*argv)[1] & 037;
25748945Sbostic 			else
25848945Sbostic 				t.c_cc[cp->sub] = **argv;
25948945Sbostic 			goto next;
26048945Sbostic 		}
26148945Sbostic 
26238674Smarc 		if (isdigit(**argv)) {
26338674Smarc 			cfsetospeed(&t, atoi(*argv));
26438674Smarc 			cfsetispeed(&t, atoi(*argv));
26538674Smarc 			goto next;
26638674Smarc 		}
26748945Sbostic 		if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) {
26848945Sbostic 			gread(&t, *argv + sizeof("gfmt1") - 1);
26943323Smarc 			goto next;
27043323Smarc 		}
27148945Sbostic 
27248945Sbostic 		err("illegal option -- %s", *argv);
27348945Sbostic next:		continue;
2741179Sbill 	}
27548945Sbostic 
27638674Smarc 	if (tcsetattr(ctl, 0, &t) < 0)
27748945Sbostic 		err("tcsetattr: %s", strerror(errno));
27838674Smarc 	if (ioctl(ctl, TIOCSWINSZ, &win) < 0)
27948945Sbostic 		warn("TIOCSWINSZ: %s", strerror(errno));
28038674Smarc 	exit(0);
2811179Sbill }
2821179Sbill 
28348945Sbostic static void
28448945Sbostic usage()
28543323Smarc {
28648945Sbostic 	(void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n");
28738674Smarc 	exit(1);
28838674Smarc }
289