xref: /386bsd/usr/src/usr.bin/tset/map.c (revision a2142627)
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[] = "@(#)map.c	5.2 (Berkeley) 12/24/91";
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 
45 int	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 
55 typedef 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 
63 MAP *cur, *maplist;
64 
65 /*
66  * Syntax for -m:
67  * [port-type][test baudrate]:terminal-type
68  * The baud rate tests are: >, <, @, =, !
69  */
70 void
add_mapping(port,arg)71 add_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 
128 next:	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. */
154 done:	if (port) {
155 		if (mapp->porttype)
156 badmopt:		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  */
184 char *
mapped(type)185 mapped(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 
220 typedef struct speeds {
221 	char	*string;
222 	int	speed;
223 } SPEEDS;
224 
225 SPEEDS 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 
248 int
baudrate(rate)249 baudrate(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