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