1 |
/* $MidnightBSD$ */ |
2 |
/*- |
3 |
* Copyright (c) 1991, 1993 |
4 |
* The Regents of the University of California. All rights reserved. |
5 |
* |
6 |
* Redistribution and use in source and binary forms, with or without |
7 |
* modification, are permitted provided that the following conditions |
8 |
* are met: |
9 |
* 1. Redistributions of source code must retain the above copyright |
10 |
* notice, this list of conditions and the following disclaimer. |
11 |
* 2. Redistributions in binary form must reproduce the above copyright |
12 |
* notice, this list of conditions and the following disclaimer in the |
13 |
* documentation and/or other materials provided with the distribution. |
14 |
* 4. Neither the name of the University nor the names of its contributors |
15 |
* may be used to endorse or promote products derived from this software |
16 |
* without specific prior written permission. |
17 |
* |
18 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
19 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
21 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
22 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
24 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 |
* SUCH DAMAGE. |
29 |
*/ |
30 |
|
31 |
#include <sys/cdefs.h> |
32 |
|
33 |
__FBSDID("$FreeBSD: stable/10/usr.bin/tset/map.c 241737 2012-10-19 14:49:42Z ed $"); |
34 |
|
35 |
#ifndef lint |
36 |
static const char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/9/93"; |
37 |
#endif |
38 |
|
39 |
#include <sys/types.h> |
40 |
|
41 |
#include <err.h> |
42 |
#include <stdlib.h> |
43 |
#include <string.h> |
44 |
#include <termios.h> |
45 |
|
46 |
#include "extern.h" |
47 |
|
48 |
static speed_t tset_baudrate(char *); |
49 |
|
50 |
/* Baud rate conditionals for mapping. */ |
51 |
#define GT 0x01 |
52 |
#define EQ 0x02 |
53 |
#define LT 0x04 |
54 |
#define NOT 0x08 |
55 |
#define GE (GT | EQ) |
56 |
#define LE (LT | EQ) |
57 |
|
58 |
typedef struct map { |
59 |
struct map *next; /* Linked list of maps. */ |
60 |
char *porttype; /* Port type, or "" for any. */ |
61 |
char *type; /* Terminal type to select. */ |
62 |
int conditional; /* Baud rate conditionals bitmask. */ |
63 |
speed_t speed; /* Baud rate to compare against. */ |
64 |
} MAP; |
65 |
|
66 |
static MAP *cur, *maplist; |
67 |
|
68 |
/* |
69 |
* Syntax for -m: |
70 |
* [port-type][test baudrate]:terminal-type |
71 |
* The baud rate tests are: >, <, @, =, ! |
72 |
*/ |
73 |
void |
74 |
add_mapping(const char *port, char *arg) |
75 |
{ |
76 |
MAP *mapp; |
77 |
char *copy, *p, *termp; |
78 |
|
79 |
copy = strdup(arg); |
80 |
mapp = malloc(sizeof(MAP)); |
81 |
if (copy == NULL || mapp == NULL) |
82 |
errx(1, "malloc"); |
83 |
mapp->next = NULL; |
84 |
if (maplist == NULL) |
85 |
cur = maplist = mapp; |
86 |
else { |
87 |
cur->next = mapp; |
88 |
cur = mapp; |
89 |
} |
90 |
|
91 |
mapp->porttype = arg; |
92 |
mapp->conditional = 0; |
93 |
|
94 |
arg = strpbrk(arg, "><@=!:"); |
95 |
|
96 |
if (arg == NULL) { /* [?]term */ |
97 |
mapp->type = mapp->porttype; |
98 |
mapp->porttype = NULL; |
99 |
goto done; |
100 |
} |
101 |
|
102 |
if (arg == mapp->porttype) /* [><@=! baud]:term */ |
103 |
termp = mapp->porttype = NULL; |
104 |
else |
105 |
termp = arg; |
106 |
|
107 |
for (;; ++arg) /* Optional conditionals. */ |
108 |
switch(*arg) { |
109 |
case '<': |
110 |
if (mapp->conditional & GT) |
111 |
goto badmopt; |
112 |
mapp->conditional |= LT; |
113 |
break; |
114 |
case '>': |
115 |
if (mapp->conditional & LT) |
116 |
goto badmopt; |
117 |
mapp->conditional |= GT; |
118 |
break; |
119 |
case '@': |
120 |
case '=': /* Not documented. */ |
121 |
mapp->conditional |= EQ; |
122 |
break; |
123 |
case '!': |
124 |
mapp->conditional |= NOT; |
125 |
break; |
126 |
default: |
127 |
goto next; |
128 |
} |
129 |
|
130 |
next: if (*arg == ':') { |
131 |
if (mapp->conditional) |
132 |
goto badmopt; |
133 |
++arg; |
134 |
} else { /* Optional baudrate. */ |
135 |
arg = strchr(p = arg, ':'); |
136 |
if (arg == NULL) |
137 |
goto badmopt; |
138 |
*arg++ = '\0'; |
139 |
mapp->speed = tset_baudrate(p); |
140 |
} |
141 |
|
142 |
if (*arg == '\0') /* Non-optional type. */ |
143 |
goto badmopt; |
144 |
|
145 |
mapp->type = arg; |
146 |
|
147 |
/* Terminate porttype, if specified. */ |
148 |
if (termp != NULL) |
149 |
*termp = '\0'; |
150 |
|
151 |
/* If a NOT conditional, reverse the test. */ |
152 |
if (mapp->conditional & NOT) |
153 |
mapp->conditional = ~mapp->conditional & (EQ | GT | LT); |
154 |
|
155 |
/* If user specified a port with an option flag, set it. */ |
156 |
done: if (port) { |
157 |
if (mapp->porttype) |
158 |
badmopt: errx(1, "illegal -m option format: %s", copy); |
159 |
mapp->porttype = strdup(port); |
160 |
} |
161 |
|
162 |
#ifdef MAPDEBUG |
163 |
(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); |
164 |
(void)printf("type: %s\n", mapp->type); |
165 |
(void)printf("conditional: "); |
166 |
p = ""; |
167 |
if (mapp->conditional & GT) { |
168 |
(void)printf("GT"); |
169 |
p = "/"; |
170 |
} |
171 |
if (mapp->conditional & EQ) { |
172 |
(void)printf("%sEQ", p); |
173 |
p = "/"; |
174 |
} |
175 |
if (mapp->conditional & LT) |
176 |
(void)printf("%sLT", p); |
177 |
(void)printf("\nspeed: %d\n", mapp->speed); |
178 |
#endif |
179 |
} |
180 |
|
181 |
/* |
182 |
* Return the type of terminal to use for a port of type 'type', as specified |
183 |
* by the first applicable mapping in 'map'. If no mappings apply, return |
184 |
* 'type'. |
185 |
*/ |
186 |
const char * |
187 |
mapped(const char *type) |
188 |
{ |
189 |
MAP *mapp; |
190 |
int match; |
191 |
|
192 |
match = 0; |
193 |
for (mapp = maplist; mapp; mapp = mapp->next) |
194 |
if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) { |
195 |
switch (mapp->conditional) { |
196 |
case 0: /* No test specified. */ |
197 |
match = 1; |
198 |
break; |
199 |
case EQ: |
200 |
match = (Ospeed == mapp->speed); |
201 |
break; |
202 |
case GE: |
203 |
match = (Ospeed >= mapp->speed); |
204 |
break; |
205 |
case GT: |
206 |
match = (Ospeed > mapp->speed); |
207 |
break; |
208 |
case LE: |
209 |
match = (Ospeed <= mapp->speed); |
210 |
break; |
211 |
case LT: |
212 |
match = (Ospeed < mapp->speed); |
213 |
break; |
214 |
} |
215 |
if (match) |
216 |
return (mapp->type); |
217 |
} |
218 |
/* No match found; return given type. */ |
219 |
return (type); |
220 |
} |
221 |
|
222 |
typedef struct speeds { |
223 |
const char *string; |
224 |
speed_t speed; |
225 |
} SPEEDS; |
226 |
|
227 |
static SPEEDS speeds[] = { |
228 |
{ "0", B0 }, |
229 |
{ "134.5", B134 }, |
230 |
{ "exta", B19200 }, |
231 |
{ "extb", B38400 }, |
232 |
{ NULL, 0 } |
233 |
}; |
234 |
|
235 |
static speed_t |
236 |
tset_baudrate(char *rate) |
237 |
{ |
238 |
SPEEDS *sp; |
239 |
speed_t speed; |
240 |
|
241 |
/* The baudrate number can be preceded by a 'B', which is ignored. */ |
242 |
if (*rate == 'B') |
243 |
++rate; |
244 |
|
245 |
for (sp = speeds; sp->string; ++sp) |
246 |
if (!strcasecmp(rate, sp->string)) |
247 |
return (sp->speed); |
248 |
speed = atol(rate); |
249 |
if (speed == 0) |
250 |
errx(1, "unknown baud rate %s", rate); |
251 |
return speed; |
252 |
} |