stab.c revision 132943
1104349Sphk/*
2104349Sphk * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers.
3104349Sphk *	All rights reserved.
4104349Sphk * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5104349Sphk * Copyright (c) 1988, 1993
6104349Sphk *	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
16SM_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
39static STAB	*SymTab[STABSIZE];
40
41STAB *
42stab(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
232void
233stabapply(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
266void
267queueup_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
311void
312copy_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
360void
361rmexpstab()
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
440void
441dumpstab()
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