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 *
stab(name,type,op)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
queueup_macros(class,qfp,e)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
copy_class(src,dst)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
rmexpstab()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
dumpstab()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