13e12c5d1SDavid du Colombier #include "common.h"
23e12c5d1SDavid du Colombier #include "send.h"
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier extern int debug;
53e12c5d1SDavid du Colombier
63e12c5d1SDavid du Colombier /*
73e12c5d1SDavid du Colombier * Routines for dealing with the rewrite rules.
83e12c5d1SDavid du Colombier */
93e12c5d1SDavid du Colombier
103e12c5d1SDavid du Colombier /* globals */
113e12c5d1SDavid du Colombier typedef struct rule rule;
123e12c5d1SDavid du Colombier
133e12c5d1SDavid du Colombier #define NSUBEXP 10
143e12c5d1SDavid du Colombier struct rule {
153e12c5d1SDavid du Colombier String *matchre; /* address match */
163e12c5d1SDavid du Colombier String *repl1; /* first replacement String */
173e12c5d1SDavid du Colombier String *repl2; /* second replacement String */
183e12c5d1SDavid du Colombier d_status type; /* type of rule */
193e12c5d1SDavid du Colombier Reprog *program;
203e12c5d1SDavid du Colombier Resub subexp[NSUBEXP];
213e12c5d1SDavid du Colombier rule *next;
223e12c5d1SDavid du Colombier };
233e12c5d1SDavid du Colombier static rule *rulep;
24219b2ee8SDavid du Colombier static rule *rlastp;
253e12c5d1SDavid du Colombier
263e12c5d1SDavid du Colombier /* predeclared */
277dd7cddfSDavid du Colombier static String *substitute(String *, Resub *, message *);
283e12c5d1SDavid du Colombier static rule *findrule(String *, int);
293e12c5d1SDavid du Colombier
303e12c5d1SDavid du Colombier
313e12c5d1SDavid du Colombier /*
323e12c5d1SDavid du Colombier * Get the next token from `line'. The symbol `\l' is replaced by
333e12c5d1SDavid du Colombier * the name of the local system.
343e12c5d1SDavid du Colombier */
353e12c5d1SDavid du Colombier extern String *
rule_parse(String * line,char * system,int * backl)36219b2ee8SDavid du Colombier rule_parse(String *line, char *system, int *backl)
373e12c5d1SDavid du Colombier {
383e12c5d1SDavid du Colombier String *token;
393e12c5d1SDavid du Colombier String *expanded;
403e12c5d1SDavid du Colombier char *cp;
413e12c5d1SDavid du Colombier
423e12c5d1SDavid du Colombier token = s_parse(line, 0);
433e12c5d1SDavid du Colombier if(token == 0)
443e12c5d1SDavid du Colombier return(token);
453e12c5d1SDavid du Colombier if(strchr(s_to_c(token), '\\')==0)
463e12c5d1SDavid du Colombier return(token);
473e12c5d1SDavid du Colombier expanded = s_new();
483e12c5d1SDavid du Colombier for(cp = s_to_c(token); *cp; cp++) {
493e12c5d1SDavid du Colombier if(*cp == '\\') switch(*++cp) {
503e12c5d1SDavid du Colombier case 'l':
51219b2ee8SDavid du Colombier s_append(expanded, system);
52219b2ee8SDavid du Colombier *backl = 1;
533e12c5d1SDavid du Colombier break;
543e12c5d1SDavid du Colombier case '\\':
553e12c5d1SDavid du Colombier s_putc(expanded, '\\');
563e12c5d1SDavid du Colombier break;
573e12c5d1SDavid du Colombier default:
583e12c5d1SDavid du Colombier s_putc(expanded, '\\');
593e12c5d1SDavid du Colombier s_putc(expanded, *cp);
603e12c5d1SDavid du Colombier break;
613e12c5d1SDavid du Colombier } else
623e12c5d1SDavid du Colombier s_putc(expanded, *cp);
633e12c5d1SDavid du Colombier }
643e12c5d1SDavid du Colombier s_free(token);
653e12c5d1SDavid du Colombier s_terminate(expanded);
663e12c5d1SDavid du Colombier return(expanded);
673e12c5d1SDavid du Colombier }
683e12c5d1SDavid du Colombier
69219b2ee8SDavid du Colombier static int
getrule(String * line,String * type,char * system)70219b2ee8SDavid du Colombier getrule(String *line, String *type, char *system)
713e12c5d1SDavid du Colombier {
72219b2ee8SDavid du Colombier rule *rp;
733e12c5d1SDavid du Colombier String *re;
74219b2ee8SDavid du Colombier int backl;
753e12c5d1SDavid du Colombier
76219b2ee8SDavid du Colombier backl = 0;
77219b2ee8SDavid du Colombier
783e12c5d1SDavid du Colombier /* get a rule */
79219b2ee8SDavid du Colombier re = rule_parse(s_restart(line), system, &backl);
80219b2ee8SDavid du Colombier if(re == 0)
81219b2ee8SDavid du Colombier return 0;
823e12c5d1SDavid du Colombier rp = (rule *)malloc(sizeof(rule));
833e12c5d1SDavid du Colombier if(rp == 0) {
843e12c5d1SDavid du Colombier perror("getrules:");
853e12c5d1SDavid du Colombier exit(1);
863e12c5d1SDavid du Colombier }
873e12c5d1SDavid du Colombier rp->next = 0;
883e12c5d1SDavid du Colombier s_tolower(re);
893e12c5d1SDavid du Colombier rp->matchre = s_new();
903e12c5d1SDavid du Colombier s_append(rp->matchre, s_to_c(re));
919a747e4fSDavid du Colombier s_restart(rp->matchre);
923e12c5d1SDavid du Colombier s_free(re);
933e12c5d1SDavid du Colombier s_parse(line, s_restart(type));
94219b2ee8SDavid du Colombier rp->repl1 = rule_parse(line, system, &backl);
95219b2ee8SDavid du Colombier rp->repl2 = rule_parse(line, system, &backl);
963e12c5d1SDavid du Colombier rp->program = 0;
973e12c5d1SDavid du Colombier if(strcmp(s_to_c(type), "|") == 0)
983e12c5d1SDavid du Colombier rp->type = d_pipe;
993e12c5d1SDavid du Colombier else if(strcmp(s_to_c(type), ">>") == 0)
1003e12c5d1SDavid du Colombier rp->type = d_cat;
1013e12c5d1SDavid du Colombier else if(strcmp(s_to_c(type), "alias") == 0)
1023e12c5d1SDavid du Colombier rp->type = d_alias;
1033e12c5d1SDavid du Colombier else if(strcmp(s_to_c(type), "translate") == 0)
1043e12c5d1SDavid du Colombier rp->type = d_translate;
1053e12c5d1SDavid du Colombier else if(strcmp(s_to_c(type), "auth") == 0)
1063e12c5d1SDavid du Colombier rp->type = d_auth;
1073e12c5d1SDavid du Colombier else {
1083e12c5d1SDavid du Colombier s_free(rp->matchre);
1093e12c5d1SDavid du Colombier s_free(rp->repl1);
1103e12c5d1SDavid du Colombier s_free(rp->repl2);
1113e12c5d1SDavid du Colombier free((char *)rp);
1123e12c5d1SDavid du Colombier fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
113219b2ee8SDavid du Colombier return 0;
1143e12c5d1SDavid du Colombier }
1153e12c5d1SDavid du Colombier if(rulep == 0)
1163e12c5d1SDavid du Colombier rulep = rlastp = rp;
1173e12c5d1SDavid du Colombier else
1183e12c5d1SDavid du Colombier rlastp = rlastp->next = rp;
119219b2ee8SDavid du Colombier return backl;
1203e12c5d1SDavid du Colombier }
121219b2ee8SDavid du Colombier
122219b2ee8SDavid du Colombier /*
123219b2ee8SDavid du Colombier * rules are of the form:
124219b2ee8SDavid du Colombier * <reg exp> <String> <repl exp> [<repl exp>]
125219b2ee8SDavid du Colombier */
126219b2ee8SDavid du Colombier extern int
getrules(void)127219b2ee8SDavid du Colombier getrules(void)
128219b2ee8SDavid du Colombier {
129219b2ee8SDavid du Colombier Biobuf *rfp;
130219b2ee8SDavid du Colombier String *line;
131219b2ee8SDavid du Colombier String *type;
132219b2ee8SDavid du Colombier String *file;
133219b2ee8SDavid du Colombier
1347dd7cddfSDavid du Colombier file = abspath("rewrite", UPASLIB, (String *)0);
135219b2ee8SDavid du Colombier rfp = sysopen(s_to_c(file), "r", 0);
136219b2ee8SDavid du Colombier if(rfp == 0) {
137219b2ee8SDavid du Colombier rulep = 0;
138219b2ee8SDavid du Colombier return -1;
139219b2ee8SDavid du Colombier }
140219b2ee8SDavid du Colombier rlastp = 0;
141219b2ee8SDavid du Colombier line = s_new();
142219b2ee8SDavid du Colombier type = s_new();
143219b2ee8SDavid du Colombier while(s_getline(rfp, s_restart(line)))
144219b2ee8SDavid du Colombier if(getrule(line, type, thissys) && altthissys)
145219b2ee8SDavid du Colombier getrule(s_restart(line), type, altthissys);
1463e12c5d1SDavid du Colombier s_free(type);
1473e12c5d1SDavid du Colombier s_free(line);
1483e12c5d1SDavid du Colombier s_free(file);
1493e12c5d1SDavid du Colombier sysclose(rfp);
1503e12c5d1SDavid du Colombier return 0;
1513e12c5d1SDavid du Colombier }
1523e12c5d1SDavid du Colombier
1533e12c5d1SDavid du Colombier /* look up a matching rule */
1543e12c5d1SDavid du Colombier static rule *
findrule(String * addrp,int authorized)1553e12c5d1SDavid du Colombier findrule(String *addrp, int authorized)
1563e12c5d1SDavid du Colombier {
1573e12c5d1SDavid du Colombier rule *rp;
1583e12c5d1SDavid du Colombier static rule defaultrule;
1593e12c5d1SDavid du Colombier
1603e12c5d1SDavid du Colombier if(rulep == 0)
1613e12c5d1SDavid du Colombier return &defaultrule;
1623e12c5d1SDavid du Colombier for (rp = rulep; rp != 0; rp = rp->next) {
1633e12c5d1SDavid du Colombier if(rp->type==d_auth && authorized)
1643e12c5d1SDavid du Colombier continue;
1653e12c5d1SDavid du Colombier if(rp->program == 0)
1663e12c5d1SDavid du Colombier rp->program = regcomp(rp->matchre->base);
1673e12c5d1SDavid du Colombier if(rp->program == 0)
1683e12c5d1SDavid du Colombier continue;
1693e12c5d1SDavid du Colombier memset(rp->subexp, 0, sizeof(rp->subexp));
1703e12c5d1SDavid du Colombier if(debug)
171*c6569576SDavid du Colombier fprint(2, "matching %s against %s\n", s_to_c(addrp),
172c4cb05bbSDavid du Colombier rp->matchre->base);
1733e12c5d1SDavid du Colombier if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
1747dd7cddfSDavid du Colombier if(s_to_c(addrp) == rp->subexp[0].sp)
1757dd7cddfSDavid du Colombier if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].ep)
1763e12c5d1SDavid du Colombier return rp;
1773e12c5d1SDavid du Colombier }
1783e12c5d1SDavid du Colombier return 0;
1793e12c5d1SDavid du Colombier }
1803e12c5d1SDavid du Colombier
1813e12c5d1SDavid du Colombier /* Transforms the address into a command.
1823e12c5d1SDavid du Colombier * Returns: -1 ifaddress not matched by reules
1833e12c5d1SDavid du Colombier * 0 ifaddress matched and ok to forward
1843e12c5d1SDavid du Colombier * 1 ifaddress matched and not ok to forward
1853e12c5d1SDavid du Colombier */
1863e12c5d1SDavid du Colombier extern int
rewrite(dest * dp,message * mp)1877dd7cddfSDavid du Colombier rewrite(dest *dp, message *mp)
1883e12c5d1SDavid du Colombier {
1893e12c5d1SDavid du Colombier rule *rp; /* rewriting rule */
1903e12c5d1SDavid du Colombier String *lower; /* lower case version of destination */
1913e12c5d1SDavid du Colombier
1923e12c5d1SDavid du Colombier /*
1933e12c5d1SDavid du Colombier * Rewrite the address. Matching is case insensitive.
1943e12c5d1SDavid du Colombier */
1957dd7cddfSDavid du Colombier lower = s_clone(dp->addr);
1963e12c5d1SDavid du Colombier s_tolower(s_restart(lower));
1973e12c5d1SDavid du Colombier rp = findrule(lower, dp->authorized);
1987dd7cddfSDavid du Colombier if(rp == 0){
1997dd7cddfSDavid du Colombier s_free(lower);
2003e12c5d1SDavid du Colombier return -1;
2017dd7cddfSDavid du Colombier }
2023e12c5d1SDavid du Colombier strcpy(s_to_c(lower), s_to_c(dp->addr));
2037dd7cddfSDavid du Colombier dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
2047dd7cddfSDavid du Colombier dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
2053e12c5d1SDavid du Colombier dp->status = rp->type;
2063e12c5d1SDavid du Colombier if(debug){
207*c6569576SDavid du Colombier fprint(2, "\t->");
2083e12c5d1SDavid du Colombier if(dp->repl1)
209*c6569576SDavid du Colombier fprint(2, "%s", s_to_c(dp->repl1));
2103e12c5d1SDavid du Colombier if(dp->repl2)
211*c6569576SDavid du Colombier fprint(2, "%s", s_to_c(dp->repl2));
212*c6569576SDavid du Colombier fprint(2, "\n");
2133e12c5d1SDavid du Colombier }
2147dd7cddfSDavid du Colombier s_free(lower);
2153e12c5d1SDavid du Colombier return 0;
2163e12c5d1SDavid du Colombier }
2173e12c5d1SDavid du Colombier
2183e12c5d1SDavid du Colombier static String *
substitute(String * source,Resub * subexp,message * mp)2197dd7cddfSDavid du Colombier substitute(String *source, Resub *subexp, message *mp)
2203e12c5d1SDavid du Colombier {
2217dd7cddfSDavid du Colombier int i;
2227dd7cddfSDavid du Colombier char *s;
2237dd7cddfSDavid du Colombier char *sp;
2247dd7cddfSDavid du Colombier String *stp;
2253e12c5d1SDavid du Colombier
2263e12c5d1SDavid du Colombier if(source == 0)
2273e12c5d1SDavid du Colombier return 0;
2283e12c5d1SDavid du Colombier sp = s_to_c(source);
2293e12c5d1SDavid du Colombier
2303e12c5d1SDavid du Colombier /* someplace to put it */
2313e12c5d1SDavid du Colombier stp = s_new();
2323e12c5d1SDavid du Colombier
2333e12c5d1SDavid du Colombier /* do the substitution */
2343e12c5d1SDavid du Colombier while (*sp != '\0') {
2353e12c5d1SDavid du Colombier if(*sp == '\\') {
2363e12c5d1SDavid du Colombier switch (*++sp) {
2373e12c5d1SDavid du Colombier case '0': case '1': case '2': case '3': case '4':
2383e12c5d1SDavid du Colombier case '5': case '6': case '7': case '8': case '9':
2393e12c5d1SDavid du Colombier i = *sp-'0';
2403e12c5d1SDavid du Colombier if(subexp[i].sp != 0)
2417dd7cddfSDavid du Colombier for (s = subexp[i].sp;
2427dd7cddfSDavid du Colombier s < subexp[i].ep;
2437dd7cddfSDavid du Colombier s++)
2447dd7cddfSDavid du Colombier s_putc(stp, *s);
2453e12c5d1SDavid du Colombier break;
2463e12c5d1SDavid du Colombier case '\\':
2473e12c5d1SDavid du Colombier s_putc(stp, '\\');
2483e12c5d1SDavid du Colombier break;
2493e12c5d1SDavid du Colombier case '\0':
2503e12c5d1SDavid du Colombier sp--;
2513e12c5d1SDavid du Colombier break;
2523e12c5d1SDavid du Colombier case 's':
2537dd7cddfSDavid du Colombier for(s = s_to_c(mp->replyaddr); *s; s++)
2547dd7cddfSDavid du Colombier s_putc(stp, *s);
2557dd7cddfSDavid du Colombier break;
2567dd7cddfSDavid du Colombier case 'p':
2577dd7cddfSDavid du Colombier if(mp->bulk)
2587dd7cddfSDavid du Colombier s = "bulk";
2597dd7cddfSDavid du Colombier else
2607dd7cddfSDavid du Colombier s = "normal";
2617dd7cddfSDavid du Colombier for(;*s; s++)
2627dd7cddfSDavid du Colombier s_putc(stp, *s);
2633e12c5d1SDavid du Colombier break;
2643e12c5d1SDavid du Colombier default:
2653e12c5d1SDavid du Colombier s_putc(stp, *sp);
2663e12c5d1SDavid du Colombier break;
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier } else if(*sp == '&') {
2693e12c5d1SDavid du Colombier if(subexp[0].sp != 0)
2707dd7cddfSDavid du Colombier for (s = subexp[0].sp;
2717dd7cddfSDavid du Colombier s < subexp[0].ep; s++)
2727dd7cddfSDavid du Colombier s_putc(stp, *s);
2733e12c5d1SDavid du Colombier } else
2743e12c5d1SDavid du Colombier s_putc(stp, *sp);
2753e12c5d1SDavid du Colombier sp++;
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier s_terminate(stp);
2783e12c5d1SDavid du Colombier
2793e12c5d1SDavid du Colombier return s_restart(stp);
2803e12c5d1SDavid du Colombier }
2813e12c5d1SDavid du Colombier
2823e12c5d1SDavid du Colombier extern void
regerror(char * s)2833e12c5d1SDavid du Colombier regerror(char* s)
2843e12c5d1SDavid du Colombier {
2853e12c5d1SDavid du Colombier fprint(2, "rewrite: %s\n", s);
286be704722SDavid du Colombier /* make sure the message is seen locally */
2877ee8ce7cSDavid du Colombier syslog(0, "mail", "regexp error in rewrite: %s", s);
2883e12c5d1SDavid du Colombier }
2893e12c5d1SDavid du Colombier
2903e12c5d1SDavid du Colombier extern void
dumprules(void)2913e12c5d1SDavid du Colombier dumprules(void)
2923e12c5d1SDavid du Colombier {
2933e12c5d1SDavid du Colombier rule *rp;
2943e12c5d1SDavid du Colombier
2953e12c5d1SDavid du Colombier for (rp = rulep; rp != 0; rp = rp->next) {
2963e12c5d1SDavid du Colombier fprint(2, "'%s'", rp->matchre->base);
2973e12c5d1SDavid du Colombier switch (rp->type) {
2983e12c5d1SDavid du Colombier case d_pipe:
2993e12c5d1SDavid du Colombier fprint(2, " |");
3003e12c5d1SDavid du Colombier break;
3013e12c5d1SDavid du Colombier case d_cat:
3023e12c5d1SDavid du Colombier fprint(2, " >>");
3033e12c5d1SDavid du Colombier break;
3043e12c5d1SDavid du Colombier case d_alias:
3053e12c5d1SDavid du Colombier fprint(2, " alias");
3063e12c5d1SDavid du Colombier break;
3073e12c5d1SDavid du Colombier case d_translate:
3083e12c5d1SDavid du Colombier fprint(2, " translate");
3093e12c5d1SDavid du Colombier break;
3103e12c5d1SDavid du Colombier default:
3113e12c5d1SDavid du Colombier fprint(2, " UNKNOWN");
3123e12c5d1SDavid du Colombier break;
3133e12c5d1SDavid du Colombier }
3143e12c5d1SDavid du Colombier fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
3153e12c5d1SDavid du Colombier fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");
3163e12c5d1SDavid du Colombier }
3173e12c5d1SDavid du Colombier }
3183e12c5d1SDavid du Colombier
319