13308Seric # include <stdio.h> 23313Seric # include "sendmail.h" 33308Seric # include <ctype.h> 43308Seric 5*4072Seric static char SccsId[] = "@(#)readcf.c 3.5 08/08/81"; 63308Seric 73308Seric /* 83308Seric ** READCF -- read control file. 93308Seric ** 103308Seric ** This routine reads the control file and builds the internal 113308Seric ** form. 123308Seric ** 133308Seric ** Parameters: 143308Seric ** cfname -- control file name. 153308Seric ** 163308Seric ** Returns: 173308Seric ** none. 183308Seric ** 193308Seric ** Side Effects: 203308Seric ** Builds several internal tables. 213308Seric */ 223308Seric 23*4072Seric struct rewrite *RewriteRules[10]; 243308Seric 253308Seric 263308Seric readcf(cfname) 273308Seric char *cfname; 283308Seric { 293308Seric FILE *cf; 303308Seric char buf[MAXLINE]; 313308Seric register char *p; 323308Seric struct rewrite *rwp = NULL; 333308Seric extern char *xalloc(); 343308Seric extern char **prescan(); 353308Seric extern char **copyplist(); 363308Seric extern char *rindex(); 373308Seric extern char *newstr(); 384061Seric int class; 39*4072Seric int ruleset = 0; 403308Seric 413308Seric cf = fopen(cfname, "r"); 423308Seric if (cf == NULL) 433308Seric { 443308Seric syserr("cannot open %s", cfname); 453308Seric exit(EX_OSFILE); 463308Seric } 473308Seric 483308Seric while (fgets(buf, sizeof buf, cf) != NULL) 493308Seric { 503308Seric p = rindex(buf, '\n'); 513308Seric if (p != NULL) 523308Seric *p = '\0'; 533308Seric 543308Seric switch (buf[0]) 553308Seric { 563308Seric case '\n': 573308Seric case '\0': 583308Seric case ' ': 593308Seric case '\t': 603308Seric case '#': /* comment */ 613308Seric break; 623308Seric 633308Seric case 'R': /* rewriting rule */ 643308Seric for (p = &buf[1]; *p != '\0' && *p != '\t'; p++) 653308Seric continue; 663308Seric 673308Seric if (*p == '\0') 683308Seric syserr("invalid rewrite line \"%s\"", buf); 693308Seric else 703308Seric { 713308Seric if (rwp == NULL) 72*4072Seric { 73*4072Seric RewriteRules[ruleset] = rwp = 74*4072Seric (struct rewrite *) xalloc(sizeof *rwp); 75*4072Seric } 763308Seric else 773308Seric { 783308Seric rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 793308Seric rwp = rwp->r_next; 803308Seric } 813308Seric rwp->r_next = NULL; 823308Seric 833308Seric rwp->r_lhs = prescan(&buf[1], '\t'); 843308Seric if (rwp->r_lhs != NULL) 853308Seric rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); 863308Seric while (*p == '\t') 873308Seric p++; 883308Seric rwp->r_rhs = prescan(p, '\t'); 893308Seric if (rwp->r_rhs != NULL) 903308Seric rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); 913308Seric } 923308Seric break; 933308Seric 94*4072Seric case 'S': /* select rewriting set */ 95*4072Seric ruleset = atoi(&buf[1]); 96*4072Seric rwp = NULL; 97*4072Seric break; 98*4072Seric 993308Seric case 'D': /* macro definition */ 1003308Seric define(buf[1], newstr(&buf[2])); 1013308Seric break; 1023308Seric 1033387Seric case 'H': /* required header line */ 1043391Seric chompheader(&buf[1], TRUE); 1053387Seric break; 1063387Seric 1074061Seric case 'C': /* word class */ 1084061Seric class = buf[1]; 1094061Seric if (!isalpha(class)) 1104061Seric goto badline; 1114061Seric if (isupper(class)) 1124061Seric class -= 'A'; 1134061Seric else 1144061Seric class -= 'a'; 1154061Seric 1164061Seric /* scan the list of words and set class 'i' for all */ 1174061Seric for (p = &buf[2]; *p != '\0'; ) 1184061Seric { 1194061Seric register char *wd; 1204061Seric char delim; 1214061Seric register STAB *s; 1224061Seric 1234061Seric while (*p != '\0' && isspace(*p)) 1244061Seric p++; 1254061Seric wd = p; 1264061Seric while (*p != '\0' && !isspace(*p)) 1274061Seric p++; 1284061Seric delim = *p; 1294061Seric *p = '\0'; 1304061Seric if (wd[0] != '\0') 1314061Seric { 1324061Seric s = stab(wd, ST_ENTER); 1334061Seric s->s_class |= 1 << class; 1344061Seric } 1354061Seric *p = delim; 1364061Seric } 1374061Seric break; 1384061Seric 1393308Seric default: 1404061Seric badline: 1413308Seric syserr("unknown control line \"%s\"", buf); 1423308Seric } 1433308Seric } 1443308Seric 1453308Seric /* 1463308Seric printrules(); 1473308Seric */ 1483308Seric } 1493308Seric /* 1503308Seric ** RWCRACK -- crack rewrite line. 1513308Seric ** 1523308Seric ** Parameters: 1533308Seric ** l -- line to crack. 1543308Seric ** 1553308Seric ** Returns: 1563308Seric ** local copy of cracked line. 1573308Seric ** 1583308Seric ** Side Effects: 1593308Seric ** none. 1603308Seric */ 1613308Seric 1623308Seric char ** 1633308Seric rwcrack(l) 1643308Seric register char *l; 1653308Seric { 1663308Seric char *av[MAXATOM]; 1673308Seric int ac = 0; 1683308Seric register char **avp; 1693308Seric char buf[MAXNAME]; 1703308Seric register char *b; 1713308Seric bool wasdelim = FALSE; 1723308Seric char *delims = ":@!^."; 1733308Seric extern char *index(); 1743308Seric bool tchange; 1753308Seric extern char *newstr(), *xalloc(); 1763308Seric 1773308Seric for (avp = av; *l != '\0' && *l != '\n'; avp++) 1783308Seric { 1793308Seric b = buf; 1803308Seric tchange = FALSE; 1813308Seric while (!tchange) 1823308Seric { 1833308Seric if (*l != '$') 1843308Seric { 1853308Seric if (wasdelim || index(delims, *l) != NULL) 1863308Seric tchange = TRUE; 1873308Seric wasdelim = (index(delims, *l) != NULL); 1883308Seric if (wasdelim) 1893308Seric tchange = TRUE; 1903308Seric *b++ = *l++; 1913308Seric continue; 1923308Seric } 1933308Seric 1943308Seric tchange = TRUE; 1953308Seric switch (*++l) 1963308Seric { 1973308Seric case '$': /* literal $ */ 1983308Seric *b++ = *l; 1993308Seric break; 2003308Seric 2013308Seric case '+': /* match anything */ 2023308Seric *b++ = MATCHANY; 2033308Seric *b++ = *++l; 2043308Seric break; 2053308Seric 2063308Seric case '-': /* match one token */ 2073308Seric *b++ = MATCHONE; 2083308Seric *b++ = *++l; 2093308Seric break; 2103308Seric 2113308Seric case '#': /* canonical net name */ 2123308Seric *b++ = CANONNET; 2133308Seric break; 2143308Seric 2153308Seric case '@': /* canonical host name */ 2163308Seric *b++ = CANONHOST; 2173308Seric break; 2183308Seric 2193308Seric case ':': /* canonical user name */ 2203308Seric *b++ = CANONUSER; 2213308Seric break; 2223308Seric 2233308Seric default: 2243308Seric *b++ = '$'; 2253308Seric l--; 2263308Seric break; 2273308Seric } 2283308Seric l++; 2293308Seric } 2303308Seric 2313308Seric /* save the argument we have collected */ 2323308Seric *b = '\0'; 2333308Seric *avp = newstr(buf); 2343308Seric ac++; 2353308Seric } 2363308Seric 2373308Seric /* allocate new space for vector */ 2383308Seric ac++; 2393308Seric *avp = NULL; 2403308Seric avp = (char **) xalloc(ac * sizeof *av); 2413308Seric bmove(av, avp, ac * sizeof *av); 2423308Seric 2433308Seric return (avp); 2443308Seric } 2453308Seric /* 2463308Seric ** PRINTRULES -- print rewrite rules (for debugging) 2473308Seric ** 2483308Seric ** Parameters: 2493308Seric ** none. 2503308Seric ** 2513308Seric ** Returns: 2523308Seric ** none. 2533308Seric ** 2543308Seric ** Side Effects: 2553308Seric ** prints rewrite rules. 2563308Seric */ 2573308Seric 2583308Seric printrules() 2593308Seric { 2603308Seric register struct rewrite *rwp; 261*4072Seric register int ruleset; 2623308Seric 263*4072Seric for (ruleset = 0; ruleset < 10; ruleset++) 2643308Seric { 265*4072Seric if (RewriteRules[ruleset] == NULL) 266*4072Seric continue; 267*4072Seric printf("\n----Rule Set %d:\n", ruleset); 2683308Seric 269*4072Seric for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 2703308Seric { 271*4072Seric register char **av; 272*4072Seric 273*4072Seric printf("\n"); 274*4072Seric for (av = rwp->r_lhs; *av != NULL; av++) 275*4072Seric { 276*4072Seric xputs(*av); 277*4072Seric putchar('_'); 278*4072Seric } 279*4072Seric printf("\n\t"); 280*4072Seric for (av = rwp->r_rhs; *av != NULL; av++) 281*4072Seric { 282*4072Seric xputs(*av); 283*4072Seric putchar('_'); 284*4072Seric } 285*4072Seric printf("\n"); 2863308Seric } 2873308Seric } 2883308Seric } 289