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.88 2003/05/21 15:36:30 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 #if SOCKETMAP 177 case ST_SOCKETMAP: 178 len = sizeof s->s_socketmap; 179 break; 180 #endif /* SOCKETMAP */ 181 182 default: 183 /* 184 ** Each mailer has its own MCI stab entry: 185 ** 186 ** s = stab(host, ST_MCI + m->m_mno, ST_ENTER); 187 ** 188 ** Therefore, anything ST_MCI or larger is an s_mci. 189 */ 190 191 if (type >= ST_MCI) 192 len = sizeof s->s_mci; 193 else 194 { 195 syserr("stab: unknown symbol type %d", type); 196 len = sizeof s->s_value; 197 } 198 break; 199 } 200 len += sizeof *s - sizeof s->s_value; 201 202 if (tTd(36, 15)) 203 sm_dprintf("size of stab entry: %d\n", len); 204 205 /* make new entry */ 206 s = (STAB *) sm_pmalloc_x(len); 207 memset((char *) s, '\0', len); 208 s->s_name = sm_pstrdup_x(name); 209 s->s_symtype = type; 210 211 /* link it in */ 212 *ps = s; 213 214 /* set a default value for rulesets */ 215 if (type == ST_RULESET) 216 s->s_ruleset = -1; 217 218 return s; 219 } 220 /* 221 ** STABAPPLY -- apply function to all stab entries 222 ** 223 ** Parameters: 224 ** func -- the function to apply. It will be given two 225 ** parameters (the stab entry and the arg). 226 ** arg -- an arbitrary argument, passed to func. 227 ** 228 ** Returns: 229 ** none. 230 */ 231 232 void 233 stabapply(func, arg) 234 void (*func)__P((STAB *, int)); 235 int arg; 236 { 237 register STAB **shead; 238 register STAB *s; 239 240 for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 241 { 242 for (s = *shead; s != NULL; s = s->s_next) 243 { 244 if (tTd(36, 90)) 245 sm_dprintf("stabapply: trying %d/%s\n", 246 s->s_symtype, s->s_name); 247 func(s, arg); 248 } 249 } 250 } 251 /* 252 ** QUEUEUP_MACROS -- queueup the macros in a class 253 ** 254 ** Write the macros listed in the specified class into the 255 ** file referenced by qfp. 256 ** 257 ** Parameters: 258 ** class -- class ID. 259 ** qfp -- file pointer to the queue file. 260 ** e -- the envelope. 261 ** 262 ** Returns: 263 ** none. 264 */ 265 266 void 267 queueup_macros(class, qfp, e) 268 int class; 269 SM_FILE_T *qfp; 270 ENVELOPE *e; 271 { 272 register STAB **shead; 273 register STAB *s; 274 275 if (e == NULL) 276 return; 277 278 class = bitidx(class); 279 for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 280 { 281 for (s = *shead; s != NULL; s = s->s_next) 282 { 283 int m; 284 char *p; 285 286 if (s->s_symtype == ST_CLASS && 287 bitnset(bitidx(class), s->s_class) && 288 (m = macid(s->s_name)) != 0 && 289 (p = macvalue(m, e)) != NULL) 290 { 291 (void) sm_io_fprintf(qfp, SM_TIME_DEFAULT, 292 "$%s%s\n", 293 s->s_name, 294 denlstring(p, true, 295 false)); 296 } 297 } 298 } 299 } 300 /* 301 ** COPY_CLASS -- copy class members from one class to another 302 ** 303 ** Parameters: 304 ** src -- source class. 305 ** dst -- destination class. 306 ** 307 ** Returns: 308 ** none. 309 */ 310 311 void 312 copy_class(src, dst) 313 int src; 314 int dst; 315 { 316 register STAB **shead; 317 register STAB *s; 318 319 src = bitidx(src); 320 dst = bitidx(dst); 321 for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) 322 { 323 for (s = *shead; s != NULL; s = s->s_next) 324 { 325 if (s->s_symtype == ST_CLASS && 326 bitnset(src, s->s_class)) 327 setbitn(dst, s->s_class); 328 } 329 } 330 } 331 332 /* 333 ** RMEXPSTAB -- remove expired entries from SymTab. 334 ** 335 ** These entries need to be removed in long-running processes, 336 ** e.g., persistent queue runners, to avoid consuming memory. 337 ** 338 ** XXX It might be useful to restrict the maximum TTL to avoid 339 ** caching data very long. 340 ** 341 ** Parameters: 342 ** none. 343 ** 344 ** Returns: 345 ** none. 346 ** 347 ** Side Effects: 348 ** can remove entries from the symbol table. 349 */ 350 351 #define SM_STAB_FREE(x) \ 352 do \ 353 { \ 354 char *o = (x); \ 355 (x) = NULL; \ 356 if (o != NULL) \ 357 sm_free(o); \ 358 } while (0) 359 360 void 361 rmexpstab() 362 { 363 int i; 364 STAB *s, *p, *f; 365 time_t now; 366 367 now = curtime(); 368 for (i = 0; i < STABSIZE; i++) 369 { 370 p = NULL; 371 s = SymTab[i]; 372 while (s != NULL) 373 { 374 switch (s->s_symtype) 375 { 376 case ST_HOSTSIG: 377 if (s->s_hostsig.hs_exp >= now) 378 goto next; /* not expired */ 379 SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */ 380 break; 381 382 case ST_NAMECANON: 383 if (s->s_namecanon.nc_exp >= now) 384 goto next; /* not expired */ 385 SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */ 386 break; 387 388 default: 389 if (s->s_symtype >= ST_MCI) 390 { 391 /* call mci_uncache? */ 392 SM_STAB_FREE(s->s_mci.mci_status); 393 SM_STAB_FREE(s->s_mci.mci_rstatus); 394 SM_STAB_FREE(s->s_mci.mci_heloname); 395 #if 0 396 /* not dynamically allocated */ 397 SM_STAB_FREE(s->s_mci.mci_host); 398 SM_STAB_FREE(s->s_mci.mci_tolist); 399 #endif /* 0 */ 400 #if SASL 401 /* should always by NULL */ 402 SM_STAB_FREE(s->s_mci.mci_sasl_string); 403 #endif /* SASL */ 404 if (s->s_mci.mci_rpool != NULL) 405 { 406 sm_rpool_free(s->s_mci.mci_rpool); 407 s->s_mci.mci_macro.mac_rpool = NULL; 408 s->s_mci.mci_rpool = NULL; 409 } 410 break; 411 } 412 next: 413 p = s; 414 s = s->s_next; 415 continue; 416 } 417 418 /* remove entry */ 419 SM_STAB_FREE(s->s_name); /* XXX */ 420 f = s; 421 s = s->s_next; 422 sm_free(f); /* XXX */ 423 if (p == NULL) 424 SymTab[i] = s; 425 else 426 p->s_next = s; 427 } 428 } 429 } 430 431 #if SM_HEAP_CHECK 432 /* 433 ** DUMPSTAB -- dump symbol table. 434 ** 435 ** For debugging. 436 */ 437 438 #define MAXSTTYPES (ST_MCI + 1) 439 440 void 441 dumpstab() 442 { 443 int i, t, total, types[MAXSTTYPES]; 444 STAB *s; 445 static int prevt[MAXSTTYPES], prev = 0; 446 447 total = 0; 448 for (i = 0; i < MAXSTTYPES; i++) 449 types[i] = 0; 450 for (i = 0; i < STABSIZE; i++) 451 { 452 s = SymTab[i]; 453 while (s != NULL) 454 { 455 ++total; 456 t = s->s_symtype; 457 if (t > MAXSTTYPES - 1) 458 t = MAXSTTYPES - 1; 459 types[t]++; 460 s = s->s_next; 461 } 462 } 463 sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev); 464 prev = total; 465 for (i = 0; i < MAXSTTYPES; i++) 466 { 467 if (types[i] != 0) 468 { 469 sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)", 470 i, types[i], types[i] - prevt[i]); 471 } 472 prevt[i] = types[i]; 473 } 474 } 475 #endif /* SM_HEAP_CHECK */ 476