13313Seric # include "sendmail.h" 23308Seric 3*4319Seric static char SccsId[] = "@(#)readcf.c 3.13 09/06/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. 134217Seric ** safe -- set if this is a system configuration file. 144217Seric ** Non-system configuration files can not do 154217Seric ** certain things (e.g., leave the SUID bit on 164217Seric ** when executing mailers). 173308Seric ** 183308Seric ** Returns: 193308Seric ** none. 203308Seric ** 213308Seric ** Side Effects: 223308Seric ** Builds several internal tables. 233308Seric */ 243308Seric 254072Seric struct rewrite *RewriteRules[10]; 263308Seric 273308Seric 284217Seric readcf(cfname, safe) 293308Seric char *cfname; 304217Seric bool safe; 313308Seric { 323308Seric FILE *cf; 333308Seric char buf[MAXLINE]; 343308Seric register char *p; 353308Seric struct rewrite *rwp = NULL; 363308Seric extern char **prescan(); 373308Seric extern char **copyplist(); 384061Seric int class; 394072Seric 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) 724072Seric { 734072Seric RewriteRules[ruleset] = rwp = 744072Seric (struct rewrite *) xalloc(sizeof *rwp); 754072Seric } 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 944072Seric case 'S': /* select rewriting set */ 954072Seric ruleset = atoi(&buf[1]); 964072Seric rwp = NULL; 974072Seric break; 984072Seric 993308Seric case 'D': /* macro definition */ 1003308Seric define(buf[1], newstr(&buf[2])); 1013308Seric break; 1023308Seric 1033387Seric case 'H': /* required header line */ 1044088Seric (void) 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 { 1324103Seric s = stab(wd, ST_CLASS, ST_ENTER); 1334061Seric s->s_class |= 1 << class; 1344061Seric } 1354061Seric *p = delim; 1364061Seric } 1374061Seric break; 1384061Seric 1394096Seric case 'M': /* define mailer */ 1404217Seric makemailer(&buf[1], safe); 1414096Seric break; 1424096Seric 1433308Seric default: 1444061Seric badline: 1453308Seric syserr("unknown control line \"%s\"", buf); 1463308Seric } 1473308Seric } 1484096Seric } 1494096Seric /* 1504096Seric ** MAKEMAILER -- define a new mailer. 1514096Seric ** 1524096Seric ** Parameters: 1534096Seric ** line -- description of mailer. This is in tokens 1544096Seric ** separated by white space. The fields are: 1554096Seric ** * the name of the mailer, as refered to 1564096Seric ** in the rewriting rules. 1574096Seric ** * the pathname of the program to fork to 1584096Seric ** execute it. 1594096Seric ** * the options needed by this program. 1604096Seric ** * the macro string needed to translate 1614096Seric ** a local "from" name to one that can be 1624096Seric ** returned to this machine. 1634096Seric ** * the argument vector (a series of parameters). 1644217Seric ** safe -- set if this is a safe configuration file. 1654096Seric ** 1664096Seric ** Returns: 1674096Seric ** none. 1684096Seric ** 1694096Seric ** Side Effects: 1704096Seric ** enters the mailer into the mailer table. 1714096Seric */ 1723308Seric 1734096Seric # define SETWORD \ 1744096Seric { \ 1754096Seric while (*p != '\0' && isspace(*p)) \ 1764096Seric p++; \ 1774096Seric q = p; \ 1784096Seric while (*p != '\0' && !isspace(*p)) \ 1794096Seric p++; \ 1804096Seric if (*p != '\0') \ 1814096Seric *p++ = '\0'; \ 1824096Seric } 1834096Seric 1844217Seric makemailer(line, safe) 1854096Seric char *line; 1864217Seric bool safe; 1874096Seric { 1884096Seric register char *p; 1894096Seric register char *q; 1904096Seric char *mname; 1914096Seric char *mpath; 1924096Seric int mopts; 1934096Seric char *mfrom; 1944096Seric register struct mailer *m; 1954096Seric char *margv[MAXPV + 1]; 1964096Seric register int i; 1974096Seric extern int NextMailer; 1984096Seric 1994096Seric if (NextMailer >= MAXMAILERS) 2004096Seric { 2014096Seric syserr("Too many mailers defined"); 2024096Seric return; 2034096Seric } 2044096Seric 2054096Seric /* collect initial information */ 2064096Seric p = line; 2074096Seric SETWORD; 2084096Seric mname = q; 2094096Seric SETWORD; 2104096Seric mpath = q; 2114096Seric SETWORD; 2124096Seric mopts = crackopts(q); 2134217Seric if (!safe) 2144217Seric mopts &= ~M_RESTR; 2154096Seric SETWORD; 2164096Seric mfrom = q; 2174096Seric 2184096Seric if (*p == '\0') 2194096Seric { 2204096Seric syserr("invalid M line in configuration file"); 2214096Seric return; 2224096Seric } 2234096Seric 2244096Seric /* allocate a mailer */ 2254096Seric m = (struct mailer *) xalloc(sizeof *m); 2264096Seric m->m_name = newstr(mname); 2274096Seric m->m_mailer = newstr(mpath); 2284096Seric m->m_flags = mopts; 2294096Seric m->m_from = newstr(mfrom); 2304096Seric m->m_badstat = EX_UNAVAILABLE; 2314096Seric m->m_sendq = NULL; 2324096Seric Mailer[NextMailer++] = m; 2334096Seric 2344096Seric /* collect the argument vector */ 2354096Seric for (i = 0; i < MAXPV - 1 && *p != '\0'; i++) 2364096Seric { 2374096Seric SETWORD; 2384096Seric margv[i] = newstr(q); 2394096Seric } 2404096Seric margv[i++] = NULL; 2414096Seric 2424096Seric /* save the argv */ 243*4319Seric m->m_argv = (char **) xalloc((unsigned) (sizeof margv[0] * i)); 2444096Seric bmove((char *) margv, (char *) m->m_argv, sizeof margv[0] * i); 2453308Seric } 2463308Seric /* 2473308Seric ** PRINTRULES -- print rewrite rules (for debugging) 2483308Seric ** 2493308Seric ** Parameters: 2503308Seric ** none. 2513308Seric ** 2523308Seric ** Returns: 2533308Seric ** none. 2543308Seric ** 2553308Seric ** Side Effects: 2563308Seric ** prints rewrite rules. 2573308Seric */ 2583308Seric 259*4319Seric # ifdef DEBUG 260*4319Seric 2613308Seric printrules() 2623308Seric { 2633308Seric register struct rewrite *rwp; 2644072Seric register int ruleset; 2653308Seric 2664072Seric for (ruleset = 0; ruleset < 10; ruleset++) 2673308Seric { 2684072Seric if (RewriteRules[ruleset] == NULL) 2694072Seric continue; 2704072Seric printf("\n----Rule Set %d:\n", ruleset); 2713308Seric 2724072Seric for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 2733308Seric { 2744072Seric register char **av; 2754072Seric 2764072Seric printf("\n"); 2774072Seric for (av = rwp->r_lhs; *av != NULL; av++) 2784072Seric { 2794072Seric xputs(*av); 2804072Seric putchar('_'); 2814072Seric } 2824072Seric printf("\n\t"); 2834072Seric for (av = rwp->r_rhs; *av != NULL; av++) 2844072Seric { 2854072Seric xputs(*av); 2864072Seric putchar('_'); 2874072Seric } 2884072Seric printf("\n"); 2893308Seric } 2903308Seric } 2913308Seric } 292*4319Seric 293*4319Seric # endif DEBUG 2944096Seric /* 2954096Seric ** CRACKOPTS -- crack mailer options 2964096Seric ** 2974096Seric ** These options modify the functioning of the mailer 2984096Seric ** from the configuration table. 2994096Seric ** 3004096Seric ** Parameters: 3014096Seric ** p -- pointer to vector of options. 3024096Seric ** 3034096Seric ** Returns: 3044096Seric ** option list in binary. 3054096Seric ** 3064096Seric ** Side Effects: 3074096Seric ** none. 3084096Seric */ 3094096Seric 3104096Seric struct optlist 3114096Seric { 3124096Seric char opt_name; /* external name of option */ 3134096Seric int opt_value; /* internal name of option */ 3144096Seric }; 3154096Seric struct optlist OptList[] = 3164096Seric { 3174096Seric 'f', M_FOPT, 3184096Seric 'r', M_ROPT, 3194096Seric 'q', M_QUIET, 3204096Seric 'S', M_RESTR, 3214096Seric 'n', M_NHDR, 3224197Seric 'l', M_LOCAL, 3234096Seric 's', M_STRIPQ, 3244096Seric 'm', M_MUSER, 3254096Seric 'F', M_NEEDFROM, 3264096Seric 'D', M_NEEDDATE, 3274096Seric 'M', M_MSGID, 3284096Seric 'u', M_USR_UPPER, 3294096Seric 'h', M_HST_UPPER, 3304096Seric 'x', M_FULLNAME, 3314096Seric 'A', M_ARPAFMT, 332*4319Seric '\0', 0 3334096Seric }; 3344096Seric 3354096Seric crackopts(p) 3364096Seric register char *p; 3374096Seric { 3384096Seric register struct optlist *o; 3394096Seric register int opts = 0; 3404096Seric 3414096Seric while (*p != '\0') 3424096Seric { 3434096Seric for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++) 3444096Seric continue; 3454096Seric if (o->opt_name == '\0') 3464096Seric syserr("bad mailer option %c", *p); 3474096Seric opts |= o->opt_value; 3484096Seric p++; 3494096Seric } 3504096Seric return (opts); 3514096Seric } 352