map.c revision 146752
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
3487701Smarkm#include <sys/cdefs.h>
3587701Smarkm
3687701Smarkm__FBSDID("$FreeBSD: head/usr.bin/tset/map.c 146752 2005-05-29 15:49:53Z charnier $");
3787701Smarkm
381590Srgrimes#ifndef lint
3987701Smarkmstatic const char sccsid[] = "@(#)map.c	8.1 (Berkeley) 6/9/93";
4028370Scharnier#endif
411590Srgrimes
421590Srgrimes#include <sys/types.h>
4387701Smarkm
4428370Scharnier#include <err.h>
451590Srgrimes#include <stdlib.h>
461590Srgrimes#include <string.h>
4728370Scharnier#include <termios.h>
4887701Smarkm
491590Srgrimes#include "extern.h"
501590Srgrimes
512599Sacheextern speed_t Ospeed;
5292922Simpspeed_t	tset_baudrate(char *);
531590Srgrimes
541590Srgrimes/* Baud rate conditionals for mapping. */
551590Srgrimes#define	GT		0x01
561590Srgrimes#define	EQ		0x02
571590Srgrimes#define	LT		0x04
581590Srgrimes#define	NOT		0x08
591590Srgrimes#define	GE		(GT | EQ)
601590Srgrimes#define	LE		(LT | EQ)
611590Srgrimes
621590Srgrimestypedef struct map {
631590Srgrimes	struct map *next;	/* Linked list of maps. */
641590Srgrimes	char *porttype;		/* Port type, or "" for any. */
651590Srgrimes	char *type;		/* Terminal type to select. */
661590Srgrimes	int conditional;	/* Baud rate conditionals bitmask. */
672599Sache	speed_t	speed;		/* Baud	rate to	compare	against. */
681590Srgrimes} MAP;
691590Srgrimes
701590SrgrimesMAP *cur, *maplist;
711590Srgrimes
721590Srgrimes/*
731590Srgrimes * Syntax for -m:
741590Srgrimes * [port-type][test baudrate]:terminal-type
751590Srgrimes * The baud rate tests are: >, <, @, =, !
761590Srgrimes */
771590Srgrimesvoid
781590Srgrimesadd_mapping(port, arg)
7987701Smarkm	const char *port;
8087701Smarkm	char *arg;
811590Srgrimes{
821590Srgrimes	MAP *mapp;
831590Srgrimes	char *copy, *p, *termp;
841590Srgrimes
851590Srgrimes	copy = strdup(arg);
8696785Sjmallett	mapp = malloc(sizeof(MAP));
871590Srgrimes	if (copy == NULL || mapp == NULL)
8828370Scharnier		errx(1, "malloc");
891590Srgrimes	mapp->next = NULL;
901590Srgrimes	if (maplist == NULL)
911590Srgrimes		cur = maplist = mapp;
921590Srgrimes	else {
931590Srgrimes		cur->next = mapp;
941590Srgrimes		cur =  mapp;
951590Srgrimes	}
961590Srgrimes
971590Srgrimes	mapp->porttype = arg;
981590Srgrimes	mapp->conditional = 0;
991590Srgrimes
1001590Srgrimes	arg = strpbrk(arg, "><@=!:");
1011590Srgrimes
1021590Srgrimes	if (arg == NULL) {			/* [?]term */
1031590Srgrimes		mapp->type = mapp->porttype;
1041590Srgrimes		mapp->porttype = NULL;
1051590Srgrimes		goto done;
1061590Srgrimes	}
1071590Srgrimes
1081590Srgrimes	if (arg == mapp->porttype)		/* [><@=! baud]:term */
1091590Srgrimes		termp = mapp->porttype = NULL;
1101590Srgrimes	else
1111590Srgrimes		termp = arg;
1121590Srgrimes
1131590Srgrimes	for (;; ++arg)				/* Optional conditionals. */
1141590Srgrimes		switch(*arg) {
1151590Srgrimes		case '<':
1161590Srgrimes			if (mapp->conditional & GT)
1171590Srgrimes				goto badmopt;
1181590Srgrimes			mapp->conditional |= LT;
1191590Srgrimes			break;
1201590Srgrimes		case '>':
1211590Srgrimes			if (mapp->conditional & LT)
1221590Srgrimes				goto badmopt;
1231590Srgrimes			mapp->conditional |= GT;
1241590Srgrimes			break;
1251590Srgrimes		case '@':
1261590Srgrimes		case '=':			/* Not documented. */
1271590Srgrimes			mapp->conditional |= EQ;
1281590Srgrimes			break;
1291590Srgrimes		case '!':
1301590Srgrimes			mapp->conditional |= NOT;
1311590Srgrimes			break;
1321590Srgrimes		default:
1331590Srgrimes			goto next;
1341590Srgrimes		}
1351590Srgrimes
1361590Srgrimesnext:	if (*arg == ':') {
1371590Srgrimes		if (mapp->conditional)
1381590Srgrimes			goto badmopt;
1391590Srgrimes		++arg;
1401590Srgrimes	} else {				/* Optional baudrate. */
1411590Srgrimes		arg = index(p = arg, ':');
1421590Srgrimes		if (arg == NULL)
1431590Srgrimes			goto badmopt;
1441590Srgrimes		*arg++ = '\0';
14550638Speter		mapp->speed = tset_baudrate(p);
1461590Srgrimes	}
1471590Srgrimes
14829574Sphk	if (*arg == '\0')			/* Non-optional type. */
1491590Srgrimes		goto badmopt;
1501590Srgrimes
1511590Srgrimes	mapp->type = arg;
1521590Srgrimes
1531590Srgrimes	/* Terminate porttype, if specified. */
1541590Srgrimes	if (termp != NULL)
1551590Srgrimes		*termp = '\0';
1561590Srgrimes
1571590Srgrimes	/* If a NOT conditional, reverse the test. */
1581590Srgrimes	if (mapp->conditional & NOT)
1591590Srgrimes		mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
1601590Srgrimes
1611590Srgrimes	/* If user specified a port with an option flag, set it. */
1621590Srgrimesdone:	if (port) {
1631590Srgrimes		if (mapp->porttype)
16428370Scharnierbadmopt:		errx(1, "illegal -m option format: %s", copy);
16587701Smarkm		mapp->porttype = strdup(port);
1661590Srgrimes	}
1671590Srgrimes
1681590Srgrimes#ifdef MAPDEBUG
1691590Srgrimes	(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
1701590Srgrimes	(void)printf("type: %s\n", mapp->type);
1711590Srgrimes	(void)printf("conditional: ");
1721590Srgrimes	p = "";
1731590Srgrimes	if (mapp->conditional & GT) {
1741590Srgrimes		(void)printf("GT");
1751590Srgrimes		p = "/";
1761590Srgrimes	}
1771590Srgrimes	if (mapp->conditional & EQ) {
1781590Srgrimes		(void)printf("%sEQ", p);
1791590Srgrimes		p = "/";
1801590Srgrimes	}
1811590Srgrimes	if (mapp->conditional & LT)
1821590Srgrimes		(void)printf("%sLT", p);
1831590Srgrimes	(void)printf("\nspeed: %d\n", mapp->speed);
1841590Srgrimes#endif
1851590Srgrimes}
1861590Srgrimes
1871590Srgrimes/*
1881590Srgrimes * Return the type of terminal to use for a port of type 'type', as specified
1891590Srgrimes * by the first applicable mapping in 'map'.  If no mappings apply, return
1901590Srgrimes * 'type'.
1911590Srgrimes */
19287701Smarkmconst char *
1931590Srgrimesmapped(type)
19487701Smarkm	const char *type;
1951590Srgrimes{
1961590Srgrimes	MAP *mapp;
1971590Srgrimes	int match;
1981590Srgrimes
199146752Scharnier	match = 0;
2001590Srgrimes	for (mapp = maplist; mapp; mapp = mapp->next)
2011590Srgrimes		if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) {
2021590Srgrimes			switch (mapp->conditional) {
2031590Srgrimes			case 0:			/* No test specified. */
2041590Srgrimes				match = 1;
2051590Srgrimes				break;
2061590Srgrimes			case EQ:
2072599Sache				match =	(Ospeed	== mapp->speed);
2081590Srgrimes				break;
2091590Srgrimes			case GE:
2102599Sache				match =	(Ospeed	>= mapp->speed);
2111590Srgrimes				break;
2121590Srgrimes			case GT:
2132599Sache				match =	(Ospeed	> mapp->speed);
2141590Srgrimes				break;
2151590Srgrimes			case LE:
2162599Sache				match =	(Ospeed	<= mapp->speed);
2171590Srgrimes				break;
2181590Srgrimes			case LT:
2192599Sache				match =	(Ospeed	< mapp->speed);
2201590Srgrimes				break;
2211590Srgrimes			}
2221590Srgrimes			if (match)
2231590Srgrimes				return (mapp->type);
2241590Srgrimes		}
2251590Srgrimes	/* No match found; return given type. */
2261590Srgrimes	return (type);
2271590Srgrimes}
2281590Srgrimes
2291590Srgrimestypedef struct speeds {
23087701Smarkm	const char	*string;
2312599Sache	speed_t	speed;
2321590Srgrimes} SPEEDS;
2331590Srgrimes
2341590SrgrimesSPEEDS speeds[] = {
23587701Smarkm	{ "0",		B0 },
23687701Smarkm	{ "134.5",	B134 },
23787701Smarkm	{ "exta",	B19200 },
23887701Smarkm	{ "extb",	B38400 },
23987701Smarkm	{ NULL, 0 }
2401590Srgrimes};
2411590Srgrimes
2422599Sachespeed_t
24350638Spetertset_baudrate(rate)
2441590Srgrimes	char *rate;
2451590Srgrimes{
2461590Srgrimes	SPEEDS *sp;
2479888Sache	speed_t speed;
2481590Srgrimes
2491590Srgrimes	/* The baudrate number can be preceded by a 'B', which is ignored. */
2501590Srgrimes	if (*rate == 'B')
2511590Srgrimes		++rate;
2521590Srgrimes
2531590Srgrimes	for (sp = speeds; sp->string; ++sp)
2541590Srgrimes		if (!strcasecmp(rate, sp->string))
2551590Srgrimes			return (sp->speed);
2569888Sache	speed = atol(rate);
2579888Sache	if (speed == 0)
25828370Scharnier		errx(1, "unknown baud rate %s", rate);
2599888Sache	return speed;
2601590Srgrimes}
261