|
|
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.