stab.c revision 168515
138032Speter/*
2120256Sgshapiro * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
538032Speter * Copyright (c) 1988, 1993
638032Speter *	The Regents of the University of California.  All rights reserved.
738032Speter *
838032Speter * By using this file, you agree to the terms and conditions set
938032Speter * forth in the LICENSE file which can be found at the top level of
1038032Speter * the sendmail distribution.
1138032Speter *
1238032Speter */
1338032Speter
1464562Sgshapiro#include <sendmail.h>
1538032Speter
16168515SgshapiroSM_RCSID("@(#)$Id: stab.c,v 8.89 2006/08/15 23:24:58 ca Exp $")
1790792Sgshapiro
1838032Speter/*
1938032Speter**  STAB -- manage the symbol table
2038032Speter**
2138032Speter**	Parameters:
2238032Speter**		name -- the name to be looked up or inserted.
2338032Speter**		type -- the type of symbol.
2438032Speter**		op -- what to do:
2590792Sgshapiro**			ST_ENTER -- enter the name if not already present.
2638032Speter**			ST_FIND -- find it only.
2738032Speter**
2838032Speter**	Returns:
2938032Speter**		pointer to a STAB entry for this name.
3038032Speter**		NULL if not found and not entered.
3138032Speter**
3238032Speter**	Side Effects:
3338032Speter**		can update the symbol table.
3438032Speter*/
3538032Speter
3664562Sgshapiro#define STABSIZE	2003
3790792Sgshapiro#define SM_LOWER(c)	((isascii(c) && isupper(c)) ? tolower(c) : (c))
3838032Speter
3938032Speterstatic STAB	*SymTab[STABSIZE];
4038032Speter
4138032SpeterSTAB *
4238032Speterstab(name, type, op)
4338032Speter	char *name;
4438032Speter	int type;
4538032Speter	int op;
4638032Speter{
4738032Speter	register STAB *s;
4838032Speter	register STAB **ps;
4938032Speter	register int hfunc;
5038032Speter	register char *p;
5138032Speter	int len;
5238032Speter
5338032Speter	if (tTd(36, 5))
5490792Sgshapiro		sm_dprintf("STAB: %s %d ", name, type);
5538032Speter
5638032Speter	/*
5738032Speter	**  Compute the hashing function
5838032Speter	*/
5938032Speter
6038032Speter	hfunc = type;
6138032Speter	for (p = name; *p != '\0'; p++)
6290792Sgshapiro		hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE;
6338032Speter
6438032Speter	if (tTd(36, 9))
6590792Sgshapiro		sm_dprintf("(hfunc=%d) ", hfunc);
6638032Speter
6738032Speter	ps = &SymTab[hfunc];
6838032Speter	if (type == ST_MACRO || type == ST_RULESET)
6938032Speter	{
7038032Speter		while ((s = *ps) != NULL &&
7190792Sgshapiro		       (s->s_symtype != type || strcmp(name, s->s_name)))
7238032Speter			ps = &s->s_next;
7338032Speter	}
7438032Speter	else
7538032Speter	{
7638032Speter		while ((s = *ps) != NULL &&
7790792Sgshapiro		       (s->s_symtype != type || sm_strcasecmp(name, s->s_name)))
7838032Speter			ps = &s->s_next;
7938032Speter	}
8038032Speter
8138032Speter	/*
8238032Speter	**  Dispose of the entry.
8338032Speter	*/
8438032Speter
8538032Speter	if (s != NULL || op == ST_FIND)
8638032Speter	{
8738032Speter		if (tTd(36, 5))
8838032Speter		{
8938032Speter			if (s == NULL)
9090792Sgshapiro				sm_dprintf("not found\n");
9138032Speter			else
9238032Speter			{
9338032Speter				long *lp = (long *) s->s_class;
9438032Speter
9590792Sgshapiro				sm_dprintf("type %d val %lx %lx %lx %lx\n",
9690792Sgshapiro					s->s_symtype, lp[0], lp[1], lp[2], lp[3]);
9738032Speter			}
9838032Speter		}
9964562Sgshapiro		return s;
10038032Speter	}
10138032Speter
10238032Speter	/*
10338032Speter	**  Make a new entry and link it in.
10438032Speter	*/
10538032Speter
10638032Speter	if (tTd(36, 5))
10790792Sgshapiro		sm_dprintf("entered\n");
10838032Speter
10938032Speter	/* determine size of new entry */
11038032Speter	switch (type)
11138032Speter	{
11238032Speter	  case ST_CLASS:
113168515Sgshapiro		len = sizeof(s->s_class);
11438032Speter		break;
11538032Speter
11638032Speter	  case ST_ADDRESS:
117168515Sgshapiro		len = sizeof(s->s_address);
11838032Speter		break;
11938032Speter
12038032Speter	  case ST_MAILER:
121168515Sgshapiro		len = sizeof(s->s_mailer);
12264562Sgshapiro		break;
12338032Speter
12438032Speter	  case ST_ALIAS:
125168515Sgshapiro		len = sizeof(s->s_alias);
12638032Speter		break;
12738032Speter
12838032Speter	  case ST_MAPCLASS:
129168515Sgshapiro		len = sizeof(s->s_mapclass);
13038032Speter		break;
13138032Speter
13238032Speter	  case ST_MAP:
133168515Sgshapiro		len = sizeof(s->s_map);
13438032Speter		break;
13538032Speter
13638032Speter	  case ST_HOSTSIG:
137168515Sgshapiro		len = sizeof(s->s_hostsig);
13838032Speter		break;
13938032Speter
14038032Speter	  case ST_NAMECANON:
141168515Sgshapiro		len = sizeof(s->s_namecanon);
14238032Speter		break;
14338032Speter
14438032Speter	  case ST_MACRO:
145168515Sgshapiro		len = sizeof(s->s_macro);
14638032Speter		break;
14738032Speter
14838032Speter	  case ST_RULESET:
149168515Sgshapiro		len = sizeof(s->s_ruleset);
15038032Speter		break;
15138032Speter
15264562Sgshapiro	  case ST_HEADER:
153168515Sgshapiro		len = sizeof(s->s_header);
15464562Sgshapiro		break;
15564562Sgshapiro
15638032Speter	  case ST_SERVICE:
157168515Sgshapiro		len = sizeof(s->s_service);
15838032Speter		break;
15938032Speter
16090792Sgshapiro#if LDAPMAP
16177349Sgshapiro	  case ST_LMAP:
162168515Sgshapiro		len = sizeof(s->s_lmap);
16338032Speter		break;
16464562Sgshapiro#endif /* LDAPMAP */
16538032Speter
16690792Sgshapiro#if MILTER
16764562Sgshapiro	  case ST_MILTER:
168168515Sgshapiro		len = sizeof(s->s_milter);
16964562Sgshapiro		break;
17090792Sgshapiro#endif /* MILTER */
17164562Sgshapiro
17290792Sgshapiro	  case ST_QUEUE:
173168515Sgshapiro		len = sizeof(s->s_quegrp);
17490792Sgshapiro		break;
17590792Sgshapiro
176132943Sgshapiro#if SOCKETMAP
177132943Sgshapiro	  case ST_SOCKETMAP:
178168515Sgshapiro		len = sizeof(s->s_socketmap);
179132943Sgshapiro		break;
180132943Sgshapiro#endif /* SOCKETMAP */
181132943Sgshapiro
18238032Speter	  default:
18364562Sgshapiro		/*
18490792Sgshapiro		**  Each mailer has its own MCI stab entry:
18564562Sgshapiro		**
18664562Sgshapiro		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
18764562Sgshapiro		**
18864562Sgshapiro		**  Therefore, anything ST_MCI or larger is an s_mci.
18964562Sgshapiro		*/
19064562Sgshapiro
19138032Speter		if (type >= ST_MCI)
192168515Sgshapiro			len = sizeof(s->s_mci);
19338032Speter		else
19438032Speter		{
19538032Speter			syserr("stab: unknown symbol type %d", type);
196168515Sgshapiro			len = sizeof(s->s_value);
19738032Speter		}
19838032Speter		break;
19938032Speter	}
200168515Sgshapiro	len += sizeof(*s) - sizeof(s->s_value);
20138032Speter
20264562Sgshapiro	if (tTd(36, 15))
20390792Sgshapiro		sm_dprintf("size of stab entry: %d\n", len);
20464562Sgshapiro
20538032Speter	/* make new entry */
20690792Sgshapiro	s = (STAB *) sm_pmalloc_x(len);
20764562Sgshapiro	memset((char *) s, '\0', len);
20890792Sgshapiro	s->s_name = sm_pstrdup_x(name);
20990792Sgshapiro	s->s_symtype = type;
21038032Speter
21138032Speter	/* link it in */
21238032Speter	*ps = s;
21338032Speter
21464562Sgshapiro	/* set a default value for rulesets */
21564562Sgshapiro	if (type == ST_RULESET)
21664562Sgshapiro		s->s_ruleset = -1;
21764562Sgshapiro
21864562Sgshapiro	return s;
21938032Speter}
22090792Sgshapiro/*
22138032Speter**  STABAPPLY -- apply function to all stab entries
22238032Speter**
22338032Speter**	Parameters:
22490792Sgshapiro**		func -- the function to apply.  It will be given two
22590792Sgshapiro**			parameters (the stab entry and the arg).
22638032Speter**		arg -- an arbitrary argument, passed to func.
22738032Speter**
22838032Speter**	Returns:
22938032Speter**		none.
23038032Speter*/
23138032Speter
23238032Spetervoid
23338032Speterstabapply(func, arg)
23438032Speter	void (*func)__P((STAB *, int));
23538032Speter	int arg;
23638032Speter{
23738032Speter	register STAB **shead;
23838032Speter	register STAB *s;
23938032Speter
24038032Speter	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
24138032Speter	{
24238032Speter		for (s = *shead; s != NULL; s = s->s_next)
24338032Speter		{
24438032Speter			if (tTd(36, 90))
24590792Sgshapiro				sm_dprintf("stabapply: trying %d/%s\n",
24690792Sgshapiro					s->s_symtype, s->s_name);
24738032Speter			func(s, arg);
24838032Speter		}
24938032Speter	}
25038032Speter}
25190792Sgshapiro/*
25264562Sgshapiro**  QUEUEUP_MACROS -- queueup the macros in a class
25364562Sgshapiro**
25464562Sgshapiro**	Write the macros listed in the specified class into the
25564562Sgshapiro**	file referenced by qfp.
25664562Sgshapiro**
25764562Sgshapiro**	Parameters:
25864562Sgshapiro**		class -- class ID.
25990792Sgshapiro**		qfp -- file pointer to the queue file.
26064562Sgshapiro**		e -- the envelope.
26164562Sgshapiro**
26264562Sgshapiro**	Returns:
26364562Sgshapiro**		none.
26464562Sgshapiro*/
26564562Sgshapiro
26664562Sgshapirovoid
26764562Sgshapiroqueueup_macros(class, qfp, e)
26864562Sgshapiro	int class;
26990792Sgshapiro	SM_FILE_T *qfp;
27064562Sgshapiro	ENVELOPE *e;
27164562Sgshapiro{
27264562Sgshapiro	register STAB **shead;
27364562Sgshapiro	register STAB *s;
27464562Sgshapiro
27564562Sgshapiro	if (e == NULL)
27664562Sgshapiro		return;
27764562Sgshapiro
27871345Sgshapiro	class = bitidx(class);
27964562Sgshapiro	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
28064562Sgshapiro	{
28164562Sgshapiro		for (s = *shead; s != NULL; s = s->s_next)
28264562Sgshapiro		{
28364562Sgshapiro			int m;
28464562Sgshapiro			char *p;
28564562Sgshapiro
28690792Sgshapiro			if (s->s_symtype == ST_CLASS &&
28790792Sgshapiro			    bitnset(bitidx(class), s->s_class) &&
288120256Sgshapiro			    (m = macid(s->s_name)) != 0 &&
28964562Sgshapiro			    (p = macvalue(m, e)) != NULL)
29064562Sgshapiro			{
29190792Sgshapiro				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
29290792Sgshapiro						      "$%s%s\n",
29390792Sgshapiro						      s->s_name,
29490792Sgshapiro						      denlstring(p, true,
29590792Sgshapiro								 false));
29664562Sgshapiro			}
29764562Sgshapiro		}
29864562Sgshapiro	}
29964562Sgshapiro}
30090792Sgshapiro/*
30164562Sgshapiro**  COPY_CLASS -- copy class members from one class to another
30264562Sgshapiro**
30364562Sgshapiro**	Parameters:
30464562Sgshapiro**		src -- source class.
30564562Sgshapiro**		dst -- destination class.
30664562Sgshapiro**
30764562Sgshapiro**	Returns:
30864562Sgshapiro**		none.
30964562Sgshapiro*/
31064562Sgshapiro
31164562Sgshapirovoid
31264562Sgshapirocopy_class(src, dst)
31364562Sgshapiro	int src;
31464562Sgshapiro	int dst;
31564562Sgshapiro{
31664562Sgshapiro	register STAB **shead;
31764562Sgshapiro	register STAB *s;
31864562Sgshapiro
31971345Sgshapiro	src = bitidx(src);
32071345Sgshapiro	dst = bitidx(dst);
32164562Sgshapiro	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
32264562Sgshapiro	{
32364562Sgshapiro		for (s = *shead; s != NULL; s = s->s_next)
32464562Sgshapiro		{
32590792Sgshapiro			if (s->s_symtype == ST_CLASS &&
32671345Sgshapiro			    bitnset(src, s->s_class))
32764562Sgshapiro				setbitn(dst, s->s_class);
32864562Sgshapiro		}
32964562Sgshapiro	}
33064562Sgshapiro}
33190792Sgshapiro
33290792Sgshapiro/*
33390792Sgshapiro**  RMEXPSTAB -- remove expired entries from SymTab.
33490792Sgshapiro**
33590792Sgshapiro**	These entries need to be removed in long-running processes,
33690792Sgshapiro**	e.g., persistent queue runners, to avoid consuming memory.
33790792Sgshapiro**
33890792Sgshapiro**	XXX It might be useful to restrict the maximum TTL to avoid
33990792Sgshapiro**		caching data very long.
34090792Sgshapiro**
34190792Sgshapiro**	Parameters:
34290792Sgshapiro**		none.
34390792Sgshapiro**
34490792Sgshapiro**	Returns:
34590792Sgshapiro**		none.
34690792Sgshapiro**
34790792Sgshapiro**	Side Effects:
34890792Sgshapiro**		can remove entries from the symbol table.
34990792Sgshapiro*/
35090792Sgshapiro
35190792Sgshapiro#define SM_STAB_FREE(x)	\
35290792Sgshapiro	do \
35390792Sgshapiro	{ \
35490792Sgshapiro		char *o = (x); \
35590792Sgshapiro		(x) = NULL; \
35690792Sgshapiro		if (o != NULL) \
35790792Sgshapiro			sm_free(o); \
35890792Sgshapiro	} while (0)
35990792Sgshapiro
36090792Sgshapirovoid
36190792Sgshapirormexpstab()
36290792Sgshapiro{
36390792Sgshapiro	int i;
36490792Sgshapiro	STAB *s, *p, *f;
36590792Sgshapiro	time_t now;
36690792Sgshapiro
36790792Sgshapiro	now = curtime();
36890792Sgshapiro	for (i = 0; i < STABSIZE; i++)
36990792Sgshapiro	{
37090792Sgshapiro		p = NULL;
37190792Sgshapiro		s = SymTab[i];
37290792Sgshapiro		while (s != NULL)
37390792Sgshapiro		{
37490792Sgshapiro			switch (s->s_symtype)
37590792Sgshapiro			{
37690792Sgshapiro			  case ST_HOSTSIG:
37790792Sgshapiro				if (s->s_hostsig.hs_exp >= now)
37890792Sgshapiro					goto next;	/* not expired */
37990792Sgshapiro				SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */
38090792Sgshapiro				break;
38190792Sgshapiro
38290792Sgshapiro			  case ST_NAMECANON:
38390792Sgshapiro				if (s->s_namecanon.nc_exp >= now)
38490792Sgshapiro					goto next;	/* not expired */
38590792Sgshapiro				SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */
38690792Sgshapiro				break;
38790792Sgshapiro
38890792Sgshapiro			  default:
38990792Sgshapiro				if (s->s_symtype >= ST_MCI)
39090792Sgshapiro				{
39190792Sgshapiro					/* call mci_uncache? */
39290792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_status);
39390792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_rstatus);
39490792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_heloname);
39590792Sgshapiro#if 0
39690792Sgshapiro					/* not dynamically allocated */
39790792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_host);
39890792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_tolist);
39990792Sgshapiro#endif /* 0 */
40090792Sgshapiro#if SASL
40190792Sgshapiro					/* should always by NULL */
40290792Sgshapiro					SM_STAB_FREE(s->s_mci.mci_sasl_string);
40390792Sgshapiro#endif /* SASL */
40490792Sgshapiro					if (s->s_mci.mci_rpool != NULL)
40590792Sgshapiro					{
40690792Sgshapiro						sm_rpool_free(s->s_mci.mci_rpool);
40790792Sgshapiro						s->s_mci.mci_macro.mac_rpool = NULL;
40890792Sgshapiro						s->s_mci.mci_rpool = NULL;
40990792Sgshapiro					}
41090792Sgshapiro					break;
41190792Sgshapiro				}
41290792Sgshapiro  next:
41390792Sgshapiro				p = s;
41490792Sgshapiro				s = s->s_next;
41590792Sgshapiro				continue;
41690792Sgshapiro			}
41790792Sgshapiro
41890792Sgshapiro			/* remove entry */
41990792Sgshapiro			SM_STAB_FREE(s->s_name); /* XXX */
42090792Sgshapiro			f = s;
42190792Sgshapiro			s = s->s_next;
42290792Sgshapiro			sm_free(f);	/* XXX */
42390792Sgshapiro			if (p == NULL)
42490792Sgshapiro				SymTab[i] = s;
42590792Sgshapiro			else
42690792Sgshapiro				p->s_next = s;
42790792Sgshapiro		}
42890792Sgshapiro	}
42990792Sgshapiro}
43090792Sgshapiro
43190792Sgshapiro#if SM_HEAP_CHECK
43290792Sgshapiro/*
43390792Sgshapiro**  DUMPSTAB -- dump symbol table.
43490792Sgshapiro**
43590792Sgshapiro**	For debugging.
43690792Sgshapiro*/
43790792Sgshapiro
43890792Sgshapiro#define MAXSTTYPES	(ST_MCI + 1)
43990792Sgshapiro
44090792Sgshapirovoid
44190792Sgshapirodumpstab()
44290792Sgshapiro{
44390792Sgshapiro	int i, t, total, types[MAXSTTYPES];
44490792Sgshapiro	STAB *s;
44590792Sgshapiro	static int prevt[MAXSTTYPES], prev = 0;
44690792Sgshapiro
44790792Sgshapiro	total = 0;
44890792Sgshapiro	for (i = 0; i < MAXSTTYPES; i++)
44990792Sgshapiro		types[i] = 0;
45090792Sgshapiro	for (i = 0; i < STABSIZE; i++)
45190792Sgshapiro	{
45290792Sgshapiro		s = SymTab[i];
45390792Sgshapiro		while (s != NULL)
45490792Sgshapiro		{
45590792Sgshapiro			++total;
45690792Sgshapiro			t = s->s_symtype;
45790792Sgshapiro			if (t > MAXSTTYPES - 1)
45890792Sgshapiro				t = MAXSTTYPES - 1;
45990792Sgshapiro			types[t]++;
46090792Sgshapiro			s = s->s_next;
46190792Sgshapiro		}
46290792Sgshapiro	}
46390792Sgshapiro	sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev);
46490792Sgshapiro	prev = total;
46590792Sgshapiro	for (i = 0; i < MAXSTTYPES; i++)
46690792Sgshapiro	{
46790792Sgshapiro		if (types[i] != 0)
46890792Sgshapiro		{
46990792Sgshapiro			sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)",
47090792Sgshapiro				i, types[i], types[i] - prevt[i]);
47190792Sgshapiro		}
47290792Sgshapiro		prevt[i] = types[i];
47390792Sgshapiro	}
47490792Sgshapiro}
47590792Sgshapiro#endif /* SM_HEAP_CHECK */
476