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