|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include <regexp.h>
4: #include "mail.h"
5: #include "string.h"
6:
7: /* configuration */
8: #define RULEFILE "rewrite"
9: #define BUFFERSIZE 512
10:
11: /*
12: * Routines for dealing with the rewrite rules.
13: */
14:
15: /* imports */
16: extern char *malloc();
17: extern int strlen();
18: extern regexp *regcomp();
19: extern int regexec();
20: extern void regsub();
21: extern char *upaspath();
22: extern char *thissys;
23:
24: /* globals */
25: typedef struct rule rule;
26:
27: struct rule {
28: char *matchre; /* address match */
29: char *cmdre; /* command used to send message */
30: char *machre; /* next hop */
31: char *restre; /* address after the next hop */
32: regexp *program;
33: rule *next;
34: };
35: static rule *rulep;
36: static rule alwayslocal = {
37: ".*",
38: "",
39: "",
40: NULL
41: };
42: static int eof = 0, eol = 0;
43:
44:
45: /* predeclared */
46: static char *getstring();
47: static char *newstring();
48: static void substitute();
49: static int geteol();
50:
51: extern int
52: getrules()
53: {
54: FILE *rfp;
55: rule *rp, *rlastp=NULL;
56: char *bp;
57:
58: eof = eol = 0;
59: rfp = fopen(upaspath(RULEFILE), "r");
60: if (rfp == NULL) {
61: rulep = &alwayslocal;
62: return -1;
63: }
64: do {
65: /* ignore comments */
66: bp = getstring(rfp);
67: if (*bp=='#' || *bp=='\0')
68: continue;
69:
70: /* get a rule */
71: rp = (rule *)malloc(sizeof(rule));
72: if (rp == NULL)
73: return -1;
74: if (rulep == NULL)
75: rulep = rlastp = rp;
76: else
77: rlastp = rlastp->next = rp;
78: rp->next = NULL;
79: rp->matchre = newstring(bp);
80: rp->cmdre = newstring(getstring(rfp));
81: rp->machre = newstring(getstring(rfp));
82: rp->restre = newstring(getstring(rfp));
83: rp->program = NULL;
84: } while (geteol(rfp));
85: fclose(rfp);
86: #ifdef DEBUG
87: dumprules();
88: #endif DEBUG
89: return 0;
90: }
91:
92: static char *
93: getstring(fp)
94: FILE *fp;
95: {
96: static char buf[BUFFERSIZE];
97: int c, term1=' ', term2='\t';
98: char *bp=buf;
99:
100: if (!eol) {
101: /* skip whitespace */
102: do {
103: c = getc(fp);
104:
105: /* hack to recognize escaped newline */
106: if (c == '\\') {
107: c = getc(fp);
108: if (c == '\n')
109: c = ' ';
110: else
111: *bp++ = '\\';
112: }
113: } while (c == ' ' || c == '\t');
114:
115: /* possible quoted string */
116: if (c == '\'' || c == '"') {
117: term1 = term2 = c;
118: c = getc(fp);
119: }
120:
121: while (c != term1 && c != term2 && !eol) {
122: switch (c) {
123: case EOF:
124: eof = 1;
125: /* fall through */
126: case '\n':
127: eol = 1;
128: break;
129: case '\\':
130: c = getc(fp);
131: /* hack to recognize escaped newline */
132: if (c == '\n') {
133: c = term1;
134: break;
135: } else {
136: *bp++ = '\\';
137: /* fall through */
138: }
139: default:
140: *bp++ = c;
141: c = getc(fp);
142: break;
143: }
144: }
145:
146: }
147: *bp = 0;
148:
149: return buf;
150: }
151:
152: static int
153: geteol(fp)
154: FILE *fp;
155: {
156: while(!eol)
157: getstring(fp);
158: eol = 0;
159: return !eof;
160: }
161:
162: static char *
163: newstring(sp)
164: char *sp;
165: {
166: char *np;
167:
168: np = malloc(strlen(sp)+1);
169: if (np == NULL) {
170: fprintf(stderr, "mail: out of memory\n");
171: exit(1);
172: }
173: strcpy(np, sp);
174: return np;
175: }
176:
177: static rule *
178: findrule(addrp)
179: char *addrp;
180: {
181: rule *rp;
182:
183: for (rp = rulep; rp != NULL; rp = rp->next) {
184: if (rp->program == NULL)
185: rp->program = regcomp(rp->matchre);
186: if (regexec(rp->program, addrp))
187: return rp;
188: }
189: return NULL;
190: }
191:
192: /* Transforms the address into a command.
193: * Returns: -1 if address not matched by reules
194: * 0 if address matched and ok to forward
195: * 1 if address matched and not ok to forward
196: */
197: extern int
198: rewrite(addrp, s, chkfl, cmdp)
199: char *addrp; /* address to rewrite */
200: char *s; /* string that matches \s */
201: int chkfl; /* non-zero if we must check forwarding */
202: char *cmdp; /* (returned) substituted strings */
203: {
204: rule *rp;
205: char dest[ADDRSIZE]; /* next hop for message */
206: char rest[ADDRSIZE]; /* rest of address after hop */
207: char addr[ADDRSIZE]; /* rest of address after hop */
208:
209: /* rewrite the address */
210: rp = findrule(addrp);
211: if (rp == NULL)
212: return -1;
213: if (cmdp != NULL)
214: substitute(rp->program, rp->cmdre, cmdp, s);
215:
216: /* check for legal forwarding */
217: if (!chkfl)
218: return 0;
219: while (1) {
220: substitute(rp->program, rp->restre, rest, s);
221: substitute(rp->program, rp->machre, dest, s);
222: #ifdef DEBUG
223: printf(" %s %s\n", dest, rest);
224: #endif DEBUG
225: if (dest[0] == '\0')
226: return 0;
227: if (!okrmt(dest))
228: return 1;
229: strcpy(addr, rest);
230: rp = findrule(addr);
231: if (rp == NULL)
232: return 1;
233:
234: }
235: }
236:
237: static void
238: substitute(progp, sp, dp, s)
239: regexp *progp; /* context of substitution */
240: char *sp; /* source string */
241: char *dp; /* destination string */
242: char *s; /* strig to substitute for \s */
243: {
244: char *ssp;
245:
246: while (*sp != '\0') {
247: if (*sp == '\\') {
248: switch (*++sp) {
249: case '0':
250: case '1':
251: case '2':
252: case '3':
253: case '4':
254: case '5':
255: case '6':
256: case '7':
257: case '8':
258: case '9':
259: if (progp->startp[*sp-'0'] != NULL)
260: for (ssp = progp->startp[*sp-'0'];
261: ssp < progp->endp[*sp-'0'];
262: ssp++)
263: *dp++ = *ssp;
264: break;
265: case '\\':
266: *dp++ = '\\';
267: break;
268: case '\0':
269: sp--;
270: break;
271: case 's':
272: for(ssp = s; *ssp; ssp++)
273: *dp++ = *ssp;
274: break;
275: default:
276: *dp++ = *sp;
277: break;
278: }
279: } else if (*sp == '&') {
280: if (progp->startp[0] != NULL)
281: for (ssp = progp->startp[0];
282: ssp < progp->endp[0]; ssp++)
283: *dp++ = *ssp;
284: } else
285: *dp++ = *sp;
286: sp++;
287: }
288: *dp = '\0';
289: }
290:
291: #ifdef DEBUG
292: regdump(subp)
293: regexp *subp;
294: {
295: int i;
296: char *cp;
297:
298: printf ("matches are:\n");
299: for (i = 0; i < NSUBEXP; i++) {
300: if (subp->startp[i] != NULL) {
301: printf("\t(%d) ", i);
302: for (cp = subp->startp[i]; cp < subp->endp[i]; cp++)
303: putchar(*cp);
304: putchar('\n');
305: }
306: }
307: }
308: #endif DEBUG
309:
310: #ifdef DEBUG
311: dumprules()
312: {
313: rule *rp;
314:
315: for (rp = rulep; rp != NULL; rp = rp->next) {
316: fprintf (stderr, "matchre: %s\n", rp->matchre);
317: fprintf (stderr, "cmdre: %s\n", rp->cmdre);
318: fprintf (stderr, "machre: %s\n", rp->machre);
319: fprintf (stderr, "restre: %s\n", rp->restre);
320: }
321: }
322: #endif DEBUG
323:
324: regerror(s)
325: char* s;
326: {
327: fprintf(stderr, "rewrite: %s\n", s);
328: exit(1);
329: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.