1 # include "sendmail.h" 2 3 static char SccsId[] = "@(#)readcf.c 3.10 08/20/81"; 4 5 /* 6 ** READCF -- read control file. 7 ** 8 ** This routine reads the control file and builds the internal 9 ** form. 10 ** 11 ** Parameters: 12 ** cfname -- control file name. 13 ** 14 ** Returns: 15 ** none. 16 ** 17 ** Side Effects: 18 ** Builds several internal tables. 19 */ 20 21 struct rewrite *RewriteRules[10]; 22 23 24 readcf(cfname) 25 char *cfname; 26 { 27 FILE *cf; 28 char buf[MAXLINE]; 29 register char *p; 30 struct rewrite *rwp = NULL; 31 extern char **prescan(); 32 extern char **copyplist(); 33 int class; 34 int ruleset = 0; 35 36 cf = fopen(cfname, "r"); 37 if (cf == NULL) 38 { 39 syserr("cannot open %s", cfname); 40 exit(EX_OSFILE); 41 } 42 43 while (fgets(buf, sizeof buf, cf) != NULL) 44 { 45 p = rindex(buf, '\n'); 46 if (p != NULL) 47 *p = '\0'; 48 49 switch (buf[0]) 50 { 51 case '\n': 52 case '\0': 53 case ' ': 54 case '\t': 55 case '#': /* comment */ 56 break; 57 58 case 'R': /* rewriting rule */ 59 for (p = &buf[1]; *p != '\0' && *p != '\t'; p++) 60 continue; 61 62 if (*p == '\0') 63 syserr("invalid rewrite line \"%s\"", buf); 64 else 65 { 66 if (rwp == NULL) 67 { 68 RewriteRules[ruleset] = rwp = 69 (struct rewrite *) xalloc(sizeof *rwp); 70 } 71 else 72 { 73 rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); 74 rwp = rwp->r_next; 75 } 76 rwp->r_next = NULL; 77 78 rwp->r_lhs = prescan(&buf[1], '\t'); 79 if (rwp->r_lhs != NULL) 80 rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); 81 while (*p == '\t') 82 p++; 83 rwp->r_rhs = prescan(p, '\t'); 84 if (rwp->r_rhs != NULL) 85 rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); 86 } 87 break; 88 89 case 'S': /* select rewriting set */ 90 ruleset = atoi(&buf[1]); 91 rwp = NULL; 92 break; 93 94 case 'D': /* macro definition */ 95 define(buf[1], newstr(&buf[2])); 96 break; 97 98 case 'H': /* required header line */ 99 (void) chompheader(&buf[1], TRUE); 100 break; 101 102 case 'C': /* word class */ 103 class = buf[1]; 104 if (!isalpha(class)) 105 goto badline; 106 if (isupper(class)) 107 class -= 'A'; 108 else 109 class -= 'a'; 110 111 /* scan the list of words and set class 'i' for all */ 112 for (p = &buf[2]; *p != '\0'; ) 113 { 114 register char *wd; 115 char delim; 116 register STAB *s; 117 118 while (*p != '\0' && isspace(*p)) 119 p++; 120 wd = p; 121 while (*p != '\0' && !isspace(*p)) 122 p++; 123 delim = *p; 124 *p = '\0'; 125 if (wd[0] != '\0') 126 { 127 s = stab(wd, ST_CLASS, ST_ENTER); 128 s->s_class |= 1 << class; 129 } 130 *p = delim; 131 } 132 break; 133 134 case 'M': /* define mailer */ 135 makemailer(&buf[1]); 136 break; 137 138 default: 139 badline: 140 syserr("unknown control line \"%s\"", buf); 141 } 142 } 143 } 144 /* 145 ** MAKEMAILER -- define a new mailer. 146 ** 147 ** Parameters: 148 ** line -- description of mailer. This is in tokens 149 ** separated by white space. The fields are: 150 ** * the name of the mailer, as refered to 151 ** in the rewriting rules. 152 ** * the pathname of the program to fork to 153 ** execute it. 154 ** * the options needed by this program. 155 ** * the macro string needed to translate 156 ** a local "from" name to one that can be 157 ** returned to this machine. 158 ** * the argument vector (a series of parameters). 159 ** 160 ** Returns: 161 ** none. 162 ** 163 ** Side Effects: 164 ** enters the mailer into the mailer table. 165 */ 166 167 # define SETWORD \ 168 { \ 169 while (*p != '\0' && isspace(*p)) \ 170 p++; \ 171 q = p; \ 172 while (*p != '\0' && !isspace(*p)) \ 173 p++; \ 174 if (*p != '\0') \ 175 *p++ = '\0'; \ 176 } 177 178 makemailer(line) 179 char *line; 180 { 181 register char *p; 182 register char *q; 183 char *mname; 184 char *mpath; 185 int mopts; 186 char *mfrom; 187 register struct mailer *m; 188 char *margv[MAXPV + 1]; 189 register int i; 190 extern int NextMailer; 191 192 if (NextMailer >= MAXMAILERS) 193 { 194 syserr("Too many mailers defined"); 195 return; 196 } 197 198 /* collect initial information */ 199 p = line; 200 SETWORD; 201 mname = q; 202 SETWORD; 203 mpath = q; 204 SETWORD; 205 mopts = crackopts(q); 206 SETWORD; 207 mfrom = q; 208 209 if (*p == '\0') 210 { 211 syserr("invalid M line in configuration file"); 212 return; 213 } 214 215 /* allocate a mailer */ 216 m = (struct mailer *) xalloc(sizeof *m); 217 m->m_name = newstr(mname); 218 m->m_mailer = newstr(mpath); 219 m->m_flags = mopts; 220 m->m_from = newstr(mfrom); 221 m->m_badstat = EX_UNAVAILABLE; 222 m->m_sendq = NULL; 223 Mailer[NextMailer++] = m; 224 225 /* collect the argument vector */ 226 for (i = 0; i < MAXPV - 1 && *p != '\0'; i++) 227 { 228 SETWORD; 229 margv[i] = newstr(q); 230 } 231 margv[i++] = NULL; 232 233 /* save the argv */ 234 m->m_argv = (char **) xalloc(sizeof margv[0] * i); 235 bmove((char *) margv, (char *) m->m_argv, sizeof margv[0] * i); 236 } 237 /* 238 ** PRINTRULES -- print rewrite rules (for debugging) 239 ** 240 ** Parameters: 241 ** none. 242 ** 243 ** Returns: 244 ** none. 245 ** 246 ** Side Effects: 247 ** prints rewrite rules. 248 */ 249 250 printrules() 251 { 252 register struct rewrite *rwp; 253 register int ruleset; 254 255 for (ruleset = 0; ruleset < 10; ruleset++) 256 { 257 if (RewriteRules[ruleset] == NULL) 258 continue; 259 printf("\n----Rule Set %d:\n", ruleset); 260 261 for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) 262 { 263 register char **av; 264 265 printf("\n"); 266 for (av = rwp->r_lhs; *av != NULL; av++) 267 { 268 xputs(*av); 269 putchar('_'); 270 } 271 printf("\n\t"); 272 for (av = rwp->r_rhs; *av != NULL; av++) 273 { 274 xputs(*av); 275 putchar('_'); 276 } 277 printf("\n"); 278 } 279 } 280 } 281 /* 282 ** CRACKOPTS -- crack mailer options 283 ** 284 ** These options modify the functioning of the mailer 285 ** from the configuration table. 286 ** 287 ** Parameters: 288 ** p -- pointer to vector of options. 289 ** 290 ** Returns: 291 ** option list in binary. 292 ** 293 ** Side Effects: 294 ** none. 295 */ 296 297 struct optlist 298 { 299 char opt_name; /* external name of option */ 300 int opt_value; /* internal name of option */ 301 }; 302 struct optlist OptList[] = 303 { 304 'f', M_FOPT, 305 'r', M_ROPT, 306 'q', M_QUIET, 307 'S', M_RESTR, 308 'n', M_NHDR, 309 'l', M_NOHOST, 310 's', M_STRIPQ, 311 'm', M_MUSER, 312 'F', M_NEEDFROM, 313 'D', M_NEEDDATE, 314 'M', M_MSGID, 315 'u', M_USR_UPPER, 316 'h', M_HST_UPPER, 317 'x', M_FULLNAME, 318 'A', M_ARPAFMT, 319 'L', M_FINAL, 320 0, 0 321 }; 322 323 crackopts(p) 324 register char *p; 325 { 326 register struct optlist *o; 327 register int opts = 0; 328 329 while (*p != '\0') 330 { 331 for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++) 332 continue; 333 if (o->opt_name == '\0') 334 syserr("bad mailer option %c", *p); 335 opts |= o->opt_value; 336 p++; 337 } 338 return (opts); 339 } 340