1 /* 2 * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: stab.c,v 8.86.4.1 2003/03/31 17:44:24 ca Exp $") 17 18 /* 19 ** STAB -- manage the symbol table 20 ** 21 ** Parameters: 22 ** name -- the name to be looked up or inserted. 23 ** type -- the type of symbol. 24 ** op -- what to do: 25 ** ST_ENTER -- enter the name if not already present. 26 ** ST_FIND -- find it only. 27 ** 28 ** Returns: 29 ** pointer to a STAB entry for this name. 30 ** NULL if not found and not entered. 31 ** 32 ** Side Effects: 33 ** can update the symbol table. 34 */ 35 36 #define STABSIZE 2003 37 #define SM_LOWER(c) ((isascii(c) && isupper(c)) ? tolower(c) : (c)) 38 39 static STAB *SymTab[STABSIZE]; 40 41 STAB * 42 stab(name, type, op) 43 char *name; 44 int type; 45 int op; 46 { 47 register STAB *s; 48 register STAB **ps; 49 register int hfunc; 50 register char *p; 51 int len; 52 53 if (tTd(36, 5)) 54 sm_dprintf("STAB: %s %d ", name, type); 55 56 /* 57 ** Compute the hashing function 58 */ 59 60 hfunc = type; 61 for (p = name; *p != '\0'; p++) 62 hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE; 63 64 if (tTd(36, 9)) 65 sm_dprintf("(hfunc=%d) ", hfunc); 66 67 ps = &SymTab[hfunc]; 68 if (type == ST_MACRO || type == ST_RULESET) 69 { 70 while ((s = *ps) != NULL && 71 (s->s_symtype != type || strcmp(name, s->s_name))) 72 ps = &s->s_next; 73 } 74 else 75 { 76 while ((s = *ps) != NULL && 77 (s->s_symtype != type || sm_strcasecmp(name, s->s_name))) 78 ps = &s->s_next; 79 } 80 81 /* 82 ** Dispose of the entry. 83 */ 84 85 if (s != NULL || op == ST_FIND) 86 { 87 if (tTd(36, 5)) 88 { 89 if (s == NULL) 90 sm_dprintf("not found\n"); 91 else 92 { 93 long *lp = (long *) s->s_class; 94 95 sm_dprintf("type %d val %lx %lx %lx %lx\n", 96 s->s_symtype, lp[0], lp[1], lp[2], lp[3]); 97 } 98 } 99 return s; 100 } 101 102 /* 103 ** Make a new entry and link it in. 104 */ 105 106 if (tTd(36, 5)) 107 sm_dprintf("entered\n"); 108 109 /* determine size of new entry */ 110 switch (type) 111 { 112 case ST_CLASS: 113 len = sizeof s->s_class; 114 break; 115 116 case ST_ADDRESS: 117 len = sizeof s->s_address; 118 break; 119 120 case ST_MAILER: 121 len = sizeof s->s_mailer; 122 break; 123 124 case ST_ALIAS: 125 len = sizeof s->s_alias; 126 break; 127 128 case ST_MAPCLASS: 129 len = sizeof s->s_mapclass; 130 break; 131 132 case ST_MAP: 133 len = sizeof s->s_map; 134 break; 135 136 case ST_HOSTSIG: 137 len = sizeof s->s_hostsig; 138 break; 139 140 case ST_NAMECANON: 141 len = sizeof s->s_namecanon; 142 break; 143 144 case ST_MACRO: 145 len = sizeof s->s_macro; 146 break; 147 148 case ST_RULESET: 149 len = sizeof s->s_ruleset; 150 break; 151 152 case ST_HEADER: 153 len = sizeof s->s_header; 154 break; 155 156 case ST_SERVICE: 157 len = sizeof s->s_service; 158 break; 159 160 #if LDAPMAP 161 case ST_LMAP: 162 len = sizeof s->s_lmap; 163 break; 164 #endif /* LDAPMAP */ 165 166 #if MILTER 167 case ST_MILTER: 168 len = sizeof s->s_milter; 169 break; 170 #endif /* MILTER */ 171 172 case ST_QUEUE: 173 len = sizeof s->s_quegrp; 174 break; 175 176 default: 177 /* 178 ** Each mailer has its own MCI stab entry: 179 ** 180 ** s = stab(host, ST_MCI + m->m_mno, ST_ENTER); 181 ** 182 ** Therefore, anything ST_MCI or larger is an s_mci. 183 */ 184 185 if (type >= ST_MCI) 186 len = sizeof s->s_mci; 187 else 188 { 189 syserr("stab: unknown symbol type %d", type); 190 len = sizeof s->s_value; 191 } 192 break; 193 } 194 len += sizeof *s - sizeof s->s_value; 195 196 if (tTd(36, 15)) 197 sm_dprintf("size of stab entry: %d\n", len); 198 199 /* make new entry */ 200 s = (STAB *) sm_pmalloc_x(len); 201 memset((char *) s, '\0', len); 202 s->s_name = sm_pstrdup_x(name); 203 s->s_symtype = type; 204 205 /* link it in */ 206 *ps = s; 207 208 /* set a default value for rulesets */ 209 if (type == ST_RULESET) 210 s->s_ruleset = -1; 211 212 return s; 213 } 214 /* 215 ** STABAPPLY -- apply function to all stab entries 216 ** 217 ** Parameters: 218 ** func -- the function to apply. It will be given two 219 ** parameters (the stab entry and the arg). 220 ** arg -- an arbitrary argument, passed to func. 221 ** 222 ** Returns: 223 ** none. 224 */ 225 226 void 227 stabapply(func, arg) 228 void (*func)__P((STAB *, int)); 229 int arg; 230 { 231 register STAB **shead; 232 register STAB *s; 233 234 for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 235 { 236 for (s = *shead; s != NULL; s = s->s_next) 237 { 238 if (tTd(36, 90)) 239 sm_dprintf("stabapply: trying %d/%s\n", 240 s->s_symtype, s->s_name); 241 func(s, arg); 242 } 243 } 244 } 245 /* 246 ** QUEUEUP_MACROS -- queueup the macros in a class 247 ** 248 ** Write the macros listed in the specified class into the 249 ** file referenced by qfp. 250 ** 251 ** Parameters: 252 ** class -- class ID. 253 ** qfp -- file pointer to the queue file. 254 ** e -- the envelope. 255 ** 256 ** Returns: 257 ** none. 258 */ 259 260 void 261 queueup_macros(class, qfp, e) 262 int class; 263 SM_FILE_T *qfp; 264 ENVELOPE *e; 265 { 266 register STAB **shead; 267 register STAB *s; 268 269 if (e == NULL) 270 return; 271 272 class = bitidx(class); 273 for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 274 { 275 for (s = *shead; s != NULL; s = s->s_next) 276 { 277 int m; 278 char *p; 279 280 if (s->s_symtype == ST_CLASS && 281 bitnset(bitidx(class), s->s_class) && 282 (m = macid(s->s_name)) != 0 && 283 (p = macvalue(m, e)) != NULL) 284 { 285 (void) sm_io_fprintf(qfp, SM_TIME_DEFAULT, 286 "$%s%s\n", 287 s->s_name, 288 denlstring(p, true, 289 false)); 290 } 291 } 292 } 293 } 294 /* 295 ** COPY_CLASS -- copy class members from one class to another 296 ** 297 ** Parameters: 298 ** src -- source class. 299 ** dst -- destination class. 300 ** 301 ** Returns: 302 ** none. 303 */ 304 305 void 306 copy_class(src, dst) 307 int src; 308 int dst; 309 { 310 register STAB **shead; 311 register STAB *s; 312 313 src = bitidx(src); 314 dst = bitidx(dst); 315 for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 316 { 317 for (s = *shead; s != NULL; s = s->s_next) 318 { 319 if (s->s_symtype == ST_CLASS && 320 bitnset(src, s->s_class)) 321 setbitn(dst, s->s_class); 322 } 323 } 324 } 325 326 /* 327 ** RMEXPSTAB -- remove expired entries from SymTab. 328 ** 329 ** These entries need to be removed in long-running processes, 330 ** e.g., persistent queue runners, to avoid consuming memory. 331 ** 332 ** XXX It might be useful to restrict the maximum TTL to avoid 333 ** caching data very long. 334 ** 335 ** Parameters: 336 ** none. 337 ** 338 ** Returns: 339 ** none. 340 ** 341 ** Side Effects: 342 ** can remove entries from the symbol table. 343 */ 344 345 #define SM_STAB_FREE(x) \ 346 do \ 347 { \ 348 char *o = (x); \ 349 (x) = NULL; \ 350 if (o != NULL) \ 351 sm_free(o); \ 352 } while (0) 353 354 void 355 rmexpstab() 356 { 357 int i; 358 STAB *s, *p, *f; 359 time_t now; 360 361 now = curtime(); 362 for (i = 0; i < STABSIZE; i++) 363 { 364 p = NULL; 365 s = SymTab[i]; 366 while (s != NULL) 367 { 368 switch (s->s_symtype) 369 { 370 case ST_HOSTSIG: 371 if (s->s_hostsig.hs_exp >= now) 372 goto next; /* not expired */ 373 SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */ 374 break; 375 376 case ST_NAMECANON: 377 if (s->s_namecanon.nc_exp >= now) 378 goto next; /* not expired */ 379 SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */ 380 break; 381 382 default: 383 if (s->s_symtype >= ST_MCI) 384 { 385 /* call mci_uncache? */ 386 SM_STAB_FREE(s->s_mci.mci_status); 387 SM_STAB_FREE(s->s_mci.mci_rstatus); 388 SM_STAB_FREE(s->s_mci.mci_heloname); 389 #if 0 390 /* not dynamically allocated */ 391 SM_STAB_FREE(s->s_mci.mci_host); 392 SM_STAB_FREE(s->s_mci.mci_tolist); 393 #endif /* 0 */ 394 #if SASL 395 /* should always by NULL */ 396 SM_STAB_FREE(s->s_mci.mci_sasl_string); 397 #endif /* SASL */ 398 if (s->s_mci.mci_rpool != NULL) 399 { 400 sm_rpool_free(s->s_mci.mci_rpool); 401 s->s_mci.mci_macro.mac_rpool = NULL; 402 s->s_mci.mci_rpool = NULL; 403 } 404 break; 405 } 406 next: 407 p = s; 408 s = s->s_next; 409 continue; 410 } 411 412 /* remove entry */ 413 SM_STAB_FREE(s->s_name); /* XXX */ 414 f = s; 415 s = s->s_next; 416 sm_free(f); /* XXX */ 417 if (p == NULL) 418 SymTab[i] = s; 419 else 420 p->s_next = s; 421 } 422 } 423 } 424 425 #if SM_HEAP_CHECK 426 /* 427 ** DUMPSTAB -- dump symbol table. 428 ** 429 ** For debugging. 430 */ 431 432 #define MAXSTTYPES (ST_MCI + 1) 433 434 void 435 dumpstab() 436 { 437 int i, t, total, types[MAXSTTYPES]; 438 STAB *s; 439 static int prevt[MAXSTTYPES], prev = 0; 440 441 total = 0; 442 for (i = 0; i < MAXSTTYPES; i++) 443 types[i] = 0; 444 for (i = 0; i < STABSIZE; i++) 445 { 446 s = SymTab[i]; 447 while (s != NULL) 448 { 449 ++total; 450 t = s->s_symtype; 451 if (t > MAXSTTYPES - 1) 452 t = MAXSTTYPES - 1; 453 types[t]++; 454 s = s->s_next; 455 } 456 } 457 sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev); 458 prev = total; 459 for (i = 0; i < MAXSTTYPES; i++) 460 { 461 if (types[i] != 0) 462 { 463 sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)", 464 i, types[i], types[i] - prevt[i]); 465 } 466 prevt[i] = types[i]; 467 } 468 } 469 #endif /* SM_HEAP_CHECK */ 470