122694Sdist /* 235073Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822694Sdist 958332Seric # include "sendmail.h" 1050577Seric # include <signal.h> 1150577Seric # include <pwd.h> 1256845Seric # ifdef DBM 1356848Seric ERROR: DBM is no longer supported -- use NDBM instead. 1456845Seric # endif 1550577Seric # ifdef NEWDB 1650577Seric # include <db.h> 1750577Seric # endif 1856766Seric # ifdef NDBM 1956845Seric # include <ndbm.h> 2056766Seric # endif 2159724Seric # ifdef NIS_ALIASES 2259673Seric # include <rpcsvc/ypclnt.h> 2359673Seric # endif 2456766Seric 2533728Sbostic #ifndef lint 2651756Seric #ifdef NEWDB 2757736Seric #ifdef NDBM 28*59758Seric static char sccsid[] = "@(#)alias.c 6.45 (Berkeley) 05/06/93 (with NEWDB and NDBM)"; 2951756Seric #else 30*59758Seric static char sccsid[] = "@(#)alias.c 6.45 (Berkeley) 05/06/93 (with NEWDB)"; 3157736Seric #endif 3257736Seric #else 3356845Seric #ifdef NDBM 34*59758Seric static char sccsid[] = "@(#)alias.c 6.45 (Berkeley) 05/06/93 (with NDBM)"; 3533728Sbostic #else 36*59758Seric static char sccsid[] = "@(#)alias.c 6.45 (Berkeley) 05/06/93 (without NEWDB or NDBM)"; 3733728Sbostic #endif 3850575Seric #endif 3933728Sbostic #endif /* not lint */ 4051756Seric /* 4159673Seric ** Alias data structures 4259673Seric */ 4359673Seric #define ALIASDB struct _aliasdb 4459673Seric 4559673Seric 4659673Seric ALIASDB 4759673Seric { 4859673Seric ALIASCLASS *ad_class; /* class of this database */ 4959673Seric char *ad_name; /* name of alias file */ 5059673Seric char *ad_domain; /* name of (NIS) domain */ 5159673Seric void *ad_dbp; /* ndbm/nis database pointer */ 5259673Seric #ifdef NEWDB 5359673Seric DB *ad_ndbp; /* newdb database pointer */ 5459673Seric #endif 5559673Seric short ad_flags; /* flag bits */ 5659673Seric }; 5759673Seric 5859673Seric /* bits for ad_flags */ 5959673Seric #define ADF_VALID 0x0001 /* database initialized */ 6059673Seric #define ADF_WRITABLE 0x0002 /* open for write */ 6159673Seric #define ADF_IMPLHASH 0x0004 /* IMPL: underlying hash database */ 6259673Seric #define ADF_IMPLNDBM 0x0008 /* IMPL: underlying NDBM database */ 6359673Seric 6459673Seric 6559673Seric ALIASCLASS 6659673Seric { 6759673Seric char *ac_name; /* name of alias class */ 6859673Seric char *(*ac_lookup)__P((ALIASDB *, char *, ENVELOPE *)); 6959673Seric /* lookup func */ 7059673Seric void (*ac_store)__P((ALIASDB *, char *, char *, ENVELOPE *)); 7159673Seric /* database store func */ 7259673Seric bool (*ac_init)__P((ALIASDB *, ENVELOPE *)); 7359673Seric /* initialization func */ 7459733Seric void (*ac_rebuild)__P((ALIASDB *, FILE *, int, ENVELOPE *)); 7559673Seric /* initialization func */ 7659673Seric void (*ac_close)__P((ALIASDB *, ENVELOPE *)); 7759673Seric /* close function */ 7859673Seric short ac_flags; /* flag bits */ 7959673Seric }; 8059673Seric 8159673Seric /* bits for ac_flags */ 8259673Seric #define ACF_BUILDABLE 0x0001 /* can build a cached version */ 8359673Seric 8459673Seric 8559673Seric ALIASDB AliasDB[MAXALIASDB + 1]; /* actual database list */ 8659673Seric int NAliasDBs; /* number of alias databases */ 8759673Seric /* 88292Seric ** ALIAS -- Compute aliases. 89292Seric ** 909368Seric ** Scans the alias file for an alias for the given address. 919368Seric ** If found, it arranges to deliver to the alias list instead. 929368Seric ** Uses libdbm database if -DDBM. 93292Seric ** 94292Seric ** Parameters: 954097Seric ** a -- address to alias. 964999Seric ** sendq -- a pointer to the head of the send queue 974999Seric ** to put the aliases in. 9858092Seric ** e -- the current envelope. 99292Seric ** 100292Seric ** Returns: 101292Seric ** none 102292Seric ** 103292Seric ** Side Effects: 1043185Seric ** Aliases found are expanded. 105292Seric ** 106292Seric ** Deficiencies: 107292Seric ** It should complain about names that are aliased to 108292Seric ** nothing. 109292Seric */ 110292Seric 11155012Seric alias(a, sendq, e) 1124097Seric register ADDRESS *a; 1134999Seric ADDRESS **sendq; 11455012Seric register ENVELOPE *e; 115292Seric { 1164081Seric register char *p; 11758082Seric int naliases; 11858170Seric char *owner; 11958170Seric char obuf[MAXNAME + 6]; 1205701Seric extern char *aliaslookup(); 121292Seric 1227671Seric if (tTd(27, 1)) 1234098Seric printf("alias(%s)\n", a->q_paddr); 124292Seric 1254098Seric /* don't realias already aliased names */ 12658680Seric if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags)) 1274098Seric return; 1284098Seric 12959673Seric if (NoAlias) 13059673Seric return; 13159673Seric 13255012Seric e->e_to = a->q_paddr; 1334098Seric 1344314Seric /* 1354314Seric ** Look up this name 1364314Seric */ 1374314Seric 13859673Seric p = aliaslookup(a->q_user, e); 1394098Seric if (p == NULL) 1404098Seric return; 141292Seric 142292Seric /* 1434098Seric ** Match on Alias. 1444098Seric ** Deliver to the target list. 1451515Seric */ 1461515Seric 1477671Seric if (tTd(27, 1)) 1484098Seric printf("%s (%s, %s) aliased to %s\n", 1494098Seric a->q_paddr, a->q_host, a->q_user, p); 15058092Seric if (bitset(EF_VRFYONLY, e->e_flags)) 15158154Seric { 15258154Seric a->q_flags |= QVERIFIED; 15358884Seric e->e_nrcpts++; 15458092Seric return; 15558154Seric } 15658154Seric message("aliased to %s", p); 15757977Seric #ifdef LOG 15858020Seric if (LogLevel > 9) 15957977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 16057977Seric #endif 16158082Seric a->q_flags &= ~QSELFREF; 1624098Seric AliasLevel++; 16358082Seric naliases = sendtolist(p, a, sendq, e); 1644098Seric AliasLevel--; 16558082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 16658065Seric { 16758065Seric if (tTd(27, 5)) 16858065Seric { 16958065Seric printf("alias: QDONTSEND "); 17058065Seric printaddr(a, FALSE); 17158065Seric } 17258065Seric a->q_flags |= QDONTSEND; 17358065Seric } 17458170Seric 17558170Seric /* 17658170Seric ** Look for owner of alias 17758170Seric */ 17858170Seric 17958170Seric (void) strcpy(obuf, "owner-"); 18058170Seric if (strncmp(a->q_user, "owner-", 6) == 0) 18158170Seric (void) strcat(obuf, "owner"); 18258170Seric else 18358170Seric (void) strcat(obuf, a->q_user); 18458170Seric if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) 18558170Seric makelower(obuf); 18659673Seric owner = aliaslookup(obuf, e); 18758170Seric if (owner != NULL) 18858170Seric { 18958170Seric if (strchr(owner, ',') != NULL) 19058170Seric owner = obuf; 19158170Seric a->q_owner = newstr(owner); 19258170Seric } 1934098Seric } 1944098Seric /* 1955701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1965701Seric ** 1975701Seric ** Parameters: 1985701Seric ** name -- the name to look up. 1995701Seric ** 2005701Seric ** Returns: 2015701Seric ** the value of name. 2025701Seric ** NULL if unknown. 2035701Seric ** 2045701Seric ** Side Effects: 2055701Seric ** none. 2065701Seric ** 2075701Seric ** Warnings: 2085701Seric ** The return value will be trashed across calls. 2095701Seric */ 2105701Seric 2115701Seric char * 21259673Seric aliaslookup(name, e) 2135701Seric char *name; 21459673Seric ENVELOPE *e; 2155701Seric { 21659673Seric register int dbno; 21759673Seric register ALIASDB *ad; 21859673Seric register char *p; 2195701Seric 22059673Seric for (dbno = 0; dbno < NAliasDBs; dbno++) 22159673Seric { 22259673Seric ad = &AliasDB[dbno]; 22359673Seric if (!bitset(ADF_VALID, ad->ad_flags)) 22459673Seric continue; 22559673Seric p = (*ad->ad_class->ac_lookup)(ad, name, e); 22659673Seric if (p != NULL) 22759673Seric return p; 22859673Seric } 22959673Seric return NULL; 23059673Seric } 23159673Seric /* 23259673Seric ** SETALIAS -- set up an alias map 23359673Seric ** 23459673Seric ** Called when reading configuration file. 23559673Seric ** 23659673Seric ** Parameters: 23759673Seric ** spec -- the alias specification 23859673Seric ** 23959673Seric ** Returns: 24059673Seric ** none. 24159673Seric */ 24257381Seric 24359673Seric setalias(spec) 24459673Seric char *spec; 24559673Seric { 24659673Seric register char *p; 24759673Seric register ALIASDB *ad; 24859673Seric char *class; 24959673Seric STAB *s; 25059673Seric 25159697Seric if (tTd(27, 8)) 25259697Seric printf("setalias(%s)\n", spec); 25359697Seric 254*59758Seric for (p = spec; p != NULL; ) 25551756Seric { 256*59758Seric while (isspace(*p)) 257*59758Seric p++; 258*59758Seric if (*p == NULL) 25959673Seric break; 26059673Seric spec = p; 26159673Seric 262*59758Seric if (NAliasDBs >= MAXALIASDB) 263*59758Seric { 264*59758Seric syserr("Too many alias databases defined, %d max", MAXALIASDB); 265*59758Seric return; 266*59758Seric } 267*59758Seric ad = &AliasDB[NAliasDBs]; 268*59758Seric 269*59758Seric p = strpbrk(p, " ,/:"); 270*59758Seric if (p != NULL && *p == ':') 271*59758Seric { 272*59758Seric /* explicit class listed */ 273*59758Seric *p++ = '\0'; 274*59758Seric class = spec; 275*59758Seric spec = p; 276*59758Seric } 277*59758Seric else 278*59758Seric { 279*59758Seric /* implicit class */ 280*59758Seric class = "implicit"; 281*59758Seric } 282*59758Seric 283*59758Seric /* find end of spec */ 284*59758Seric if (p != NULL) 285*59758Seric p = strchr(p, ','); 286*59758Seric if (p != NULL) 287*59758Seric *p++ = '\0'; 288*59758Seric 289*59758Seric /* look up class */ 290*59758Seric s = stab(class, ST_ALIASCLASS, ST_FIND); 291*59758Seric if (s == NULL) 292*59758Seric { 293*59758Seric if (tTd(27, 1)) 294*59758Seric printf("Unknown alias class %s\n", class); 295*59758Seric } 296*59758Seric else 297*59758Seric { 298*59758Seric ad->ad_class = s->s_aliasclass; 299*59758Seric ad->ad_name = newstr(spec); 300*59758Seric NAliasDBs++; 301*59758Seric } 30259756Seric } 3035701Seric } 3045701Seric /* 3054098Seric ** INITALIASES -- initialize for aliasing 3064098Seric ** 30756845Seric ** Very different depending on whether we are running NDBM or not. 3084098Seric ** 3094098Seric ** Parameters: 31059673Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 31159673Seric ** e -- current envelope. 3124098Seric ** 3134098Seric ** Returns: 3144098Seric ** none. 3154098Seric ** 3164098Seric ** Side Effects: 3174098Seric ** initializes aliases: 31856845Seric ** if NDBM: opens the database. 31956845Seric ** if ~NDBM: reads the aliases into the symbol table. 3204098Seric */ 3214098Seric 32240559Sbostic # define DBMMODE 0644 3234157Seric 32459673Seric initaliases(rebuild, e) 32559673Seric bool rebuild; 32655012Seric register ENVELOPE *e; 3274098Seric { 32859673Seric int dbno; 32959673Seric register ALIASDB *ad; 3304322Seric 33159673Seric for (dbno = 0; dbno < NAliasDBs; dbno++) 3328437Seric { 33359673Seric ad = &AliasDB[dbno]; 33459697Seric 33559697Seric if (tTd(27, 2)) 33659697Seric printf("initaliases(%s:%s)\n", 33759697Seric ad->ad_class->ac_name, ad->ad_name); 33859697Seric 33959673Seric if (rebuild) 34050576Seric { 34159673Seric rebuildaliases(ad, FALSE, e); 34250576Seric } 34359673Seric else 34457249Seric { 34559697Seric if (ad->ad_class->ac_init(ad, e)) 34659756Seric { 34759756Seric if (tTd(27, 4)) 34859756Seric printf("%s:%s: valid\n", 34959756Seric ad->ad_class->ac_name, 35059756Seric ad->ad_name); 35159697Seric ad->ad_flags |= ADF_VALID; 35259756Seric } 35359756Seric else if (tTd(27, 4)) 35459756Seric printf("%s:%s: invalid: %s\n", 35559756Seric ad->ad_class->ac_name, ad->ad_name, 35659756Seric errstring(errno)); 35757249Seric } 35850575Seric } 35959673Seric } 36059673Seric /* 36159673Seric ** ALIASWAIT -- wait for distinguished @:@ token to appear. 36259673Seric ** 36359673Seric ** This can decide to reopen or rebuild the alias file 36459673Seric */ 36559673Seric 36659673Seric aliaswait(ad, ext, e) 36759673Seric ALIASDB *ad; 36859673Seric char *ext; 36959673Seric ENVELOPE *e; 37059673Seric { 37159673Seric int atcnt; 37259673Seric time_t mtime; 37359673Seric struct stat stb; 37459673Seric char buf[MAXNAME]; 37559673Seric 37659697Seric if (tTd(27, 3)) 37759697Seric printf("aliaswait\n"); 37859697Seric 37917471Seric atcnt = SafeAlias * 2; 38017471Seric if (atcnt > 0) 38117471Seric { 38259673Seric while (atcnt-- >= 0 && 38359673Seric ad->ad_class->ac_lookup(ad, "@", e) == NULL) 38425689Seric { 38525689Seric /* 38659673Seric ** Close and re-open the alias database in case 38759673Seric ** the one is mv'ed instead of cp'ed in. 38825689Seric */ 38925689Seric 39059697Seric if (tTd(27, 2)) 39159697Seric printf("aliaswait: sleeping\n"); 39259697Seric 39359673Seric ad->ad_class->ac_close(ad, e); 39417471Seric sleep(30); 39559673Seric ad->ad_class->ac_init(ad, e); 39625689Seric } 39717471Seric } 3988437Seric 39959673Seric /* see if we need to go into auto-rebuild mode */ 40059673Seric if (stat(ad->ad_name, &stb) < 0) 40159673Seric return; 40259673Seric mtime = stb.st_mtime; 40359673Seric (void) strcpy(buf, ad->ad_name); 40459673Seric (void) strcat(buf, ext); 40559673Seric if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || atcnt < 0) 4064322Seric { 40759673Seric /* database is out of date */ 40840559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 4094322Seric { 41059673Seric message("auto-rebuilding alias database %s", 41159673Seric ad->ad_name); 41259673Seric rebuildaliases(ad, TRUE, e); 4134322Seric } 4144322Seric else 4154322Seric { 41619039Seric #ifdef LOG 41758020Seric if (LogLevel > 3) 41859673Seric syslog(LOG_INFO, "alias database %s out of date", 41959673Seric ad->ad_name); 42056795Seric #endif /* LOG */ 42159673Seric message("Warning: alias database %s out of date", 42259673Seric ad->ad_name); 4234322Seric } 4244322Seric } 42559673Seric } 42659673Seric /* 42759673Seric ** REBUILDALIASES -- rebuild the alias database. 42859673Seric ** 42959673Seric ** Parameters: 43059673Seric ** ad -- the database to rebuild. 43159673Seric ** automatic -- set if this was automatically generated. 43259673Seric ** e -- current envelope. 43359673Seric ** 43459673Seric ** Returns: 43559673Seric ** none. 43659673Seric ** 43759673Seric ** Side Effects: 43859673Seric ** Reads the text version of the database, builds the 43959673Seric ** DBM or DB version. 44059673Seric */ 4414322Seric 44259673Seric rebuildaliases(ad, automatic, e) 44359673Seric register ALIASDB *ad; 44459673Seric bool automatic; 44559673Seric register ENVELOPE *e; 44659673Seric { 44759673Seric FILE *af; 44859673Seric void (*oldsigint)(); 4494322Seric 45059673Seric if (!bitset(ACF_BUILDABLE, ad->ad_class->ac_flags)) 45159673Seric return; 4524322Seric 45359673Seric #ifdef LOG 45459673Seric if (LogLevel > 7) 4558437Seric { 45659673Seric extern char *username(); 45725522Seric 45859673Seric syslog(LOG_NOTICE, "alias database %s %srebuilt by %s", 45959673Seric ad->ad_name, automatic ? "auto" : "", username()); 46059673Seric } 46156795Seric #endif /* LOG */ 46259673Seric 46359673Seric /* try to lock the source file */ 46459673Seric if ((af = fopen(ad->ad_name, "r+")) == NULL) 46559673Seric { 46659756Seric if (tTd(27, 1)) 46759756Seric printf("Can't open %s: %s\n", 46859756Seric ad->ad_name, errstring(errno)); 46959756Seric ad->ad_flags &= ~ADF_VALID; 47059673Seric errno = 0; 47159673Seric return; 4728437Seric } 47359673Seric 47459673Seric /* see if someone else is rebuilding the alias file */ 47559673Seric if (!lockfile(fileno(af), ad->ad_name, LOCK_EX|LOCK_NB)) 47659673Seric { 47759673Seric /* yes, they are -- wait until done */ 47859673Seric message("Alias file %s is already being rebuilt", 47959673Seric ad->ad_name); 48059673Seric if (OpMode != MD_INITALIAS) 48159673Seric { 48259673Seric /* wait for other rebuild to complete */ 48359673Seric (void) lockfile(fileno(af), ad->ad_name, 48459673Seric LOCK_EX); 48559673Seric } 48659673Seric (void) fclose(af); 48759673Seric errno = 0; 48859673Seric return; 48959673Seric } 49059673Seric 49159673Seric oldsigint = signal(SIGINT, SIG_IGN); 49259673Seric 49359733Seric ad->ad_class->ac_rebuild(ad, af, automatic, e); 49459673Seric 49559673Seric /* close the file, thus releasing locks */ 49659673Seric fclose(af); 49759673Seric 49859673Seric /* add distinguished entries and close the database */ 49959701Seric if (bitset(ADF_VALID, ad->ad_flags)) 50059701Seric ad->ad_class->ac_close(ad, e); 50159673Seric 50259673Seric /* restore the old signal */ 50359673Seric (void) signal(SIGINT, oldsigint); 5044157Seric } 5054157Seric /* 5064157Seric ** READALIASES -- read and process the alias file. 5074157Seric ** 5084157Seric ** This routine implements the part of initaliases that occurs 5094157Seric ** when we are not going to use the DBM stuff. 5104157Seric ** 5114157Seric ** Parameters: 51259673Seric ** ad -- the alias database descriptor. 51359673Seric ** af -- file to read the aliases from. 51459733Seric ** automatic -- set if this was an automatic rebuild. 51559673Seric ** e -- the current alias file. 5164157Seric ** 5174157Seric ** Returns: 5184157Seric ** none. 5194157Seric ** 5204157Seric ** Side Effects: 5214157Seric ** Reads aliasfile into the symbol table. 5224157Seric ** Optionally, builds the .dir & .pag files. 5234157Seric */ 5244157Seric 5254157Seric static 52659733Seric readaliases(ad, af, automatic, e) 52759673Seric register ALIASDB *ad; 52859673Seric FILE *af; 52959733Seric int automatic; 53055012Seric register ENVELOPE *e; 5314157Seric { 5324098Seric register char *p; 5334098Seric char *rhs; 5344098Seric bool skipping; 53559673Seric long naliases, bytes, longest; 5364098Seric ADDRESS al, bl; 5374106Seric register STAB *s; 5389368Seric char line[BUFSIZ]; 5394098Seric 5404314Seric /* 5414314Seric ** Read and interpret lines 5424314Seric */ 5434314Seric 54459673Seric FileName = ad->ad_name; 5459368Seric LineNumber = 0; 5464322Seric naliases = bytes = longest = 0; 5474098Seric skipping = FALSE; 5484098Seric while (fgets(line, sizeof (line), af) != NULL) 5494098Seric { 5504322Seric int lhssize, rhssize; 5514322Seric 5529368Seric LineNumber++; 55356795Seric p = strchr(line, '\n'); 55425278Seric if (p != NULL) 55525278Seric *p = '\0'; 5564098Seric switch (line[0]) 5574098Seric { 5584098Seric case '#': 5594098Seric case '\0': 5604098Seric skipping = FALSE; 5614098Seric continue; 5624065Seric 5634098Seric case ' ': 5644098Seric case '\t': 5654098Seric if (!skipping) 56658151Seric syserr("554 Non-continuation line starts with space"); 5674098Seric skipping = TRUE; 5684097Seric continue; 5694098Seric } 5704098Seric skipping = FALSE; 5711874Seric 5724314Seric /* 5734314Seric ** Process the LHS 57457736Seric ** Find the colon separator, and parse the address. 57516898Seric ** It should resolve to a local name -- this will 57616898Seric ** be checked later (we want to optionally do 57716898Seric ** parsing of the RHS first to maximize error 57816898Seric ** detection). 5794314Seric */ 5804314Seric 5814098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5824097Seric continue; 58316898Seric if (*p++ != ':') 5844098Seric { 58558151Seric syserr("554 missing colon"); 5864097Seric continue; 5874098Seric } 58858333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 5894098Seric { 59058151Seric syserr("554 illegal alias name"); 59116898Seric continue; 5924098Seric } 5934314Seric 5944314Seric /* 5954314Seric ** Process the RHS. 5964314Seric ** 'al' is the internal form of the LHS address. 5974314Seric ** 'p' points to the text of the RHS. 5984314Seric */ 5994314Seric 60058914Seric while (isascii(*p) && isspace(*p)) 60158914Seric p++; 6024098Seric rhs = p; 6034098Seric for (;;) 6044098Seric { 6054098Seric register char c; 60658662Seric register char *nlp; 6071515Seric 60858662Seric nlp = &p[strlen(p)]; 60958662Seric if (nlp[-1] == '\n') 61058662Seric *--nlp = '\0'; 61158662Seric 61259673Seric if (CheckAliases) 6134098Seric { 6144157Seric /* do parsing & compression of addresses */ 61525278Seric while (*p != '\0') 6164098Seric { 61758333Seric auto char *delimptr; 61825278Seric 61958050Seric while ((isascii(*p) && isspace(*p)) || 62058050Seric *p == ',') 6214157Seric p++; 62225278Seric if (*p == '\0') 62325278Seric break; 62458333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 62558151Seric usrerr("553 %s... bad address", p); 62658333Seric p = delimptr; 6274098Seric } 6284098Seric } 6294157Seric else 63015769Seric { 63158662Seric p = nlp; 63215769Seric } 6331515Seric 6344098Seric /* see if there should be a continuation line */ 6354106Seric c = fgetc(af); 6364106Seric if (!feof(af)) 6374314Seric (void) ungetc(c, af); 6384106Seric if (c != ' ' && c != '\t') 6394098Seric break; 6404098Seric 6414098Seric /* read continuation line */ 6424098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6434098Seric break; 6449368Seric LineNumber++; 64557135Seric 64657135Seric /* check for line overflow */ 64757135Seric if (strchr(p, '\n') == NULL) 64857135Seric { 64958151Seric usrerr("554 alias too long"); 65057135Seric break; 65157135Seric } 6524098Seric } 65316898Seric if (al.q_mailer != LocalMailer) 65416898Seric { 65558151Seric syserr("554 cannot alias non-local names"); 65616898Seric continue; 65716898Seric } 6584314Seric 6594314Seric /* 6604314Seric ** Insert alias into symbol table or DBM file 6614314Seric */ 6624314Seric 66357381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 66457381Seric makelower(al.q_user); 6654322Seric 66659673Seric lhssize = strlen(al.q_user); 66759673Seric rhssize = strlen(rhs); 66859673Seric ad->ad_class->ac_store(ad, al.q_user, rhs, e); 6694157Seric 67059673Seric if (al.q_paddr != NULL) 67159673Seric free(al.q_paddr); 67259673Seric if (al.q_host != NULL) 67359673Seric free(al.q_host); 67459673Seric if (al.q_user != NULL) 67559673Seric free(al.q_user); 6764322Seric 6774322Seric /* statistics */ 6784322Seric naliases++; 6794322Seric bytes += lhssize + rhssize; 6804322Seric if (rhssize > longest) 6814322Seric longest = rhssize; 6821515Seric } 68319784Seric 68459673Seric e->e_to = NULL; 68559673Seric FileName = NULL; 68659733Seric if (Verbose || !automatic) 68759733Seric message("%s: %d aliases, longest %d bytes, %d bytes total", 68859673Seric ad->ad_name, naliases, longest, bytes); 68959673Seric # ifdef LOG 69059673Seric if (LogLevel > 7) 69159673Seric syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total", 69259673Seric ad->ad_name, naliases, longest, bytes); 69359673Seric # endif /* LOG */ 69459673Seric } 69559673Seric /* 69659673Seric ** NDBM modules 69759673Seric */ 69859673Seric 69959673Seric #ifdef NDBM 70059673Seric 70159673Seric /* 70259673Seric ** NDBM_ALOOKUP -- look up alias in ndbm file 70359673Seric */ 70459673Seric 70559673Seric char * 70659673Seric ndbm_alookup(ad, name, e) 70759673Seric register ALIASDB *ad; 70859673Seric char *name; 70959673Seric ENVELOPE *e; 71059673Seric { 71159673Seric int i; 71259673Seric datum rhs, lhs; 71359673Seric char keybuf[MAXNAME + 1]; 71459673Seric 71559697Seric if (tTd(27, 20)) 71659697Seric printf("ndbm_lookup(%s)\n", name); 71759697Seric 71859673Seric /* create a key for fetch */ 71959673Seric i = strlen(name) + 1; 72059673Seric if (i > sizeof keybuf) 72159673Seric i = sizeof keybuf; 72259673Seric bcopy(name, keybuf, i); 72359673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 72459673Seric makelower(keybuf); 72559673Seric 72659673Seric lhs.dsize = i; 72759673Seric lhs.dptr = keybuf; 72859673Seric rhs = dbm_fetch((DBM *) ad->ad_dbp, lhs); 72959673Seric return (rhs.dptr); 73059673Seric } 73159673Seric 73259673Seric 73359673Seric /* 73459673Seric ** NDBM_ASTORE -- store a datum in the database 73559673Seric */ 73659673Seric 73759673Seric void 73859673Seric ndbm_astore(ad, lhs, rhs, e) 73959673Seric register ALIASDB *ad; 74059673Seric char *lhs; 74159673Seric char *rhs; 74259673Seric ENVELOPE *e; 74359673Seric { 74459673Seric datum key; 74559673Seric datum data; 74659673Seric int stat; 74759673Seric 74859697Seric key.dsize = strlen(lhs) + 1; 74959673Seric key.dptr = lhs; 75059673Seric 75159697Seric data.dsize = strlen(rhs) + 1; 75259673Seric data.dptr = rhs; 75359673Seric 75459673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_INSERT); 75559673Seric if (stat > 0) 75619784Seric { 75759673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 75859673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_REPLACE); 75959673Seric } 76059673Seric if (stat != 0) 76159673Seric syserr("readaliases: dbm put (%s)", lhs); 76259673Seric } 76319784Seric 76459673Seric 76559673Seric /* 76659673Seric ** NDBM_AINIT -- initialize DBM database 76759673Seric */ 76859673Seric 76959673Seric bool 77059673Seric ndbm_ainit(ad, e) 77159673Seric register ALIASDB *ad; 77259673Seric ENVELOPE *e; 77359673Seric { 77459673Seric char buf[MAXNAME]; 77559673Seric 77659697Seric if (tTd(27, 2)) 77759697Seric printf("ndbm_ainit(%s)\n", ad->ad_name); 77859697Seric 77959673Seric /* open the database */ 78059673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDONLY, DBMMODE); 78159673Seric if (ad->ad_dbp == NULL) 78259673Seric return FALSE; 78359673Seric 78459673Seric /* wait for @:@ to appear */ 78559673Seric aliaswait(ad, ".pag", e); 78659673Seric 78759673Seric return TRUE; 78859673Seric } 78959673Seric 79059673Seric 79159673Seric /* 79259673Seric ** NDBM_AREBUILD -- rebuild hash database 79359673Seric */ 79459673Seric 79559673Seric void 79659733Seric ndbm_arebuild(ad, fp, automatic, e) 79759673Seric register ALIASDB *ad; 79859673Seric FILE *fp; 79959733Seric int automatic; 80059673Seric ENVELOPE *e; 80159673Seric { 80259673Seric register DBM *db; 80359673Seric int i; 80459673Seric char buf[MAXNAME]; 80559673Seric 80659697Seric if (tTd(27, 2)) 80759697Seric printf("ndbm_arebuild(%s)\n", ad->ad_name); 80859697Seric 80959673Seric db = dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 81059673Seric if (db == NULL) 81159673Seric { 81259701Seric syserr("ndbm_arebuild: cannot create %s", buf); 81359673Seric return; 81459673Seric } 81559673Seric ad->ad_dbp = (void *) db; 81659701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 81759673Seric 81859673Seric /* read and store the aliases */ 81959733Seric readaliases(ad, fp, automatic, e); 82059673Seric } 82159673Seric 82259673Seric /* 82359673Seric ** NDBM_ACLOSE -- close the database 82459673Seric */ 82559673Seric 82659673Seric void 82759673Seric ndbm_aclose(ad, e) 82859673Seric register ALIASDB *ad; 82959673Seric ENVELOPE *e; 83059673Seric { 83159673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 83259673Seric { 83358059Seric #ifdef YPCOMPAT 83459673Seric char buf[200]; 83558846Seric 83659673Seric (void) sprintf(buf, "%010ld", curtime()); 83759673Seric ndbm_astore(ad, "YP_LAST_MODIFIED", buf, e); 83859673Seric 83959673Seric (void) myhostname(buf, sizeof buf); 84059673Seric ndbm_astore(ad, "YP_MASTER_NAME", buf, e); 84158059Seric #endif 84219784Seric 84359673Seric /* write out the distinguished alias */ 84459673Seric ndbm_astore(ad, "@", "@", e); 84519784Seric } 84659673Seric dbm_close((DBM *) ad->ad_dbp); 84759673Seric } 84819784Seric 84959673Seric #endif 85059673Seric /* 85159673Seric ** HASH (NEWDB) Modules 85259673Seric */ 85359673Seric 85459673Seric #ifdef NEWDB 85559673Seric 85659673Seric /* 85759673Seric ** HASH_ALOOKUP -- look up alias in hash file 85859673Seric */ 85959673Seric 86059673Seric char * 86159673Seric hash_alookup(ad, name, e) 86259673Seric register ALIASDB *ad; 86359673Seric char *name; 86459673Seric ENVELOPE *e; 86559673Seric { 86659673Seric int i; 86759673Seric DBT rhs, lhs; 86859673Seric int s; 86959673Seric char keybuf[MAXNAME + 1]; 87059673Seric 87159697Seric if (tTd(27, 20)) 87259697Seric printf("hash_alookup(%s)\n", name); 87359697Seric 87459673Seric /* create a key for fetch */ 87559673Seric i = strlen(name) + 1; 87659673Seric if (i > sizeof keybuf) 87759673Seric i = sizeof keybuf; 87859673Seric bcopy(name, keybuf, i); 87959673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 88059673Seric makelower(keybuf); 88159673Seric 88259673Seric lhs.size = i; 88359673Seric lhs.data = keybuf; 88459673Seric i = ad->ad_ndbp->get(ad->ad_ndbp, &lhs, &rhs, 0); 88559673Seric if (i == 0) 88659673Seric return (rhs.data); 88759673Seric return (NULL); 888292Seric } 88959673Seric 89059673Seric 89159673Seric /* 89259673Seric ** HASH_ASTORE -- store a datum in the database 89359673Seric */ 89459673Seric 89559673Seric void 89659673Seric hash_astore(ad, lhs, rhs, e) 89759673Seric register ALIASDB *ad; 89859673Seric char *lhs; 89959673Seric char *rhs; 90059673Seric ENVELOPE *e; 90159673Seric { 90259673Seric int stat; 90359673Seric DBT key; 90459673Seric DBT data; 90559673Seric 90659697Seric if (tTd(27, 20)) 90759697Seric printf("hash_astore(%s, %s)\n", lhs, rhs); 90859697Seric 90959697Seric key.size = strlen(lhs) + 1; 91059673Seric key.data = lhs; 91159673Seric 91259697Seric data.size = strlen(rhs) + 1; 91359673Seric data.data = rhs; 91459673Seric 91559673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, R_NOOVERWRITE); 91659673Seric if (stat > 0) 91759673Seric { 91859673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 91959673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, 0); 92059673Seric } 92159673Seric if (stat != 0) 92259673Seric syserr("readaliases: db put (%s)", lhs); 92359673Seric } 92459673Seric 92559673Seric 92659673Seric /* 92759673Seric ** HASH_AINIT -- initialize hash database 92859673Seric */ 92959673Seric 93059673Seric bool 93159673Seric hash_ainit(ad, e) 93259673Seric register ALIASDB *ad; 93359673Seric ENVELOPE *e; 93459673Seric { 93559673Seric char buf[MAXNAME]; 93659673Seric 93759697Seric if (tTd(27, 2)) 93859697Seric printf("hash_ainit(%s)\n", ad->ad_name); 93959697Seric 94059673Seric /* open the database */ 94159673Seric (void) strcpy(buf, ad->ad_name); 94259673Seric (void) strcat(buf, ".db"); 94359673Seric ad->ad_ndbp = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 94459673Seric if (ad->ad_ndbp == NULL) 94559673Seric return FALSE; 94659673Seric 94759673Seric /* wait for @:@ to appear */ 94859673Seric aliaswait(ad, ".db", e); 94959673Seric return TRUE; 95059673Seric } 95159673Seric 95259673Seric 95359673Seric /* 95459673Seric ** HASH_AREBUILD -- rebuild hash database 95559673Seric */ 95659673Seric 95759673Seric void 95859733Seric hash_arebuild(ad, fp, automatic, e) 95959673Seric register ALIASDB *ad; 96059673Seric FILE *fp; 96159733Seric int automatic; 96259673Seric ENVELOPE *e; 96359673Seric { 96459673Seric register DB *db; 96559673Seric char buf[MAXNAME]; 96659673Seric 96759697Seric if (tTd(27, 2)) 96859697Seric printf("hash_arebuild(%s)\n", ad->ad_name); 96959697Seric 97059701Seric (void) strcpy(buf, ad->ad_name); 97159701Seric (void) strcat(buf, ".db"); 97259673Seric db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 97359673Seric if (db == NULL) 97459673Seric { 97559701Seric syserr("hash_arebuild: cannot create %s", buf); 97659673Seric return; 97759673Seric } 97859673Seric ad->ad_ndbp = db; 97959701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 98059673Seric 98159673Seric /* read and store the aliases */ 98259733Seric readaliases(ad, fp, automatic, e); 98359673Seric } 98459673Seric 98559673Seric 98659673Seric /* 98759673Seric ** HASH_ACLOSE -- add distinguished entries and close the database 98859673Seric */ 98959673Seric 99059673Seric void 99159673Seric hash_aclose(ad, e) 99259673Seric ALIASDB *ad; 99359673Seric ENVELOPE *e; 99459673Seric { 99559697Seric if (tTd(27, 9)) 99659697Seric printf("hash_aclose(%x)\n", ad->ad_flags); 99759697Seric 99859673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 99959673Seric { 100059673Seric /* write out the distinguished alias */ 100159673Seric hash_astore(ad, "@", "@", e); 100259673Seric } 100359673Seric 100459673Seric if (ad->ad_ndbp->close(ad->ad_ndbp) != 0) 100559673Seric syserr("readaliases: db close failure"); 100659673Seric } 100759673Seric 100859673Seric #endif 1009292Seric /* 101059673Seric ** STAB (Symbol Table) Modules 101159673Seric */ 101259673Seric 101359673Seric 101459673Seric /* 101559673Seric ** STAB_ALOOKUP -- look up alias in symbol table 101659673Seric */ 101759673Seric 101859673Seric char * 101959673Seric stab_alookup(ad, name, e) 102059673Seric register ALIASDB *ad; 102159673Seric char *name; 102259673Seric ENVELOPE *e; 102359673Seric { 102459673Seric register STAB *s; 102559673Seric 102659697Seric if (tTd(27, 20)) 102759697Seric printf("stab_lookup(%s)\n", name); 102859697Seric 102959673Seric s = stab(name, ST_ALIAS, ST_FIND); 103059673Seric if (s != NULL) 103159673Seric return (s->s_alias); 103259673Seric return (NULL); 103359673Seric } 103459673Seric 103559673Seric 103659673Seric /* 103759673Seric ** STAB_ASTORE -- store in symtab (actually using during init, not rebuild) 103859673Seric */ 103959673Seric 104059673Seric void 104159673Seric stab_astore(ad, lhs, rhs, e) 104259673Seric register ALIASDB *ad; 104359673Seric char *lhs; 104459673Seric char *rhs; 104559673Seric ENVELOPE *e; 104659673Seric { 104759673Seric register STAB *s; 104859673Seric 104959673Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 105059673Seric s->s_alias = newstr(rhs); 105159673Seric } 105259673Seric 105359673Seric 105459673Seric /* 105559673Seric ** STAB_AINIT -- initialize (reads data file) 105659673Seric */ 105759673Seric 105859673Seric bool 105959673Seric stab_ainit(ad, e) 106059673Seric register ALIASDB *ad; 106159673Seric ENVELOPE *e; 106259673Seric { 106359673Seric FILE *af; 106459673Seric 106559697Seric if (tTd(27, 2)) 106659697Seric printf("stab_ainit(%s)\n", ad->ad_name); 106759697Seric 106859673Seric af = fopen(ad->ad_name, "r"); 106959673Seric if (af == NULL) 107059673Seric return FALSE; 107159673Seric 107259733Seric readaliases(ad, af, TRUE, e); 107359673Seric } 107459673Seric 107559673Seric 107659673Seric /* 107759673Seric ** STAB_AREBUILD -- rebuild alias file 107859673Seric */ 107959673Seric 108059673Seric void 108159733Seric stab_arebuild(ad, fp, automatic, e) 108259673Seric ALIASDB *ad; 108359673Seric FILE *fp; 108459733Seric int automatic; 108559673Seric ENVELOPE *e; 108659673Seric { 108759697Seric if (tTd(27, 2)) 108859697Seric printf("stab_arebuild(%s)\n", ad->ad_name); 108959697Seric 109059701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 109159673Seric } 109259673Seric 109359673Seric 109459673Seric /* 109559673Seric ** STAB_ACLOSE -- close symbol table (???) 109659673Seric */ 109759673Seric 109859673Seric void 109959673Seric stab_aclose(ad, e) 110059673Seric ALIASDB *ad; 110159673Seric ENVELOPE *e; 110259673Seric { 110359673Seric /* ignore it */ 110459673Seric } 110559673Seric /* 110659673Seric ** NIS Modules 110759673Seric */ 110859673Seric 110959724Seric #ifdef NIS_ALIASES 111059673Seric 111159673Seric /* 111259673Seric ** NIS_ALOOKUP 111359673Seric */ 111459673Seric 111559673Seric char * 111659673Seric nis_alookup(ad, name, e) 111759673Seric ALIASDB *ad; 111859673Seric char *name; 111959673Seric ENVELOPE *e; 112059673Seric { 112159673Seric auto char *vp; 112259673Seric auto int vsize; 112359756Seric int yperr; 112459756Seric int keylen; 112559673Seric 112659697Seric if (tTd(27, 20)) 112759697Seric printf("nis_lookup(%s)\n", name); 112859697Seric 112959756Seric keylen = strlen(name); 113059756Seric yperr = yp_match(ad->ad_domain, ad->ad_name, name, keylen, 113159756Seric &vp, &vsize); 113259756Seric if (yperr == YPERR_KEY) 113359756Seric yperr = yp_match(ad->ad_domain, ad->ad_name, name, ++keylen, 113459756Seric &vp, &vsize); 113559756Seric if (yperr == 0) 113659756Seric return vp; 113759756Seric 113859756Seric if (tTd(27, 10)) 113959756Seric printf("nis_alookup: yp_match(%s, %s, %s) => %s\n", 114059756Seric ad->ad_domain, ad->ad_name, name, yperr_string(yperr)); 114159756Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 114259756Seric ad->ad_flags &= ~ADF_VALID; 114359756Seric return NULL; 114459673Seric } 114559673Seric 114659673Seric /* 114759673Seric ** NIS_ASTORE 114859673Seric */ 114959673Seric 115059673Seric void 115159673Seric nis_astore(ad, lhs, rhs, e) 115259673Seric ALIASDB *ad; 115359673Seric char *lhs; 115459673Seric char *rhs; 115559673Seric ENVELOPE *e; 115659673Seric { 115759673Seric /* nothing */ 115859673Seric } 115959673Seric 116059673Seric /* 116159673Seric ** NIS_AINIT 116259673Seric */ 116359673Seric 116459673Seric bool 116559673Seric nis_ainit(ad, e) 116659673Seric ALIASDB *ad; 116759673Seric ENVELOPE *e; 116859673Seric { 116959673Seric register char *p; 117059756Seric int yperr; 117159756Seric auto char *vp; 117259756Seric auto int vsize; 117359673Seric 117459697Seric if (tTd(27, 2)) 117559697Seric printf("nis_ainit(%s)\n", ad->ad_name); 117659697Seric 117759673Seric p = strchr(ad->ad_name, '@'); 117859673Seric if (p != NULL) 117959673Seric { 118059673Seric *p++ = '\0'; 118159673Seric if (*p != '\0') 118259673Seric ad->ad_domain = p; 118359673Seric } 118459673Seric if (ad->ad_domain == NULL) 118559673Seric yp_get_default_domain(&ad->ad_domain); 118659673Seric 118759673Seric if (*ad->ad_name == '\0') 118859673Seric ad->ad_name = "mail.aliases"; 118959673Seric 119059756Seric yperr = yp_match(ad->ad_domain, ad->ad_name, "@", 1, 119159756Seric &vp, &vsize); 119259756Seric if (tTd(27, 10)) 119359756Seric printf("nis_ainit: yp_match(%s, %s) => %s\n", 119459756Seric ad->ad_domain, ad->ad_name, yperr_string(yperr)); 119559756Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 119659756Seric return TRUE; 119759756Seric return FALSE; 119859673Seric } 119959673Seric 120059673Seric /* 120159673Seric ** NIS_AREBUILD 120259673Seric */ 120359673Seric 120459673Seric void 120559733Seric nis_arebuild(ad, fp, automatic, e) 120659673Seric ALIASDB *ad; 120759673Seric FILE *fp; 120859733Seric int automatic; 120959673Seric ENVELOPE *e; 121059673Seric { 121159697Seric if (tTd(27, 2)) 121259697Seric printf("nis_arebuild(%s)\n", ad->ad_name); 121359673Seric } 121459673Seric 121559673Seric 121659673Seric /* 121759673Seric ** NIS_ACLOSE 121859673Seric */ 121959673Seric 122059673Seric void 122159673Seric nis_aclose(ad, e) 122259673Seric ALIASDB *ad; 122359673Seric ENVELOPE *e; 122459673Seric { 122559673Seric /* nothing */ 122659673Seric } 122759673Seric 122859724Seric #endif /* NIS_ALIASES */ 122959673Seric /* 123059673Seric ** Implicit Modules 123158059Seric ** 123259673Seric ** Tries several types. For back compatibility. 123358059Seric */ 123458059Seric 123559673Seric /* 123659673Seric ** IMPL_ALOOKUP -- lookup in best open database 123759673Seric */ 123858059Seric 123959673Seric char * 124059673Seric impl_alookup(ad, name, e) 124159673Seric ALIASDB *ad; 124259673Seric char *name; 124359673Seric ENVELOPE *e; 124458059Seric { 124559697Seric if (tTd(27, 20)) 124659697Seric printf("impl_lookup(%s)\n", name); 124759697Seric 124859673Seric #ifdef NEWDB 124959673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 125059673Seric return hash_alookup(ad, name, e); 125159673Seric #endif 125259673Seric #ifdef NDBM 125359673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 125459673Seric return ndbm_alookup(ad, name, e); 125559673Seric #endif 125659673Seric return stab_alookup(ad, name, e); 125759673Seric } 125859673Seric 125959673Seric /* 126059673Seric ** IMPL_ASTORE -- store in open databases 126159673Seric */ 126259673Seric 126359673Seric void 126459673Seric impl_astore(ad, lhs, rhs, e) 126559673Seric ALIASDB *ad; 126659673Seric char *lhs; 126759673Seric char *rhs; 126859673Seric ENVELOPE *e; 126959673Seric { 127059673Seric #ifdef NEWDB 127159673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 127259673Seric hash_astore(ad, lhs, rhs, e); 127359673Seric #endif 127459673Seric #ifdef NDBM 127559673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 127659673Seric ndbm_astore(ad, lhs, rhs, e); 127759673Seric #endif 127859673Seric stab_astore(ad, lhs, rhs, e); 127959673Seric } 128059673Seric 128159673Seric /* 128259673Seric ** IMPL_AINIT -- implicit database lookup 128359673Seric */ 128459673Seric 128559673Seric bool 128659673Seric impl_ainit(ad, e) 128759673Seric ALIASDB *ad; 128859673Seric ENVELOPE *e; 128959673Seric { 129059733Seric struct stat stb; 129159733Seric 129259697Seric if (tTd(27, 2)) 129359697Seric printf("impl_ainit(%s)\n", ad->ad_name); 129459697Seric 129559733Seric if (stat(ad->ad_name, &stb) < 0) 129659733Seric { 129759733Seric /* no alias file at all */ 129859733Seric return FALSE; 129959733Seric } 130059733Seric 130159673Seric #ifdef NEWDB 130259697Seric ad->ad_flags |= ADF_IMPLHASH; 130359673Seric if (hash_ainit(ad, e)) 130458059Seric { 130559697Seric return TRUE; 130659673Seric } 130759697Seric ad->ad_flags &= ~ADF_IMPLHASH; 130859673Seric #endif 130959673Seric #ifdef NDBM 131059697Seric ad->ad_flags |= ADF_IMPLNDBM; 131159673Seric if (ndbm_ainit(ad, e)) 131259673Seric { 131359697Seric return TRUE; 131459673Seric } 131559697Seric ad->ad_flags &= ~ADF_IMPLNDBM; 131659673Seric #endif 131758059Seric 131859733Seric if (Verbose) 131959733Seric message("WARNING: cannot open alias database %s", ad->ad_name); 132059733Seric 132159673Seric if (stab_ainit(ad, e)) 132259673Seric { 132359697Seric return TRUE; 132459673Seric } 132559697Seric 132659697Seric return FALSE; 132759673Seric } 132858059Seric 132959673Seric /* 133059673Seric ** IMPL_AREBUILD -- rebuild alias database 133159673Seric */ 133258059Seric 133359673Seric void 133459733Seric impl_arebuild(ad, fp, automatic, e) 133559673Seric ALIASDB *ad; 133659673Seric FILE *fp; 133759733Seric int automatic; 133859673Seric ENVELOPE *e; 133959673Seric { 134059673Seric #ifdef NEWDB 134159673Seric DB *ndb; 134259673Seric char buf[MAXNAME]; 134359697Seric #endif 134459673Seric 134559697Seric if (tTd(27, 2)) 134659697Seric printf("impl_arebuild(%s)\n", ad->ad_name); 134759697Seric 134859697Seric #ifdef NEWDB 134959673Seric (void) strcpy(buf, ad->ad_name); 135059673Seric (void) strcat(buf, ".db"); 135159673Seric ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 135259673Seric if (ndb == NULL) 135358059Seric { 135459673Seric syserr("rebuildaliases: cannot create %s", buf); 135558059Seric } 135659673Seric else 135759673Seric { 135859673Seric ad->ad_ndbp = ndb; 135959673Seric ad->ad_flags |= ADF_IMPLHASH; 136059673Seric #if defined(NDBM) && defined(YPCOMPAT) 136159673Seric if (access("/var/yp/Makefile", R_OK) != 0) 136259673Seric #endif 136359697Seric goto readem; 136459673Seric } 136559673Seric #endif 136659673Seric 136759673Seric #ifdef NDBM 136859673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 136959673Seric if (ad->ad_dbp == NULL) 137059673Seric { 137159673Seric syserr("rebuildaliases: cannot create %s.{pag,dir}", 137259673Seric ad->ad_name); 137359673Seric } 137459673Seric else 137559673Seric { 137659673Seric ad->ad_flags |= ADF_IMPLNDBM; 137759673Seric } 137859673Seric #endif 137959673Seric 138059673Seric if (!bitset(ADF_IMPLHASH|ADF_IMPLNDBM, ad->ad_flags)) 138159673Seric return; 138259673Seric 138359697Seric readem: 138459701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 138559673Seric 138659673Seric /* read and store aliases */ 138759733Seric readaliases(ad, fp, automatic, e); 138858059Seric } 138958059Seric 139059673Seric 139159673Seric /* 139259673Seric ** IMPL_ACLOSE -- close any open database(s) 139359673Seric */ 139459673Seric 139559673Seric void 139659673Seric impl_aclose(ad, e) 139759673Seric ALIASDB *ad; 139859673Seric ENVELOPE *e; 139959673Seric { 140059673Seric #ifdef NEWDB 140159697Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 140259697Seric hash_aclose(ad, e); 140359673Seric #endif 140459673Seric 140559673Seric #ifdef NDBM 140659697Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 140759697Seric ndbm_aclose(ad, e); 140859673Seric #endif 140959673Seric } 141058059Seric /* 141159673Seric ** SETUPALIASES -- set up aliases classes 141259673Seric */ 141359673Seric 141459673Seric #ifdef NEWDB 141559673Seric ALIASCLASS HashAClass = 141659673Seric { 141759673Seric "hash", hash_alookup, hash_astore, 141859673Seric hash_ainit, hash_arebuild, hash_aclose, 141959673Seric ACF_BUILDABLE 142059673Seric }; 142159673Seric #endif 142259673Seric 142359673Seric #ifdef NDBM 142459673Seric ALIASCLASS DbmAClass = 142559673Seric { 142659673Seric "dbm", ndbm_alookup, ndbm_astore, 142759673Seric ndbm_ainit, ndbm_arebuild, ndbm_aclose, 142859673Seric ACF_BUILDABLE 142959673Seric }; 143059673Seric #endif 143159673Seric 143259724Seric #ifdef NIS_ALIASES 143359673Seric ALIASCLASS NisAClass = 143459673Seric { 143559673Seric "nis", nis_alookup, nis_astore, 143659673Seric nis_ainit, nis_arebuild, nis_aclose, 143759673Seric 0 143859673Seric }; 143959673Seric #endif 144059673Seric 144159673Seric ALIASCLASS StabAClass = 144259673Seric { 144359673Seric "stab", stab_alookup, stab_astore, 144459673Seric stab_ainit, stab_arebuild, stab_aclose, 144559673Seric 0 144659673Seric }; 144759673Seric 144859673Seric ALIASCLASS ImplAClass = 144959673Seric { 145059673Seric "implicit", impl_alookup, impl_astore, 145159673Seric impl_ainit, impl_arebuild, impl_aclose, 145259673Seric ACF_BUILDABLE 145359673Seric }; 145459673Seric 145559673Seric setupaliases() 145659673Seric { 145759673Seric register STAB *s; 145859673Seric 145959673Seric #ifdef NEWDB 146059673Seric s = stab("hash", ST_ALIASCLASS, ST_ENTER); 146159673Seric s->s_aliasclass = &HashAClass; 146259673Seric #endif 146359673Seric 146459673Seric #ifdef NDBM 146559673Seric s = stab("dbm", ST_ALIASCLASS, ST_ENTER); 146659673Seric s->s_aliasclass = &DbmAClass; 146759673Seric #endif 146859673Seric 146959724Seric #ifdef NIS_ALIASES 147059673Seric s = stab("nis", ST_ALIASCLASS, ST_ENTER); 147159673Seric s->s_aliasclass = &NisAClass; 147259673Seric #endif 147359673Seric 147459673Seric #if !defined(NEWDB) && !defined(NDBM) 147559673Seric s = stab("stab", ST_ALIASCLASS, ST_ENTER); 147659673Seric s->s_aliasclass = &StabAClass; 147759673Seric #endif 147859673Seric 147959673Seric s = stab("implicit", ST_ALIASCLASS, ST_ENTER); 148059673Seric s->s_aliasclass = &ImplAClass; 148159673Seric } 148259673Seric /* 1483292Seric ** FORWARD -- Try to forward mail 1484292Seric ** 1485292Seric ** This is similar but not identical to aliasing. 1486292Seric ** 1487292Seric ** Parameters: 14884314Seric ** user -- the name of the user who's mail we would like 14894314Seric ** to forward to. It must have been verified -- 14904314Seric ** i.e., the q_home field must have been filled 14914314Seric ** in. 14924999Seric ** sendq -- a pointer to the head of the send queue to 14934999Seric ** put this user's aliases in. 1494292Seric ** 1495292Seric ** Returns: 14964098Seric ** none. 1497292Seric ** 1498292Seric ** Side Effects: 14993185Seric ** New names are added to send queues. 1500292Seric */ 1501292Seric 150255012Seric forward(user, sendq, e) 15032966Seric ADDRESS *user; 15044999Seric ADDRESS **sendq; 150555012Seric register ENVELOPE *e; 1506292Seric { 150757136Seric char *pp; 150857136Seric char *ep; 15094069Seric 15107671Seric if (tTd(27, 1)) 15114098Seric printf("forward(%s)\n", user->q_paddr); 15124098Seric 15134594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 15144098Seric return; 15154314Seric if (user->q_home == NULL) 151658059Seric { 151758151Seric syserr("554 forward: no home"); 151858059Seric user->q_home = "/nosuchdirectory"; 151958059Seric } 15204069Seric 15214069Seric /* good address -- look for .forward file in home */ 152255012Seric define('z', user->q_home, e); 152357136Seric define('u', user->q_user, e); 152457136Seric define('h', user->q_host, e); 152557136Seric if (ForwardPath == NULL) 152658050Seric ForwardPath = newstr("\201z/.forward"); 152757136Seric 152857136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 152957136Seric { 153058247Seric int err; 153157232Seric char buf[MAXPATHLEN+1]; 153257136Seric 153357136Seric ep = strchr(pp, ':'); 153457136Seric if (ep != NULL) 153557136Seric *ep = '\0'; 153657136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 153757136Seric if (ep != NULL) 153857136Seric *ep++ = ':'; 153957136Seric if (tTd(27, 3)) 154057136Seric printf("forward: trying %s\n", buf); 154158247Seric err = include(buf, TRUE, user, sendq, e); 154258247Seric if (err == 0) 154357136Seric break; 154458247Seric if (transienterror(err)) 154558247Seric { 154658247Seric /* we have to suspend this message */ 154759563Seric if (tTd(27, 2)) 154859563Seric printf("forward: transient error on %s\n", buf); 154959563Seric #ifdef LOG 155059563Seric if (LogLevel > 2) 155159624Seric syslog(LOG_ERR, "%s: forward %s: transient error: %s", 155259624Seric e->e_id, buf, errstring(err)); 155359563Seric #endif 155459611Seric message("%s: %s: message queued", buf, errstring(err)); 155558247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 155658247Seric return; 155758247Seric } 155857136Seric } 1559292Seric } 1560