]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/sendmail/src/stab.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / sendmail / src / stab.c
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 */