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