7 * Routines for dealing with the rewrite rules.
11 typedef struct rule rule;
15 String *matchre; /* address match */
16 String *repl1; /* first replacement String */
17 String *repl2; /* second replacement String */
18 d_status type; /* type of rule */
20 Resub subexp[NSUBEXP];
27 static String *substitute(String *, Resub *, message *);
28 static rule *findrule(String *, int);
32 * Get the next token from `line'. The symbol `\l' is replaced by
33 * the name of the local system.
36 rule_parse(String *line, char *system, int *backl)
42 token = s_parse(line, 0);
45 if(strchr(s_to_c(token), '\\')==0)
48 for(cp = s_to_c(token); *cp; cp++) {
49 if(*cp == '\\') switch(*++cp) {
51 s_append(expanded, system);
55 s_putc(expanded, '\\');
58 s_putc(expanded, '\\');
59 s_putc(expanded, *cp);
62 s_putc(expanded, *cp);
65 s_terminate(expanded);
70 getrule(String *line, String *type, char *system)
79 re = rule_parse(s_restart(line), system, &backl);
82 rp = (rule *)malloc(sizeof(rule));
89 rp->matchre = s_new();
90 s_append(rp->matchre, s_to_c(re));
91 s_restart(rp->matchre);
93 s_parse(line, s_restart(type));
94 rp->repl1 = rule_parse(line, system, &backl);
95 rp->repl2 = rule_parse(line, system, &backl);
97 if(strcmp(s_to_c(type), "|") == 0)
99 else if(strcmp(s_to_c(type), ">>") == 0)
101 else if(strcmp(s_to_c(type), "alias") == 0)
103 else if(strcmp(s_to_c(type), "translate") == 0)
104 rp->type = d_translate;
105 else if(strcmp(s_to_c(type), "auth") == 0)
112 fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
118 rlastp = rlastp->next = rp;
123 * rules are of the form:
124 * <reg exp> <String> <repl exp> [<repl exp>]
134 file = abspath("rewrite", UPASLIB, (String *)0);
135 rfp = sysopen(s_to_c(file), "r", 0);
143 while(s_getline(rfp, s_restart(line)))
144 if(getrule(line, type, thissys) && altthissys)
145 getrule(s_restart(line), type, altthissys);
153 /* look up a matching rule */
155 findrule(String *addrp, int authorized)
158 static rule defaultrule;
162 for (rp = rulep; rp != 0; rp = rp->next) {
163 if(rp->type==d_auth && authorized)
166 rp->program = regcomp(rp->matchre->base);
169 memset(rp->subexp, 0, sizeof(rp->subexp));
171 fprint(2, "matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base);
172 if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
173 if(s_to_c(addrp) == rp->subexp[0].s.sp)
174 if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].e.ep)
180 /* Transforms the address into a command.
181 * Returns: -1 ifaddress not matched by reules
182 * 0 ifaddress matched and ok to forward
183 * 1 ifaddress matched and not ok to forward
186 rewrite(dest *dp, message *mp)
188 rule *rp; /* rewriting rule */
189 String *lower; /* lower case version of destination */
192 * Rewrite the address. Matching is case insensitive.
194 lower = s_clone(dp->addr);
195 s_tolower(s_restart(lower));
196 rp = findrule(lower, dp->authorized);
201 strcpy(s_to_c(lower), s_to_c(dp->addr));
202 dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
203 dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
204 dp->status = rp->type;
208 fprint(2, "%s", s_to_c(dp->repl1));
210 fprint(2, "%s", s_to_c(dp->repl2));
217 /* stolen from rc/lex.c */
221 return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
225 getrcvar(char* p, char** rv)
233 bufe=buf+sizeof buf-1;
234 while(p<bufe && idchr(*p))
237 memcpy(buf, p0, p-p0);
241 fprint(2, "varsubst: %s → %s\n", buf, *rv);
246 substitute(String *source, Resub *subexp, message *mp)
257 /* someplace to put it */
260 /* do the substitution */
261 while (*sp != '\0') {
264 case '0': case '1': case '2': case '3': case '4':
265 case '5': case '6': case '7': case '8': case '9':
267 if(subexp[i].s.sp != 0)
268 for (s = subexp[i].s.sp;
280 for(s = s_to_c(mp->replyaddr); *s; s++)
295 } else if(*sp == '&') {
296 if(subexp[0].s.sp != 0)
297 for (s = subexp[0].s.sp;
298 s < subexp[0].e.ep; s++)
300 } else if(*sp == '$') {
301 sp = getrcvar(sp+1, &s);
304 sp--; /* counter sp++ below */
311 return s_restart(stp);
317 fprint(2, "rewrite: %s\n", s);
325 for (rp = rulep; rp != 0; rp = rp->next) {
326 fprint(2, "'%s'", rp->matchre->base);
338 fprint(2, " translate");
341 fprint(2, " UNKNOWN");
344 fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
345 fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");