xref: /csrg-svn/bin/stty/stty.c (revision 47843)
1*47843Sbostic /*-
2*47843Sbostic  * Copyright (c) 1980, 1989, 1991 The Regents of the University of California.
3*47843Sbostic  * All rights reserved.
4*47843Sbostic  *
5*47843Sbostic  * %sccs.include.proprietary.c%
619907Sdist  */
719907Sdist 
813073Ssam #ifndef lint
919907Sdist char copyright[] =
10*47843Sbostic "@(#) Copyright (c) 1980, 1989, 1991 The Regents of the University of California.\n\
1119907Sdist  All rights reserved.\n";
12*47843Sbostic #endif /* not lint */
1319907Sdist 
1419907Sdist #ifndef lint
15*47843Sbostic static char sccsid[] = "@(#)stty.c	5.20 (Berkeley) 04/08/91";
16*47843Sbostic #endif /* not lint */
1719907Sdist 
181179Sbill /*
191179Sbill  * set teletype modes
201179Sbill  */
211179Sbill 
2238674Smarc #include <sys/types.h>
2338674Smarc #include <sys/stat.h>
2437609Sbostic #include <sys/ioctl.h>
2538674Smarc #include <sys/syslog.h>
2638674Smarc #define KERNEL
2738674Smarc #include <sys/tty.h>
2838674Smarc #undef KERNEL
2938674Smarc #include <sys/termios.h>
3038674Smarc #include <sys/file.h>
3138674Smarc #include <errno.h>
3238674Smarc #include <ctype.h>
331179Sbill #include <stdio.h>
341179Sbill 
3540170Smarc #define eq(s1, s2)	(strcmp((s1), (s2)) == 0)
3638674Smarc #define WRAPCOL 65
3738674Smarc 
3840170Smarc struct modes {
3938674Smarc 	char *name;
4038674Smarc 	long set;
4138674Smarc 	long unset;
421179Sbill };
431179Sbill 
4440170Smarc struct modes imodes[] = {
4538674Smarc 	"ignbrk",	IGNBRK, 0,
4638674Smarc 	"-ignbrk",	0, IGNBRK,
4738674Smarc 	"brkint",	BRKINT, 0,
4838674Smarc 	"-brkint",	0, BRKINT,
4938674Smarc 	"ignpar",	IGNPAR, 0,
5038674Smarc 	"-ignpar",	0, IGNPAR,
5138674Smarc 	"parmrk",	PARMRK, 0,
5238674Smarc 	"-parmrk",	0, PARMRK,
5338674Smarc 	"inpck",	INPCK, 0,
5438674Smarc 	"-inpck",	0, INPCK,
5538674Smarc 	"istrip",	ISTRIP, 0,
5638674Smarc 	"-istrip",	0, ISTRIP,
5738674Smarc 	"inlcr",	INLCR, 0,
5838674Smarc 	"-inlcr",	0, INLCR,
5938674Smarc 	"igncr",	IGNCR, 0,
6038674Smarc 	"-igncr",	0, IGNCR,
6138674Smarc 	"icrnl",	ICRNL, 0,
6238674Smarc 	"-icrnl",	0, ICRNL,
6338674Smarc 	"ixon",		IXON, 0,
6438674Smarc 	"-ixon",	0, IXON,
6538674Smarc 	"flow",		IXON, 0,
6638674Smarc 	"-flow",	0, IXON,
6738674Smarc 	"ixoff",	IXOFF, 0,
6838674Smarc 	"-ixoff",	0, IXOFF,
6938674Smarc 	"tandem",	IXOFF, 0,
7038674Smarc 	"-tandem",	0, IXOFF,
7138674Smarc 	"ixany",	IXANY, 0,
7238674Smarc 	"-ixany",	0, IXANY,
7338674Smarc 	"decctlq",	0, IXANY,
7438674Smarc 	"-decctlq",	IXANY, 0,
7538674Smarc 	"imaxbel",	IMAXBEL, 0,
7638674Smarc 	"-imaxbel",	0, IMAXBEL,
7738674Smarc 	0
7838674Smarc };
791179Sbill 
8040170Smarc struct modes omodes[] = {
8138674Smarc 	"opost",	OPOST, 0,
8238674Smarc 	"-opost",	0, OPOST,
8338674Smarc 	"-litout",	OPOST, 0,
8438674Smarc 	"litout",	0, OPOST,
8538674Smarc 	"onlcr",	ONLCR, 0,
8638674Smarc 	"-onlcr",	0, ONLCR,
8738674Smarc 	"tabs",		0, OXTABS,	/* "preserve" tabs */
8838674Smarc 	"-tabs",	OXTABS, 0,
8940210Smarc 	"xtabs",	OXTABS, 0,
9040210Smarc 	"-xtabs",	0, OXTABS,
9138674Smarc 	"oxtabs",	OXTABS, 0,
9238674Smarc 	"-oxtabs",	0, OXTABS,
931179Sbill 	0
941179Sbill };
951179Sbill 
9640170Smarc struct modes cmodes[] = {
9738674Smarc 	"cs5",		CS5, CSIZE,
9838674Smarc 	"cs6",		CS6, CSIZE,
9938674Smarc 	"cs7",		CS7, CSIZE,
10038674Smarc 	"cs8",		CS8, CSIZE,
10138674Smarc 	"cstopb",	CSTOPB, 0,
10238674Smarc 	"-cstopb",	0, CSTOPB,
10338674Smarc 	"cread",	CREAD, 0,
10438674Smarc 	"-cread",	0, CREAD,
10538674Smarc 	"parenb",	PARENB, 0,
10638674Smarc 	"-parenb",	0, PARENB,
10738674Smarc 	"parodd",	PARODD, 0,
10838674Smarc 	"-parodd",	0, PARODD,
10938674Smarc 	"parity",	PARENB | CS7, PARODD | CSIZE,
11038674Smarc 	"evenp",	PARENB | CS7, PARODD | CSIZE,
11138674Smarc 	"oddp",		PARENB | CS7 | PARODD, CSIZE,
11238674Smarc 	"-parity",	CS8, PARODD | PARENB | CSIZE,
11340169Skarels 	"pass8",	CS8, PARODD | PARENB | CSIZE,
11438674Smarc 	"-evenp",	CS8, PARODD | PARENB | CSIZE,
11538674Smarc 	"-oddp",	CS8, PARODD | PARENB | CSIZE,
11638674Smarc 	"hupcl",	HUPCL, 0,
11738674Smarc 	"-hupcl",	0, HUPCL,
11838674Smarc 	"hup",		HUPCL, 0,
11938674Smarc 	"-hup",		0, HUPCL,
12038674Smarc 	"clocal",	CLOCAL, 0,
12138674Smarc 	"-clocal",	0, CLOCAL,
12238674Smarc 	"crtscts",	CRTSCTS, 0,
12338674Smarc 	"-crtscts",	0, CRTSCTS,
12438674Smarc 	0
12538674Smarc };
12638674Smarc 
12740170Smarc struct modes lmodes[] = {
12838674Smarc 	"echo",		ECHO, 0,
12938674Smarc 	"-echo",	0, ECHO,
13038674Smarc 	"echoe",	ECHOE, 0,
13138674Smarc 	"-echoe",	0, ECHOE,
13238674Smarc 	"crterase",	ECHOE, 0,
13338674Smarc 	"-crterase",	0, ECHOE,
13438674Smarc 	"crtbs",	ECHOE, 0,   /* crtbs not supported, close enough */
13538674Smarc 	"-crtbs",	0, ECHOE,
13638674Smarc 	"echok",	ECHOK, 0,
13738674Smarc 	"-echok",	0, ECHOK,
13838674Smarc 	"echoke",	ECHOKE, 0,
13938674Smarc 	"-echoke",	0, ECHOKE,
14038674Smarc 	"crtkill",	ECHOKE, 0,
14138674Smarc 	"-crtkill",	0, ECHOKE,
14238674Smarc 	"altwerase",	ALTWERASE, 0,
14338674Smarc 	"-altwerase",	0, ALTWERASE,
14438674Smarc 	"iexten",	IEXTEN, 0,
14538674Smarc 	"-iexten",	0, IEXTEN,
14638674Smarc 	"echonl",	ECHONL, 0,
14738674Smarc 	"-echonl",	0, ECHONL,
14838674Smarc 	"echoctl",	ECHOCTL, 0,
14938674Smarc 	"-echoctl",	0, ECHOCTL,
15038674Smarc 	"ctlecho",	ECHOCTL, 0,
15138674Smarc 	"-ctlecho",	0, ECHOCTL,
15238674Smarc 	"echoprt",	ECHOPRT, 0,
15338674Smarc 	"-echoprt",	0, ECHOPRT,
15438674Smarc 	"prterase",	ECHOPRT, 0,
15538674Smarc 	"-prterase",	0, ECHOPRT,
15638674Smarc 	"isig",		ISIG, 0,
15738674Smarc 	"-isig",	0, ISIG,
15838674Smarc 	"icanon",	ICANON, 0,
15938674Smarc 	"-icanon",	0, ICANON,
16038674Smarc 	"noflsh",	NOFLSH, 0,
16138674Smarc 	"-noflsh",	0, NOFLSH,
16238674Smarc 	"tostop",	TOSTOP, 0,
16338674Smarc 	"-tostop",	0, TOSTOP,
16438674Smarc 	"mdmbuf",	MDMBUF, 0,
16538674Smarc 	"-mdmbuf",	0, MDMBUF,
16638674Smarc 	"flusho",	FLUSHO, 0,
16738674Smarc 	"-flusho",	0, FLUSHO,
16838674Smarc 	"pendin",	PENDIN, 0,
16938674Smarc 	"-pendin",	0, PENDIN,
17038674Smarc 	"crt",		ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT,
17138674Smarc 	"-crt",		ECHOK, ECHOE|ECHOKE|ECHOCTL,
17238674Smarc 	"newcrt",	ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT,
17338674Smarc 	"-newcrt",	ECHOK, ECHOE|ECHOKE|ECHOCTL,
17445235Sborman 	"nokerninfo",	NOKERNINFO, 0,
17545235Sborman 	"-nokerninfo",	0, NOKERNINFO,
17645235Sborman 	"kerninfo",	0, NOKERNINFO,
17745235Sborman 	"-kerninfo",	NOKERNINFO, 0,
17838674Smarc 	0
17938674Smarc };
18038674Smarc 
18138674Smarc /*
18238674Smarc  * Special control characters.
18338674Smarc  *
18438674Smarc  * Each entry has a list of names.  The first is the primary name
18538674Smarc  * and is used when printing the control character in the "name = val;"
18638674Smarc  * form.  The second is an abbreviation which is guaranteed to be less
18738674Smarc  * than or equal to four characters in length and is primarily used
18838674Smarc  * when printing the values in columunar form (guarantees all will
18938674Smarc  * fit within 80 cols).  The rest are optional aliases.
19038674Smarc  * All names are recognized on the command line.
19138674Smarc  */
19240170Smarc #define MAXNAMES 3
19340170Smarc struct {
19440210Smarc 	char	*names[MAXNAMES+1];
19538674Smarc 	int	sub;
19638674Smarc 	u_char	def;
19738674Smarc } cchars[] = {
19843098Sbostic 	{{ "erase", "era" },		VERASE,	CERASE, },
19943098Sbostic 	{{ "werase", "wera" },		VWERASE, CWERASE, },
20043098Sbostic 	{{ "kill", "kill" },		VKILL,	CKILL, },
20143098Sbostic 	{{ "intr", "int" },		VINTR,	CINTR, },
20243098Sbostic 	{{ "quit", "quit" },		VQUIT,	CQUIT, },
20343098Sbostic 	{{ "susp", "susp" },		VSUSP,	CSUSP, },
20443098Sbostic 	{{ "dsusp", "dsus" },		VDSUSP,	CDSUSP, },
20543098Sbostic 	{{ "eof", "eof" },		VEOF,	CEOF, },
20643098Sbostic 	{{ "eol", "eol", "brk" },	VEOL,	CEOL, },
20743098Sbostic 	{{ "eol2", "eol2" },		VEOL2,	CEOL, },
20843098Sbostic 	{{ "stop", "stop", "xoff" },	VSTOP,	CSTOP, },
20943098Sbostic 	{{ "start", "star", "xon" },	VSTART,	CSTART, },
21043098Sbostic 	{{ "lnext", "lnxt" },		VLNEXT,	CLNEXT, },
21144286Smarc 	{{ "discard", "disc", "flush" },	VDISCARD, CDISCARD, },
21243098Sbostic 	{{ "reprint", "rpnt", "rprnt" },	VREPRINT, CREPRINT, },
21344286Smarc 	{{ "status", "stat" },		VSTATUS, CSTATUS, },
21438674Smarc 	0
21538674Smarc };
21643098Sbostic 
21740170Smarc struct winsize win;
21840170Smarc int ldisc;
21940170Smarc int debug = 0;
22040170Smarc int trace, dotrace;
22145235Sborman int extproc;
22238674Smarc 
22338674Smarc #define OUT	stdout		/* informational output stream */
22438674Smarc #define ERR	stderr		/* error message stream */
22538674Smarc #define CTL	0		/* default control descriptor */
22640170Smarc int ctl = CTL;
22738674Smarc 
22838674Smarc extern errno;
22938674Smarc 
23038674Smarc #define NORMAL	0	/* only print modes differing from defaults */
23138674Smarc #define ALL	1	/* print all modes - POSIX standard format */
23238674Smarc #define ALL_BSD	2	/* print all modes - using BSD shorthand for cc's */
23343323Smarc #define	GFMT	3	/* print modes in form suitable to be re-input */
23438674Smarc 
23538674Smarc main(argc, argv)
23638674Smarc 	char *argv[];
2371179Sbill {
23838674Smarc 	struct termios t;
23938674Smarc 	int i, fmt = NORMAL;
24038674Smarc 	extern char *optarg;
24138674Smarc 	extern int optind;
24238674Smarc 	int ch;
2431179Sbill 
24438674Smarc 	argc--, argv++;
24538674Smarc 	if (argc > 0 && eq(argv[0], "-a")) {
24638674Smarc 		fmt = ALL;
24738674Smarc 		argc--, argv++;
2481179Sbill 	}
24943323Smarc 	if (argc > 0 && eq(argv[0], "-g")) {
25043323Smarc 		fmt = GFMT;
25143323Smarc 		argc--, argv++;
25243323Smarc 	}
25338674Smarc 	if (argc > 0 && eq(argv[0], "-f")) {
25438674Smarc 		argc--, argv++;
25538674Smarc 		if ((ctl = open(argv[0], O_RDONLY | O_NONBLOCK)) < 0)
25638674Smarc 			syserrexit(*argv);
25738674Smarc 		argc--, argv++;
2581179Sbill 	}
25938674Smarc 	if (ioctl(ctl, TIOCGETD, &ldisc) < 0)
26038674Smarc 		syserrexit("TIOCGETD");
26138674Smarc 	if (tcgetattr(ctl, &t) < 0)
26238674Smarc 		syserrexit("tcgetattr");
26338674Smarc 	if (ioctl(ctl, TIOCGWINSZ, &win) < 0)
26440170Smarc 		warning("TIOCGWINSZ: %s", strerror(errno));
26538674Smarc 	checkredirect();	/* conversion aid */
26638674Smarc 
26738674Smarc 	if (argc == 0 || fmt) {
26838674Smarc 		prmode(&t, ldisc, fmt);
2691179Sbill 		exit(0);
2701179Sbill 	}
27138674Smarc 
27238674Smarc 	while (*argv) {
27338674Smarc 		if (eq("everything", *argv)) {
27438674Smarc 			prmode(&t, ldisc, ALL_BSD);
27538674Smarc 			exit(0);
2761179Sbill 		}
27738674Smarc 		if (eq("all", *argv)) {
27838674Smarc 			prmode(&t, ldisc, ALL);
27938674Smarc 			exit(0);
2801179Sbill 		}
28146310Skarels 		if (eq("tty", *argv) || eq("old", *argv) || eq("new", *argv)) {
28246310Skarels 			int nldisc = TTYDISC;
28346310Skarels 
28446310Skarels 			if (ioctl(0, TIOCSETD, &nldisc) < 0)
28546310Skarels 				syserrexit("TIOCSETD");
28638674Smarc 			goto next;
2871179Sbill 		}
28838674Smarc 		if (eq("nl", *argv)) {
28938674Smarc 			t.c_iflag &= ~ICRNL;
29038674Smarc 			t.c_oflag &= ~ONLCR;
29138674Smarc 			goto next;
2921179Sbill 		}
29338674Smarc 		if (eq("-nl", *argv)) {
29438674Smarc 			t.c_iflag |= ICRNL;
29538674Smarc 			t.c_oflag |= ONLCR;
29638674Smarc 			goto next;
2973797Sroot 		}
29838674Smarc 		if (eq("dec", *argv)){
29938674Smarc 			t.c_cc[VERASE] = (u_char)0177;
30038674Smarc 			t.c_cc[VKILL] = CTRL('u');
30138674Smarc 			t.c_cc[VINTR] = CTRL('c');
30238674Smarc 			t.c_lflag &= ~ECHOPRT;
30338674Smarc 			t.c_lflag |= ECHOE|ECHOKE|ECHOCTL;
30438674Smarc 			t.c_iflag &= ~IXANY;
30538674Smarc 			goto next;
3061179Sbill 		}
30740169Skarels 		if (eq("raw", *argv)) {
30840169Skarels 			cfmakeraw(&t);
30940169Skarels 			t.c_cflag &= ~(CSIZE|PARENB);
31040169Skarels 			t.c_cflag |= CS8;
31140169Skarels 			goto next;
31240169Skarels 		}
31345029Smarc 		if (eq("cbreak", *argv)) {
31445029Smarc 			t.c_iflag |  BRKINT|IXON|IMAXBEL;
31545029Smarc 			t.c_oflag |= OPOST;
31645029Smarc 			t.c_lflag |= ISIG|IEXTEN;
31745029Smarc 			t.c_lflag &= ~ICANON;
31845029Smarc 		}
31940169Skarels 		if (eq("cooked", *argv) || eq("-raw", *argv) ||
32045029Smarc 		    eq("sane", *argv) || eq("-cbreak", *argv)) {
32140169Skarels 			t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL);
32240169Skarels 			t.c_iflag = TTYDEF_IFLAG;
32340169Skarels 			t.c_iflag |= ICRNL;
32440169Skarels 			/* preserve user-preference flags in lflag */
32540169Skarels #define	LKEEP	(ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH)
32640169Skarels 			t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP);
32740169Skarels 			t.c_oflag = TTYDEF_OFLAG;
32840169Skarels 			goto next;
32940169Skarels 		}
33038674Smarc 		if (eq("rows", *argv)) {
33138674Smarc 			if (*(argv+1) == 0)
33238674Smarc 				goto setit;
33318023Sbloom 			win.ws_row = atoi(*++argv);
33438674Smarc 			goto next;
33518023Sbloom 		}
33638674Smarc 		if (eq("ispeed", *argv)) {
33738674Smarc 			int code;
33838674Smarc 			if (*(argv+1) == 0)
33938674Smarc 				errexit("missing ispeed");
34038674Smarc 			cfsetispeed(&t, atoi(*++argv));
34138674Smarc 			goto next;
34238674Smarc 		}
34338674Smarc 		if (eq("ospeed", *argv)) {
34438674Smarc 			if (*(argv+1) == 0)
34538674Smarc 				errexit("missing ospeed");
34638674Smarc 			cfsetospeed(&t, atoi(*++argv));
34738674Smarc 			goto next;
34838674Smarc 		}
34938674Smarc 		if (eq("cols", *argv) || eq("columns", *argv)) {
35038674Smarc 			if (*(argv+1) == 0)
35138674Smarc 				goto setit;
35218023Sbloom 			win.ws_col = atoi(*++argv);
35338674Smarc 			goto next;
35418023Sbloom 		}
35538674Smarc 		if (eq("size", *argv)) {
35638674Smarc 			put("%d %d\n", win.ws_row, win.ws_col);
35725791Skarels 			exit(0);
35825791Skarels 		}
35945235Sborman 		if (eq("extrpc", *argv) || eq("-extproc", *argv)) {
36045235Sborman 			if (**argv == '-')
36145235Sborman 				extproc = 0;
36245235Sborman 			else
36345235Sborman 				extproc = 1;
36445235Sborman 			ioctl(ctl, TIOCEXT, &extproc);
36545235Sborman 		}
36638674Smarc 		if (eq("speed", *argv)) {
36738674Smarc 			put("%d\n", cfgetospeed(&t));
36838674Smarc 			exit(0);
36938674Smarc 		}
37038674Smarc 		for (i=0; imodes[i].name; i++)
37138674Smarc 			if (eq(imodes[i].name, *argv)) {
37238674Smarc 				t.c_iflag &= ~imodes[i].unset;
37338674Smarc 				t.c_iflag |= imodes[i].set;
37438674Smarc 				goto next;
3751179Sbill 			}
37638674Smarc 		for (i=0; omodes[i].name; i++)
37738674Smarc 			if (eq(omodes[i].name, *argv)) {
37838674Smarc 				t.c_oflag &= ~omodes[i].unset;
37938674Smarc 				t.c_oflag |= omodes[i].set;
38038674Smarc 				goto next;
38138674Smarc 			}
38238674Smarc 		for (i=0; cmodes[i].name; i++)
38338674Smarc 			if (eq(cmodes[i].name, *argv)) {
38438674Smarc 				t.c_cflag &= ~cmodes[i].unset;
38538674Smarc 				t.c_cflag |= cmodes[i].set;
38638674Smarc 				goto next;
38738674Smarc 			}
38838674Smarc 		for (i=0; lmodes[i].name; i++)
38938674Smarc 			if (eq(lmodes[i].name, *argv)) {
39038674Smarc 				t.c_lflag &= ~lmodes[i].unset;
39138674Smarc 				t.c_lflag |= lmodes[i].set;
39238674Smarc 				goto next;
39338674Smarc 			}
39438674Smarc 		for (i=0; *cchars[i].names; i++) {
39538674Smarc 			char **cp = cchars[i].names;
39638674Smarc 			while (*cp) {
39738674Smarc 				if (eq(*cp, *argv)) {
39838674Smarc 					if (*++argv == 0)
39938674Smarc 						goto setit;
40038674Smarc 					if (eq(*argv, "undef") ||
40138674Smarc 					    eq(*argv, "disable"))
40238674Smarc 						t.c_cc[cchars[i].sub] =
40338674Smarc 						   _POSIX_VDISABLE;
40438674Smarc 					else if (**argv == '^')
40538674Smarc 						t.c_cc[cchars[i].sub] =
40638674Smarc 						    ((*argv)[1] == '?') ? 0177 :
40738674Smarc 						    ((*argv)[1] == '-') ?
40838674Smarc 						     _POSIX_VDISABLE :
40938674Smarc 						     (*argv)[1] & 037;
41038674Smarc 					else
41138674Smarc 						t.c_cc[cchars[i].sub] = **argv;
41238674Smarc 					goto next;
4131179Sbill 				}
41438674Smarc 				cp++;
41538674Smarc 			}
4161179Sbill 		}
41738674Smarc 		if (isdigit(**argv)) {
41838674Smarc 			cfsetospeed(&t, atoi(*argv));
41938674Smarc 			cfsetispeed(&t, atoi(*argv));
42038674Smarc 			goto next;
42138674Smarc 		}
42243323Smarc 		if (strncmp(*argv, "-gfmt", sizeof ("-gfmt") - 1) == 0) {
42343323Smarc 			gfmtset(&t, *argv);
42443323Smarc 			goto next;
42543323Smarc 		}
42638674Smarc 		/* didn't match anything */
42738674Smarc 		errexit("unknown option: %s", *argv);
42838674Smarc 		exit(1);
42938674Smarc next:
43038674Smarc 		argv++;
4311179Sbill 	}
43238674Smarc setit:
43338674Smarc 	if (tcsetattr(ctl, 0, &t) < 0)
43438674Smarc 		syserrexit("tcsetattr");
43538674Smarc 	if (ioctl(ctl, TIOCSWINSZ, &win) < 0)
43638674Smarc 		warning("can't set window size");
43738674Smarc 
43838674Smarc 	exit(0);
4391179Sbill }
4401179Sbill 
44143323Smarc gfmtset(tp, s)
44243323Smarc 	register struct termios *tp;
44343323Smarc 	char *s;
44443323Smarc {
44543323Smarc 	register int cnt;
44643323Smarc 	char sep;
44743323Smarc 	char *saves = s;
44843323Smarc 	int cval;
44943323Smarc #define advance(c)	while (*(s) && *(s) != (c)) (s)++; if (*s) (s)++ ; \
45043323Smarc 				else \
45143323Smarc 					errexit("bad gfmt operand: %s", saves)
45243323Smarc #define chkeq(string)	if (strncmp(s, (string), strlen(string))) \
45343323Smarc 				errexit("bad gfmt operand: %s", saves)
45443323Smarc 
45543323Smarc 	if (s == NULL)
45643323Smarc 		errexit("missing gfmt string");
45743323Smarc 	advance(':');
45843323Smarc 	chkeq("iflag=");
45943323Smarc 	advance('=');
46043323Smarc 	sscanf(s, "%x", &tp->c_iflag);
46143323Smarc 
46243323Smarc 	advance(':');
46343323Smarc 	chkeq("oflag");
46443323Smarc 	advance('=');
46543323Smarc 	sscanf(s, "%x", &tp->c_oflag);
46643323Smarc 
46743323Smarc 	advance(':');
46843323Smarc 	chkeq("cflag");
46943323Smarc 	advance('=');
47043323Smarc 	sscanf(s, "%x", &tp->c_cflag);
47143323Smarc 
47243323Smarc 	advance(':');
47343323Smarc 	chkeq("lflag");
47443323Smarc 	advance('=');
47543323Smarc 	sscanf(s, "%x", &tp->c_lflag);
47643323Smarc 
47743323Smarc 	advance(':');
47843323Smarc 	chkeq("cc=");
47943323Smarc 
48043323Smarc 	for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',') {
48143323Smarc 		advance(sep);
48243323Smarc 		sscanf(s, "%o", &cval);
48343323Smarc 		tp->c_cc[cnt] = cval;
48443323Smarc 	}
48543323Smarc 
48643323Smarc 	advance(':');
48743323Smarc 	chkeq("ispeed=");
48843323Smarc 	advance('=');
48943323Smarc 	sscanf(s, "%d", &tp->c_ispeed);
49043323Smarc 
49143323Smarc 	advance(':');
49243323Smarc 	chkeq("ospeed=");
49343323Smarc 	advance('=');
49443323Smarc 	sscanf(s, "%d", &tp->c_ospeed);
4951179Sbill }
4961179Sbill 
49738674Smarc prmode(tp, ldisc, fmt)
49838674Smarc 	struct termios *tp;
4991179Sbill {
50038674Smarc 	long	i = tp->c_iflag,
50138674Smarc 		o = tp->c_oflag,
50238674Smarc 		c = tp->c_cflag,
50338674Smarc 		l = tp->c_lflag;
50438674Smarc 	u_char	*cc = tp->c_cc;
50538674Smarc 	int	ispeed = cfgetispeed(tp),
50638674Smarc 		ospeed = cfgetospeed(tp);
50738674Smarc 	char	unknown[32],
50838674Smarc 		*ld;
50938674Smarc 	char *ccval();
51043323Smarc 
51143323Smarc 	if (fmt == GFMT) {
51243323Smarc 		int	cnt;
51343323Smarc 		char	sep;
51443323Smarc 
51543323Smarc 		printf("-gfmt:iflag=%x:oflag=%x:cflag=%x:lflag=%x:cc",
51643323Smarc 			i, o, c, l);
51743323Smarc 		for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',')
51843323Smarc 			printf("%c%o", sep, cc[cnt]);
51943323Smarc 		printf(":ispeed=%d:ospeed=%d:\n", ispeed, ospeed);
52043323Smarc 		return;
52143323Smarc 	}
52238674Smarc 
52338674Smarc 	/*
52438674Smarc 	 * line discipline
52538674Smarc 	 */
52638674Smarc 	if (ldisc != TTYDISC) {
52738674Smarc 		switch(ldisc) {
52838674Smarc 		case TABLDISC:
52938674Smarc 			ld = "tablet";
5301179Sbill 			break;
53138674Smarc 		case SLIPDISC:
53240170Smarc 			ld = "slip";
5331179Sbill 			break;
53438674Smarc 		default:
53538674Smarc 			sprintf(unknown, "#%d", ldisc);
53638674Smarc 			ld = unknown;
53746310Skarels 			break;
5381179Sbill 		}
53938674Smarc 		put("%s disc; ", ld);
54038674Smarc 	}
54138674Smarc 	/*
54238674Smarc 	 * line speed
54338674Smarc 	 */
54438674Smarc 	if (ispeed != ospeed)
54538674Smarc 		put("ispeed %d baud; ospeed %d baud;",
54638674Smarc 		     ispeed, ospeed);
54738674Smarc 	else
54838674Smarc 		put("speed %d baud;", ispeed);
54938674Smarc 	if (fmt)
55038674Smarc 		put(" %d rows; %d columns;", win.ws_row, win.ws_col);
55138674Smarc 	put("\n");
55213817Ssam 
55338674Smarc #define lput(n, f, d) if (fmt || on(f) != d) mdput(n+on(f))
55438674Smarc 	/*
55538674Smarc 	 * "local" flags
55638674Smarc 	 */
55738674Smarc #define on(f)	((l&f) != 0)
55838674Smarc 	if (debug) mdput("LFLAG: ");
55938674Smarc 	lput("-icanon ",ICANON, 1);
56038674Smarc 	lput("-isig ", ISIG, 1);
56138674Smarc 	lput("-iexten ", IEXTEN, 1);
56238674Smarc 	lput("-echo ",ECHO, 1);
56338674Smarc 	lput("-echoe ",ECHOE, 0);
56438674Smarc 	lput("-echok ",ECHOK, 0);
56538674Smarc 	lput("-echoke ",ECHOKE, 0);
56638674Smarc 	lput("-echonl ",ECHONL, 0);
56738674Smarc 	lput("-echoctl ",ECHOCTL, 0);
56838674Smarc 	lput("-echoprt ",ECHOPRT, 0);
56938674Smarc 	lput("-altwerase ",ALTWERASE, 0);
57038674Smarc 	lput("-noflsh ",NOFLSH, 0);
57138674Smarc 	lput("-tostop ",TOSTOP, 0);
57238674Smarc 	lput("-mdmbuf ",MDMBUF, 0);
57338674Smarc 	lput("-flusho ",FLUSHO, 0);
57438674Smarc 	lput("-pendin ",PENDIN, 0);
57545235Sborman 	lput("-nokerninfo ",NOKERNINFO, 0);
57645235Sborman 	lput("-extproc ",EXTPROC, 0);
57738674Smarc 	/*
57838674Smarc 	 * input flags
57938674Smarc 	 */
58038674Smarc #undef on
58138674Smarc #define on(f)	((i&f) != 0)
58238674Smarc 	mdput(0);
58338674Smarc 	if (debug) mdput("IFLAG: ");
58438674Smarc 	lput("-istrip ", ISTRIP, 0);
58538674Smarc 	lput("-icrnl ", ICRNL, 1);
58638674Smarc 	lput("-inlcr ", INLCR, 0);
58738674Smarc 	lput("-igncr ", IGNCR, 0);
58838674Smarc 	lput("-ixon ", IXON, 1);
58938674Smarc 	lput("-ixoff ", IXOFF, 0);
59038674Smarc 	lput("-ixany ", IXANY, 1);
59138674Smarc 	lput("-imaxbel ", IMAXBEL, 1);
59238674Smarc 	lput("-ignbrk ", IGNBRK, 0);
59338674Smarc 	lput("-brkint ", BRKINT, 1);
59438674Smarc 	lput("-inpck ", INPCK, 0);
59538674Smarc 	lput("-ignpar ", IGNPAR, 0);
59638674Smarc 	lput("-parmrk ", PARMRK, 0);
59738674Smarc #undef on
59838674Smarc 	/*
59938674Smarc 	 * output flags
60038674Smarc 	 */
60138674Smarc #define on(f)	((o&f) != 0)
60238674Smarc 	mdput(0);
60338674Smarc 	if (debug) mdput("OFLAG: ");
60438674Smarc 	lput("-opost ", OPOST, 1);
60538674Smarc 	lput("-onlcr ", ONLCR, 1);
60638674Smarc 	lput("-oxtabs ", OXTABS, 1);
60738674Smarc #undef on
60838674Smarc 	/*
60938674Smarc 	 * control flags (hardware state)
61038674Smarc 	 */
61138674Smarc #define on(f)	((c&f) != 0)
61238674Smarc 	mdput(0);
61338674Smarc 	if (debug) mdput("CFLAG: ");
61438674Smarc 	lput("-cread ", CREAD, 1);
61538674Smarc 	switch(c&CSIZE) {
61638674Smarc 	case CS5: mdput("cs5 "); break;
61738674Smarc 	case CS6: mdput("cs6 "); break;
61838674Smarc 	case CS7: mdput("cs7 "); break;
61938674Smarc 	case CS8: mdput("cs8 "); break;
62038674Smarc 	}
62138674Smarc 	mdput("-parenb "+on(PARENB));
62238674Smarc 	lput("-parodd ", PARODD, 0);
62338674Smarc 	lput("-hupcl ", HUPCL, 1);
62438674Smarc 	lput("-clocal ", CLOCAL, 0);
62538674Smarc 	lput("-cstopb ", CSTOPB, 0);
62638674Smarc 	lput("-crtscts ", CRTSCTS, 0);
62738674Smarc 	mdput(0);
62838674Smarc #undef on
62938674Smarc 	/*
63038674Smarc 	 * special control characters
63138674Smarc 	 */
63238674Smarc 	if (debug) mdput("CCHARS: ");
63338674Smarc 	if (fmt != 2) {
63438674Smarc 		for (i=0; *cchars[i].names; i++) {
63538674Smarc 			char temp[64];
63638674Smarc 
63738674Smarc 			if (fmt || cc[cchars[i].sub] != cchars[i].def) {
63838674Smarc 				sprintf(temp, "%s = %s; ", *cchars[i].names,
63938674Smarc 					ccval(cc[cchars[i].sub]), fmt);
64038674Smarc 				mdput(temp);
64138674Smarc 			}
6421179Sbill 		}
64338674Smarc 		mdput(0);
64438674Smarc 	} else {
64538674Smarc 		for (i=0; *cchars[i].names; i++)
64638674Smarc 			put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0),
64738674Smarc 				*(cchars[i].names+1));
64838674Smarc 		printf("\n");
64938674Smarc 		for (i=0; *cchars[i].names; i++)
65038674Smarc 			put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0),
65138674Smarc 				ccval(cc[cchars[i].sub], fmt));
65238674Smarc 		printf("\n");
6531179Sbill 	}
6541179Sbill }
6551179Sbill 
65638674Smarc /*
65738674Smarc  * gross, but since we're changing the control descriptor
65838674Smarc  * from 1 to 0, most users will be probably be doing
65938674Smarc  * "stty > /dev/sometty" by accident. If 1 and 2 are both ttys,
66038674Smarc  * but not the same, assume that 1 was incorrectly redirected.
66138674Smarc  */
66238674Smarc checkredirect() {
66338674Smarc 	struct stat st1, st2;
66438674Smarc 
66538674Smarc 	if (isatty(1) && isatty(2) && fstat(1, &st1) != -1 &&
66638674Smarc 	    fstat(2, &st2) != -1 && (st1.st_rdev != st2.st_rdev))
66738674Smarc warning("stdout appears redirected, but stdin is the control descriptor");
66838674Smarc }
66938674Smarc 
67040170Smarc char *
67138674Smarc ccval(c, fmt)
67238674Smarc 	unsigned char c;
6731179Sbill {
67438674Smarc 	static char buf[128];
67538674Smarc 	char *bp;
6761179Sbill 
67738674Smarc 	*buf = 0, bp = buf;
67838674Smarc 	if (c == _POSIX_VDISABLE)
67938674Smarc 		if (fmt == 2)
68038674Smarc 			return("<u>");
68138674Smarc 		else
68238674Smarc 			return("<undef>");
68338674Smarc 	if (c & 0200) {
68438674Smarc 		strcat(buf, "M-");
68538674Smarc 		*bp++ = 'M';
68638674Smarc 		*bp++ = '-';
68738674Smarc 		c &= 0177;
6881179Sbill 	}
68938674Smarc 	if (c == 0177) {
69038674Smarc 		*bp++ = '^';
69138674Smarc 		*bp++ = '?';
6921179Sbill 	}
69338674Smarc 	else if (c < 040) {
69438674Smarc 		*bp++ = '^';
69538674Smarc 		*bp++ = c + '@';
69638674Smarc 	}
69738674Smarc 	else
69838674Smarc 		*bp++ = c;
69938674Smarc 	*bp = 0;
70038674Smarc 	return(buf);
7011179Sbill }
7021179Sbill 
70340170Smarc 
70438674Smarc mdput(s)
70538674Smarc 	char *s;
7061179Sbill {
70738674Smarc 	static int col = 0;
7081179Sbill 
70938674Smarc 	if (s == (char *)0) {
71038674Smarc 		if (col) {
71138674Smarc 			put("\n");
71238674Smarc 			col = 0;
71338674Smarc 		}
7141179Sbill 		return;
7151179Sbill 	}
71638674Smarc 	if ((col += strlen(s)) > WRAPCOL) {
71738674Smarc 		put("\n");
71838674Smarc 		col = strlen(s);
7191179Sbill 	}
72038674Smarc 	put(s);
7211179Sbill }
7221179Sbill 
72340170Smarc #include <varargs.h>
72440170Smarc 
72540170Smarc put(va_alist)
72640170Smarc 	va_dcl
7271179Sbill {
72840170Smarc 	char *fmt;
72940170Smarc 	va_list ap;
73040170Smarc 
73140170Smarc 	va_start(ap);
73240170Smarc 	fmt = va_arg(ap, char *);
73340170Smarc 	(void) vfprintf(OUT, fmt, ap);
73440170Smarc 	va_end(ap);
73538674Smarc }
7361179Sbill 
73740170Smarc 
73840170Smarc warning(va_alist)
73940170Smarc 	va_dcl
74038674Smarc {
74140170Smarc 	char *fmt;
74240170Smarc 	va_list ap;
74340170Smarc 
74438674Smarc 	fprintf(ERR, "stty: warning: ");
74540170Smarc 	va_start(ap);
74640170Smarc 	fmt = va_arg(ap, char *);
74740170Smarc 	(void) vfprintf(ERR, fmt, ap);
74840170Smarc 	va_end(ap);
74938674Smarc 	fprintf(ERR, "\n");
7501179Sbill }
7511179Sbill 
75240170Smarc 
75340170Smarc errexit(va_alist)
75440170Smarc 	va_dcl
75538674Smarc {
75640170Smarc 	char *fmt;
75740170Smarc 	va_list ap;
75840170Smarc 
75938674Smarc 	fprintf(ERR, "stty: ");
76040170Smarc 	va_start(ap);
76140170Smarc 	fmt = va_arg(ap, char *);
76240170Smarc 	(void) vfprintf(ERR, fmt, ap);
76340170Smarc 	va_end(ap);
76438674Smarc 	fprintf(ERR, "\n");
76538674Smarc 	exit(1);
76638674Smarc }
7671179Sbill 
76840170Smarc 
76940170Smarc syserrexit(va_alist)
77040170Smarc 	va_dcl
7711179Sbill {
77240170Smarc 	char *fmt;
77340170Smarc 	va_list ap;
77440170Smarc 
77538674Smarc 	fprintf(ERR, "stty: ");
77640170Smarc 	va_start(ap);
77740170Smarc 	fmt = va_arg(ap, char *);
77840170Smarc 	(void) vfprintf(ERR, fmt, ap);
77940170Smarc 	va_end(ap);
78040170Smarc 	fprintf(ERR, ": %s\n", strerror(errno));
78138674Smarc 	exit(1);
7821179Sbill }
783