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