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