13313Seric # include "sendmail.h" 23308Seric 3*4197Seric static char SccsId[] = "@(#)readcf.c 3.11 08/21/81"; 43308Seric 53308Seric /* 63308Seric ** READCF -- read control file. 73308Seric ** 83308Seric ** This routine reads the control file and builds the internal 93308Seric ** form. 103308Seric ** 113308Seric ** Parameters: 123308Seric ** cfname -- control file name. 133308Seric ** 143308Seric ** Returns: 153308Seric ** none. 163308Seric ** 173308Seric ** Side Effects: 183308Seric ** Builds several internal tables. 193308Seric */ 203308Seric 214072Seric struct rewrite *RewriteRules[10]; 223308Seric 233308Seric 243308Seric readcf(cfname) 253308Seric char *cfname; 263308Seric { 273308Seric FILE *cf; 283308Seric char buf[MAXLINE]; 293308Seric register char *p; 303308Seric struct rewrite *rwp = NULL; 313308Seric extern char **prescan(); 323308Seric extern char **copyplist(); 334061Seric int class; 344072Seric int ruleset = 0; 353308Seric 363308Seric cf = fopen(cfname, "r"); 373308Seric if (cf == NULL) 383308Seric { 393308Seric syserr("cannot open %s", cfname); 403308Seric exit(EX_OSFILE); 413308Seric } 423308Seric 433308Seric while (fgets(buf, sizeof buf, cf) != NULL) 443308Seric { 453308Seric p = rindex(buf, '\n'); 463308Seric if (p != NULL) 473308Seric *p = '\0'; 483308Seric 493308Seric switch (buf[0]) 503308Seric { 513308Seric case '\n': 523308Seric case '\0': 533308Seric case ' ': 543308Seric case '\t': 553308Seric case '#': /* comment */ 563308Seric break; 573308Seric 583308Seric case 'R': /* rewriting rule */ 593308Seric for (p = &buf[1]; *p != '\0' && *p != '\t'; p++) 603308Seric continue; 613308Seric 623308Seric if (*p == '\0') 633308Seric syserr("invalid rewrite line \"%s\"", buf); 643308Seric else 653308Seric { 663308Seric if (rwp == NULL) 674072Seric { 684072Seric RewriteRules[ruleset] = rwp = 694072Seric (struct rewrite *) xalloc(sizeof *rwp); 704072Seric } 713308Seric else 723308Seric { 733308Seric rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 743308Seric rwp = rwp->r_next; 753308Seric } 763308Seric rwp->r_next = NULL; 773308Seric 783308Seric rwp->r_lhs = prescan(&buf[1], '\t'); 793308Seric if (rwp->r_lhs != NULL) 803308Seric rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); 813308Seric while (*p == '\t') 823308Seric p++; 833308Seric rwp->r_rhs = prescan(p, '\t'); 843308Seric if (rwp->r_rhs != NULL) 853308Seric rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); 863308Seric } 873308Seric break; 883308Seric 894072Seric case 'S': /* select rewriting set */ 904072Seric ruleset = atoi(&buf[1]); 914072Seric rwp = NULL; 924072Seric break; 934072Seric 943308Seric case 'D': /* macro definition */ 953308Seric define(buf[1], newstr(&buf[2])); 963308Seric break; 973308Seric 983387Seric case 'H': /* required header line */ 994088Seric (void) chompheader(&buf[1], TRUE); 1003387Seric break; 1013387Seric 1024061Seric case 'C': /* word class */ 1034061Seric class = buf[1]; 1044061Seric if (!isalpha(class)) 1054061Seric goto badline; 1064061Seric if (isupper(class)) 1074061Seric class -= 'A'; 1084061Seric else 1094061Seric class -= 'a'; 1104061Seric 1114061Seric /* scan the list of words and set class 'i' for all */ 1124061Seric for (p = &buf[2]; *p != '\0'; ) 1134061Seric { 1144061Seric register char *wd; 1154061Seric char delim; 1164061Seric register STAB *s; 1174061Seric 1184061Seric while (*p != '\0' && isspace(*p)) 1194061Seric p++; 1204061Seric wd = p; 1214061Seric while (*p != '\0' && !isspace(*p)) 1224061Seric p++; 1234061Seric delim = *p; 1244061Seric *p = '\0'; 1254061Seric if (wd[0] != '\0') 1264061Seric { 1274103Seric s = stab(wd, ST_CLASS, ST_ENTER); 1284061Seric s->s_class |= 1 << class; 1294061Seric } 1304061Seric *p = delim; 1314061Seric } 1324061Seric break; 1334061Seric 1344096Seric case 'M': /* define mailer */ 1354096Seric makemailer(&buf[1]); 1364096Seric break; 1374096Seric 1383308Seric default: 1394061Seric badline: 1403308Seric syserr("unknown control line \"%s\"", buf); 1413308Seric } 1423308Seric } 1434096Seric } 1444096Seric /* 1454096Seric ** MAKEMAILER -- define a new mailer. 1464096Seric ** 1474096Seric ** Parameters: 1484096Seric ** line -- description of mailer. This is in tokens 1494096Seric ** separated by white space. The fields are: 1504096Seric ** * the name of the mailer, as refered to 1514096Seric ** in the rewriting rules. 1524096Seric ** * the pathname of the program to fork to 1534096Seric ** execute it. 1544096Seric ** * the options needed by this program. 1554096Seric ** * the macro string needed to translate 1564096Seric ** a local "from" name to one that can be 1574096Seric ** returned to this machine. 1584096Seric ** * the argument vector (a series of parameters). 1594096Seric ** 1604096Seric ** Returns: 1614096Seric ** none. 1624096Seric ** 1634096Seric ** Side Effects: 1644096Seric ** enters the mailer into the mailer table. 1654096Seric */ 1663308Seric 1674096Seric # define SETWORD \ 1684096Seric { \ 1694096Seric while (*p != '\0' && isspace(*p)) \ 1704096Seric p++; \ 1714096Seric q = p; \ 1724096Seric while (*p != '\0' && !isspace(*p)) \ 1734096Seric p++; \ 1744096Seric if (*p != '\0') \ 1754096Seric *p++ = '\0'; \ 1764096Seric } 1774096Seric 1784096Seric makemailer(line) 1794096Seric char *line; 1804096Seric { 1814096Seric register char *p; 1824096Seric register char *q; 1834096Seric char *mname; 1844096Seric char *mpath; 1854096Seric int mopts; 1864096Seric char *mfrom; 1874096Seric register struct mailer *m; 1884096Seric char *margv[MAXPV + 1]; 1894096Seric register int i; 1904096Seric extern int NextMailer; 1914096Seric 1924096Seric if (NextMailer >= MAXMAILERS) 1934096Seric { 1944096Seric syserr("Too many mailers defined"); 1954096Seric return; 1964096Seric } 1974096Seric 1984096Seric /* collect initial information */ 1994096Seric p = line; 2004096Seric SETWORD; 2014096Seric mname = q; 2024096Seric SETWORD; 2034096Seric mpath = q; 2044096Seric SETWORD; 2054096Seric mopts = crackopts(q); 2064096Seric SETWORD; 2074096Seric mfrom = q; 2084096Seric 2094096Seric if (*p == '\0') 2104096Seric { 2114096Seric syserr("invalid M line in configuration file"); 2124096Seric return; 2134096Seric } 2144096Seric 2154096Seric /* allocate a mailer */ 2164096Seric m = (struct mailer *) xalloc(sizeof *m); 2174096Seric m->m_name = newstr(mname); 2184096Seric m->m_mailer = newstr(mpath); 2194096Seric m->m_flags = mopts; 2204096Seric m->m_from = newstr(mfrom); 2214096Seric m->m_badstat = EX_UNAVAILABLE; 2224096Seric m->m_sendq = NULL; 2234096Seric Mailer[NextMailer++] = m; 2244096Seric 2254096Seric /* collect the argument vector */ 2264096Seric for (i = 0; i < MAXPV - 1 && *p != '\0'; i++) 2274096Seric { 2284096Seric SETWORD; 2294096Seric margv[i] = newstr(q); 2304096Seric } 2314096Seric margv[i++] = NULL; 2324096Seric 2334096Seric /* save the argv */ 2344096Seric m->m_argv = (char **) xalloc(sizeof margv[0] * i); 2354096Seric bmove((char *) margv, (char *) m->m_argv, sizeof margv[0] * i); 2363308Seric } 2373308Seric /* 2383308Seric ** PRINTRULES -- print rewrite rules (for debugging) 2393308Seric ** 2403308Seric ** Parameters: 2413308Seric ** none. 2423308Seric ** 2433308Seric ** Returns: 2443308Seric ** none. 2453308Seric ** 2463308Seric ** Side Effects: 2473308Seric ** prints rewrite rules. 2483308Seric */ 2493308Seric 2503308Seric printrules() 2513308Seric { 2523308Seric register struct rewrite *rwp; 2534072Seric register int ruleset; 2543308Seric 2554072Seric for (ruleset = 0; ruleset < 10; ruleset++) 2563308Seric { 2574072Seric if (RewriteRules[ruleset] == NULL) 2584072Seric continue; 2594072Seric printf("\n----Rule Set %d:\n", ruleset); 2603308Seric 2614072Seric for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 2623308Seric { 2634072Seric register char **av; 2644072Seric 2654072Seric printf("\n"); 2664072Seric for (av = rwp->r_lhs; *av != NULL; av++) 2674072Seric { 2684072Seric xputs(*av); 2694072Seric putchar('_'); 2704072Seric } 2714072Seric printf("\n\t"); 2724072Seric for (av = rwp->r_rhs; *av != NULL; av++) 2734072Seric { 2744072Seric xputs(*av); 2754072Seric putchar('_'); 2764072Seric } 2774072Seric printf("\n"); 2783308Seric } 2793308Seric } 2803308Seric } 2814096Seric /* 2824096Seric ** CRACKOPTS -- crack mailer options 2834096Seric ** 2844096Seric ** These options modify the functioning of the mailer 2854096Seric ** from the configuration table. 2864096Seric ** 2874096Seric ** Parameters: 2884096Seric ** p -- pointer to vector of options. 2894096Seric ** 2904096Seric ** Returns: 2914096Seric ** option list in binary. 2924096Seric ** 2934096Seric ** Side Effects: 2944096Seric ** none. 2954096Seric */ 2964096Seric 2974096Seric struct optlist 2984096Seric { 2994096Seric char opt_name; /* external name of option */ 3004096Seric int opt_value; /* internal name of option */ 3014096Seric }; 3024096Seric struct optlist OptList[] = 3034096Seric { 3044096Seric 'f', M_FOPT, 3054096Seric 'r', M_ROPT, 3064096Seric 'q', M_QUIET, 3074096Seric 'S', M_RESTR, 3084096Seric 'n', M_NHDR, 309*4197Seric 'l', M_LOCAL, 3104096Seric 's', M_STRIPQ, 3114096Seric 'm', M_MUSER, 3124096Seric 'F', M_NEEDFROM, 3134096Seric 'D', M_NEEDDATE, 3144096Seric 'M', M_MSGID, 3154096Seric 'u', M_USR_UPPER, 3164096Seric 'h', M_HST_UPPER, 3174096Seric 'x', M_FULLNAME, 3184096Seric 'A', M_ARPAFMT, 3194096Seric 0, 0 3204096Seric }; 3214096Seric 3224096Seric crackopts(p) 3234096Seric register char *p; 3244096Seric { 3254096Seric register struct optlist *o; 3264096Seric register int opts = 0; 3274096Seric 3284096Seric while (*p != '\0') 3294096Seric { 3304096Seric for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++) 3314096Seric continue; 3324096Seric if (o->opt_name == '\0') 3334096Seric syserr("bad mailer option %c", *p); 3344096Seric opts |= o->opt_value; 3354096Seric p++; 3364096Seric } 3374096Seric return (opts); 3384096Seric } 339