xref: /illumos-gate/usr/src/cmd/sendmail/src/stab.c (revision 058561cb)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
15 
16 #include <sendmail.h>
17 
18 SM_RCSID("@(#)$Id: stab.c,v 8.89 2006/08/15 23:24:58 ca Exp $")
19 
20 /*
21 **  STAB -- manage the symbol table
22 **
23 **	Parameters:
24 **		name -- the name to be looked up or inserted.
25 **		type -- the type of symbol.
26 **		op -- what to do:
27 **			ST_ENTER -- enter the name if not already present.
28 **			ST_FIND -- find it only.
29 **
30 **	Returns:
31 **		pointer to a STAB entry for this name.
32 **		NULL if not found and not entered.
33 **
34 **	Side Effects:
35 **		can update the symbol table.
36 */
37 
38 #define STABSIZE	2003
39 #define SM_LOWER(c)	((isascii(c) && isupper(c)) ? tolower(c) : (c))
40 
41 static STAB	*SymTab[STABSIZE];
42 
43 STAB *
44 stab(name, type, op)
45 	char *name;
46 	int type;
47 	int op;
48 {
49 	register STAB *s;
50 	register STAB **ps;
51 	register int hfunc;
52 	register char *p;
53 	int len;
54 
55 	if (tTd(36, 5))
56 		sm_dprintf("STAB: %s %d ", name, type);
57 
58 	/*
59 	**  Compute the hashing function
60 	*/
61 
62 	hfunc = type;
63 	for (p = name; *p != '\0'; p++)
64 		hfunc = ((hfunc << 1) ^ (SM_LOWER(*p) & 0377)) % STABSIZE;
65 
66 	if (tTd(36, 9))
67 		sm_dprintf("(hfunc=%d) ", hfunc);
68 
69 	ps = &SymTab[hfunc];
70 	if (type == ST_MACRO || type == ST_RULESET)
71 	{
72 		while ((s = *ps) != NULL &&
73 		       (s->s_symtype != type || strcmp(name, s->s_name)))
74 			ps = &s->s_next;
75 	}
76 	else
77 	{
78 		while ((s = *ps) != NULL &&
79 		       (s->s_symtype != type || sm_strcasecmp(name, s->s_name)))
80 			ps = &s->s_next;
81 	}
82 
83 	/*
84 	**  Dispose of the entry.
85 	*/
86 
87 	if (s != NULL || op == ST_FIND)
88 	{
89 		if (tTd(36, 5))
90 		{
91 			if (s == NULL)
92 				sm_dprintf("not found\n");
93 			else
94 			{
95 				long *lp = (long *) s->s_class;
96 
97 				sm_dprintf("type %d val %lx %lx %lx %lx\n",
98 					s->s_symtype, lp[0], lp[1], lp[2], lp[3]);
99 			}
100 		}
101 		return s;
102 	}
103 
104 	/*
105 	**  Make a new entry and link it in.
106 	*/
107 
108 	if (tTd(36, 5))
109 		sm_dprintf("entered\n");
110 
111 	/* determine size of new entry */
112 	switch (type)
113 	{
114 	  case ST_CLASS:
115 		len = sizeof(s->s_class);
116 		break;
117 
118 	  case ST_ADDRESS:
119 		len = sizeof(s->s_address);
120 		break;
121 
122 	  case ST_MAILER:
123 		len = sizeof(s->s_mailer);
124 		break;
125 
126 	  case ST_ALIAS:
127 		len = sizeof(s->s_alias);
128 		break;
129 
130 	  case ST_MAPCLASS:
131 		len = sizeof(s->s_mapclass);
132 		break;
133 
134 	  case ST_MAP:
135 		len = sizeof(s->s_map);
136 		break;
137 
138 	  case ST_HOSTSIG:
139 		len = sizeof(s->s_hostsig);
140 		break;
141 
142 	  case ST_NAMECANON:
143 		len = sizeof(s->s_namecanon);
144 		break;
145 
146 	  case ST_MACRO:
147 		len = sizeof(s->s_macro);
148 		break;
149 
150 	  case ST_RULESET:
151 		len = sizeof(s->s_ruleset);
152 		break;
153 
154 	  case ST_HEADER:
155 		len = sizeof(s->s_header);
156 		break;
157 
158 	  case ST_SERVICE:
159 		len = sizeof(s->s_service);
160 		break;
161 
162 #if LDAPMAP
163 	  case ST_LMAP:
164 		len = sizeof(s->s_lmap);
165 		break;
166 #endif /* LDAPMAP */
167 
168 #if MILTER
169 	  case ST_MILTER:
170 		len = sizeof(s->s_milter);
171 		break;
172 #endif /* MILTER */
173 
174 	  case ST_QUEUE:
175 		len = sizeof(s->s_quegrp);
176 		break;
177 
178 #if SOCKETMAP
179 	  case ST_SOCKETMAP:
180 		len = sizeof(s->s_socketmap);
181 		break;
182 #endif /* SOCKETMAP */
183 
184 	  default:
185 		/*
186 		**  Each mailer has its own MCI stab entry:
187 		**
188 		**  s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
189 		**
190 		**  Therefore, anything ST_MCI or larger is an s_mci.
191 		*/
192 
193 		if (type >= ST_MCI)
194 			len = sizeof(s->s_mci);
195 		else
196 		{
197 			syserr("stab: unknown symbol type %d", type);
198 			len = sizeof(s->s_value);
199 		}
200 		break;
201 	}
202 	len += sizeof(*s) - sizeof(s->s_value);
203 
204 	if (tTd(36, 15))
205 		sm_dprintf("size of stab entry: %d\n", len);
206 
207 	/* make new entry */
208 	s = (STAB *) sm_pmalloc_x(len);
209 	memset((char *) s, '\0', len);
210 	s->s_name = sm_pstrdup_x(name);
211 	s->s_symtype = type;
212 
213 	/* link it in */
214 	*ps = s;
215 
216 	/* set a default value for rulesets */
217 	if (type == ST_RULESET)
218 		s->s_ruleset = -1;
219 
220 	return s;
221 }
222 /*
223 **  STABAPPLY -- apply function to all stab entries
224 **
225 **	Parameters:
226 **		func -- the function to apply.  It will be given two
227 **			parameters (the stab entry and the arg).
228 **		arg -- an arbitrary argument, passed to func.
229 **
230 **	Returns:
231 **		none.
232 */
233 
234 void
235 stabapply(func, arg)
236 	void (*func)__P((STAB *, int));
237 	int arg;
238 {
239 	register STAB **shead;
240 	register STAB *s;
241 
242 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
243 	{
244 		for (s = *shead; s != NULL; s = s->s_next)
245 		{
246 			if (tTd(36, 90))
247 				sm_dprintf("stabapply: trying %d/%s\n",
248 					s->s_symtype, s->s_name);
249 			func(s, arg);
250 		}
251 	}
252 }
253 /*
254 **  QUEUEUP_MACROS -- queueup the macros in a class
255 **
256 **	Write the macros listed in the specified class into the
257 **	file referenced by qfp.
258 **
259 **	Parameters:
260 **		class -- class ID.
261 **		qfp -- file pointer to the queue file.
262 **		e -- the envelope.
263 **
264 **	Returns:
265 **		none.
266 */
267 
268 void
269 queueup_macros(class, qfp, e)
270 	int class;
271 	SM_FILE_T *qfp;
272 	ENVELOPE *e;
273 {
274 	register STAB **shead;
275 	register STAB *s;
276 
277 	if (e == NULL)
278 		return;
279 
280 	class = bitidx(class);
281 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
282 	{
283 		for (s = *shead; s != NULL; s = s->s_next)
284 		{
285 			int m;
286 			char *p;
287 
288 			if (s->s_symtype == ST_CLASS &&
289 			    bitnset(bitidx(class), s->s_class) &&
290 			    (m = macid(s->s_name)) != 0 &&
291 			    (p = macvalue(m, e)) != NULL)
292 			{
293 				(void) sm_io_fprintf(qfp, SM_TIME_DEFAULT,
294 						      "$%s%s\n",
295 						      s->s_name,
296 						      denlstring(p, true,
297 								 false));
298 			}
299 		}
300 	}
301 }
302 /*
303 **  COPY_CLASS -- copy class members from one class to another
304 **
305 **	Parameters:
306 **		src -- source class.
307 **		dst -- destination class.
308 **
309 **	Returns:
310 **		none.
311 */
312 
313 void
314 copy_class(src, dst)
315 	int src;
316 	int dst;
317 {
318 	register STAB **shead;
319 	register STAB *s;
320 
321 	src = bitidx(src);
322 	dst = bitidx(dst);
323 	for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
324 	{
325 		for (s = *shead; s != NULL; s = s->s_next)
326 		{
327 			if (s->s_symtype == ST_CLASS &&
328 			    bitnset(src, s->s_class))
329 				setbitn(dst, s->s_class);
330 		}
331 	}
332 }
333 
334 /*
335 **  RMEXPSTAB -- remove expired entries from SymTab.
336 **
337 **	These entries need to be removed in long-running processes,
338 **	e.g., persistent queue runners, to avoid consuming memory.
339 **
340 **	XXX It might be useful to restrict the maximum TTL to avoid
341 **		caching data very long.
342 **
343 **	Parameters:
344 **		none.
345 **
346 **	Returns:
347 **		none.
348 **
349 **	Side Effects:
350 **		can remove entries from the symbol table.
351 */
352 
353 #define SM_STAB_FREE(x)	\
354 	do \
355 	{ \
356 		char *o = (x); \
357 		(x) = NULL; \
358 		if (o != NULL) \
359 			sm_free(o); \
360 	} while (0)
361 
362 void
363 rmexpstab()
364 {
365 	int i;
366 	STAB *s, *p, *f;
367 	time_t now;
368 
369 	now = curtime();
370 	for (i = 0; i < STABSIZE; i++)
371 	{
372 		p = NULL;
373 		s = SymTab[i];
374 		while (s != NULL)
375 		{
376 			switch (s->s_symtype)
377 			{
378 			  case ST_HOSTSIG:
379 				if (s->s_hostsig.hs_exp >= now)
380 					goto next;	/* not expired */
381 				SM_STAB_FREE(s->s_hostsig.hs_sig); /* XXX */
382 				break;
383 
384 			  case ST_NAMECANON:
385 				if (s->s_namecanon.nc_exp >= now)
386 					goto next;	/* not expired */
387 				SM_STAB_FREE(s->s_namecanon.nc_cname); /* XXX */
388 				break;
389 
390 			  default:
391 				if (s->s_symtype >= ST_MCI)
392 				{
393 					/* call mci_uncache? */
394 					SM_STAB_FREE(s->s_mci.mci_status);
395 					SM_STAB_FREE(s->s_mci.mci_rstatus);
396 					SM_STAB_FREE(s->s_mci.mci_heloname);
397 #if 0
398 					/* not dynamically allocated */
399 					SM_STAB_FREE(s->s_mci.mci_host);
400 					SM_STAB_FREE(s->s_mci.mci_tolist);
401 #endif /* 0 */
402 #if SASL
403 					/* should always by NULL */
404 					SM_STAB_FREE(s->s_mci.mci_sasl_string);
405 #endif /* SASL */
406 					if (s->s_mci.mci_rpool != NULL)
407 					{
408 						sm_rpool_free(s->s_mci.mci_rpool);
409 						s->s_mci.mci_macro.mac_rpool = NULL;
410 						s->s_mci.mci_rpool = NULL;
411 					}
412 					break;
413 				}
414   next:
415 				p = s;
416 				s = s->s_next;
417 				continue;
418 			}
419 
420 			/* remove entry */
421 			SM_STAB_FREE(s->s_name); /* XXX */
422 			f = s;
423 			s = s->s_next;
424 			sm_free(f);	/* XXX */
425 			if (p == NULL)
426 				SymTab[i] = s;
427 			else
428 				p->s_next = s;
429 		}
430 	}
431 }
432 
433 #if SM_HEAP_CHECK
434 /*
435 **  DUMPSTAB -- dump symbol table.
436 **
437 **	For debugging.
438 */
439 
440 #define MAXSTTYPES	(ST_MCI + 1)
441 
442 void
443 dumpstab()
444 {
445 	int i, t, total, types[MAXSTTYPES];
446 	STAB *s;
447 	static int prevt[MAXSTTYPES], prev = 0;
448 
449 	total = 0;
450 	for (i = 0; i < MAXSTTYPES; i++)
451 		types[i] = 0;
452 	for (i = 0; i < STABSIZE; i++)
453 	{
454 		s = SymTab[i];
455 		while (s != NULL)
456 		{
457 			++total;
458 			t = s->s_symtype;
459 			if (t > MAXSTTYPES - 1)
460 				t = MAXSTTYPES - 1;
461 			types[t]++;
462 			s = s->s_next;
463 		}
464 	}
465 	sm_syslog(LOG_INFO, NOQID, "stab: total=%d (%d)", total, total - prev);
466 	prev = total;
467 	for (i = 0; i < MAXSTTYPES; i++)
468 	{
469 		if (types[i] != 0)
470 		{
471 			sm_syslog(LOG_INFO, NOQID, "stab: type[%2d]=%2d (%d)",
472 				i, types[i], types[i] - prevt[i]);
473 		}
474 		prevt[i] = types[i];
475 	}
476 }
477 #endif /* SM_HEAP_CHECK */
478