|
|
researchv8 Dan Cross
#include <stdio.h>
#include <ctype.h>
#include <regexp.h>
#include "mail.h"
#include "string.h"
/* configuration */
#define RULEFILE "rewrite"
#define BUFFERSIZE 512
/*
* Routines for dealing with the rewrite rules.
*/
/* imports */
extern char *malloc();
extern int strlen();
extern regexp *regcomp();
extern int regexec();
extern void regsub();
extern char *upaspath();
extern char *thissys;
/* globals */
typedef struct rule rule;
struct rule {
char *matchre; /* address match */
char *cmdre; /* command used to send message */
char *machre; /* next hop */
char *restre; /* address after the next hop */
regexp *program;
rule *next;
};
static rule *rulep;
static rule alwayslocal = {
".*",
"",
"",
NULL
};
static int eof = 0, eol = 0;
/* predeclared */
static char *getstring();
static char *newstring();
static void substitute();
static int geteol();
extern int
getrules()
{
FILE *rfp;
rule *rp, *rlastp=NULL;
char *bp;
eof = eol = 0;
rfp = fopen(upaspath(RULEFILE), "r");
if (rfp == NULL) {
rulep = &alwayslocal;
return -1;
}
do {
/* ignore comments */
bp = getstring(rfp);
if (*bp=='#' || *bp=='\0')
continue;
/* get a rule */
rp = (rule *)malloc(sizeof(rule));
if (rp == NULL)
return -1;
if (rulep == NULL)
rulep = rlastp = rp;
else
rlastp = rlastp->next = rp;
rp->next = NULL;
rp->matchre = newstring(bp);
rp->cmdre = newstring(getstring(rfp));
rp->machre = newstring(getstring(rfp));
rp->restre = newstring(getstring(rfp));
rp->program = NULL;
} while (geteol(rfp));
fclose(rfp);
#ifdef DEBUG
dumprules();
#endif DEBUG
return 0;
}
static char *
getstring(fp)
FILE *fp;
{
static char buf[BUFFERSIZE];
int c, term1=' ', term2='\t';
char *bp=buf;
if (!eol) {
/* skip whitespace */
do {
c = getc(fp);
/* hack to recognize escaped newline */
if (c == '\\') {
c = getc(fp);
if (c == '\n')
c = ' ';
else
*bp++ = '\\';
}
} while (c == ' ' || c == '\t');
/* possible quoted string */
if (c == '\'' || c == '"') {
term1 = term2 = c;
c = getc(fp);
}
while (c != term1 && c != term2 && !eol) {
switch (c) {
case EOF:
eof = 1;
/* fall through */
case '\n':
eol = 1;
break;
case '\\':
c = getc(fp);
/* hack to recognize escaped newline */
if (c == '\n') {
c = term1;
break;
} else {
*bp++ = '\\';
/* fall through */
}
default:
*bp++ = c;
c = getc(fp);
break;
}
}
}
*bp = 0;
return buf;
}
static int
geteol(fp)
FILE *fp;
{
while(!eol)
getstring(fp);
eol = 0;
return !eof;
}
static char *
newstring(sp)
char *sp;
{
char *np;
np = malloc(strlen(sp)+1);
if (np == NULL) {
fprintf(stderr, "mail: out of memory\n");
exit(1);
}
strcpy(np, sp);
return np;
}
static rule *
findrule(addrp)
char *addrp;
{
rule *rp;
for (rp = rulep; rp != NULL; rp = rp->next) {
if (rp->program == NULL)
rp->program = regcomp(rp->matchre);
if (regexec(rp->program, addrp))
return rp;
}
return NULL;
}
/* Transforms the address into a command.
* Returns: -1 if address not matched by reules
* 0 if address matched and ok to forward
* 1 if address matched and not ok to forward
*/
extern int
rewrite(addrp, s, chkfl, cmdp)
char *addrp; /* address to rewrite */
char *s; /* string that matches \s */
int chkfl; /* non-zero if we must check forwarding */
char *cmdp; /* (returned) substituted strings */
{
rule *rp;
char dest[ADDRSIZE]; /* next hop for message */
char rest[ADDRSIZE]; /* rest of address after hop */
char addr[ADDRSIZE]; /* rest of address after hop */
/* rewrite the address */
rp = findrule(addrp);
if (rp == NULL)
return -1;
if (cmdp != NULL)
substitute(rp->program, rp->cmdre, cmdp, s);
/* check for legal forwarding */
if (!chkfl)
return 0;
while (1) {
substitute(rp->program, rp->restre, rest, s);
substitute(rp->program, rp->machre, dest, s);
#ifdef DEBUG
printf(" %s %s\n", dest, rest);
#endif DEBUG
if (dest[0] == '\0')
return 0;
if (!okrmt(dest))
return 1;
strcpy(addr, rest);
rp = findrule(addr);
if (rp == NULL)
return 1;
}
}
static void
substitute(progp, sp, dp, s)
regexp *progp; /* context of substitution */
char *sp; /* source string */
char *dp; /* destination string */
char *s; /* strig to substitute for \s */
{
char *ssp;
while (*sp != '\0') {
if (*sp == '\\') {
switch (*++sp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (progp->startp[*sp-'0'] != NULL)
for (ssp = progp->startp[*sp-'0'];
ssp < progp->endp[*sp-'0'];
ssp++)
*dp++ = *ssp;
break;
case '\\':
*dp++ = '\\';
break;
case '\0':
sp--;
break;
case 's':
for(ssp = s; *ssp; ssp++)
*dp++ = *ssp;
break;
default:
*dp++ = *sp;
break;
}
} else if (*sp == '&') {
if (progp->startp[0] != NULL)
for (ssp = progp->startp[0];
ssp < progp->endp[0]; ssp++)
*dp++ = *ssp;
} else
*dp++ = *sp;
sp++;
}
*dp = '\0';
}
#ifdef DEBUG
regdump(subp)
regexp *subp;
{
int i;
char *cp;
printf ("matches are:\n");
for (i = 0; i < NSUBEXP; i++) {
if (subp->startp[i] != NULL) {
printf("\t(%d) ", i);
for (cp = subp->startp[i]; cp < subp->endp[i]; cp++)
putchar(*cp);
putchar('\n');
}
}
}
#endif DEBUG
#ifdef DEBUG
dumprules()
{
rule *rp;
for (rp = rulep; rp != NULL; rp = rp->next) {
fprintf (stderr, "matchre: %s\n", rp->matchre);
fprintf (stderr, "cmdre: %s\n", rp->cmdre);
fprintf (stderr, "machre: %s\n", rp->machre);
fprintf (stderr, "restre: %s\n", rp->restre);
}
}
#endif DEBUG
regerror(s)
char* s;
{
fprintf(stderr, "rewrite: %s\n", s);
exit(1);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.