2 * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers.
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.
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.
16 SM_RCSID("@(#)$Id: stab.c,v 8.89 2006/08/15 23:24:58 ca Exp $")
19 ** STAB -- manage the symbol table
22 ** name -- the name to be looked up or inserted.
23 ** type -- the type of symbol.
25 ** ST_ENTER -- enter the name if not already present.
26 ** ST_FIND -- find it only.
29 ** pointer to a STAB entry for this name.
30 ** NULL if not found and not entered.
33 ** can update the symbol table.
37 #define SM_LOWER(c) ((isascii(c) && isupper(c)) ? tolower(c) : (c))
39 static STAB
*SymTab
[STABSIZE
];
54 sm_dprintf("STAB: %s %d ", name
, type
);
57 ** Compute the hashing function
61 for (p
= name
; *p
!= '\0'; p
++)
62 hfunc
= ((hfunc
<< 1) ^ (SM_LOWER(*p
) & 0377)) % STABSIZE
;
65 sm_dprintf("(hfunc=%d) ", hfunc
);
68 if (type
== ST_MACRO
|| type
== ST_RULESET
)
70 while ((s
= *ps
) != NULL
&&
71 (s
->s_symtype
!= type
|| strcmp(name
, s
->s_name
)))
76 while ((s
= *ps
) != NULL
&&
77 (s
->s_symtype
!= type
|| sm_strcasecmp(name
, s
->s_name
)))
82 ** Dispose of the entry.
85 if (s
!= NULL
|| op
== ST_FIND
)
90 sm_dprintf("not found\n");
93 long *lp
= (long *) s
->s_class
;
95 sm_dprintf("type %d val %lx %lx %lx %lx\n",
96 s
->s_symtype
, lp
[0], lp
[1], lp
[2], lp
[3]);
103 ** Make a new entry and link it in.
107 sm_dprintf("entered\n");
109 /* determine size of new entry */
113 len
= sizeof(s
->s_class
);
117 len
= sizeof(s
->s_address
);
121 len
= sizeof(s
->s_mailer
);
125 len
= sizeof(s
->s_alias
);
129 len
= sizeof(s
->s_mapclass
);
133 len
= sizeof(s
->s_map
);
137 len
= sizeof(s
->s_hostsig
);
141 len
= sizeof(s
->s_namecanon
);
145 len
= sizeof(s
->s_macro
);
149 len
= sizeof(s
->s_ruleset
);
153 len
= sizeof(s
->s_header
);
157 len
= sizeof(s
->s_service
);
162 len
= sizeof(s
->s_lmap
);
168 len
= sizeof(s
->s_milter
);
173 len
= sizeof(s
->s_quegrp
);
178 len
= sizeof(s
->s_socketmap
);
180 #endif /* SOCKETMAP */
184 ** Each mailer has its own MCI stab entry:
186 ** s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
188 ** Therefore, anything ST_MCI or larger is an s_mci.
192 len
= sizeof(s
->s_mci
);
195 syserr("stab: unknown symbol type %d", type
);
196 len
= sizeof(s
->s_value
);
200 len
+= sizeof(*s
) - sizeof(s
->s_value
);
203 sm_dprintf("size of stab entry: %d\n", len
);
206 s
= (STAB
*) sm_pmalloc_x(len
);
207 memset((char *) s
, '\0', len
);
208 s
->s_name
= sm_pstrdup_x(name
);
214 /* set a default value for rulesets */
215 if (type
== ST_RULESET
)
221 ** STABAPPLY -- apply function to all stab entries
224 ** func -- the function to apply. It will be given two
225 ** parameters (the stab entry and the arg).
226 ** arg -- an arbitrary argument, passed to func.
234 void (*func
)__P((STAB
*, int));
237 register STAB
**shead
;
240 for (shead
= SymTab
; shead
< &SymTab
[STABSIZE
]; shead
++)
242 for (s
= *shead
; s
!= NULL
; s
= s
->s_next
)
245 sm_dprintf("stabapply: trying %d/%s\n",
246 s
->s_symtype
, s
->s_name
);
252 ** QUEUEUP_MACROS -- queueup the macros in a class
254 ** Write the macros listed in the specified class into the
255 ** file referenced by qfp.
258 ** class -- class ID.
259 ** qfp -- file pointer to the queue file.
260 ** e -- the envelope.
267 queueup_macros(class, qfp
, e
)
272 register STAB
**shead
;
278 class = bitidx(class);
279 for (shead
= SymTab
; shead
< &SymTab
[STABSIZE
]; shead
++)
281 for (s
= *shead
; s
!= NULL
; s
= s
->s_next
)
286 if (s
->s_symtype
== ST_CLASS
&&
287 bitnset(bitidx(class), s
->s_class
) &&
288 (m
= macid(s
->s_name
)) != 0 &&
289 (p
= macvalue(m
, e
)) != NULL
)
291 (void) sm_io_fprintf(qfp
, SM_TIME_DEFAULT
,
301 ** COPY_CLASS -- copy class members from one class to another
304 ** src -- source class.
305 ** dst -- destination class.
316 register STAB
**shead
;
321 for (shead
= SymTab
; shead
< &SymTab
[STABSIZE
]; shead
++)
323 for (s
= *shead
; s
!= NULL
; s
= s
->s_next
)
325 if (s
->s_symtype
== ST_CLASS
&&
326 bitnset(src
, s
->s_class
))
327 setbitn(dst
, s
->s_class
);
333 ** RMEXPSTAB -- remove expired entries from SymTab.
335 ** These entries need to be removed in long-running processes,
336 ** e.g., persistent queue runners, to avoid consuming memory.
338 ** XXX It might be useful to restrict the maximum TTL to avoid
339 ** caching data very long.
348 ** can remove entries from the symbol table.
351 #define SM_STAB_FREE(x) \
368 for (i
= 0; i
< STABSIZE
; i
++)
374 switch (s
->s_symtype
)
377 if (s
->s_hostsig
.hs_exp
>= now
)
378 goto next
; /* not expired */
379 SM_STAB_FREE(s
->s_hostsig
.hs_sig
); /* XXX */
383 if (s
->s_namecanon
.nc_exp
>= now
)
384 goto next
; /* not expired */
385 SM_STAB_FREE(s
->s_namecanon
.nc_cname
); /* XXX */
389 if (s
->s_symtype
>= ST_MCI
)
391 /* call mci_uncache? */
392 SM_STAB_FREE(s
->s_mci
.mci_status
);
393 SM_STAB_FREE(s
->s_mci
.mci_rstatus
);
394 SM_STAB_FREE(s
->s_mci
.mci_heloname
);
396 /* not dynamically allocated */
397 SM_STAB_FREE(s
->s_mci
.mci_host
);
398 SM_STAB_FREE(s
->s_mci
.mci_tolist
);
401 /* should always by NULL */
402 SM_STAB_FREE(s
->s_mci
.mci_sasl_string
);
404 if (s
->s_mci
.mci_rpool
!= NULL
)
406 sm_rpool_free(s
->s_mci
.mci_rpool
);
407 s
->s_mci
.mci_macro
.mac_rpool
= NULL
;
408 s
->s_mci
.mci_rpool
= NULL
;
419 SM_STAB_FREE(s
->s_name
); /* XXX */
422 sm_free(f
); /* XXX */
433 ** DUMPSTAB -- dump symbol table.
438 #define MAXSTTYPES (ST_MCI + 1)
443 int i
, t
, total
, types
[MAXSTTYPES
];
445 static int prevt
[MAXSTTYPES
], prev
= 0;
448 for (i
= 0; i
< MAXSTTYPES
; i
++)
450 for (i
= 0; i
< STABSIZE
; i
++)
457 if (t
> MAXSTTYPES
- 1)
463 sm_syslog(LOG_INFO
, NOQID
, "stab: total=%d (%d)", total
, total
- prev
);
465 for (i
= 0; i
< MAXSTTYPES
; i
++)
469 sm_syslog(LOG_INFO
, NOQID
, "stab: type[%2d]=%2d (%d)",
470 i
, types
[i
], types
[i
] - prevt
[i
]);
475 #endif /* SM_HEAP_CHECK */