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