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