1 /* $NetBSD: modes.c,v 1.18 2015/05/01 17:01:08 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1991, 1993, 1994
5  *        The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)modes.c     8.3 (Berkeley) 4/2/94";
36 #else
37 __RCSID("$NetBSD: modes.c,v 1.18 2015/05/01 17:01:08 christos Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/types.h>
42 
43 #include <stddef.h>
44 #include <string.h>
45 #include <stdbool.h>
46 
47 #include "stty.h"
48 #include "extern.h"
49 
50 struct modes {
51           const char *name;
52           tcflag_t flag;
53 };
54 
55 struct specialmodes {
56           const char *name;
57           tcflag_t set;
58           tcflag_t 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  */
65 const struct modes cmodes[] = {
66           { "cstopb",         CSTOPB },
67           { "cread",          CREAD },
68           { "parenb",         PARENB },
69           { "parodd",         PARODD },
70           { "hupcl",          HUPCL },
71           { "hup",  HUPCL },
72           { "clocal",         CLOCAL },
73           { "crtscts",        CRTSCTS },
74           { "mdmbuf",         MDMBUF },
75           { "cdtrcts",        CDTRCTS },
76           { .name = NULL },
77 };
78 
79 const struct specialmodes cspecialmodes[] = {
80           { "cs5",  CS5, CSIZE },
81           { "cs6",  CS6, CSIZE },
82           { "cs7",  CS7, CSIZE },
83           { "cs8",  CS8, CSIZE },
84           { "parity",         PARENB | CS7, PARODD | CSIZE },
85           { "-parity",        CS8, PARODD | PARENB | CSIZE },
86           { "evenp",          PARENB | CS7, PARODD | CSIZE },
87           { "-evenp",         CS8, PARODD | PARENB | CSIZE },
88           { "oddp", PARENB | CS7 | PARODD, CSIZE },
89           { "-oddp",          CS8, PARODD | PARENB | CSIZE },
90           { "pass8",          CS8, PARODD | PARENB | CSIZE },
91           { "-pass8",         PARENB | CS7, PARODD | CSIZE },
92           { .name = NULL },
93 };
94 
95 const struct modes imodes[] = {
96           { "ignbrk",         IGNBRK },
97           { "brkint",         BRKINT },
98           { "ignpar",         IGNPAR },
99           { "parmrk",         PARMRK },
100           { "inpck",          INPCK },
101           { "istrip",         ISTRIP },
102           { "inlcr",          INLCR },
103           { "igncr",          IGNCR },
104           { "icrnl",          ICRNL },
105           { "ixon", IXON },
106           { "flow", IXON },
107           { "ixoff",          IXOFF },
108           { "tandem",         IXOFF },
109           { "ixany",          IXANY },
110           { "imaxbel",        IMAXBEL },
111           { .name = NULL },
112 };
113 
114 const struct specialmodes ispecialmodes[] = {
115           { "decctlq",        0, IXANY },
116           { "-decctlq",       IXANY, 0 },
117           { .name = NULL },
118 };
119 
120 const struct modes lmodes[] = {
121           { "echo", ECHO },
122           { "echoe",          ECHOE },
123           { "crterase",       ECHOE },
124           { "crtbs",          ECHOE },  /* crtbs not supported, close enough */
125           { "echok",          ECHOK },
126           { "echoke",         ECHOKE },
127           { "crtkill",        ECHOKE },
128           { "altwerase",      ALTWERASE },
129           { "iexten",         IEXTEN },
130           { "echonl",         ECHONL },
131           { "echoctl",        ECHOCTL },
132           { "ctlecho",        ECHOCTL },
133           { "echoprt",        ECHOPRT },
134           { "prterase",       ECHOPRT },
135           { "isig", ISIG },
136           { "icanon",         ICANON },
137           { "noflsh",         NOFLSH },
138           { "tostop",         TOSTOP },
139           { "flusho",         FLUSHO },
140           { "pendin",         PENDIN },
141           { "nokerninfo",     NOKERNINFO },
142           { .name = NULL },
143 };
144 
145 const struct specialmodes lspecialmodes[] = {
146           { "crt",  ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT },
147           { "-crt", ECHOK, ECHOE|ECHOKE|ECHOCTL },
148           { "newcrt",         ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT },
149           { "-newcrt",        ECHOK, ECHOE|ECHOKE|ECHOCTL },
150           { "kerninfo",       0, NOKERNINFO },
151           { "-kerninfo",      NOKERNINFO, 0 },
152           { .name = NULL },
153 };
154 
155 const struct modes omodes[] = {
156           { "opost",          OPOST },
157           { "onlcr",          ONLCR },
158           { "ocrnl",          OCRNL },
159           { "oxtabs",         OXTABS },
160           { "onocr",          ONOCR },
161           { "onlret",         ONLRET },
162           { .name = NULL },
163 };
164 
165 const struct specialmodes ospecialmodes[] = {
166           { "litout",         0, OPOST },
167           { "-litout",        OPOST, 0 },
168           { "tabs", 0, OXTABS },                  /* "preserve" tabs */
169           { "-tabs",          OXTABS, 0 },
170           { .name = NULL },
171 };
172 
173 #define   CHK(s)    (!strcmp(name, s))
174 
175 static int
modeset(const char * name,const struct modes * mp,const struct specialmodes * smp,tcflag_t * f)176 modeset(const char *name, const struct modes *mp,
177     const struct specialmodes *smp, tcflag_t *f)
178 {
179           bool neg;
180 
181           for (; smp->name; ++smp)
182                     if (CHK(smp->name)) {
183                               *f &= ~smp->unset;
184                               *f |= smp->set;
185                               return 1;
186                     }
187 
188           if ((neg = (*name == '-')))
189                     name++;
190 
191           for (; mp->name; ++mp)
192                     if (CHK(mp->name)) {
193                               if (neg)
194                                         *f &= ~mp->flag;
195                               else
196                                         *f |= mp->flag;
197                               return 1;
198                     }
199 
200           return 0;
201 }
202 
203 int
msearch(char *** argvp,struct info * ip)204 msearch(char ***argvp, struct info *ip)
205 {
206           const char *name = **argvp;
207 
208           if (modeset(name, cmodes, cspecialmodes, &ip->t.c_cflag))
209                     goto out;
210 
211           if (modeset(name, imodes, ispecialmodes, &ip->t.c_iflag))
212                     goto out;
213 
214           if (modeset(name, lmodes, lspecialmodes, &ip->t.c_lflag))
215                     goto out;
216 
217           if (modeset(name, omodes, ospecialmodes, &ip->t.c_oflag))
218                     goto out;
219 
220           return 0;
221 out:
222           ip->set = 1;
223           return 1;
224 }
225