13308Seric # include <stdio.h> 23313Seric # include "sendmail.h" 33308Seric # include <ctype.h> 43308Seric 5*4061Seric static char SccsId[] = "@(#)readcf.c 3.4 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 233308Seric struct rewrite *RewriteRules; 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(); 38*4061Seric int class; 393308Seric 403308Seric cf = fopen(cfname, "r"); 413308Seric if (cf == NULL) 423308Seric { 433308Seric syserr("cannot open %s", cfname); 443308Seric exit(EX_OSFILE); 453308Seric } 463308Seric 473308Seric while (fgets(buf, sizeof buf, cf) != NULL) 483308Seric { 493308Seric p = rindex(buf, '\n'); 503308Seric if (p != NULL) 513308Seric *p = '\0'; 523308Seric 533308Seric switch (buf[0]) 543308Seric { 553308Seric case '\n': 563308Seric case '\0': 573308Seric case ' ': 583308Seric case '\t': 593308Seric case '#': /* comment */ 603308Seric break; 613308Seric 623308Seric case 'R': /* rewriting rule */ 633308Seric for (p = &buf[1]; *p != '\0' && *p != '\t'; p++) 643308Seric continue; 653308Seric 663308Seric if (*p == '\0') 673308Seric syserr("invalid rewrite line \"%s\"", buf); 683308Seric else 693308Seric { 703308Seric if (rwp == NULL) 713308Seric RewriteRules = rwp = (struct rewrite *) xalloc(sizeof *rwp); 723308Seric else 733308Seric { 743308Seric rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 753308Seric rwp = rwp->r_next; 763308Seric } 773308Seric rwp->r_next = NULL; 783308Seric 793308Seric rwp->r_lhs = prescan(&buf[1], '\t'); 803308Seric if (rwp->r_lhs != NULL) 813308Seric rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); 823308Seric while (*p == '\t') 833308Seric p++; 843308Seric rwp->r_rhs = prescan(p, '\t'); 853308Seric if (rwp->r_rhs != NULL) 863308Seric rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); 873308Seric } 883308Seric break; 893308Seric 903308Seric case 'D': /* macro definition */ 913308Seric define(buf[1], newstr(&buf[2])); 923308Seric break; 933308Seric 943387Seric case 'H': /* required header line */ 953391Seric chompheader(&buf[1], TRUE); 963387Seric break; 973387Seric 98*4061Seric case 'C': /* word class */ 99*4061Seric class = buf[1]; 100*4061Seric if (!isalpha(class)) 101*4061Seric goto badline; 102*4061Seric if (isupper(class)) 103*4061Seric class -= 'A'; 104*4061Seric else 105*4061Seric class -= 'a'; 106*4061Seric 107*4061Seric /* scan the list of words and set class 'i' for all */ 108*4061Seric for (p = &buf[2]; *p != '\0'; ) 109*4061Seric { 110*4061Seric register char *wd; 111*4061Seric char delim; 112*4061Seric register STAB *s; 113*4061Seric 114*4061Seric while (*p != '\0' && isspace(*p)) 115*4061Seric p++; 116*4061Seric wd = p; 117*4061Seric while (*p != '\0' && !isspace(*p)) 118*4061Seric p++; 119*4061Seric delim = *p; 120*4061Seric *p = '\0'; 121*4061Seric if (wd[0] != '\0') 122*4061Seric { 123*4061Seric s = stab(wd, ST_ENTER); 124*4061Seric s->s_class |= 1 << class; 125*4061Seric } 126*4061Seric *p = delim; 127*4061Seric } 128*4061Seric break; 129*4061Seric 1303308Seric default: 131*4061Seric badline: 1323308Seric syserr("unknown control line \"%s\"", buf); 1333308Seric } 1343308Seric } 1353308Seric 1363308Seric /* 1373308Seric printrules(); 1383308Seric */ 1393308Seric } 1403308Seric /* 1413308Seric ** RWCRACK -- crack rewrite line. 1423308Seric ** 1433308Seric ** Parameters: 1443308Seric ** l -- line to crack. 1453308Seric ** 1463308Seric ** Returns: 1473308Seric ** local copy of cracked line. 1483308Seric ** 1493308Seric ** Side Effects: 1503308Seric ** none. 1513308Seric */ 1523308Seric 1533308Seric char ** 1543308Seric rwcrack(l) 1553308Seric register char *l; 1563308Seric { 1573308Seric char *av[MAXATOM]; 1583308Seric int ac = 0; 1593308Seric register char **avp; 1603308Seric char buf[MAXNAME]; 1613308Seric register char *b; 1623308Seric bool wasdelim = FALSE; 1633308Seric char *delims = ":@!^."; 1643308Seric extern char *index(); 1653308Seric bool tchange; 1663308Seric extern char *newstr(), *xalloc(); 1673308Seric 1683308Seric for (avp = av; *l != '\0' && *l != '\n'; avp++) 1693308Seric { 1703308Seric b = buf; 1713308Seric tchange = FALSE; 1723308Seric while (!tchange) 1733308Seric { 1743308Seric if (*l != '$') 1753308Seric { 1763308Seric if (wasdelim || index(delims, *l) != NULL) 1773308Seric tchange = TRUE; 1783308Seric wasdelim = (index(delims, *l) != NULL); 1793308Seric if (wasdelim) 1803308Seric tchange = TRUE; 1813308Seric *b++ = *l++; 1823308Seric continue; 1833308Seric } 1843308Seric 1853308Seric tchange = TRUE; 1863308Seric switch (*++l) 1873308Seric { 1883308Seric case '$': /* literal $ */ 1893308Seric *b++ = *l; 1903308Seric break; 1913308Seric 1923308Seric case '+': /* match anything */ 1933308Seric *b++ = MATCHANY; 1943308Seric *b++ = *++l; 1953308Seric break; 1963308Seric 1973308Seric case '-': /* match one token */ 1983308Seric *b++ = MATCHONE; 1993308Seric *b++ = *++l; 2003308Seric break; 2013308Seric 2023308Seric case '#': /* canonical net name */ 2033308Seric *b++ = CANONNET; 2043308Seric break; 2053308Seric 2063308Seric case '@': /* canonical host name */ 2073308Seric *b++ = CANONHOST; 2083308Seric break; 2093308Seric 2103308Seric case ':': /* canonical user name */ 2113308Seric *b++ = CANONUSER; 2123308Seric break; 2133308Seric 2143308Seric default: 2153308Seric *b++ = '$'; 2163308Seric l--; 2173308Seric break; 2183308Seric } 2193308Seric l++; 2203308Seric } 2213308Seric 2223308Seric /* save the argument we have collected */ 2233308Seric *b = '\0'; 2243308Seric *avp = newstr(buf); 2253308Seric ac++; 2263308Seric } 2273308Seric 2283308Seric /* allocate new space for vector */ 2293308Seric ac++; 2303308Seric *avp = NULL; 2313308Seric avp = (char **) xalloc(ac * sizeof *av); 2323308Seric bmove(av, avp, ac * sizeof *av); 2333308Seric 2343308Seric return (avp); 2353308Seric } 2363308Seric /* 2373308Seric ** PRINTRULES -- print rewrite rules (for debugging) 2383308Seric ** 2393308Seric ** Parameters: 2403308Seric ** none. 2413308Seric ** 2423308Seric ** Returns: 2433308Seric ** none. 2443308Seric ** 2453308Seric ** Side Effects: 2463308Seric ** prints rewrite rules. 2473308Seric */ 2483308Seric 2493308Seric printrules() 2503308Seric { 2513308Seric register struct rewrite *rwp; 2523308Seric 2533308Seric for (rwp = RewriteRules; rwp != NULL; rwp = rwp->r_next) 2543308Seric { 2553308Seric register char **av; 2563308Seric 2573308Seric printf("\n"); 2583308Seric for (av = rwp->r_lhs; *av != NULL; av++) 2593308Seric { 2603308Seric xputs(*av); 2613308Seric putchar('_'); 2623308Seric } 2633308Seric printf("\n\t"); 2643308Seric for (av = rwp->r_rhs; *av != NULL; av++) 2653308Seric { 2663308Seric xputs(*av); 2673308Seric putchar('_'); 2683308Seric } 2693308Seric printf("\n"); 2703308Seric } 2713308Seric } 272