freebsd-nq/usr.bin/tset/map.c
Juli Mallett 47bca8b02c Clean up malloc(3)'s argument. Remove casts which do nothing when we're
using sizeof() anyway.  Use slightly more consistent (per-file) error
reporting for malloc(3) returning NULL.  If "malloc failed" was being printed,
don't use err(3).  If a NULL format is being used, use err(3).  In one case
errx(3) was being used with strerror(3), so just use err(3).
2002-05-17 05:11:07 +00:00

260 lines
6.2 KiB
C

/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifndef lint
static const char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/9/93";
#endif
#include <sys/types.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include "extern.h"
extern speed_t Ospeed;
speed_t tset_baudrate(char *);
/* Baud rate conditionals for mapping. */
#define GT 0x01
#define EQ 0x02
#define LT 0x04
#define NOT 0x08
#define GE (GT | EQ)
#define LE (LT | EQ)
typedef struct map {
struct map *next; /* Linked list of maps. */
char *porttype; /* Port type, or "" for any. */
char *type; /* Terminal type to select. */
int conditional; /* Baud rate conditionals bitmask. */
speed_t speed; /* Baud rate to compare against. */
} MAP;
MAP *cur, *maplist;
/*
* Syntax for -m:
* [port-type][test baudrate]:terminal-type
* The baud rate tests are: >, <, @, =, !
*/
void
add_mapping(port, arg)
const char *port;
char *arg;
{
MAP *mapp;
char *copy, *p, *termp;
copy = strdup(arg);
mapp = malloc(sizeof(MAP));
if (copy == NULL || mapp == NULL)
errx(1, "malloc");
mapp->next = NULL;
if (maplist == NULL)
cur = maplist = mapp;
else {
cur->next = mapp;
cur = mapp;
}
mapp->porttype = arg;
mapp->conditional = 0;
arg = strpbrk(arg, "><@=!:");
if (arg == NULL) { /* [?]term */
mapp->type = mapp->porttype;
mapp->porttype = NULL;
goto done;
}
if (arg == mapp->porttype) /* [><@=! baud]:term */
termp = mapp->porttype = NULL;
else
termp = arg;
for (;; ++arg) /* Optional conditionals. */
switch(*arg) {
case '<':
if (mapp->conditional & GT)
goto badmopt;
mapp->conditional |= LT;
break;
case '>':
if (mapp->conditional & LT)
goto badmopt;
mapp->conditional |= GT;
break;
case '@':
case '=': /* Not documented. */
mapp->conditional |= EQ;
break;
case '!':
mapp->conditional |= NOT;
break;
default:
goto next;
}
next: if (*arg == ':') {
if (mapp->conditional)
goto badmopt;
++arg;
} else { /* Optional baudrate. */
arg = index(p = arg, ':');
if (arg == NULL)
goto badmopt;
*arg++ = '\0';
mapp->speed = tset_baudrate(p);
}
if (*arg == '\0') /* Non-optional type. */
goto badmopt;
mapp->type = arg;
/* Terminate porttype, if specified. */
if (termp != NULL)
*termp = '\0';
/* If a NOT conditional, reverse the test. */
if (mapp->conditional & NOT)
mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
/* If user specified a port with an option flag, set it. */
done: if (port) {
if (mapp->porttype)
badmopt: errx(1, "illegal -m option format: %s", copy);
mapp->porttype = strdup(port);
}
#ifdef MAPDEBUG
(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
(void)printf("type: %s\n", mapp->type);
(void)printf("conditional: ");
p = "";
if (mapp->conditional & GT) {
(void)printf("GT");
p = "/";
}
if (mapp->conditional & EQ) {
(void)printf("%sEQ", p);
p = "/";
}
if (mapp->conditional & LT)
(void)printf("%sLT", p);
(void)printf("\nspeed: %d\n", mapp->speed);
#endif
}
/*
* Return the type of terminal to use for a port of type 'type', as specified
* by the first applicable mapping in 'map'. If no mappings apply, return
* 'type'.
*/
const char *
mapped(type)
const char *type;
{
MAP *mapp;
int match;
for (mapp = maplist; mapp; mapp = mapp->next)
if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) {
switch (mapp->conditional) {
case 0: /* No test specified. */
match = 1;
break;
case EQ:
match = (Ospeed == mapp->speed);
break;
case GE:
match = (Ospeed >= mapp->speed);
break;
case GT:
match = (Ospeed > mapp->speed);
break;
case LE:
match = (Ospeed <= mapp->speed);
break;
case LT:
match = (Ospeed < mapp->speed);
break;
}
if (match)
return (mapp->type);
}
/* No match found; return given type. */
return (type);
}
typedef struct speeds {
const char *string;
speed_t speed;
} SPEEDS;
SPEEDS speeds[] = {
{ "0", B0 },
{ "134.5", B134 },
{ "exta", B19200 },
{ "extb", B38400 },
{ NULL, 0 }
};
speed_t
tset_baudrate(rate)
char *rate;
{
SPEEDS *sp;
speed_t speed;
/* The baudrate number can be preceded by a 'B', which is ignored. */
if (*rate == 'B')
++rate;
for (sp = speeds; sp->string; ++sp)
if (!strcasecmp(rate, sp->string))
return (sp->speed);
speed = atol(rate);
if (speed == 0)
errx(1, "unknown baud rate %s", rate);
return speed;
}