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