11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1991, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 3087701Smarkm#include <sys/cdefs.h> 3187701Smarkm 3287701Smarkm__FBSDID("$FreeBSD$"); 3387701Smarkm 341590Srgrimes#ifndef lint 3587701Smarkmstatic const char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/9/93"; 3628370Scharnier#endif 371590Srgrimes 381590Srgrimes#include <sys/types.h> 3987701Smarkm 4028370Scharnier#include <err.h> 411590Srgrimes#include <stdlib.h> 421590Srgrimes#include <string.h> 4328370Scharnier#include <termios.h> 4487701Smarkm 451590Srgrimes#include "extern.h" 461590Srgrimes 47241737Sedstatic speed_t tset_baudrate(char *); 481590Srgrimes 491590Srgrimes/* Baud rate conditionals for mapping. */ 501590Srgrimes#define GT 0x01 511590Srgrimes#define EQ 0x02 521590Srgrimes#define LT 0x04 531590Srgrimes#define NOT 0x08 541590Srgrimes#define GE (GT | EQ) 551590Srgrimes#define LE (LT | EQ) 561590Srgrimes 571590Srgrimestypedef struct map { 581590Srgrimes struct map *next; /* Linked list of maps. */ 591590Srgrimes char *porttype; /* Port type, or "" for any. */ 601590Srgrimes char *type; /* Terminal type to select. */ 611590Srgrimes int conditional; /* Baud rate conditionals bitmask. */ 622599Sache speed_t speed; /* Baud rate to compare against. */ 631590Srgrimes} MAP; 641590Srgrimes 65241737Sedstatic MAP *cur, *maplist; 661590Srgrimes 671590Srgrimes/* 681590Srgrimes * Syntax for -m: 691590Srgrimes * [port-type][test baudrate]:terminal-type 701590Srgrimes * The baud rate tests are: >, <, @, =, ! 711590Srgrimes */ 721590Srgrimesvoid 73200419Sdelphijadd_mapping(const char *port, char *arg) 741590Srgrimes{ 751590Srgrimes MAP *mapp; 761590Srgrimes char *copy, *p, *termp; 771590Srgrimes 781590Srgrimes copy = strdup(arg); 7996785Sjmallett mapp = malloc(sizeof(MAP)); 801590Srgrimes if (copy == NULL || mapp == NULL) 8128370Scharnier errx(1, "malloc"); 821590Srgrimes mapp->next = NULL; 831590Srgrimes if (maplist == NULL) 841590Srgrimes cur = maplist = mapp; 851590Srgrimes else { 861590Srgrimes cur->next = mapp; 871590Srgrimes cur = mapp; 881590Srgrimes } 891590Srgrimes 901590Srgrimes mapp->porttype = arg; 911590Srgrimes mapp->conditional = 0; 921590Srgrimes 931590Srgrimes arg = strpbrk(arg, "><@=!:"); 941590Srgrimes 951590Srgrimes if (arg == NULL) { /* [?]term */ 961590Srgrimes mapp->type = mapp->porttype; 971590Srgrimes mapp->porttype = NULL; 981590Srgrimes goto done; 991590Srgrimes } 1001590Srgrimes 1011590Srgrimes if (arg == mapp->porttype) /* [><@=! baud]:term */ 1021590Srgrimes termp = mapp->porttype = NULL; 1031590Srgrimes else 1041590Srgrimes termp = arg; 1051590Srgrimes 1061590Srgrimes for (;; ++arg) /* Optional conditionals. */ 1071590Srgrimes switch(*arg) { 1081590Srgrimes case '<': 1091590Srgrimes if (mapp->conditional & GT) 1101590Srgrimes goto badmopt; 1111590Srgrimes mapp->conditional |= LT; 1121590Srgrimes break; 1131590Srgrimes case '>': 1141590Srgrimes if (mapp->conditional & LT) 1151590Srgrimes goto badmopt; 1161590Srgrimes mapp->conditional |= GT; 1171590Srgrimes break; 1181590Srgrimes case '@': 1191590Srgrimes case '=': /* Not documented. */ 1201590Srgrimes mapp->conditional |= EQ; 1211590Srgrimes break; 1221590Srgrimes case '!': 1231590Srgrimes mapp->conditional |= NOT; 1241590Srgrimes break; 1251590Srgrimes default: 1261590Srgrimes goto next; 1271590Srgrimes } 1281590Srgrimes 1291590Srgrimesnext: if (*arg == ':') { 1301590Srgrimes if (mapp->conditional) 1311590Srgrimes goto badmopt; 1321590Srgrimes ++arg; 1331590Srgrimes } else { /* Optional baudrate. */ 134229403Sed arg = strchr(p = arg, ':'); 1351590Srgrimes if (arg == NULL) 1361590Srgrimes goto badmopt; 1371590Srgrimes *arg++ = '\0'; 13850638Speter mapp->speed = tset_baudrate(p); 1391590Srgrimes } 1401590Srgrimes 14129574Sphk if (*arg == '\0') /* Non-optional type. */ 1421590Srgrimes goto badmopt; 1431590Srgrimes 1441590Srgrimes mapp->type = arg; 1451590Srgrimes 1461590Srgrimes /* Terminate porttype, if specified. */ 1471590Srgrimes if (termp != NULL) 1481590Srgrimes *termp = '\0'; 1491590Srgrimes 1501590Srgrimes /* If a NOT conditional, reverse the test. */ 1511590Srgrimes if (mapp->conditional & NOT) 1521590Srgrimes mapp->conditional = ~mapp->conditional & (EQ | GT | LT); 1531590Srgrimes 1541590Srgrimes /* If user specified a port with an option flag, set it. */ 1551590Srgrimesdone: if (port) { 1561590Srgrimes if (mapp->porttype) 15728370Scharnierbadmopt: errx(1, "illegal -m option format: %s", copy); 15887701Smarkm mapp->porttype = strdup(port); 1591590Srgrimes } 1601590Srgrimes 1611590Srgrimes#ifdef MAPDEBUG 1621590Srgrimes (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); 1631590Srgrimes (void)printf("type: %s\n", mapp->type); 1641590Srgrimes (void)printf("conditional: "); 1651590Srgrimes p = ""; 1661590Srgrimes if (mapp->conditional & GT) { 1671590Srgrimes (void)printf("GT"); 1681590Srgrimes p = "/"; 1691590Srgrimes } 1701590Srgrimes if (mapp->conditional & EQ) { 1711590Srgrimes (void)printf("%sEQ", p); 1721590Srgrimes p = "/"; 1731590Srgrimes } 1741590Srgrimes if (mapp->conditional & LT) 1751590Srgrimes (void)printf("%sLT", p); 1761590Srgrimes (void)printf("\nspeed: %d\n", mapp->speed); 1771590Srgrimes#endif 1781590Srgrimes} 1791590Srgrimes 1801590Srgrimes/* 1811590Srgrimes * Return the type of terminal to use for a port of type 'type', as specified 1821590Srgrimes * by the first applicable mapping in 'map'. If no mappings apply, return 1831590Srgrimes * 'type'. 1841590Srgrimes */ 18587701Smarkmconst char * 186200419Sdelphijmapped(const char *type) 1871590Srgrimes{ 1881590Srgrimes MAP *mapp; 1891590Srgrimes int match; 1901590Srgrimes 191146752Scharnier match = 0; 1921590Srgrimes for (mapp = maplist; mapp; mapp = mapp->next) 1931590Srgrimes if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) { 1941590Srgrimes switch (mapp->conditional) { 1951590Srgrimes case 0: /* No test specified. */ 1961590Srgrimes match = 1; 1971590Srgrimes break; 1981590Srgrimes case EQ: 1992599Sache match = (Ospeed == mapp->speed); 2001590Srgrimes break; 2011590Srgrimes case GE: 2022599Sache match = (Ospeed >= mapp->speed); 2031590Srgrimes break; 2041590Srgrimes case GT: 2052599Sache match = (Ospeed > mapp->speed); 2061590Srgrimes break; 2071590Srgrimes case LE: 2082599Sache match = (Ospeed <= mapp->speed); 2091590Srgrimes break; 2101590Srgrimes case LT: 2112599Sache match = (Ospeed < mapp->speed); 2121590Srgrimes break; 2131590Srgrimes } 2141590Srgrimes if (match) 2151590Srgrimes return (mapp->type); 2161590Srgrimes } 2171590Srgrimes /* No match found; return given type. */ 2181590Srgrimes return (type); 2191590Srgrimes} 2201590Srgrimes 2211590Srgrimestypedef struct speeds { 22287701Smarkm const char *string; 2232599Sache speed_t speed; 2241590Srgrimes} SPEEDS; 2251590Srgrimes 226241737Sedstatic SPEEDS speeds[] = { 22787701Smarkm { "0", B0 }, 22887701Smarkm { "134.5", B134 }, 22987701Smarkm { "exta", B19200 }, 23087701Smarkm { "extb", B38400 }, 23187701Smarkm { NULL, 0 } 2321590Srgrimes}; 2331590Srgrimes 234241737Sedstatic speed_t 235200419Sdelphijtset_baudrate(char *rate) 2361590Srgrimes{ 2371590Srgrimes SPEEDS *sp; 2389888Sache speed_t speed; 2391590Srgrimes 2401590Srgrimes /* The baudrate number can be preceded by a 'B', which is ignored. */ 2411590Srgrimes if (*rate == 'B') 2421590Srgrimes ++rate; 2431590Srgrimes 2441590Srgrimes for (sp = speeds; sp->string; ++sp) 2451590Srgrimes if (!strcasecmp(rate, sp->string)) 2461590Srgrimes return (sp->speed); 2479888Sache speed = atol(rate); 2489888Sache if (speed == 0) 24928370Scharnier errx(1, "unknown baud rate %s", rate); 2509888Sache return speed; 2511590Srgrimes} 252