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 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 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