8 * Routines for dealing with the rewrite rules.
12 typedef struct rule rule;
16 String *matchre; /* address match */
17 String *repl1; /* first replacement String */
18 String *repl2; /* second replacement String */
19 d_status type; /* type of rule */
21 Resub subexp[NSUBEXP];
28 static String *substitute(String *, Resub *, message *);
29 static rule *findrule(String *, int);
33 * Get the next token from `line'. The symbol `\l' is replaced by
34 * the name of the local system.
37 rule_parse(String *line, char *system, int *backl)
43 token = s_parse(line, 0);
46 if(strchr(s_to_c(token), '\\')==0)
49 for(cp = s_to_c(token); *cp; cp++) {
50 if(*cp == '\\') switch(*++cp) {
52 s_append(expanded, system);
56 s_putc(expanded, '\\');
59 s_putc(expanded, '\\');
60 s_putc(expanded, *cp);
63 s_putc(expanded, *cp);
66 s_terminate(expanded);
71 getrule(String *line, String *type, char *system)
80 re = rule_parse(s_restart(line), system, &backl);
83 rp = (rule *)malloc(sizeof(rule));
85 sysfatal("malloc: %r");
88 rp->matchre = s_new();
89 s_append(rp->matchre, s_to_c(re));
90 s_restart(rp->matchre);
92 s_parse(line, s_restart(type));
93 rp->repl1 = rule_parse(line, system, &backl);
94 rp->repl2 = rule_parse(line, system, &backl);
96 if(strcmp(s_to_c(type), "|") == 0)
98 else if(strcmp(s_to_c(type), ">>") == 0)
100 else if(strcmp(s_to_c(type), "alias") == 0)
102 else if(strcmp(s_to_c(type), "translate") == 0)
103 rp->type = d_translate;
104 else if(strcmp(s_to_c(type), "auth") == 0)
111 fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
117 rlastp = rlastp->next = rp;
122 * rules are of the form:
123 * <reg exp> <String> <repl exp> [<repl exp>]
132 snprint(file, sizeof file, "%s/rewrite", UPASLIB);
133 rfp = sysopen(file, "r", 0);
141 while(s_getline(rfp, s_restart(line)))
142 if(getrule(line, type, thissys) && altthissys)
143 getrule(s_restart(line), type, altthissys);
150 /* look up a matching rule */
152 findrule(String *addrp, int authorized)
155 static rule defaultrule;
159 for (rp = rulep; rp != 0; rp = rp->next) {
160 if(rp->type==d_auth && authorized)
163 rp->program = regcomp(rp->matchre->base);
166 memset(rp->subexp, 0, sizeof(rp->subexp));
168 fprint(2, "matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base);
169 if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
170 if(s_to_c(addrp) == rp->subexp[0].sp)
171 if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].ep)
177 /* Transforms the address into a command.
178 * Returns: -1 ifaddress not matched by reules
179 * 0 ifaddress matched and ok to forward
180 * 1 ifaddress matched and not ok to forward
183 rewrite(dest *dp, message *mp)
185 rule *rp; /* rewriting rule */
186 String *lower; /* lower case version of destination */
189 * Rewrite the address. Matching is case insensitive.
191 lower = s_clone(dp->addr);
192 s_tolower(s_restart(lower));
193 rp = findrule(lower, dp->authorized);
198 strcpy(s_to_c(lower), s_to_c(dp->addr));
199 dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
200 dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
201 dp->status = rp->type;
205 fprint(2, "%s", s_to_c(dp->repl1));
207 fprint(2, "%s", s_to_c(dp->repl2));
215 substitute(String *source, Resub *subexp, message *mp)
226 /* someplace to put it */
229 /* do the substitution */
230 while (*sp != '\0') {
233 case '0': case '1': case '2': case '3': case '4':
234 case '5': case '6': case '7': case '8': case '9':
236 if(subexp[i].sp != 0)
237 for (s = subexp[i].sp;
249 for(s = s_to_c(mp->replyaddr); *s; s++)
264 } else if(*sp == '&') {
265 if(subexp[0].sp != 0)
266 for (s = subexp[0].sp;
267 s < subexp[0].ep; s++)
275 return s_restart(stp);
281 fprint(2, "rewrite: %s\n", s);
282 /* make sure the message is seen locally */
283 syslog(0, "mail", "error in rewrite: %s", s);
291 // for (rp = rulep; rp != 0; rp = rp->next) {
292 // fprint(2, "'%s'", rp->matchre->base);
293 // switch (rp->type) {
301 // fprint(2, " alias");
304 // fprint(2, " translate");
307 // fprint(2, " UNKNOWN");
310 // fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
311 // fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");