1/*-
2 * Copyright (c) 1991, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static char sccsid[] = "@(#)modes.c	8.3 (Berkeley) 4/2/94";
37#endif
38#endif /* not lint */
39#include <sys/cdefs.h>
40__RCSID("$FreeBSD: src/bin/stty/modes.c,v 1.12 2002/06/30 05:15:04 obrien Exp $");
41
42#include <sys/types.h>
43#include <stddef.h>
44#include <string.h>
45#include "stty.h"
46
47#ifdef __APPLE__
48#include <get_compat.h>
49#else
50#define COMPAT_MODE(a,b) (1)
51#endif /* __APPLE__ */
52
53int msearch(char ***, struct info *);
54
55struct modes {
56	const char *name;
57	long set;
58	long unset;
59};
60
61/*
62 * The code in optlist() depends on minus options following regular
63 * options, i.e. "foo" must immediately precede "-foo".
64 */
65struct modes cmodes[] = {
66	{ "cs5",	CS5, CSIZE },
67	{ "cs6",	CS6, CSIZE },
68	{ "cs7",	CS7, CSIZE },
69	{ "cs8",	CS8, CSIZE },
70	{ "cstopb",	CSTOPB, 0 },
71	{ "-cstopb",	0, CSTOPB },
72	{ "cread",	CREAD, 0 },
73	{ "-cread",	0, CREAD },
74	{ "parenb",	PARENB, 0 },
75	{ "-parenb",	0, PARENB },
76	{ "parodd",	PARODD, 0 },
77	{ "-parodd",	0, PARODD },
78	{ "parity",	PARENB | CS7, PARODD | CSIZE },
79	{ "-parity",	CS8, PARODD | PARENB | CSIZE },
80	{ "evenp",	PARENB | CS7, PARODD | CSIZE },
81	{ "-evenp",	CS8, PARODD | PARENB | CSIZE },
82	{ "oddp",	PARENB | CS7 | PARODD, CSIZE },
83	{ "-oddp",	CS8, PARODD | PARENB | CSIZE },
84	{ "pass8",	CS8, PARODD | PARENB | CSIZE },
85	{ "-pass8",	PARENB | CS7, PARODD | CSIZE },
86	{ "hupcl",	HUPCL, 0 },
87	{ "-hupcl",	0, HUPCL },
88	{ "hup",	HUPCL, 0 },
89	{ "-hup",	0, HUPCL },
90	{ "clocal",	CLOCAL, 0 },
91	{ "-clocal",	0, CLOCAL },
92	{ "crtscts",	CRTSCTS, 0 },
93	{ "-crtscts",	0, CRTSCTS },
94	{ "ctsflow",	CCTS_OFLOW, 0 },
95	{ "-ctsflow",	0, CCTS_OFLOW },
96	{ "dsrflow",	CDSR_OFLOW, 0 },
97	{ "-dsrflow",	0, CDSR_OFLOW },
98	{ "dtrflow",	CDTR_IFLOW, 0 },
99	{ "-dtrflow",	0, CDTR_IFLOW },
100	{ "rtsflow",	CRTS_IFLOW, 0 },
101	{ "-rtsflow",	0, CRTS_IFLOW },
102	{ "mdmbuf",	MDMBUF, 0 },
103	{ "-mdmbuf",	0, MDMBUF },
104	{ NULL,		0, 0 },
105};
106
107struct modes imodes[] = {
108	{ "ignbrk",	IGNBRK, 0 },
109	{ "-ignbrk",	0, IGNBRK },
110	{ "brkint",	BRKINT, 0 },
111	{ "-brkint",	0, BRKINT },
112	{ "ignpar",	IGNPAR, 0 },
113	{ "-ignpar",	0, IGNPAR },
114	{ "parmrk",	PARMRK, 0 },
115	{ "-parmrk",	0, PARMRK },
116	{ "inpck",	INPCK, 0 },
117	{ "-inpck",	0, INPCK },
118	{ "istrip",	ISTRIP, 0 },
119	{ "-istrip",	0, ISTRIP },
120	{ "inlcr",	INLCR, 0 },
121	{ "-inlcr",	0, INLCR },
122	{ "igncr",	IGNCR, 0 },
123	{ "-igncr",	0, IGNCR },
124	{ "icrnl",	ICRNL, 0 },
125	{ "-icrnl",	0, ICRNL },
126	{ "ixon",	IXON, 0 },
127	{ "-ixon",	0, IXON },
128	{ "flow",	IXON, 0 },
129	{ "-flow",	0, IXON },
130	{ "ixoff",	IXOFF, 0 },
131	{ "-ixoff",	0, IXOFF },
132	{ "tandem",	IXOFF, 0 },
133	{ "-tandem",	0, IXOFF },
134	{ "ixany",	IXANY, 0 },
135	{ "-ixany",	0, IXANY },
136	{ "decctlq",	0, IXANY },
137	{ "-decctlq",	IXANY, 0 },
138	{ "imaxbel",	IMAXBEL, 0 },
139	{ "-imaxbel",	0, IMAXBEL },
140	{ "iutf8",	IUTF8, 0 },
141	{ "-iutf8",	0, IUTF8 },
142	{ NULL,		0, 0 },
143};
144
145struct modes lmodes[] = {
146	{ "echo",	ECHO, 0 },
147	{ "-echo",	0, ECHO },
148	{ "echoe",	ECHOE, 0 },
149	{ "-echoe",	0, ECHOE },
150	{ "crterase",	ECHOE, 0 },
151	{ "-crterase",	0, ECHOE },
152	{ "crtbs",	ECHOE, 0 },	/* crtbs not supported, close enough */
153	{ "-crtbs",	0, ECHOE },
154	{ "echok",	ECHOK, 0 },
155	{ "-echok",	0, ECHOK },
156	{ "echoke",	ECHOKE, 0 },
157	{ "-echoke",	0, ECHOKE },
158	{ "crtkill",	ECHOKE, 0 },
159	{ "-crtkill",	0, ECHOKE },
160	{ "altwerase",	ALTWERASE, 0 },
161	{ "-altwerase",	0, ALTWERASE },
162	{ "iexten",	IEXTEN, 0 },
163	{ "-iexten",	0, IEXTEN },
164	{ "echonl",	ECHONL, 0 },
165	{ "-echonl",	0, ECHONL },
166	{ "echoctl",	ECHOCTL, 0 },
167	{ "-echoctl",	0, ECHOCTL },
168	{ "ctlecho",	ECHOCTL, 0 },
169	{ "-ctlecho",	0, ECHOCTL },
170	{ "echoprt",	ECHOPRT, 0 },
171	{ "-echoprt",	0, ECHOPRT },
172	{ "prterase",	ECHOPRT, 0 },
173	{ "-prterase",	0, ECHOPRT },
174	{ "isig",	ISIG, 0 },
175	{ "-isig",	0, ISIG },
176	{ "icanon",	ICANON, 0 },
177	{ "-icanon",	0, ICANON },
178	{ "noflsh",	NOFLSH, 0 },
179	{ "-noflsh",	0, NOFLSH },
180	{ "tostop",	TOSTOP, 0 },
181	{ "-tostop",	0, TOSTOP },
182	{ "flusho",	FLUSHO, 0 },
183	{ "-flusho",	0, FLUSHO },
184	{ "pendin",	PENDIN, 0 },
185	{ "-pendin",	0, PENDIN },
186	{ "crt",	ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT },
187	{ "-crt",	ECHOK, ECHOE|ECHOKE|ECHOCTL },
188	{ "newcrt",	ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT },
189	{ "-newcrt",	ECHOK, ECHOE|ECHOKE|ECHOCTL },
190	{ "nokerninfo",	NOKERNINFO, 0 },
191	{ "-nokerninfo",0, NOKERNINFO },
192	{ "kerninfo",	0, NOKERNINFO },
193	{ "-kerninfo",	NOKERNINFO, 0 },
194	{ NULL,		0, 0 },
195};
196
197struct modes omodes[] = {
198	{ "opost",	OPOST, 0 },
199	{ "-opost",	0, OPOST },
200	{ "litout",	0, OPOST },
201	{ "-litout",	OPOST, 0 },
202	{ "onlcr",	ONLCR, 0 },
203	{ "-onlcr",	0, ONLCR },
204#ifndef __APPLE__
205	{ "ocrnl",	OCRNL, 0 },
206	{ "-ocrnl",	0, OCRNL },
207#endif
208	{ "tabs",	0, OXTABS },		/* "preserve" tabs */
209	{ "-tabs",	OXTABS, 0 },
210	{ "oxtabs",	OXTABS, 0 },
211	{ "-oxtabs",	0, OXTABS },
212#ifndef __APPLE__
213	{ "onocr",	ONOCR, 0 },
214	{ "-onocr",	0, ONOCR },
215	{ "onlret",	ONLRET, 0 },
216	{ "-onlret",	0, ONLRET },
217#endif
218	{ NULL,		0, 0 },
219};
220
221struct modes umodes[] = {	/* For Unix conformance only */
222	{ "ocrnl",	OCRNL, 0 },
223	{ "-ocrnl",	0, OCRNL },
224	{ "onocr",	ONOCR, 0 },
225	{ "-onocr",	0, ONOCR },
226	{ "onlret",	ONLRET, 0 },
227	{ "-onlret",	0, ONLRET },
228
229	{ "ofill",	OFILL, 0 },
230	{ "-ofill",	0, OFILL },
231
232	{ "ofdel",	OFDEL, 0 },
233	{ "-ofdel",	0, OFDEL },
234
235	{ "bs0",	BS0, 0 },
236	{ "bs1",	BS1, 0 },
237
238	{ "cr0",	CR0, 0 },
239	{ "cr1",	CR1, 0 },
240	{ "cr2",	CR2, 0 },
241	{ "cr3",	CR3, 0 },
242
243	{ "ff0",	FF0, 0 },
244	{ "ff1",	FF1, 0 },
245
246	{ "nl0",	NL0, 0 },
247	{ "nl1",	NL1, 0 },
248
249	{ "tab0",	TAB0, 0 },
250	{ "tab1",	TAB1, 0 },
251	{ "tab2",	TAB2, 0 },
252	{ "tab3",	TAB3, 0 },
253
254	{ "vt0",	VT0, 0 },
255	{ "vt1",	VT1, 0 },
256
257	{ NULL,		0, 0 },
258};
259
260#define	CHK(s)	(*name == s[0] && !strcmp(name, s))
261
262int
263msearch(char ***argvp, struct info *ip)
264{
265	struct modes *mp;
266	char *name;
267
268	name = **argvp;
269
270	for (mp = cmodes; mp->name; ++mp)
271		if (CHK(mp->name)) {
272			ip->t.c_cflag &= ~mp->unset;
273			ip->t.c_cflag |= mp->set;
274			ip->set = 1;
275			return (1);
276		}
277	for (mp = imodes; mp->name; ++mp)
278		if (CHK(mp->name)) {
279			ip->t.c_iflag &= ~mp->unset;
280			ip->t.c_iflag |= mp->set;
281			ip->set = 1;
282			return (1);
283		}
284	for (mp = lmodes; mp->name; ++mp)
285		if (CHK(mp->name)) {
286			ip->t.c_lflag &= ~mp->unset;
287			ip->t.c_lflag |= mp->set;
288			ip->set = 1;
289			return (1);
290		}
291	for (mp = omodes; mp->name; ++mp)
292		if (CHK(mp->name)) {
293			ip->t.c_oflag &= ~mp->unset;
294			ip->t.c_oflag |= mp->set;
295			ip->set = 1;
296			return (1);
297		}
298	if (COMPAT_MODE("bin/stty", "Unix2003")) {
299		for (mp = umodes; mp->name; ++mp)
300			if (CHK(mp->name)) {
301				ip->t.c_oflag &= ~mp->unset;
302				ip->t.c_oflag |= mp->set;
303				ip->set = 1;
304				return (1);
305		}
306	}
307	return (0);
308}
309