forked from mirrors/tftp-hpa-google
Reformat the source code
The source code was a mix of different styles; normalize on NASM style; basically K&R style with 4 space indentation.
This commit is contained in:
parent
62533e7441
commit
22accddda0
18 changed files with 2794 additions and 2820 deletions
655
tftpd/remap.c
655
tftpd/remap.c
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
*
|
||||
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
|
||||
*
|
||||
* This program is free software available under the same license
|
||||
|
@ -14,7 +14,7 @@
|
|||
* Perform regular-expression based filename remapping.
|
||||
*/
|
||||
|
||||
#include "config.h" /* Must be included first! */
|
||||
#include "config.h" /* Must be included first! */
|
||||
#include <ctype.h>
|
||||
#include <syslog.h>
|
||||
#include <regex.h>
|
||||
|
@ -23,123 +23,131 @@
|
|||
#include "remap.h"
|
||||
|
||||
#define DEADMAN_MAX_STEPS 1024 /* Timeout after this many steps */
|
||||
#define MAXLINE 16384 /* Truncate a line at this many bytes */
|
||||
#define MAXLINE 16384 /* Truncate a line at this many bytes */
|
||||
|
||||
#define RULE_REWRITE 0x01 /* This is a rewrite rule */
|
||||
#define RULE_GLOBAL 0x02 /* Global rule (repeat until no match) */
|
||||
#define RULE_EXIT 0x04 /* Exit after matching this rule */
|
||||
#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
|
||||
#define RULE_ABORT 0x10 /* Terminate processing with an error */
|
||||
#define RULE_GETONLY 0x20 /* Applicable to GET only */
|
||||
#define RULE_PUTONLY 0x40 /* Applicable to PUT only */
|
||||
#define RULE_INVERSE 0x80 /* Execute if regex *doesn't* match */
|
||||
#define RULE_REWRITE 0x01 /* This is a rewrite rule */
|
||||
#define RULE_GLOBAL 0x02 /* Global rule (repeat until no match) */
|
||||
#define RULE_EXIT 0x04 /* Exit after matching this rule */
|
||||
#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
|
||||
#define RULE_ABORT 0x10 /* Terminate processing with an error */
|
||||
#define RULE_GETONLY 0x20 /* Applicable to GET only */
|
||||
#define RULE_PUTONLY 0x40 /* Applicable to PUT only */
|
||||
#define RULE_INVERSE 0x80 /* Execute if regex *doesn't* match */
|
||||
|
||||
struct rule {
|
||||
struct rule *next;
|
||||
int nrule;
|
||||
int rule_flags;
|
||||
regex_t rx;
|
||||
const char *pattern;
|
||||
struct rule *next;
|
||||
int nrule;
|
||||
int rule_flags;
|
||||
regex_t rx;
|
||||
const char *pattern;
|
||||
};
|
||||
|
||||
static int xform_null(int c)
|
||||
{
|
||||
return c;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int xform_toupper(int c)
|
||||
{
|
||||
return toupper(c);
|
||||
return toupper(c);
|
||||
}
|
||||
|
||||
static int xform_tolower(int c)
|
||||
{
|
||||
return tolower(c);
|
||||
return tolower(c);
|
||||
}
|
||||
|
||||
/* Do \-substitution. Call with string == NULL to get length only. */
|
||||
static int genmatchstring(char *string, const char *pattern, const char *input,
|
||||
const regmatch_t *pmatch, match_pattern_callback macrosub)
|
||||
static int genmatchstring(char *string, const char *pattern,
|
||||
const char *input, const regmatch_t * pmatch,
|
||||
match_pattern_callback macrosub)
|
||||
{
|
||||
int (*xform)(int) = xform_null;
|
||||
int len = 0;
|
||||
int n, mlen, sublen;
|
||||
int endbytes;
|
||||
int (*xform) (int) = xform_null;
|
||||
int len = 0;
|
||||
int n, mlen, sublen;
|
||||
int endbytes;
|
||||
|
||||
/* Get section before match; note pmatch[0] is the whole match */
|
||||
endbytes = strlen(input) - pmatch[0].rm_eo;
|
||||
len = pmatch[0].rm_so + endbytes;
|
||||
if ( string ) {
|
||||
memcpy(string, input, pmatch[0].rm_so);
|
||||
string += pmatch[0].rm_so;
|
||||
}
|
||||
|
||||
/* Transform matched section */
|
||||
while ( *pattern ) {
|
||||
mlen = 0;
|
||||
|
||||
if ( *pattern == '\\' && pattern[1] != '\0' ) {
|
||||
char macro = pattern[1];
|
||||
switch ( macro ) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
n = pattern[1] - '0';
|
||||
|
||||
if ( pmatch[n].rm_so != -1 ) {
|
||||
mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
|
||||
len += mlen;
|
||||
if ( string ) {
|
||||
const char *p = input+pmatch[n].rm_so;
|
||||
while ( mlen-- )
|
||||
*string++ = xform(*p++);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
xform = xform_tolower;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
xform = xform_toupper;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
xform = xform_null;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( macrosub &&
|
||||
(sublen = macrosub(macro, string)) >= 0 ) {
|
||||
while ( sublen-- ) {
|
||||
len++;
|
||||
if ( string ) {
|
||||
*string = xform(*string);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len++;
|
||||
if ( string )
|
||||
*string++ = xform(pattern[1]);
|
||||
}
|
||||
}
|
||||
pattern += 2;
|
||||
} else {
|
||||
len++;
|
||||
if ( string )
|
||||
*string++ = xform(*pattern);
|
||||
pattern++;
|
||||
/* Get section before match; note pmatch[0] is the whole match */
|
||||
endbytes = strlen(input) - pmatch[0].rm_eo;
|
||||
len = pmatch[0].rm_so + endbytes;
|
||||
if (string) {
|
||||
memcpy(string, input, pmatch[0].rm_so);
|
||||
string += pmatch[0].rm_so;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy section after match */
|
||||
if ( string ) {
|
||||
memcpy(string, input+pmatch[0].rm_eo, endbytes);
|
||||
string[endbytes] = '\0';
|
||||
}
|
||||
/* Transform matched section */
|
||||
while (*pattern) {
|
||||
mlen = 0;
|
||||
|
||||
return len;
|
||||
if (*pattern == '\\' && pattern[1] != '\0') {
|
||||
char macro = pattern[1];
|
||||
switch (macro) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
n = pattern[1] - '0';
|
||||
|
||||
if (pmatch[n].rm_so != -1) {
|
||||
mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
|
||||
len += mlen;
|
||||
if (string) {
|
||||
const char *p = input + pmatch[n].rm_so;
|
||||
while (mlen--)
|
||||
*string++ = xform(*p++);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
xform = xform_tolower;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
xform = xform_toupper;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
xform = xform_null;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (macrosub && (sublen = macrosub(macro, string)) >= 0) {
|
||||
while (sublen--) {
|
||||
len++;
|
||||
if (string) {
|
||||
*string = xform(*string);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len++;
|
||||
if (string)
|
||||
*string++ = xform(pattern[1]);
|
||||
}
|
||||
}
|
||||
pattern += 2;
|
||||
} else {
|
||||
len++;
|
||||
if (string)
|
||||
*string++ = xform(*pattern);
|
||||
pattern++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy section after match */
|
||||
if (string) {
|
||||
memcpy(string, input + pmatch[0].rm_eo, endbytes);
|
||||
string[endbytes] = '\0';
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -149,277 +157,284 @@ static int genmatchstring(char *string, const char *pattern, const char *input,
|
|||
*/
|
||||
static int readescstring(char *buf, char **str)
|
||||
{
|
||||
char *p = *str;
|
||||
int wasbs = 0, len = 0;
|
||||
char *p = *str;
|
||||
int wasbs = 0, len = 0;
|
||||
|
||||
while ( *p && isspace(*p) )
|
||||
p++;
|
||||
while (*p && isspace(*p))
|
||||
p++;
|
||||
|
||||
if (!*p) {
|
||||
*buf = '\0';
|
||||
*str = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
if (!wasbs && (isspace(*p) || *p == '#')) {
|
||||
*buf = '\0';
|
||||
*str = p;
|
||||
return len;
|
||||
}
|
||||
/* Important: two backslashes leave us in the !wasbs state! */
|
||||
wasbs = !wasbs && (*p == '\\');
|
||||
*buf++ = *p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
if ( ! *p ) {
|
||||
*buf = '\0';
|
||||
*str = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ( *p ) {
|
||||
if ( !wasbs && (isspace(*p) || *p == '#') ) {
|
||||
*buf = '\0';
|
||||
*str = p;
|
||||
return len;
|
||||
}
|
||||
/* Important: two backslashes leave us in the !wasbs state! */
|
||||
wasbs = !wasbs && ( *p == '\\' );
|
||||
*buf++ = *p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
*buf = '\0';
|
||||
*str = p;
|
||||
return len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Parse a line into a set of instructions */
|
||||
static int parseline(char *line, struct rule *r, int lineno)
|
||||
{
|
||||
char buffer[MAXLINE];
|
||||
char *p;
|
||||
int rv;
|
||||
int rxflags = REG_EXTENDED;
|
||||
static int nrule;
|
||||
char buffer[MAXLINE];
|
||||
char *p;
|
||||
int rv;
|
||||
int rxflags = REG_EXTENDED;
|
||||
static int nrule;
|
||||
|
||||
memset(r, 0, sizeof *r);
|
||||
r->nrule = nrule;
|
||||
memset(r, 0, sizeof *r);
|
||||
r->nrule = nrule;
|
||||
|
||||
if ( !readescstring(buffer, &line) )
|
||||
return 0; /* No rule found */
|
||||
if (!readescstring(buffer, &line))
|
||||
return 0; /* No rule found */
|
||||
|
||||
for ( p = buffer ; *p ; p++ ) {
|
||||
switch(*p) {
|
||||
case 'r':
|
||||
r->rule_flags |= RULE_REWRITE;
|
||||
break;
|
||||
case 'g':
|
||||
r->rule_flags |= RULE_GLOBAL;
|
||||
break;
|
||||
case 'e':
|
||||
r->rule_flags |= RULE_EXIT;
|
||||
break;
|
||||
case 's':
|
||||
r->rule_flags |= RULE_RESTART;
|
||||
break;
|
||||
case 'a':
|
||||
r->rule_flags |= RULE_ABORT;
|
||||
break;
|
||||
case 'i':
|
||||
rxflags |= REG_ICASE;
|
||||
break;
|
||||
case 'G':
|
||||
r->rule_flags |= RULE_GETONLY;
|
||||
break;
|
||||
case 'P':
|
||||
r->rule_flags |= RULE_PUTONLY;
|
||||
break;
|
||||
case '~':
|
||||
r->rule_flags |= RULE_INVERSE;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "Remap command \"%s\" on line %d contains invalid char \"%c\"",
|
||||
buffer, lineno, *p);
|
||||
return -1; /* Error */
|
||||
break;
|
||||
for (p = buffer; *p; p++) {
|
||||
switch (*p) {
|
||||
case 'r':
|
||||
r->rule_flags |= RULE_REWRITE;
|
||||
break;
|
||||
case 'g':
|
||||
r->rule_flags |= RULE_GLOBAL;
|
||||
break;
|
||||
case 'e':
|
||||
r->rule_flags |= RULE_EXIT;
|
||||
break;
|
||||
case 's':
|
||||
r->rule_flags |= RULE_RESTART;
|
||||
break;
|
||||
case 'a':
|
||||
r->rule_flags |= RULE_ABORT;
|
||||
break;
|
||||
case 'i':
|
||||
rxflags |= REG_ICASE;
|
||||
break;
|
||||
case 'G':
|
||||
r->rule_flags |= RULE_GETONLY;
|
||||
break;
|
||||
case 'P':
|
||||
r->rule_flags |= RULE_PUTONLY;
|
||||
break;
|
||||
case '~':
|
||||
r->rule_flags |= RULE_INVERSE;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR,
|
||||
"Remap command \"%s\" on line %d contains invalid char \"%c\"",
|
||||
buffer, lineno, *p);
|
||||
return -1; /* Error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RULE_GLOBAL only applies when RULE_REWRITE specified */
|
||||
if ( !(r->rule_flags & RULE_REWRITE) )
|
||||
r->rule_flags &= ~RULE_GLOBAL;
|
||||
/* RULE_GLOBAL only applies when RULE_REWRITE specified */
|
||||
if (!(r->rule_flags & RULE_REWRITE))
|
||||
r->rule_flags &= ~RULE_GLOBAL;
|
||||
|
||||
if ( (r->rule_flags & (RULE_INVERSE|RULE_REWRITE)) ==
|
||||
(RULE_INVERSE|RULE_REWRITE) ) {
|
||||
syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n", lineno, line);
|
||||
return -1; /* Error */
|
||||
}
|
||||
if ((r->rule_flags & (RULE_INVERSE | RULE_REWRITE)) ==
|
||||
(RULE_INVERSE | RULE_REWRITE)) {
|
||||
syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n",
|
||||
lineno, line);
|
||||
return -1; /* Error */
|
||||
}
|
||||
|
||||
/* Read and compile the regex */
|
||||
if ( !readescstring(buffer, &line) ) {
|
||||
syslog(LOG_ERR, "No regex on remap line %d: %s\n", lineno, line);
|
||||
return -1; /* Error */
|
||||
}
|
||||
/* Read and compile the regex */
|
||||
if (!readescstring(buffer, &line)) {
|
||||
syslog(LOG_ERR, "No regex on remap line %d: %s\n", lineno, line);
|
||||
return -1; /* Error */
|
||||
}
|
||||
|
||||
if ( (rv = regcomp(&r->rx, buffer, rxflags)) != 0 ) {
|
||||
char errbuf[BUFSIZ];
|
||||
regerror(rv, &r->rx, errbuf, BUFSIZ);
|
||||
syslog(LOG_ERR, "Bad regex in remap line %d: %s\n", lineno, errbuf);
|
||||
return -1; /* Error */
|
||||
}
|
||||
if ((rv = regcomp(&r->rx, buffer, rxflags)) != 0) {
|
||||
char errbuf[BUFSIZ];
|
||||
regerror(rv, &r->rx, errbuf, BUFSIZ);
|
||||
syslog(LOG_ERR, "Bad regex in remap line %d: %s\n", lineno,
|
||||
errbuf);
|
||||
return -1; /* Error */
|
||||
}
|
||||
|
||||
/* Read the rewrite pattern, if any */
|
||||
if ( readescstring(buffer, &line) ) {
|
||||
r->pattern = tfstrdup(buffer);
|
||||
} else {
|
||||
r->pattern = "";
|
||||
}
|
||||
/* Read the rewrite pattern, if any */
|
||||
if (readescstring(buffer, &line)) {
|
||||
r->pattern = tfstrdup(buffer);
|
||||
} else {
|
||||
r->pattern = "";
|
||||
}
|
||||
|
||||
nrule++;
|
||||
return 1; /* Rule found */
|
||||
nrule++;
|
||||
return 1; /* Rule found */
|
||||
}
|
||||
|
||||
/* Read a rule file */
|
||||
struct rule *parserulefile(FILE *f)
|
||||
struct rule *parserulefile(FILE * f)
|
||||
{
|
||||
char line[MAXLINE];
|
||||
struct rule *first_rule = NULL;
|
||||
struct rule **last_rule = &first_rule;
|
||||
struct rule *this_rule = tfmalloc(sizeof(struct rule));
|
||||
int rv;
|
||||
int lineno = 0;
|
||||
int err = 0;
|
||||
char line[MAXLINE];
|
||||
struct rule *first_rule = NULL;
|
||||
struct rule **last_rule = &first_rule;
|
||||
struct rule *this_rule = tfmalloc(sizeof(struct rule));
|
||||
int rv;
|
||||
int lineno = 0;
|
||||
int err = 0;
|
||||
|
||||
while ( lineno++, fgets(line, MAXLINE, f) ) {
|
||||
rv = parseline(line, this_rule, lineno);
|
||||
if ( rv < 0 )
|
||||
err = 1;
|
||||
if ( rv > 0 ) {
|
||||
*last_rule = this_rule;
|
||||
last_rule = &this_rule->next;
|
||||
this_rule = tfmalloc(sizeof(struct rule));
|
||||
while (lineno++, fgets(line, MAXLINE, f)) {
|
||||
rv = parseline(line, this_rule, lineno);
|
||||
if (rv < 0)
|
||||
err = 1;
|
||||
if (rv > 0) {
|
||||
*last_rule = this_rule;
|
||||
last_rule = &this_rule->next;
|
||||
this_rule = tfmalloc(sizeof(struct rule));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(this_rule); /* Last one is always unused */
|
||||
free(this_rule); /* Last one is always unused */
|
||||
|
||||
if ( err ) {
|
||||
/* Bail on error, we have already logged an error message */
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
if (err) {
|
||||
/* Bail on error, we have already logged an error message */
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
|
||||
return first_rule;
|
||||
return first_rule;
|
||||
}
|
||||
|
||||
/* Destroy a rule file data structure */
|
||||
void freerules(struct rule *r)
|
||||
{
|
||||
struct rule *next;
|
||||
struct rule *next;
|
||||
|
||||
while ( r ) {
|
||||
next = r->next;
|
||||
while (r) {
|
||||
next = r->next;
|
||||
|
||||
regfree(&r->rx);
|
||||
regfree(&r->rx);
|
||||
|
||||
/* "" patterns aren't allocated by malloc() */
|
||||
if ( r->pattern && *r->pattern )
|
||||
free((void *)r->pattern);
|
||||
|
||||
free(r);
|
||||
/* "" patterns aren't allocated by malloc() */
|
||||
if (r->pattern && *r->pattern)
|
||||
free((void *)r->pattern);
|
||||
|
||||
r = next;
|
||||
}
|
||||
free(r);
|
||||
|
||||
r = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute a rule set on a string; returns a malloc'd new string. */
|
||||
char *rewrite_string(const char *input, const struct rule *rules,
|
||||
int is_put, match_pattern_callback macrosub,
|
||||
const char **errmsg)
|
||||
int is_put, match_pattern_callback macrosub,
|
||||
const char **errmsg)
|
||||
{
|
||||
char *current = tfstrdup(input);
|
||||
char *newstr;
|
||||
const struct rule *ruleptr = rules;
|
||||
regmatch_t pmatch[10];
|
||||
int len;
|
||||
int was_match = 0;
|
||||
int deadman = DEADMAN_MAX_STEPS;
|
||||
char *current = tfstrdup(input);
|
||||
char *newstr;
|
||||
const struct rule *ruleptr = rules;
|
||||
regmatch_t pmatch[10];
|
||||
int len;
|
||||
int was_match = 0;
|
||||
int deadman = DEADMAN_MAX_STEPS;
|
||||
|
||||
/* Default error */
|
||||
*errmsg = "Remap table failure";
|
||||
/* Default error */
|
||||
*errmsg = "Remap table failure";
|
||||
|
||||
if ( verbosity >= 3 ) {
|
||||
syslog(LOG_INFO, "remap: input: %s", current);
|
||||
}
|
||||
|
||||
for ( ruleptr = rules ; ruleptr ; ruleptr = ruleptr->next ) {
|
||||
if ( ((ruleptr->rule_flags & RULE_GETONLY) && is_put) ||
|
||||
((ruleptr->rule_flags & RULE_PUTONLY) && !is_put) ) {
|
||||
continue; /* Rule not applicable, try next */
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: input: %s", current);
|
||||
}
|
||||
|
||||
if ( ! deadman-- ) {
|
||||
syslog(LOG_WARNING, "remap: Breaking loop, input = %s, last = %s",
|
||||
input, current);
|
||||
free(current);
|
||||
return NULL; /* Did not terminate! */
|
||||
for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) {
|
||||
if (((ruleptr->rule_flags & RULE_GETONLY) && is_put) ||
|
||||
((ruleptr->rule_flags & RULE_PUTONLY) && !is_put)) {
|
||||
continue; /* Rule not applicable, try next */
|
||||
}
|
||||
|
||||
if (!deadman--) {
|
||||
syslog(LOG_WARNING,
|
||||
"remap: Breaking loop, input = %s, last = %s", input,
|
||||
current);
|
||||
free(current);
|
||||
return NULL; /* Did not terminate! */
|
||||
}
|
||||
|
||||
do {
|
||||
if (regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
|
||||
(ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0)) {
|
||||
/* Match on this rule */
|
||||
was_match = 1;
|
||||
|
||||
if (ruleptr->rule_flags & RULE_INVERSE) {
|
||||
/* No actual match, so clear out the pmatch array */
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
pmatch[i].rm_so = pmatch[i].rm_eo = -1;
|
||||
}
|
||||
|
||||
if (ruleptr->rule_flags & RULE_ABORT) {
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: abort: %s",
|
||||
ruleptr->nrule, current);
|
||||
}
|
||||
if (ruleptr->pattern[0]) {
|
||||
/* Custom error message */
|
||||
len =
|
||||
genmatchstring(NULL, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
newstr = tfmalloc(len + 1);
|
||||
genmatchstring(newstr, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
*errmsg = newstr;
|
||||
} else {
|
||||
*errmsg = NULL;
|
||||
}
|
||||
free(current);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (ruleptr->rule_flags & RULE_REWRITE) {
|
||||
len = genmatchstring(NULL, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
newstr = tfmalloc(len + 1);
|
||||
genmatchstring(newstr, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
free(current);
|
||||
current = newstr;
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
|
||||
ruleptr->nrule, current);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break; /* No match, terminate unconditionally */
|
||||
}
|
||||
/* If the rule is global, keep going until no match */
|
||||
} while (ruleptr->rule_flags & RULE_GLOBAL);
|
||||
|
||||
if (was_match) {
|
||||
was_match = 0;
|
||||
|
||||
if (ruleptr->rule_flags & RULE_EXIT) {
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: exit",
|
||||
ruleptr->nrule);
|
||||
}
|
||||
return current; /* Exit here, we're done */
|
||||
} else if (ruleptr->rule_flags & RULE_RESTART) {
|
||||
ruleptr = rules; /* Start from the top */
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: rule %d: restart",
|
||||
ruleptr->nrule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if ( regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
|
||||
(ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0) ) {
|
||||
/* Match on this rule */
|
||||
was_match = 1;
|
||||
|
||||
if ( ruleptr->rule_flags & RULE_INVERSE ) {
|
||||
/* No actual match, so clear out the pmatch array */
|
||||
int i;
|
||||
for ( i = 0 ; i < 10 ; i++ )
|
||||
pmatch[i].rm_so = pmatch[i].rm_eo = -1;
|
||||
}
|
||||
|
||||
if ( ruleptr->rule_flags & RULE_ABORT ) {
|
||||
if ( verbosity >= 3 ) {
|
||||
syslog(LOG_INFO, "remap: rule %d: abort: %s",
|
||||
ruleptr->nrule, current);
|
||||
}
|
||||
if ( ruleptr->pattern[0] ) {
|
||||
/* Custom error message */
|
||||
len = genmatchstring(NULL, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
newstr = tfmalloc(len+1);
|
||||
genmatchstring(newstr, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
*errmsg = newstr;
|
||||
} else {
|
||||
*errmsg = NULL;
|
||||
}
|
||||
free(current);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if ( ruleptr->rule_flags & RULE_REWRITE ) {
|
||||
len = genmatchstring(NULL, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
newstr = tfmalloc(len+1);
|
||||
genmatchstring(newstr, ruleptr->pattern, current,
|
||||
pmatch, macrosub);
|
||||
free(current);
|
||||
current = newstr;
|
||||
if ( verbosity >= 3 ) {
|
||||
syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
|
||||
ruleptr->nrule, current);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break; /* No match, terminate unconditionally */
|
||||
}
|
||||
/* If the rule is global, keep going until no match */
|
||||
} while ( ruleptr->rule_flags & RULE_GLOBAL );
|
||||
|
||||
if ( was_match ) {
|
||||
was_match = 0;
|
||||
|
||||
if ( ruleptr->rule_flags & RULE_EXIT ) {
|
||||
if ( verbosity >= 3 ) {
|
||||
syslog(LOG_INFO, "remap: rule %d: exit", ruleptr->nrule);
|
||||
}
|
||||
return current; /* Exit here, we're done */
|
||||
} else if ( ruleptr->rule_flags & RULE_RESTART ) {
|
||||
ruleptr = rules; /* Start from the top */
|
||||
if ( verbosity >= 3 ) {
|
||||
syslog(LOG_INFO, "remap: rule %d: restart", ruleptr->nrule);
|
||||
}
|
||||
}
|
||||
if (verbosity >= 3) {
|
||||
syslog(LOG_INFO, "remap: done");
|
||||
}
|
||||
}
|
||||
|
||||
if ( verbosity >= 3 ) {
|
||||
syslog(LOG_INFO, "remap: done");
|
||||
}
|
||||
return current;
|
||||
return current;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue