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