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.89 2006/08/15 23:24:58 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 *
stab(name,type,op)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
queueup_macros(class,qfp,e)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
copy_class(src,dst)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
rmexpstab()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
dumpstab()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