map.c revision 9888
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 * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
351590Srgrimesstatic char sccsid[] = "@(#)map.c	8.1 (Berkeley) 6/9/93";
361590Srgrimes#endif /* not lint */
371590Srgrimes
381590Srgrimes#include <sys/types.h>
391590Srgrimes#include <termios.h>
401590Srgrimes#include <errno.h>
411590Srgrimes#include <stdlib.h>
421590Srgrimes#include <string.h>
431590Srgrimes#include "extern.h"
441590Srgrimes
452599Sacheextern speed_t Ospeed;
462599Sachespeed_t	baudrate __P((char *));
471590Srgrimes
481590Srgrimes/* Baud rate conditionals for mapping. */
491590Srgrimes#define	GT		0x01
501590Srgrimes#define	EQ		0x02
511590Srgrimes#define	LT		0x04
521590Srgrimes#define	NOT		0x08
531590Srgrimes#define	GE		(GT | EQ)
541590Srgrimes#define	LE		(LT | EQ)
551590Srgrimes
561590Srgrimestypedef struct map {
571590Srgrimes	struct map *next;	/* Linked list of maps. */
581590Srgrimes	char *porttype;		/* Port type, or "" for any. */
591590Srgrimes	char *type;		/* Terminal type to select. */
601590Srgrimes	int conditional;	/* Baud rate conditionals bitmask. */
612599Sache	speed_t	speed;		/* Baud	rate to	compare	against. */
621590Srgrimes} MAP;
631590Srgrimes
641590SrgrimesMAP *cur, *maplist;
651590Srgrimes
661590Srgrimes/*
671590Srgrimes * Syntax for -m:
681590Srgrimes * [port-type][test baudrate]:terminal-type
691590Srgrimes * The baud rate tests are: >, <, @, =, !
701590Srgrimes */
711590Srgrimesvoid
721590Srgrimesadd_mapping(port, arg)
731590Srgrimes	char *port, *arg;
741590Srgrimes{
751590Srgrimes	MAP *mapp;
761590Srgrimes	char *copy, *p, *termp;
771590Srgrimes
781590Srgrimes	copy = strdup(arg);
791590Srgrimes	mapp = malloc((u_int)sizeof(MAP));
801590Srgrimes	if (copy == NULL || mapp == NULL)
811590Srgrimes		err("%s", strerror(errno));
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. */
1341590Srgrimes		arg = index(p = arg, ':');
1351590Srgrimes		if (arg == NULL)
1361590Srgrimes			goto badmopt;
1371590Srgrimes		*arg++ = '\0';
1381590Srgrimes		mapp->speed = baudrate(p);
1391590Srgrimes	}
1401590Srgrimes
1411590Srgrimes	if (*arg == NULL)			/* 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)
1571590Srgrimesbadmopt:		err("illegal -m option format: %s", copy);
1581590Srgrimes		mapp->porttype = 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 */
1851590Srgrimeschar *
1861590Srgrimesmapped(type)
1871590Srgrimes	char *type;
1881590Srgrimes{
1891590Srgrimes	MAP *mapp;
1901590Srgrimes	int match;
1911590Srgrimes
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 {
2221590Srgrimes	char	*string;
2232599Sache	speed_t	speed;
2241590Srgrimes} SPEEDS;
2251590Srgrimes
2261590SrgrimesSPEEDS speeds[] = {
2271590Srgrimes	"0",		B0,
2281590Srgrimes	"134.5",	B134,
2291590Srgrimes	"exta",		B19200,
2301590Srgrimes	"extb",		B38400,
2311590Srgrimes	NULL
2321590Srgrimes};
2331590Srgrimes
2342599Sachespeed_t
2351590Srgrimesbaudrate(rate)
2361590Srgrimes	char *rate;
2371590Srgrimes{
2381590Srgrimes	SPEEDS *sp;
2399888Sache	speed_t speed;
2401590Srgrimes
2411590Srgrimes	/* The baudrate number can be preceded by a 'B', which is ignored. */
2421590Srgrimes	if (*rate == 'B')
2431590Srgrimes		++rate;
2441590Srgrimes
2451590Srgrimes	for (sp = speeds; sp->string; ++sp)
2461590Srgrimes		if (!strcasecmp(rate, sp->string))
2471590Srgrimes			return (sp->speed);
2489888Sache	speed = atol(rate);
2499888Sache	if (speed == 0)
2509888Sache		err("unknown baud rate %s", rate);
2519888Sache	return speed;
2521590Srgrimes}
253