13308Seric # include <stdio.h> 23313Seric # include "sendmail.h" 33308Seric # include <ctype.h> 43308Seric 5*4103Seric static char SccsId[] = "@(#)readcf.c 3.8 08/10/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 234072Seric 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 **prescan(); 343308Seric extern char **copyplist(); 354061Seric int class; 364072Seric int ruleset = 0; 373308Seric 383308Seric cf = fopen(cfname, "r"); 393308Seric if (cf == NULL) 403308Seric { 413308Seric syserr("cannot open %s", cfname); 423308Seric exit(EX_OSFILE); 433308Seric } 443308Seric 453308Seric while (fgets(buf, sizeof buf, cf) != NULL) 463308Seric { 473308Seric p = rindex(buf, '\n'); 483308Seric if (p != NULL) 493308Seric *p = '\0'; 503308Seric 513308Seric switch (buf[0]) 523308Seric { 533308Seric case '\n': 543308Seric case '\0': 553308Seric case ' ': 563308Seric case '\t': 573308Seric case '#': /* comment */ 583308Seric break; 593308Seric 603308Seric case 'R': /* rewriting rule */ 613308Seric for (p = &buf[1]; *p != '\0' && *p != '\t'; p++) 623308Seric continue; 633308Seric 643308Seric if (*p == '\0') 653308Seric syserr("invalid rewrite line \"%s\"", buf); 663308Seric else 673308Seric { 683308Seric if (rwp == NULL) 694072Seric { 704072Seric RewriteRules[ruleset] = rwp = 714072Seric (struct rewrite *) xalloc(sizeof *rwp); 724072Seric } 733308Seric else 743308Seric { 753308Seric rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 763308Seric rwp = rwp->r_next; 773308Seric } 783308Seric rwp->r_next = NULL; 793308Seric 803308Seric rwp->r_lhs = prescan(&buf[1], '\t'); 813308Seric if (rwp->r_lhs != NULL) 823308Seric rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); 833308Seric while (*p == '\t') 843308Seric p++; 853308Seric rwp->r_rhs = prescan(p, '\t'); 863308Seric if (rwp->r_rhs != NULL) 873308Seric rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); 883308Seric } 893308Seric break; 903308Seric 914072Seric case 'S': /* select rewriting set */ 924072Seric ruleset = atoi(&buf[1]); 934072Seric rwp = NULL; 944072Seric break; 954072Seric 963308Seric case 'D': /* macro definition */ 973308Seric define(buf[1], newstr(&buf[2])); 983308Seric break; 993308Seric 1003387Seric case 'H': /* required header line */ 1014088Seric (void) chompheader(&buf[1], TRUE); 1023387Seric break; 1033387Seric 1044061Seric case 'C': /* word class */ 1054061Seric class = buf[1]; 1064061Seric if (!isalpha(class)) 1074061Seric goto badline; 1084061Seric if (isupper(class)) 1094061Seric class -= 'A'; 1104061Seric else 1114061Seric class -= 'a'; 1124061Seric 1134061Seric /* scan the list of words and set class 'i' for all */ 1144061Seric for (p = &buf[2]; *p != '\0'; ) 1154061Seric { 1164061Seric register char *wd; 1174061Seric char delim; 1184061Seric register STAB *s; 1194061Seric 1204061Seric while (*p != '\0' && isspace(*p)) 1214061Seric p++; 1224061Seric wd = p; 1234061Seric while (*p != '\0' && !isspace(*p)) 1244061Seric p++; 1254061Seric delim = *p; 1264061Seric *p = '\0'; 1274061Seric if (wd[0] != '\0') 1284061Seric { 129*4103Seric s = stab(wd, ST_CLASS, ST_ENTER); 1304061Seric s->s_class |= 1 << class; 1314061Seric } 1324061Seric *p = delim; 1334061Seric } 1344061Seric break; 1354061Seric 1364096Seric case 'M': /* define mailer */ 1374096Seric makemailer(&buf[1]); 1384096Seric break; 1394096Seric 1403308Seric default: 1414061Seric badline: 1423308Seric syserr("unknown control line \"%s\"", buf); 1433308Seric } 1443308Seric } 1454096Seric } 1464096Seric /* 1474096Seric ** MAKEMAILER -- define a new mailer. 1484096Seric ** 1494096Seric ** Parameters: 1504096Seric ** line -- description of mailer. This is in tokens 1514096Seric ** separated by white space. The fields are: 1524096Seric ** * the name of the mailer, as refered to 1534096Seric ** in the rewriting rules. 1544096Seric ** * the pathname of the program to fork to 1554096Seric ** execute it. 1564096Seric ** * the options needed by this program. 1574096Seric ** * the macro string needed to translate 1584096Seric ** a local "from" name to one that can be 1594096Seric ** returned to this machine. 1604096Seric ** * the argument vector (a series of parameters). 1614096Seric ** 1624096Seric ** Returns: 1634096Seric ** none. 1644096Seric ** 1654096Seric ** Side Effects: 1664096Seric ** enters the mailer into the mailer table. 1674096Seric */ 1683308Seric 1694096Seric # define SETWORD \ 1704096Seric { \ 1714096Seric while (*p != '\0' && isspace(*p)) \ 1724096Seric p++; \ 1734096Seric q = p; \ 1744096Seric while (*p != '\0' && !isspace(*p)) \ 1754096Seric p++; \ 1764096Seric if (*p != '\0') \ 1774096Seric *p++ = '\0'; \ 1784096Seric } 1794096Seric 1804096Seric makemailer(line) 1814096Seric char *line; 1824096Seric { 1834096Seric register char *p; 1844096Seric register char *q; 1854096Seric char *mname; 1864096Seric char *mpath; 1874096Seric int mopts; 1884096Seric char *mfrom; 1894096Seric register struct mailer *m; 1904096Seric char *margv[MAXPV + 1]; 1914096Seric register int i; 1924096Seric extern int NextMailer; 1934096Seric 1944096Seric if (NextMailer >= MAXMAILERS) 1954096Seric { 1964096Seric syserr("Too many mailers defined"); 1974096Seric return; 1984096Seric } 1994096Seric 2004096Seric /* collect initial information */ 2014096Seric p = line; 2024096Seric SETWORD; 2034096Seric mname = q; 2044096Seric SETWORD; 2054096Seric mpath = q; 2064096Seric SETWORD; 2074096Seric mopts = crackopts(q); 2084096Seric SETWORD; 2094096Seric mfrom = q; 2104096Seric 2114096Seric if (*p == '\0') 2124096Seric { 2134096Seric syserr("invalid M line in configuration file"); 2144096Seric return; 2154096Seric } 2164096Seric 2174096Seric /* allocate a mailer */ 2184096Seric m = (struct mailer *) xalloc(sizeof *m); 2194096Seric m->m_name = newstr(mname); 2204096Seric m->m_mailer = newstr(mpath); 2214096Seric m->m_flags = mopts; 2224096Seric m->m_from = newstr(mfrom); 2234096Seric m->m_badstat = EX_UNAVAILABLE; 2244096Seric m->m_sendq = NULL; 2254096Seric Mailer[NextMailer++] = m; 2264096Seric 2274096Seric /* collect the argument vector */ 2284096Seric for (i = 0; i < MAXPV - 1 && *p != '\0'; i++) 2294096Seric { 2304096Seric SETWORD; 2314096Seric margv[i] = newstr(q); 2324096Seric } 2334096Seric margv[i++] = NULL; 2344096Seric 2354096Seric /* save the argv */ 2364096Seric m->m_argv = (char **) xalloc(sizeof margv[0] * i); 2374096Seric bmove((char *) margv, (char *) m->m_argv, sizeof margv[0] * i); 2383308Seric } 2393308Seric /* 2403308Seric ** PRINTRULES -- print rewrite rules (for debugging) 2413308Seric ** 2423308Seric ** Parameters: 2433308Seric ** none. 2443308Seric ** 2453308Seric ** Returns: 2463308Seric ** none. 2473308Seric ** 2483308Seric ** Side Effects: 2493308Seric ** prints rewrite rules. 2503308Seric */ 2513308Seric 2523308Seric printrules() 2533308Seric { 2543308Seric register struct rewrite *rwp; 2554072Seric register int ruleset; 2563308Seric 2574072Seric for (ruleset = 0; ruleset < 10; ruleset++) 2583308Seric { 2594072Seric if (RewriteRules[ruleset] == NULL) 2604072Seric continue; 2614072Seric printf("\n----Rule Set %d:\n", ruleset); 2623308Seric 2634072Seric for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 2643308Seric { 2654072Seric register char **av; 2664072Seric 2674072Seric printf("\n"); 2684072Seric for (av = rwp->r_lhs; *av != NULL; av++) 2694072Seric { 2704072Seric xputs(*av); 2714072Seric putchar('_'); 2724072Seric } 2734072Seric printf("\n\t"); 2744072Seric for (av = rwp->r_rhs; *av != NULL; av++) 2754072Seric { 2764072Seric xputs(*av); 2774072Seric putchar('_'); 2784072Seric } 2794072Seric printf("\n"); 2803308Seric } 2813308Seric } 2823308Seric } 2834096Seric /* 2844096Seric ** CRACKOPTS -- crack mailer options 2854096Seric ** 2864096Seric ** These options modify the functioning of the mailer 2874096Seric ** from the configuration table. 2884096Seric ** 2894096Seric ** Parameters: 2904096Seric ** p -- pointer to vector of options. 2914096Seric ** 2924096Seric ** Returns: 2934096Seric ** option list in binary. 2944096Seric ** 2954096Seric ** Side Effects: 2964096Seric ** none. 2974096Seric */ 2984096Seric 2994096Seric struct optlist 3004096Seric { 3014096Seric char opt_name; /* external name of option */ 3024096Seric int opt_value; /* internal name of option */ 3034096Seric }; 3044096Seric struct optlist OptList[] = 3054096Seric { 3064096Seric 'f', M_FOPT, 3074096Seric 'r', M_ROPT, 3084096Seric 'q', M_QUIET, 3094096Seric 'S', M_RESTR, 3104096Seric 'n', M_NHDR, 3114096Seric 'l', M_NOHOST, 3124096Seric 's', M_STRIPQ, 3134096Seric 'm', M_MUSER, 3144096Seric 'F', M_NEEDFROM, 3154096Seric 'D', M_NEEDDATE, 3164096Seric 'M', M_MSGID, 3174096Seric 'u', M_USR_UPPER, 3184096Seric 'h', M_HST_UPPER, 3194096Seric 'x', M_FULLNAME, 3204096Seric 'A', M_ARPAFMT, 3214096Seric 0, 0 3224096Seric }; 3234096Seric 3244096Seric crackopts(p) 3254096Seric register char *p; 3264096Seric { 3274096Seric register struct optlist *o; 3284096Seric register int opts = 0; 3294096Seric 3304096Seric while (*p != '\0') 3314096Seric { 3324096Seric for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++) 3334096Seric continue; 3344096Seric if (o->opt_name == '\0') 3354096Seric syserr("bad mailer option %c", *p); 3364096Seric opts |= o->opt_value; 3374096Seric p++; 3384096Seric } 3394096Seric return (opts); 3404096Seric } 341