|
|
1.1 root 1: #include <stdio.h>
2: #include <regexp.h>
3: #include "mail.h"
4: #include "string.h"
5: #include "dest.h"
6: #include "aux.h"
7:
8: /* configuration */
9: #define RULEFILE "rewrite"
10:
11: /*
12: * Routines for dealing with the rewrite rules.
13: */
14:
15: /* imports */
16: extern char *malloc();
17: extern regexp *regcomp();
18: extern int regexec();
19: extern void regsub();
20: extern void exit();
21: extern char *thissys;
22:
23: /* globals */
24: typedef struct rule rule;
25:
26: #define NSUBEXP 10
27: struct rule {
28: string *matchre; /* address match */
29: string *repl1; /* first replacement string */
30: string *repl2; /* second replacement string */
31: d_status type; /* type of rule */
32: regexp *program;
33: regsubexp subexp[NSUBEXP];
34: rule *next;
35: };
36: static rule *rulep;
37:
38: /* predeclared */
39: static string *substitute();
40:
41: /*
42: * Get the next token from `line'. The symbol `\l' is replaced by
43: * the name of the local system.
44: */
45: string *
46: rule_parse(line)
47: string *line;
48: {
49: string *token;
50: string *expanded = (string *)NULL;
51: char *cp;
52:
53: token = s_parse(line, (string *)NULL);
54: if(token == (string *)NULL)
55: return(token);
56: if ((cp = strchr(s_to_c(token), '\\'))==NULL)
57: return(token);
58: expanded = s_new();
59: if (expanded == NULL) {
60: s_free(token);
61: return((string *)NULL);
62: }
63: for(cp = s_to_c(token); *cp; cp++) {
64: if(*cp == '\\') switch(*++cp) {
65: case 'l':
66: s_append(expanded, thissys);
67: break;
68: case '\\':
69: s_putc(expanded, '\\');
70: break;
71: default:
72: s_putc(expanded, '\\');
73: s_putc(expanded, *cp);
74: break;
75: } else
76: s_putc(expanded, *cp);
77: }
78: s_free(token);
79: s_terminate(expanded);
80: return(expanded);
81: }
82:
83: /*
84: * rules are of the form:
85: * <reg exp> <string> <repl exp> [<repl exp>]
86: */
87: extern int
88: getrules()
89: {
90: FILE *rfp;
91: rule *rp, *rlastp=NULL;
92: string *line;
93: string *type;
94: string *file;
95: string *re;
96:
97: file = abspath(RULEFILE, UPASROOT, (string *)NULL);
98: rfp = fopen(s_to_c(file), "r");
99: if (rfp == NULL) {
100: rulep = NULL;
101: return -1;
102: }
103: line = s_new();
104: type = s_new();
105: while(s_getline(rfp, s_restart(line)) != NULL) {
106: /* get a rule */
107: rp = (rule *)malloc(sizeof(rule));
108: if (rp == NULL) {
109: perror("getrules:");
110: exit(1);
111: }
112: rp->next = NULL;
113: re = rule_parse(s_restart(line));
114: s_tolower(re);
115: rp->matchre = s_new();
116: if(*s_to_c(re)!='^')
117: s_append(rp->matchre, "^");
118: s_append(rp->matchre, s_to_c(re));
119: s_append(rp->matchre, "$");
120: s_restart(rp->matchre);
121: s_free(re);
122: s_parse(line, s_restart(type));
123: rp->repl1 = rule_parse(line);
124: rp->repl2 = rule_parse(line);
125: rp->program = NULL;
126: if (strcmp(s_to_c(type), "|") == 0)
127: rp->type = d_pipe;
128: else if (strcmp(s_to_c(type), ">>") == 0)
129: rp->type = d_cat;
130: else if (strcmp(s_to_c(type), "alias") == 0)
131: rp->type = d_alias;
132: else if (strcmp(s_to_c(type), "translate") == 0)
133: rp->type = d_translate;
134: else if (strcmp(s_to_c(type), "auth") == 0)
135: rp->type = d_auth;
136: else {
137: s_free(rp->matchre);
138: s_free(rp->repl1);
139: s_free(rp->repl2);
140: free((char *)rp);
141: fprintf(stderr,"illegal rewrite rule: %s\n", s_to_c(line));
142: continue;
143: }
144: if (rulep == NULL)
145: rulep = rlastp = rp;
146: else
147: rlastp = rlastp->next = rp;
148: }
149: s_free(type);
150: s_free(line);
151: s_free(file);
152: fclose(rfp);
153: return 0;
154: }
155:
156: /* look up a matching rule */
157: static rule *
158: findrule(addrp, authorized)
159: string *addrp;
160: {
161: rule *rp;
162: static rule defaultrule;
163: string *matcher;
164:
165: if (rulep == NULL)
166: return &defaultrule;
167: for (rp = rulep; rp != NULL; rp = rp->next) {
168: if (rp->type==d_auth && authorized)
169: continue;
170: if (rp->program == NULL)
171: rp->program = regcomp(rp->matchre->base);
172: if (rp->program == NULL)
173: continue;
174: if (regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
175: return rp;
176: }
177: return NULL;
178: }
179:
180: /* Transforms the address into a command.
181: * Returns: -1 if address not matched by reules
182: * 0 if address matched and ok to forward
183: * 1 if address matched and not ok to forward
184: */
185: extern int
186: rewrite(dp, s)
187: dest *dp; /* destination to rewrite */
188: char *s; /* string that matches \s */
189: {
190: rule *rp; /* rewriting rule */
191: string *lower; /* lower case version of destination */
192: char *cp;
193:
194: /*
195: * Rewrite the address. Matching is case insensitive.
196: */
197: lower = s_clone(s_restart(dp->addr));
198: s_tolower(s_restart(lower));
199: rp = findrule(lower, dp->authorized);
200: if (rp == NULL)
201: return -1;
202: strcpy(s_to_c(lower), s_to_c(dp->addr));
203: dp->repl1 = substitute(rp->repl1, rp->subexp, s);
204: dp->repl2 = substitute(rp->repl2, rp->subexp, s);
205: dp->status = rp->type;
206: return 0;
207: }
208:
209: static string *
210: substitute(source, subexp, s)
211: string *source; /* substitution expression */
212: regsubexp *subexp; /* the matches */
213: char *s; /* string to substitute for \s */
214: {
215: register char *sp;
216: register char *ssp;
217: register string *stp;
218: register int i;
219:
220: if (source == NULL)
221: return NULL;
222: sp = s_to_c(source);
223:
224: /* someplace to put it */
225: stp = s_new();
226:
227: /* do the substitution */
228: while (*sp != '\0') {
229: if (*sp == '\\') {
230: switch (*++sp) {
231: case '0': case '1': case '2': case '3': case '4':
232: case '5': case '6': case '7': case '8': case '9':
233: i = *sp-'0';
234: if (subexp[i].sp != NULL)
235: for (ssp = subexp[i].sp;
236: ssp < subexp[i].ep;
237: ssp++)
238: s_putc(stp, *ssp);
239: break;
240: case '\\':
241: s_putc(stp, '\\');
242: break;
243: case '\0':
244: sp--;
245: break;
246: case 's':
247: for(ssp = s; *ssp; ssp++)
248: s_putc(stp, *ssp);
249: break;
250: default:
251: s_putc(stp, *sp);
252: break;
253: }
254: } else if (*sp == '&') {
255: if (subexp[0].sp != NULL)
256: for (ssp = subexp[0].sp;
257: ssp < subexp[0].ep; ssp++)
258: s_putc(stp, *ssp);
259: } else
260: s_putc(stp, *sp);
261: sp++;
262: }
263: s_terminate(stp);
264:
265: return s_restart(stp);
266: }
267:
268: regerror(s)
269: char* s;
270: {
271: fprintf(stderr, "rewrite: %s\n", s);
272: }
273:
274: dumprules()
275: {
276: rule *rp;
277:
278: for (rp = rulep; rp != NULL; rp = rp->next) {
279: fprintf (stderr, "'%s'", rp->matchre->base);
280: switch (rp->type) {
281: case d_pipe:
282: fprintf(stderr, " |");
283: break;
284: case d_cat:
285: fprintf(stderr, " >>");
286: break;
287: case d_alias:
288: fprintf(stderr, " alias");
289: break;
290: case d_translate:
291: fprintf(stderr, " translate");
292: break;
293: default:
294: fprintf(stderr, " UNKNOWN");
295: break;
296: }
297: fprintf (stderr, " '%s'", rp->repl1 ? rp->repl1->base:"...");
298: fprintf (stderr, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");
299: }
300: }
301:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.