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