1/*- 2 * Copyright (c) 1991, 1993 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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31 32__FBSDID("$FreeBSD$"); 33 34#ifndef lint 35static const char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/9/93"; 36#endif 37 38#include <sys/types.h> 39 40#include <err.h> 41#include <stdlib.h> 42#include <string.h> 43#include <termios.h> 44 45#include "extern.h" 46 47extern speed_t Ospeed; 48speed_t tset_baudrate(char *); 49 50/* Baud rate conditionals for mapping. */ 51#define GT 0x01 52#define EQ 0x02 53#define LT 0x04 54#define NOT 0x08 55#define GE (GT | EQ) 56#define LE (LT | EQ) 57 58typedef struct map { 59 struct map *next; /* Linked list of maps. */ 60 char *porttype; /* Port type, or "" for any. */ 61 char *type; /* Terminal type to select. */ 62 int conditional; /* Baud rate conditionals bitmask. */ 63 speed_t speed; /* Baud rate to compare against. */ 64} MAP; 65 66MAP *cur, *maplist; 67 68/* 69 * Syntax for -m: 70 * [port-type][test baudrate]:terminal-type 71 * The baud rate tests are: >, <, @, =, ! 72 */ 73void 74add_mapping(const char *port, char *arg) 75{ 76 MAP *mapp; 77 char *copy, *p, *termp; 78 79 copy = strdup(arg); 80 mapp = malloc(sizeof(MAP)); 81 if (copy == NULL || mapp == NULL) 82 errx(1, "malloc"); 83 mapp->next = NULL; 84 if (maplist == NULL) 85 cur = maplist = mapp; 86 else { 87 cur->next = mapp; 88 cur = mapp; 89 } 90 91 mapp->porttype = arg; 92 mapp->conditional = 0; 93 94 arg = strpbrk(arg, "><@=!:"); 95 96 if (arg == NULL) { /* [?]term */ 97 mapp->type = mapp->porttype; 98 mapp->porttype = NULL; 99 goto done; 100 } 101 102 if (arg == mapp->porttype) /* [><@=! baud]:term */ 103 termp = mapp->porttype = NULL; 104 else 105 termp = arg; 106 107 for (;; ++arg) /* Optional conditionals. */ 108 switch(*arg) { 109 case '<': 110 if (mapp->conditional & GT) 111 goto badmopt; 112 mapp->conditional |= LT; 113 break; 114 case '>': 115 if (mapp->conditional & LT) 116 goto badmopt; 117 mapp->conditional |= GT; 118 break; 119 case '@': 120 case '=': /* Not documented. */ 121 mapp->conditional |= EQ; 122 break; 123 case '!': 124 mapp->conditional |= NOT; 125 break; 126 default: 127 goto next; 128 } 129 130next: if (*arg == ':') { 131 if (mapp->conditional) 132 goto badmopt; 133 ++arg; 134 } else { /* Optional baudrate. */ 135 arg = index(p = arg, ':'); 136 if (arg == NULL) 137 goto badmopt; 138 *arg++ = '\0'; 139 mapp->speed = tset_baudrate(p); 140 } 141 142 if (*arg == '\0') /* Non-optional type. */ 143 goto badmopt; 144 145 mapp->type = arg; 146 147 /* Terminate porttype, if specified. */ 148 if (termp != NULL) 149 *termp = '\0'; 150 151 /* If a NOT conditional, reverse the test. */ 152 if (mapp->conditional & NOT) 153 mapp->conditional = ~mapp->conditional & (EQ | GT | LT); 154 155 /* If user specified a port with an option flag, set it. */ 156done: if (port) { 157 if (mapp->porttype) 158badmopt: errx(1, "illegal -m option format: %s", copy); 159 mapp->porttype = strdup(port); 160 } 161 162#ifdef MAPDEBUG 163 (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); 164 (void)printf("type: %s\n", mapp->type); 165 (void)printf("conditional: "); 166 p = ""; 167 if (mapp->conditional & GT) { 168 (void)printf("GT"); 169 p = "/"; 170 } 171 if (mapp->conditional & EQ) { 172 (void)printf("%sEQ", p); 173 p = "/"; 174 } 175 if (mapp->conditional & LT) 176 (void)printf("%sLT", p); 177 (void)printf("\nspeed: %d\n", mapp->speed); 178#endif 179} 180 181/* 182 * Return the type of terminal to use for a port of type 'type', as specified 183 * by the first applicable mapping in 'map'. If no mappings apply, return 184 * 'type'. 185 */ 186const char * 187mapped(const char *type) 188{ 189 MAP *mapp; 190 int match; 191 192 match = 0; 193 for (mapp = maplist; mapp; mapp = mapp->next) 194 if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) { 195 switch (mapp->conditional) { 196 case 0: /* No test specified. */ 197 match = 1; 198 break; 199 case EQ: 200 match = (Ospeed == mapp->speed); 201 break; 202 case GE: 203 match = (Ospeed >= mapp->speed); 204 break; 205 case GT: 206 match = (Ospeed > mapp->speed); 207 break; 208 case LE: 209 match = (Ospeed <= mapp->speed); 210 break; 211 case LT: 212 match = (Ospeed < mapp->speed); 213 break; 214 } 215 if (match) 216 return (mapp->type); 217 } 218 /* No match found; return given type. */ 219 return (type); 220} 221 222typedef struct speeds { 223 const char *string; 224 speed_t speed; 225} SPEEDS; 226 227SPEEDS speeds[] = { 228 { "0", B0 }, 229 { "134.5", B134 }, 230 { "exta", B19200 }, 231 { "extb", B38400 }, 232 { NULL, 0 } 233}; 234 235speed_t 236tset_baudrate(char *rate) 237{ 238 SPEEDS *sp; 239 speed_t speed; 240 241 /* The baudrate number can be preceded by a 'B', which is ignored. */ 242 if (*rate == 'B') 243 ++rate; 244 245 for (sp = speeds; sp->string; ++sp) 246 if (!strcasecmp(rate, sp->string)) 247 return (sp->speed); 248 speed = atol(rate); 249 if (speed == 0) 250 errx(1, "unknown baud rate %s", rate); 251 return speed; 252} 253