stab.c revision 261363
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1998-2001, 2003 Proofpoint, Inc. and its suppliers.
31590Srgrimes *	All rights reserved.
41590Srgrimes * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
51590Srgrimes * Copyright (c) 1988, 1993
61590Srgrimes *	The Regents of the University of California.  All rights reserved.
71590Srgrimes *
81590Srgrimes * By using this file, you agree to the terms and conditions set
91590Srgrimes * forth in the LICENSE file which can be found at the top level of
101590Srgrimes * the sendmail distribution.
111590Srgrimes *
121590Srgrimes */
131590Srgrimes
141590Srgrimes#include <sendmail.h>
151590Srgrimes
161590SrgrimesSM_RCSID("@(#)$Id: stab.c,v 8.92 2013/11/22 20:51:56 ca Exp $")
171590Srgrimes
181590Srgrimes/*
191590Srgrimes**  STAB -- manage the symbol table
201590Srgrimes**
211590Srgrimes**	Parameters:
221590Srgrimes**		name -- the name to be looked up or inserted.
231590Srgrimes**		type -- the type of symbol.
241590Srgrimes**		op -- what to do:
251590Srgrimes**			ST_ENTER -- enter the name if not already present.
261590Srgrimes**			ST_FIND -- find it only.
271590Srgrimes**
281590Srgrimes**	Returns:
291590Srgrimes**		pointer to a STAB entry for this name.
301590Srgrimes**		NULL if not found and not entered.
3191792Smike**
321590Srgrimes**	Side Effects:
331590Srgrimes**		can update the symbol table.
3491481Smike*/
351590Srgrimes
3691792Smike#define STABSIZE	2003
371590Srgrimes#define SM_LOWER(c)	((isascii(c) && isupper(c)) ? tolower(c) : (c))
3891481Smike
3991481Smikestatic STAB	*SymTab[STABSIZE];
4015233Sbde
411590SrgrimesSTAB *
4291481Smikestab(name, type, op)
4391481Smike	char *name;
4491481Smike	int type;
451590Srgrimes	int op;
461590Srgrimes{
4715233Sbde	register STAB *s;
4815233Sbde	register STAB **ps;
4915233Sbde	register int hfunc;
5098165Stjr	register char *p;
511590Srgrimes	int len;
5213380Sache
5391481Smike	if (tTd(36, 5))
541590Srgrimes		sm_dprintf("STAB: %s %d ", name, type);
551590Srgrimes
561590Srgrimes	/*
5715233Sbde	**  Compute the hashing function
58128049Stjr	*/
59101670Stjr
601590Srgrimes	hfunc = type;
61227201Sed	for (p = name; *p != '\0'; p++)
62227201Sed		hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE;
63208210Spjd
641590Srgrimes	if (tTd(36, 9))
65208170Spjd		sm_dprintf("(hfunc=%d) ", hfunc);
66208170Spjd
6792922Simp	ps = &SymTab[hfunc];
6892922Simp	if (type == ST_MACRO || type == ST_RULESET || type == ST_NAMECANON)
691590Srgrimes	{
70208170Spjd		while ((s = *ps) != NULL &&
71208170Spjd		       (s->s_symtype != type || strcmp(name, s->s_name)))
72208170Spjd			ps = &s->s_next;
73208170Spjd	}
74208170Spjd	else
75208170Spjd	{
76208170Spjd		while ((s = *ps) != NULL &&
77282278Sbdrewery		       (s->s_symtype != type || sm_strcasecmp(name, s->s_name)))
78282278Sbdrewery			ps = &s->s_next;
79282278Sbdrewery	}
80282278Sbdrewery
81282278Sbdrewery	/*
82282278Sbdrewery	**  Dispose of the entry.
83282278Sbdrewery	*/
84282278Sbdrewery
851590Srgrimes	if (s != NULL || op == ST_FIND)
86139364Sjosef	{
871590Srgrimes		if (tTd(36, 5))
8849685Ssheldonh		{
891590Srgrimes			if (s == NULL)
9013380Sache				sm_dprintf("not found\n");
9113380Sache			else
92185714Skeramida			{
931590Srgrimes				long *lp = (long *) s->s_class;
941590Srgrimes
951590Srgrimes				sm_dprintf("type %d val %lx %lx %lx %lx\n",
961590Srgrimes					s->s_symtype, lp[0], lp[1], lp[2], lp[3]);
971590Srgrimes			}
981590Srgrimes		}
991590Srgrimes		return s;
1001590Srgrimes	}
1011590Srgrimes
10298165Stjr	/*
1031590Srgrimes	**  Make a new entry and link it in.
104185714Skeramida	*/
105185714Skeramida
106185714Skeramida	if (tTd(36, 5))
10798165Stjr		sm_dprintf("entered\n");
10898165Stjr
10998165Stjr	/* determine size of new entry */
11098165Stjr	switch (type)
1111590Srgrimes	{
1121590Srgrimes	  case ST_CLASS:
1131590Srgrimes		len = sizeof(s->s_class);
1141590Srgrimes		break;
1151590Srgrimes
1161590Srgrimes	  case ST_MAILER:
1171590Srgrimes		len = sizeof(s->s_mailer);
118208170Spjd		break;
119208170Spjd
1201590Srgrimes	  case ST_ALIAS:
121185714Skeramida		len = sizeof(s->s_alias);
1221590Srgrimes		break;
1231590Srgrimes
12415233Sbde	  case ST_MAPCLASS:
1251590Srgrimes		len = sizeof(s->s_mapclass);
1261590Srgrimes		break;
12715233Sbde
12815233Sbde	  case ST_MAP:
129208170Spjd		len = sizeof(s->s_map);
130208170Spjd		break;
131208170Spjd
132208170Spjd	  case ST_HOSTSIG:
133208170Spjd		len = sizeof(s->s_hostsig);
134208170Spjd		break;
1351590Srgrimes
1361590Srgrimes	  case ST_NAMECANON:
137208170Spjd		len = sizeof(s->s_namecanon);
138208170Spjd		break;
13915233Sbde
1401590Srgrimes	  case ST_MACRO:
1411590Srgrimes		len = sizeof(s->s_macro);
142208170Spjd		break;
143208170Spjd
144208170Spjd	  case ST_RULESET:
145208170Spjd		len = sizeof(s->s_ruleset);
146208170Spjd		break;
147208170Spjd
148208170Spjd	  case ST_HEADER:
149208170Spjd		len = sizeof(s->s_header);
150208170Spjd		break;
151208170Spjd
152208170Spjd	  case ST_SERVICE:
153208170Spjd		len = sizeof(s->s_service);
154208170Spjd		break;
155208170Spjd
156208170Spjd#if LDAPMAP
157208170Spjd	  case ST_LMAP:
158208170Spjd		len = sizeof(s->s_lmap);
159208170Spjd		break;
160208170Spjd#endif /* LDAPMAP */
161208170Spjd
162208170Spjd#if MILTER
163208170Spjd	  case ST_MILTER:
164208170Spjd		len = sizeof(s->s_milter);
165208170Spjd		break;
166208170Spjd#endif /* MILTER */
167208170Spjd
168208170Spjd	  case ST_QUEUE:
16991481Smike		len = sizeof(s->s_quegrp);
170139364Sjosef		break;
1711590Srgrimes
17249685Ssheldonh#if SOCKETMAP
173185714Skeramida	  case ST_SOCKETMAP:
174128049Stjr		len = sizeof(s->s_socketmap);
175128049Stjr		break;
17649461Ssheldonh#endif /* SOCKETMAP */
17749685Ssheldonh
17898291Stjr	  default:
17998165Stjr		/*
180128049Stjr		**  Each mailer has its own MCI stab entry:
1811590Srgrimes		**
182185714Skeramida		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
183208170Spjd		**
18415233Sbde		**  Therefore, anything ST_MCI or larger is an s_mci.
185208170Spjd		*/
18615179Swosch
18715233Sbde		if (type >= ST_MCI)
18815233Sbde			len = sizeof(s->s_mci);
18915179Swosch		else
19098165Stjr		{
1911590Srgrimes			syserr("stab: unknown symbol type %d", type);
1921590Srgrimes			len = sizeof(s->s_value);
1931590Srgrimes		}
1941590Srgrimes		break;
1951590Srgrimes	}
1961590Srgrimes	len += sizeof(*s) - sizeof(s->s_value);
1971590Srgrimes
19828696Scharnier	if (tTd(36, 15))
19915233Sbde		sm_dprintf("size of stab entry: %d\n", len);
20015233Sbde
20115233Sbde	/* make new entry */
20215233Sbde	s = (STAB *) sm_pmalloc_x(len);
20315233Sbde	memset((char *) s, '\0', len);
204208170Spjd	s->s_name = sm_pstrdup_x(name);
205208170Spjd	s->s_symtype = type;
206208170Spjd
207208170Spjd	/* link it in */
2081590Srgrimes	*ps = s;
2091590Srgrimes
210185714Skeramida	/* set a default value for rulesets */
211185714Skeramida	if (type == ST_RULESET)
212185714Skeramida		s->s_ruleset = -1;
213185714Skeramida
2141590Srgrimes	return s;
215185714Skeramida}
216185714Skeramida/*
2171590Srgrimes**  STABAPPLY -- apply function to all stab entries
218282278Sbdrewery**
2191590Srgrimes**	Parameters:
220208170Spjd**		func -- the function to apply.  It will be given two
2211590Srgrimes**			parameters (the stab entry and the arg).
222185714Skeramida**		arg -- an arbitrary argument, passed to func.
223185714Skeramida**
224185714Skeramida**	Returns:
225185714Skeramida**		none.
226208170Spjd*/
2271590Srgrimes
22815233Sbdevoid
2291590Srgrimesstabapply(func, arg)
2301590Srgrimes	void (*func)__P((STAB *, int));
2311590Srgrimes	int arg;
23298245Stjr{
2331590Srgrimes	register STAB **shead;
23498165Stjr	register STAB *s;
23515233Sbde
23615233Sbde	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
23715233Sbde	{
23815233Sbde		for (s = *shead; s != NULL; s = s->s_next)
23915233Sbde		{
24098245Stjr			if (tTd(36, 90))
241282278Sbdrewery				sm_dprintf("stabapply: trying %d/%s\n",
242208170Spjd					s->s_symtype, s->s_name);
243208170Spjd			func(s, arg);
244208170Spjd		}
2451590Srgrimes	}
24615233Sbde}
2471590Srgrimes/*
2481590Srgrimes**  QUEUEUP_MACROS -- queueup the macros in a class
2491590Srgrimes**
2501590Srgrimes**	Write the macros listed in the specified class into the
2511590Srgrimes**	file referenced by qfp.
25298165Stjr**
25398165Stjr**	Parameters:
254128049Stjr**		class -- class ID.
255128049Stjr**		qfp -- file pointer to the queue file.
256128049Stjr**		e -- the envelope.
257208170Spjd**
25815233Sbde**	Returns:
25915233Sbde**		none.
26015233Sbde*/
26198165Stjr
26298165Stjrvoid
263208170Spjdqueueup_macros(class, qfp, e)
264208170Spjd	int class;
26598165Stjr	SM_FILE_T *qfp;
26698165Stjr	ENVELOPE *e;
26798165Stjr{
268128049Stjr	register STAB **shead;
269128049Stjr	register STAB *s;
270128049Stjr
271128049Stjr	if (e == NULL)
272208170Spjd		return;
273208170Spjd
274128049Stjr	class = bitidx(class);
27598165Stjr	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
276128049Stjr	{
277128049Stjr		for (s = *shead; s != NULL; s = s->s_next)
278128049Stjr		{
279128049Stjr			int m;
280128049Stjr			char *p;
281128049Stjr
282128049Stjr			if (s->s_symtype == ST_CLASS &&
28398165Stjr			    bitnset(bitidx(class), s->s_class) &&
284185714Skeramida			    (m = macid(s->s_name)) != 0 &&
285185714Skeramida			    (p = macvalue(m, e)) != NULL)
28698165Stjr			{
28798165Stjr				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
288185714Skeramida						      "$%s%s\n",
289185714Skeramida						      s->s_name,
290185714Skeramida						      denlstring(p, true,
291185714Skeramida								 false));
2921590Srgrimes			}
293185714Skeramida		}
294101670Stjr	}
2951590Srgrimes}
2961590Srgrimes/*
2971590Srgrimes**  COPY_CLASS -- copy class members from one class to another
2981590Srgrimes**
2991590Srgrimes**	Parameters:
3001590Srgrimes**		src -- source class.
3011590Srgrimes**		dst -- destination class.
302282278Sbdrewery**
303128049Stjr**	Returns:
304128049Stjr**		none.
305208170Spjd*/
306208170Spjd
3071590Srgrimesvoid
308208170Spjdcopy_class(src, dst)
3091590Srgrimes	int src;
310208170Spjd	int dst;
3111590Srgrimes{
312185714Skeramida	register STAB **shead;
313185714Skeramida	register STAB *s;
314185714Skeramida
315185714Skeramida	src = bitidx(src);
316208170Spjd	dst = bitidx(dst);
3171590Srgrimes	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
31815233Sbde	{
3191590Srgrimes		for (s = *shead; s != NULL; s = s->s_next)
3201590Srgrimes		{
32191481Smike			if (s->s_symtype == ST_CLASS &&
322201181Sed			    bitnset(src, s->s_class))
3231590Srgrimes				setbitn(dst, s->s_class);
324185714Skeramida		}
3251590Srgrimes	}
3261590Srgrimes}
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
356void
357rmexpstab()
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
436void
437dumpstab()
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