xref: /freebsd/contrib/sendmail/src/stab.c (revision f1f890804985a1043da42a5def13c79dc005f5e9)
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.91 2011/08/08 17:33:34 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 *
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 || type == ST_NAMECANON)
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_MAILER:
117 		len = sizeof(s->s_mailer);
118 		break;
119 
120 	  case ST_ALIAS:
121 		len = sizeof(s->s_alias);
122 		break;
123 
124 	  case ST_MAPCLASS:
125 		len = sizeof(s->s_mapclass);
126 		break;
127 
128 	  case ST_MAP:
129 		len = sizeof(s->s_map);
130 		break;
131 
132 	  case ST_HOSTSIG:
133 		len = sizeof(s->s_hostsig);
134 		break;
135 
136 	  case ST_NAMECANON:
137 		len = sizeof(s->s_namecanon);
138 		break;
139 
140 	  case ST_MACRO:
141 		len = sizeof(s->s_macro);
142 		break;
143 
144 	  case ST_RULESET:
145 		len = sizeof(s->s_ruleset);
146 		break;
147 
148 	  case ST_HEADER:
149 		len = sizeof(s->s_header);
150 		break;
151 
152 	  case ST_SERVICE:
153 		len = sizeof(s->s_service);
154 		break;
155 
156 #if LDAPMAP
157 	  case ST_LMAP:
158 		len = sizeof(s->s_lmap);
159 		break;
160 #endif /* LDAPMAP */
161 
162 #if MILTER
163 	  case ST_MILTER:
164 		len = sizeof(s->s_milter);
165 		break;
166 #endif /* MILTER */
167 
168 	  case ST_QUEUE:
169 		len = sizeof(s->s_quegrp);
170 		break;
171 
172 #if SOCKETMAP
173 	  case ST_SOCKETMAP:
174 		len = sizeof(s->s_socketmap);
175 		break;
176 #endif /* SOCKETMAP */
177 
178 	  default:
179 		/*
180 		**  Each mailer has its own MCI stab entry:
181 		**
182 		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
183 		**
184 		**  Therefore, anything ST_MCI or larger is an s_mci.
185 		*/
186 
187 		if (type >= ST_MCI)
188 			len = sizeof(s->s_mci);
189 		else
190 		{
191 			syserr("stab: unknown symbol type %d", type);
192 			len = sizeof(s->s_value);
193 		}
194 		break;
195 	}
196 	len += sizeof(*s) - sizeof(s->s_value);
197 
198 	if (tTd(36, 15))
199 		sm_dprintf("size of stab entry: %d\n", len);
200 
201 	/* make new entry */
202 	s = (STAB *) sm_pmalloc_x(len);
203 	memset((char *) s, '\0', len);
204 	s->s_name = sm_pstrdup_x(name);
205 	s->s_symtype = type;
206 
207 	/* link it in */
208 	*ps = s;
209 
210 	/* set a default value for rulesets */
211 	if (type == ST_RULESET)
212 		s->s_ruleset = -1;
213 
214 	return s;
215 }
216 /*
217 **  STABAPPLY -- apply function to all stab entries
218 **
219 **	Parameters:
220 **		func -- the function to apply.  It will be given two
221 **			parameters (the stab entry and the arg).
222 **		arg -- an arbitrary argument, passed to func.
223 **
224 **	Returns:
225 **		none.
226 */
227 
228 void
229 stabapply(func, arg)
230 	void (*func)__P((STAB *, int));
231 	int arg;
232 {
233 	register STAB **shead;
234 	register STAB *s;
235 
236 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
237 	{
238 		for (s = *shead; s != NULL; s = s->s_next)
239 		{
240 			if (tTd(36, 90))
241 				sm_dprintf("stabapply: trying %d/%s\n",
242 					s->s_symtype, s->s_name);
243 			func(s, arg);
244 		}
245 	}
246 }
247 /*
248 **  QUEUEUP_MACROS -- queueup the macros in a class
249 **
250 **	Write the macros listed in the specified class into the
251 **	file referenced by qfp.
252 **
253 **	Parameters:
254 **		class -- class ID.
255 **		qfp -- file pointer to the queue file.
256 **		e -- the envelope.
257 **
258 **	Returns:
259 **		none.
260 */
261 
262 void
263 queueup_macros(class, qfp, e)
264 	int class;
265 	SM_FILE_T *qfp;
266 	ENVELOPE *e;
267 {
268 	register STAB **shead;
269 	register STAB *s;
270 
271 	if (e == NULL)
272 		return;
273 
274 	class = bitidx(class);
275 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
276 	{
277 		for (s = *shead; s != NULL; s = s->s_next)
278 		{
279 			int m;
280 			char *p;
281 
282 			if (s->s_symtype == ST_CLASS &&
283 			    bitnset(bitidx(class), s->s_class) &&
284 			    (m = macid(s->s_name)) != 0 &&
285 			    (p = macvalue(m, e)) != NULL)
286 			{
287 				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
288 						      "$%s%s\n",
289 						      s->s_name,
290 						      denlstring(p, true,
291 								 false));
292 			}
293 		}
294 	}
295 }
296 /*
297 **  COPY_CLASS -- copy class members from one class to another
298 **
299 **	Parameters:
300 **		src -- source class.
301 **		dst -- destination class.
302 **
303 **	Returns:
304 **		none.
305 */
306 
307 void
308 copy_class(src, dst)
309 	int src;
310 	int dst;
311 {
312 	register STAB **shead;
313 	register STAB *s;
314 
315 	src = bitidx(src);
316 	dst = bitidx(dst);
317 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
318 	{
319 		for (s = *shead; s != NULL; s = s->s_next)
320 		{
321 			if (s->s_symtype == ST_CLASS &&
322 			    bitnset(src, s->s_class))
323 				setbitn(dst, s->s_class);
324 		}
325 	}
326 }
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 
356 void
357 rmexpstab()
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 
436 void
437 dumpstab()
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