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