map.c revision 1591
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
35static char sccsid[] = "@(#)map.c	8.1 (Berkeley) 6/9/93";
36#endif /* not lint */
37
38#include <sys/types.h>
39#include <termios.h>
40#include <errno.h>
41#include <stdlib.h>
42#include <string.h>
43#include "extern.h"
44
45int	baudrate __P((char *));
46
47/* Baud rate conditionals for mapping. */
48#define	GT		0x01
49#define	EQ		0x02
50#define	LT		0x04
51#define	NOT		0x08
52#define	GE		(GT | EQ)
53#define	LE		(LT | EQ)
54
55typedef struct map {
56	struct map *next;	/* Linked list of maps. */
57	char *porttype;		/* Port type, or "" for any. */
58	char *type;		/* Terminal type to select. */
59	int conditional;	/* Baud rate conditionals bitmask. */
60	int speed;		/* Baud rate to compare against. */
61} MAP;
62
63MAP *cur, *maplist;
64
65/*
66 * Syntax for -m:
67 * [port-type][test baudrate]:terminal-type
68 * The baud rate tests are: >, <, @, =, !
69 */
70void
71add_mapping(port, arg)
72	char *port, *arg;
73{
74	MAP *mapp;
75	char *copy, *p, *termp;
76
77	copy = strdup(arg);
78	mapp = malloc((u_int)sizeof(MAP));
79	if (copy == NULL || mapp == NULL)
80		err("%s", strerror(errno));
81	mapp->next = NULL;
82	if (maplist == NULL)
83		cur = maplist = mapp;
84	else {
85		cur->next = mapp;
86		cur =  mapp;
87	}
88
89	mapp->porttype = arg;
90	mapp->conditional = 0;
91
92	arg = strpbrk(arg, "><@=!:");
93
94	if (arg == NULL) {			/* [?]term */
95		mapp->type = mapp->porttype;
96		mapp->porttype = NULL;
97		goto done;
98	}
99
100	if (arg == mapp->porttype)		/* [><@=! baud]:term */
101		termp = mapp->porttype = NULL;
102	else
103		termp = arg;
104
105	for (;; ++arg)				/* Optional conditionals. */
106		switch(*arg) {
107		case '<':
108			if (mapp->conditional & GT)
109				goto badmopt;
110			mapp->conditional |= LT;
111			break;
112		case '>':
113			if (mapp->conditional & LT)
114				goto badmopt;
115			mapp->conditional |= GT;
116			break;
117		case '@':
118		case '=':			/* Not documented. */
119			mapp->conditional |= EQ;
120			break;
121		case '!':
122			mapp->conditional |= NOT;
123			break;
124		default:
125			goto next;
126		}
127
128next:	if (*arg == ':') {
129		if (mapp->conditional)
130			goto badmopt;
131		++arg;
132	} else {				/* Optional baudrate. */
133		arg = index(p = arg, ':');
134		if (arg == NULL)
135			goto badmopt;
136		*arg++ = '\0';
137		mapp->speed = baudrate(p);
138	}
139
140	if (*arg == NULL)			/* Non-optional type. */
141		goto badmopt;
142
143	mapp->type = arg;
144
145	/* Terminate porttype, if specified. */
146	if (termp != NULL)
147		*termp = '\0';
148
149	/* If a NOT conditional, reverse the test. */
150	if (mapp->conditional & NOT)
151		mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
152
153	/* If user specified a port with an option flag, set it. */
154done:	if (port) {
155		if (mapp->porttype)
156badmopt:		err("illegal -m option format: %s", copy);
157		mapp->porttype = port;
158	}
159
160#ifdef MAPDEBUG
161	(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
162	(void)printf("type: %s\n", mapp->type);
163	(void)printf("conditional: ");
164	p = "";
165	if (mapp->conditional & GT) {
166		(void)printf("GT");
167		p = "/";
168	}
169	if (mapp->conditional & EQ) {
170		(void)printf("%sEQ", p);
171		p = "/";
172	}
173	if (mapp->conditional & LT)
174		(void)printf("%sLT", p);
175	(void)printf("\nspeed: %d\n", mapp->speed);
176#endif
177}
178
179/*
180 * Return the type of terminal to use for a port of type 'type', as specified
181 * by the first applicable mapping in 'map'.  If no mappings apply, return
182 * 'type'.
183 */
184char *
185mapped(type)
186	char *type;
187{
188	MAP *mapp;
189	int match;
190
191	for (mapp = maplist; mapp; mapp = mapp->next)
192		if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) {
193			switch (mapp->conditional) {
194			case 0:			/* No test specified. */
195				match = 1;
196				break;
197			case EQ:
198				match = (ospeed == mapp->speed);
199				break;
200			case GE:
201				match = (ospeed >= mapp->speed);
202				break;
203			case GT:
204				match = (ospeed > mapp->speed);
205				break;
206			case LE:
207				match = (ospeed <= mapp->speed);
208				break;
209			case LT:
210				match = (ospeed < mapp->speed);
211				break;
212			}
213			if (match)
214				return (mapp->type);
215		}
216	/* No match found; return given type. */
217	return (type);
218}
219
220typedef struct speeds {
221	char	*string;
222	int	speed;
223} SPEEDS;
224
225SPEEDS speeds[] = {
226	"0",		B0,
227	"50",		B50,
228	"75",		B75,
229	"110",		B110,
230	"134",		B134,
231	"134.5",	B134,
232	"150",		B150,
233	"200",		B200,
234	"300",		B300,
235	"600",		B600,
236	"1200",		B1200,
237	"1800",		B1800,
238	"2400",		B2400,
239	"4800",		B4800,
240	"9600",		B9600,
241	"19200",	B19200,
242	"38400",	B38400,
243	"exta",		B19200,
244	"extb",		B38400,
245	NULL
246};
247
248int
249baudrate(rate)
250	char *rate;
251{
252	SPEEDS *sp;
253
254	/* The baudrate number can be preceded by a 'B', which is ignored. */
255	if (*rate == 'B')
256		++rate;
257
258	for (sp = speeds; sp->string; ++sp)
259		if (!strcasecmp(rate, sp->string))
260			return (sp->speed);
261	err("unknown baud rate %s", rate);
262	/* NOTREACHED */
263}
264