13308Seric # include <stdio.h> 23313Seric # include "sendmail.h" 33308Seric # include <ctype.h> 43308Seric 5*4096Seric static char SccsId[] = "@(#)readcf.c 3.7 08/09/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 { 1294061Seric s = stab(wd, ST_ENTER); 1304061Seric s->s_class |= 1 << class; 1314061Seric } 1324061Seric *p = delim; 1334061Seric } 1344061Seric break; 1354061Seric 136*4096Seric case 'M': /* define mailer */ 137*4096Seric makemailer(&buf[1]); 138*4096Seric break; 139*4096Seric 1403308Seric default: 1414061Seric badline: 1423308Seric syserr("unknown control line \"%s\"", buf); 1433308Seric } 1443308Seric } 145*4096Seric } 146*4096Seric /* 147*4096Seric ** MAKEMAILER -- define a new mailer. 148*4096Seric ** 149*4096Seric ** Parameters: 150*4096Seric ** line -- description of mailer. This is in tokens 151*4096Seric ** separated by white space. The fields are: 152*4096Seric ** * the name of the mailer, as refered to 153*4096Seric ** in the rewriting rules. 154*4096Seric ** * the pathname of the program to fork to 155*4096Seric ** execute it. 156*4096Seric ** * the options needed by this program. 157*4096Seric ** * the macro string needed to translate 158*4096Seric ** a local "from" name to one that can be 159*4096Seric ** returned to this machine. 160*4096Seric ** * the argument vector (a series of parameters). 161*4096Seric ** 162*4096Seric ** Returns: 163*4096Seric ** none. 164*4096Seric ** 165*4096Seric ** Side Effects: 166*4096Seric ** enters the mailer into the mailer table. 167*4096Seric */ 1683308Seric 169*4096Seric # define SETWORD \ 170*4096Seric { \ 171*4096Seric while (*p != '\0' && isspace(*p)) \ 172*4096Seric p++; \ 173*4096Seric q = p; \ 174*4096Seric while (*p != '\0' && !isspace(*p)) \ 175*4096Seric p++; \ 176*4096Seric if (*p != '\0') \ 177*4096Seric *p++ = '\0'; \ 178*4096Seric } 179*4096Seric 180*4096Seric makemailer(line) 181*4096Seric char *line; 182*4096Seric { 183*4096Seric register char *p; 184*4096Seric register char *q; 185*4096Seric char *mname; 186*4096Seric char *mpath; 187*4096Seric int mopts; 188*4096Seric char *mfrom; 189*4096Seric register struct mailer *m; 190*4096Seric char *margv[MAXPV + 1]; 191*4096Seric register int i; 192*4096Seric extern int NextMailer; 193*4096Seric 194*4096Seric if (NextMailer >= MAXMAILERS) 195*4096Seric { 196*4096Seric syserr("Too many mailers defined"); 197*4096Seric return; 198*4096Seric } 199*4096Seric 200*4096Seric /* collect initial information */ 201*4096Seric p = line; 202*4096Seric SETWORD; 203*4096Seric mname = q; 204*4096Seric SETWORD; 205*4096Seric mpath = q; 206*4096Seric SETWORD; 207*4096Seric mopts = crackopts(q); 208*4096Seric SETWORD; 209*4096Seric mfrom = q; 210*4096Seric 211*4096Seric if (*p == '\0') 212*4096Seric { 213*4096Seric syserr("invalid M line in configuration file"); 214*4096Seric return; 215*4096Seric } 216*4096Seric 217*4096Seric /* allocate a mailer */ 218*4096Seric m = (struct mailer *) xalloc(sizeof *m); 219*4096Seric m->m_name = newstr(mname); 220*4096Seric m->m_mailer = newstr(mpath); 221*4096Seric m->m_flags = mopts; 222*4096Seric m->m_from = newstr(mfrom); 223*4096Seric m->m_badstat = EX_UNAVAILABLE; 224*4096Seric m->m_sendq = NULL; 225*4096Seric Mailer[NextMailer++] = m; 226*4096Seric 227*4096Seric /* collect the argument vector */ 228*4096Seric for (i = 0; i < MAXPV - 1 && *p != '\0'; i++) 229*4096Seric { 230*4096Seric SETWORD; 231*4096Seric margv[i] = newstr(q); 232*4096Seric } 233*4096Seric margv[i++] = NULL; 234*4096Seric 235*4096Seric /* save the argv */ 236*4096Seric m->m_argv = (char **) xalloc(sizeof margv[0] * i); 237*4096Seric 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 } 283*4096Seric /* 284*4096Seric ** CRACKOPTS -- crack mailer options 285*4096Seric ** 286*4096Seric ** These options modify the functioning of the mailer 287*4096Seric ** from the configuration table. 288*4096Seric ** 289*4096Seric ** Parameters: 290*4096Seric ** p -- pointer to vector of options. 291*4096Seric ** 292*4096Seric ** Returns: 293*4096Seric ** option list in binary. 294*4096Seric ** 295*4096Seric ** Side Effects: 296*4096Seric ** none. 297*4096Seric */ 298*4096Seric 299*4096Seric struct optlist 300*4096Seric { 301*4096Seric char opt_name; /* external name of option */ 302*4096Seric int opt_value; /* internal name of option */ 303*4096Seric }; 304*4096Seric struct optlist OptList[] = 305*4096Seric { 306*4096Seric 'f', M_FOPT, 307*4096Seric 'r', M_ROPT, 308*4096Seric 'q', M_QUIET, 309*4096Seric 'S', M_RESTR, 310*4096Seric 'n', M_NHDR, 311*4096Seric 'l', M_NOHOST, 312*4096Seric 's', M_STRIPQ, 313*4096Seric 'm', M_MUSER, 314*4096Seric 'F', M_NEEDFROM, 315*4096Seric 'D', M_NEEDDATE, 316*4096Seric 'M', M_MSGID, 317*4096Seric 'u', M_USR_UPPER, 318*4096Seric 'h', M_HST_UPPER, 319*4096Seric 'x', M_FULLNAME, 320*4096Seric 'A', M_ARPAFMT, 321*4096Seric 0, 0 322*4096Seric }; 323*4096Seric 324*4096Seric crackopts(p) 325*4096Seric register char *p; 326*4096Seric { 327*4096Seric register struct optlist *o; 328*4096Seric register int opts = 0; 329*4096Seric 330*4096Seric while (*p != '\0') 331*4096Seric { 332*4096Seric for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++) 333*4096Seric continue; 334*4096Seric if (o->opt_name == '\0') 335*4096Seric syserr("bad mailer option %c", *p); 336*4096Seric opts |= o->opt_value; 337*4096Seric p++; 338*4096Seric } 339*4096Seric return (opts); 340*4096Seric } 341