1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
/* David Leonard, 2002. Public domain. */
/* $Id: abbrev.c 1207 2012-03-04 14:22:05Z d $ */
/*
* Abbreviations are a way of collapsing similar packet
* activity into single lines. A file of 'abbreviation patterns'
* is read into the linked list of patterns, and every
* generated tag is matched and translated accordingly.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#if STDC_HEADERS
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
#endif
#include "abbrev.h"
#include "compat.h"
#define iswhite(c) ((c) == ' ' || (c) == '\t')
struct pattern {
char *name;
char *pattern; /* pointer into name */
};
static int npatterns;
static int allocpatterns;
static struct pattern *patterns;
static int abbrev_match(const char *, const char *);
/*
* Match an abbreviation pattern with a tag string.
* Return 1 if they match.
*/
static int
abbrev_match(tag, pattern)
const char *tag, *pattern;
{
while (*pattern) {
/* '*' matches zero or more non-space characters */
if (*pattern == '*') {
if (*tag && !iswhite(*tag))
/* Try a greedy match first */
if (abbrev_match(tag + 1, pattern))
return 1;
/* matched zero tag characters; carry on */
pattern++;
}
/* one or more spaces matches one or more spaces */
else if (iswhite(*pattern)) {
if (!iswhite(*tag))
return 0;
while (iswhite(*tag))
tag++;
while (iswhite(*pattern))
pattern++;
}
/* other characters match themselves */
else if (*pattern == *tag) {
pattern++;
tag++;
}
/* anything else is a fail*/
else
return 0;
}
return *tag == '\0';
}
/*
* Search through the abbreviation patterns, returning the first pattern
* that matches the tag; otherwise return the original tag.
*/
const char *
abbrev_tag(tag)
const char *tag;
{
int i;
if (tag)
for (i = 0; i < npatterns; i++)
if (abbrev_match(tag, patterns[i].pattern))
return patterns[i].name;
return tag;
}
/* Add an abbreviation pattern to the list of known patterns */
void
abbrev_add(abbrev)
const char *abbrev;
{
char *name, *pattern, *p;
while (npatterns >= allocpatterns) {
if (allocpatterns > 0)
patterns = (struct pattern *)realloc(patterns,
sizeof *patterns * (allocpatterns *= 2));
else
patterns = (struct pattern *)malloc(sizeof *patterns *
(allocpatterns = 16));
if (patterns == NULL)
errx(1, "malloc/realloc");
}
name = pattern = strdup(abbrev);
/* Check for "name @ pattern" */
for (p = pattern; *p; p++)
if (*p == '@') {
char *atsign = p;
/* skip trailing space of name */
while (p > pattern && (*(p-1) == ' ' || *(p-1) == '\t'))
p--;
*p = '\0';
/* skip leading space of new pattern */
for (p = atsign + 1; *p; p++)
if (*p != ' ' && *p != '\t')
break;
pattern = p;
break;
}
patterns[npatterns].name = name;
patterns[npatterns].pattern = pattern;
npatterns++;
}
/* Load the abbreviations listed in the given file */
void
abbrev_add_file(filename, ignore_open_error)
const char *filename;
int ignore_open_error;
{
FILE *f;
char pattern[1024]; /* XXX arbitrary limit? */
char *p, *q;
char *endpattern = pattern + sizeof pattern;
f = fopen(filename, "r");
if (!f) {
if (ignore_open_error)
return;
err(1, "%s", filename);
}
while ((p = fgets(pattern, sizeof pattern, f)) != NULL) {
/* Ignore leading space */
while (*p == ' ' || *p == '\t')
p++;
/* Ignore comment lines */
if (*p == '#')
continue;
/* Search for end of line */
for (q = p; q < endpattern && *q; q++)
if (*q == '\n')
break;
/* Ignore trailing space */
while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
q--;
/* Terminate string */
*q = '\0';
/* Add it */
if (*p)
abbrev_add(p);
}
if (ferror(f))
warn("%s", filename);
fclose(f);
}
/* Try loading .pktstatrc, $HOME/.pktstatrc and /etc/pktstatrc */
void
abbrev_add_default_files()
{
char path[FILENAME_MAX];
char *home;
abbrev_add_file(".pktstatrc", 1);
#if HAVE_GETENV
home = getenv("HOME");
#else
home = "";
#endif
if (home) {
snprintf(path, sizeof path, "%s/.pktstatrc", home);
abbrev_add_file(path, 1);
}
abbrev_add_file(PATH_PKTSTATRC, 1);
}
void
abbrev_free()
{
while (npatterns--)
free(patterns[npatterns].name);
if (allocpatterns) {
free(patterns);
allocpatterns = 0;
}
npatterns = 0;
}
|