map.c revision 200419
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 200419 2009-12-11 23:30:22Z delphij $");
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(const char *port, char *arg)
79{
80	MAP *mapp;
81	char *copy, *p, *termp;
82
83	copy = strdup(arg);
84	mapp = malloc(sizeof(MAP));
85	if (copy == NULL || mapp == NULL)
86		errx(1, "malloc");
87	mapp->next = NULL;
88	if (maplist == NULL)
89		cur = maplist = mapp;
90	else {
91		cur->next = mapp;
92		cur =  mapp;
93	}
94
95	mapp->porttype = arg;
96	mapp->conditional = 0;
97
98	arg = strpbrk(arg, "><@=!:");
99
100	if (arg == NULL) {			/* [?]term */
101		mapp->type = mapp->porttype;
102		mapp->porttype = NULL;
103		goto done;
104	}
105
106	if (arg == mapp->porttype)		/* [><@=! baud]:term */
107		termp = mapp->porttype = NULL;
108	else
109		termp = arg;
110
111	for (;; ++arg)				/* Optional conditionals. */
112		switch(*arg) {
113		case '<':
114			if (mapp->conditional & GT)
115				goto badmopt;
116			mapp->conditional |= LT;
117			break;
118		case '>':
119			if (mapp->conditional & LT)
120				goto badmopt;
121			mapp->conditional |= GT;
122			break;
123		case '@':
124		case '=':			/* Not documented. */
125			mapp->conditional |= EQ;
126			break;
127		case '!':
128			mapp->conditional |= NOT;
129			break;
130		default:
131			goto next;
132		}
133
134next:	if (*arg == ':') {
135		if (mapp->conditional)
136			goto badmopt;
137		++arg;
138	} else {				/* Optional baudrate. */
139		arg = index(p = arg, ':');
140		if (arg == NULL)
141			goto badmopt;
142		*arg++ = '\0';
143		mapp->speed = tset_baudrate(p);
144	}
145
146	if (*arg == '\0')			/* Non-optional type. */
147		goto badmopt;
148
149	mapp->type = arg;
150
151	/* Terminate porttype, if specified. */
152	if (termp != NULL)
153		*termp = '\0';
154
155	/* If a NOT conditional, reverse the test. */
156	if (mapp->conditional & NOT)
157		mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
158
159	/* If user specified a port with an option flag, set it. */
160done:	if (port) {
161		if (mapp->porttype)
162badmopt:		errx(1, "illegal -m option format: %s", copy);
163		mapp->porttype = strdup(port);
164	}
165
166#ifdef MAPDEBUG
167	(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
168	(void)printf("type: %s\n", mapp->type);
169	(void)printf("conditional: ");
170	p = "";
171	if (mapp->conditional & GT) {
172		(void)printf("GT");
173		p = "/";
174	}
175	if (mapp->conditional & EQ) {
176		(void)printf("%sEQ", p);
177		p = "/";
178	}
179	if (mapp->conditional & LT)
180		(void)printf("%sLT", p);
181	(void)printf("\nspeed: %d\n", mapp->speed);
182#endif
183}
184
185/*
186 * Return the type of terminal to use for a port of type 'type', as specified
187 * by the first applicable mapping in 'map'.  If no mappings apply, return
188 * 'type'.
189 */
190const char *
191mapped(const char *type)
192{
193	MAP *mapp;
194	int match;
195
196	match = 0;
197	for (mapp = maplist; mapp; mapp = mapp->next)
198		if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) {
199			switch (mapp->conditional) {
200			case 0:			/* No test specified. */
201				match = 1;
202				break;
203			case EQ:
204				match =	(Ospeed	== mapp->speed);
205				break;
206			case GE:
207				match =	(Ospeed	>= mapp->speed);
208				break;
209			case GT:
210				match =	(Ospeed	> mapp->speed);
211				break;
212			case LE:
213				match =	(Ospeed	<= mapp->speed);
214				break;
215			case LT:
216				match =	(Ospeed	< mapp->speed);
217				break;
218			}
219			if (match)
220				return (mapp->type);
221		}
222	/* No match found; return given type. */
223	return (type);
224}
225
226typedef struct speeds {
227	const char	*string;
228	speed_t	speed;
229} SPEEDS;
230
231SPEEDS speeds[] = {
232	{ "0",		B0 },
233	{ "134.5",	B134 },
234	{ "exta",	B19200 },
235	{ "extb",	B38400 },
236	{ NULL, 0 }
237};
238
239speed_t
240tset_baudrate(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