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*59756Seric static char sccsid[] = "@(#)alias.c 6.44 (Berkeley) 05/06/93 (with NEWDB and NDBM)"; 2951756Seric #else 30*59756Seric static char sccsid[] = "@(#)alias.c 6.44 (Berkeley) 05/06/93 (with NEWDB)"; 3157736Seric #endif 3257736Seric #else 3356845Seric #ifdef NDBM 34*59756Seric static char sccsid[] = "@(#)alias.c 6.44 (Berkeley) 05/06/93 (with NDBM)"; 3533728Sbostic #else 36*59756Seric static char sccsid[] = "@(#)alias.c 6.44 (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 25459673Seric if (NAliasDBs >= MAXALIASDB) 25551756Seric { 25659673Seric syserr("Too many alias databases defined, %d max", MAXALIASDB); 25759673Seric return; 25851756Seric } 25959673Seric ad = &AliasDB[NAliasDBs]; 26059673Seric 26159673Seric for (p = spec; *p != '\0'; p++) 26251756Seric { 26359673Seric if (strchr(" /:", *p) != NULL) 26459673Seric break; 26551756Seric } 26659673Seric 26759673Seric if (*p == ':') 26859673Seric { 26959673Seric /* explicit class listed */ 27059673Seric *p++ = '\0'; 27159673Seric class = spec; 27259673Seric spec = p; 27359673Seric } 27459673Seric else 27559673Seric { 27659673Seric /* implicit class */ 27759673Seric class = "implicit"; 27859673Seric } 27959673Seric 28059673Seric /* look up class */ 28159673Seric s = stab(class, ST_ALIASCLASS, ST_FIND); 28259673Seric if (s == NULL) 283*59756Seric { 284*59756Seric if (tTd(27, 1)) 285*59756Seric printf("Unknown alias class %s\n", class); 286*59756Seric } 28759673Seric else 28859673Seric { 28959673Seric ad->ad_class = s->s_aliasclass; 29059673Seric ad->ad_name = newstr(spec); 29159673Seric NAliasDBs++; 29259673Seric } 2935701Seric } 2945701Seric /* 2954098Seric ** INITALIASES -- initialize for aliasing 2964098Seric ** 29756845Seric ** Very different depending on whether we are running NDBM or not. 2984098Seric ** 2994098Seric ** Parameters: 30059673Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 30159673Seric ** e -- current envelope. 3024098Seric ** 3034098Seric ** Returns: 3044098Seric ** none. 3054098Seric ** 3064098Seric ** Side Effects: 3074098Seric ** initializes aliases: 30856845Seric ** if NDBM: opens the database. 30956845Seric ** if ~NDBM: reads the aliases into the symbol table. 3104098Seric */ 3114098Seric 31240559Sbostic # define DBMMODE 0644 3134157Seric 31459673Seric initaliases(rebuild, e) 31559673Seric bool rebuild; 31655012Seric register ENVELOPE *e; 3174098Seric { 31859673Seric int dbno; 31959673Seric register ALIASDB *ad; 3204322Seric 32159673Seric for (dbno = 0; dbno < NAliasDBs; dbno++) 3228437Seric { 32359673Seric ad = &AliasDB[dbno]; 32459697Seric 32559697Seric if (tTd(27, 2)) 32659697Seric printf("initaliases(%s:%s)\n", 32759697Seric ad->ad_class->ac_name, ad->ad_name); 32859697Seric 32959673Seric if (rebuild) 33050576Seric { 33159673Seric rebuildaliases(ad, FALSE, e); 33250576Seric } 33359673Seric else 33457249Seric { 33559697Seric if (ad->ad_class->ac_init(ad, e)) 336*59756Seric { 337*59756Seric if (tTd(27, 4)) 338*59756Seric printf("%s:%s: valid\n", 339*59756Seric ad->ad_class->ac_name, 340*59756Seric ad->ad_name); 34159697Seric ad->ad_flags |= ADF_VALID; 342*59756Seric } 343*59756Seric else if (tTd(27, 4)) 344*59756Seric printf("%s:%s: invalid: %s\n", 345*59756Seric ad->ad_class->ac_name, ad->ad_name, 346*59756Seric errstring(errno)); 34757249Seric } 34850575Seric } 34959673Seric } 35059673Seric /* 35159673Seric ** ALIASWAIT -- wait for distinguished @:@ token to appear. 35259673Seric ** 35359673Seric ** This can decide to reopen or rebuild the alias file 35459673Seric */ 35559673Seric 35659673Seric aliaswait(ad, ext, e) 35759673Seric ALIASDB *ad; 35859673Seric char *ext; 35959673Seric ENVELOPE *e; 36059673Seric { 36159673Seric int atcnt; 36259673Seric time_t mtime; 36359673Seric struct stat stb; 36459673Seric char buf[MAXNAME]; 36559673Seric 36659697Seric if (tTd(27, 3)) 36759697Seric printf("aliaswait\n"); 36859697Seric 36917471Seric atcnt = SafeAlias * 2; 37017471Seric if (atcnt > 0) 37117471Seric { 37259673Seric while (atcnt-- >= 0 && 37359673Seric ad->ad_class->ac_lookup(ad, "@", e) == NULL) 37425689Seric { 37525689Seric /* 37659673Seric ** Close and re-open the alias database in case 37759673Seric ** the one is mv'ed instead of cp'ed in. 37825689Seric */ 37925689Seric 38059697Seric if (tTd(27, 2)) 38159697Seric printf("aliaswait: sleeping\n"); 38259697Seric 38359673Seric ad->ad_class->ac_close(ad, e); 38417471Seric sleep(30); 38559673Seric ad->ad_class->ac_init(ad, e); 38625689Seric } 38717471Seric } 3888437Seric 38959673Seric /* see if we need to go into auto-rebuild mode */ 39059673Seric if (stat(ad->ad_name, &stb) < 0) 39159673Seric return; 39259673Seric mtime = stb.st_mtime; 39359673Seric (void) strcpy(buf, ad->ad_name); 39459673Seric (void) strcat(buf, ext); 39559673Seric if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || atcnt < 0) 3964322Seric { 39759673Seric /* database is out of date */ 39840559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3994322Seric { 40059673Seric message("auto-rebuilding alias database %s", 40159673Seric ad->ad_name); 40259673Seric rebuildaliases(ad, TRUE, e); 4034322Seric } 4044322Seric else 4054322Seric { 40619039Seric #ifdef LOG 40758020Seric if (LogLevel > 3) 40859673Seric syslog(LOG_INFO, "alias database %s out of date", 40959673Seric ad->ad_name); 41056795Seric #endif /* LOG */ 41159673Seric message("Warning: alias database %s out of date", 41259673Seric ad->ad_name); 4134322Seric } 4144322Seric } 41559673Seric } 41659673Seric /* 41759673Seric ** REBUILDALIASES -- rebuild the alias database. 41859673Seric ** 41959673Seric ** Parameters: 42059673Seric ** ad -- the database to rebuild. 42159673Seric ** automatic -- set if this was automatically generated. 42259673Seric ** e -- current envelope. 42359673Seric ** 42459673Seric ** Returns: 42559673Seric ** none. 42659673Seric ** 42759673Seric ** Side Effects: 42859673Seric ** Reads the text version of the database, builds the 42959673Seric ** DBM or DB version. 43059673Seric */ 4314322Seric 43259673Seric rebuildaliases(ad, automatic, e) 43359673Seric register ALIASDB *ad; 43459673Seric bool automatic; 43559673Seric register ENVELOPE *e; 43659673Seric { 43759673Seric FILE *af; 43859673Seric void (*oldsigint)(); 4394322Seric 44059673Seric if (!bitset(ACF_BUILDABLE, ad->ad_class->ac_flags)) 44159673Seric return; 4424322Seric 44359673Seric #ifdef LOG 44459673Seric if (LogLevel > 7) 4458437Seric { 44659673Seric extern char *username(); 44725522Seric 44859673Seric syslog(LOG_NOTICE, "alias database %s %srebuilt by %s", 44959673Seric ad->ad_name, automatic ? "auto" : "", username()); 45059673Seric } 45156795Seric #endif /* LOG */ 45259673Seric 45359673Seric /* try to lock the source file */ 45459673Seric if ((af = fopen(ad->ad_name, "r+")) == NULL) 45559673Seric { 456*59756Seric if (tTd(27, 1)) 457*59756Seric printf("Can't open %s: %s\n", 458*59756Seric ad->ad_name, errstring(errno)); 459*59756Seric ad->ad_flags &= ~ADF_VALID; 46059673Seric errno = 0; 46159673Seric return; 4628437Seric } 46359673Seric 46459673Seric /* see if someone else is rebuilding the alias file */ 46559673Seric if (!lockfile(fileno(af), ad->ad_name, LOCK_EX|LOCK_NB)) 46659673Seric { 46759673Seric /* yes, they are -- wait until done */ 46859673Seric message("Alias file %s is already being rebuilt", 46959673Seric ad->ad_name); 47059673Seric if (OpMode != MD_INITALIAS) 47159673Seric { 47259673Seric /* wait for other rebuild to complete */ 47359673Seric (void) lockfile(fileno(af), ad->ad_name, 47459673Seric LOCK_EX); 47559673Seric } 47659673Seric (void) fclose(af); 47759673Seric errno = 0; 47859673Seric return; 47959673Seric } 48059673Seric 48159673Seric oldsigint = signal(SIGINT, SIG_IGN); 48259673Seric 48359733Seric ad->ad_class->ac_rebuild(ad, af, automatic, e); 48459673Seric 48559673Seric /* close the file, thus releasing locks */ 48659673Seric fclose(af); 48759673Seric 48859673Seric /* add distinguished entries and close the database */ 48959701Seric if (bitset(ADF_VALID, ad->ad_flags)) 49059701Seric ad->ad_class->ac_close(ad, e); 49159673Seric 49259673Seric /* restore the old signal */ 49359673Seric (void) signal(SIGINT, oldsigint); 4944157Seric } 4954157Seric /* 4964157Seric ** READALIASES -- read and process the alias file. 4974157Seric ** 4984157Seric ** This routine implements the part of initaliases that occurs 4994157Seric ** when we are not going to use the DBM stuff. 5004157Seric ** 5014157Seric ** Parameters: 50259673Seric ** ad -- the alias database descriptor. 50359673Seric ** af -- file to read the aliases from. 50459733Seric ** automatic -- set if this was an automatic rebuild. 50559673Seric ** e -- the current alias file. 5064157Seric ** 5074157Seric ** Returns: 5084157Seric ** none. 5094157Seric ** 5104157Seric ** Side Effects: 5114157Seric ** Reads aliasfile into the symbol table. 5124157Seric ** Optionally, builds the .dir & .pag files. 5134157Seric */ 5144157Seric 5154157Seric static 51659733Seric readaliases(ad, af, automatic, e) 51759673Seric register ALIASDB *ad; 51859673Seric FILE *af; 51959733Seric int automatic; 52055012Seric register ENVELOPE *e; 5214157Seric { 5224098Seric register char *p; 5234098Seric char *rhs; 5244098Seric bool skipping; 52559673Seric long naliases, bytes, longest; 5264098Seric ADDRESS al, bl; 5274106Seric register STAB *s; 5289368Seric char line[BUFSIZ]; 5294098Seric 5304314Seric /* 5314314Seric ** Read and interpret lines 5324314Seric */ 5334314Seric 53459673Seric FileName = ad->ad_name; 5359368Seric LineNumber = 0; 5364322Seric naliases = bytes = longest = 0; 5374098Seric skipping = FALSE; 5384098Seric while (fgets(line, sizeof (line), af) != NULL) 5394098Seric { 5404322Seric int lhssize, rhssize; 5414322Seric 5429368Seric LineNumber++; 54356795Seric p = strchr(line, '\n'); 54425278Seric if (p != NULL) 54525278Seric *p = '\0'; 5464098Seric switch (line[0]) 5474098Seric { 5484098Seric case '#': 5494098Seric case '\0': 5504098Seric skipping = FALSE; 5514098Seric continue; 5524065Seric 5534098Seric case ' ': 5544098Seric case '\t': 5554098Seric if (!skipping) 55658151Seric syserr("554 Non-continuation line starts with space"); 5574098Seric skipping = TRUE; 5584097Seric continue; 5594098Seric } 5604098Seric skipping = FALSE; 5611874Seric 5624314Seric /* 5634314Seric ** Process the LHS 56457736Seric ** Find the colon separator, and parse the address. 56516898Seric ** It should resolve to a local name -- this will 56616898Seric ** be checked later (we want to optionally do 56716898Seric ** parsing of the RHS first to maximize error 56816898Seric ** detection). 5694314Seric */ 5704314Seric 5714098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5724097Seric continue; 57316898Seric if (*p++ != ':') 5744098Seric { 57558151Seric syserr("554 missing colon"); 5764097Seric continue; 5774098Seric } 57858333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 5794098Seric { 58058151Seric syserr("554 illegal alias name"); 58116898Seric continue; 5824098Seric } 5834314Seric 5844314Seric /* 5854314Seric ** Process the RHS. 5864314Seric ** 'al' is the internal form of the LHS address. 5874314Seric ** 'p' points to the text of the RHS. 5884314Seric */ 5894314Seric 59058914Seric while (isascii(*p) && isspace(*p)) 59158914Seric p++; 5924098Seric rhs = p; 5934098Seric for (;;) 5944098Seric { 5954098Seric register char c; 59658662Seric register char *nlp; 5971515Seric 59858662Seric nlp = &p[strlen(p)]; 59958662Seric if (nlp[-1] == '\n') 60058662Seric *--nlp = '\0'; 60158662Seric 60259673Seric if (CheckAliases) 6034098Seric { 6044157Seric /* do parsing & compression of addresses */ 60525278Seric while (*p != '\0') 6064098Seric { 60758333Seric auto char *delimptr; 60825278Seric 60958050Seric while ((isascii(*p) && isspace(*p)) || 61058050Seric *p == ',') 6114157Seric p++; 61225278Seric if (*p == '\0') 61325278Seric break; 61458333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 61558151Seric usrerr("553 %s... bad address", p); 61658333Seric p = delimptr; 6174098Seric } 6184098Seric } 6194157Seric else 62015769Seric { 62158662Seric p = nlp; 62215769Seric } 6231515Seric 6244098Seric /* see if there should be a continuation line */ 6254106Seric c = fgetc(af); 6264106Seric if (!feof(af)) 6274314Seric (void) ungetc(c, af); 6284106Seric if (c != ' ' && c != '\t') 6294098Seric break; 6304098Seric 6314098Seric /* read continuation line */ 6324098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6334098Seric break; 6349368Seric LineNumber++; 63557135Seric 63657135Seric /* check for line overflow */ 63757135Seric if (strchr(p, '\n') == NULL) 63857135Seric { 63958151Seric usrerr("554 alias too long"); 64057135Seric break; 64157135Seric } 6424098Seric } 64316898Seric if (al.q_mailer != LocalMailer) 64416898Seric { 64558151Seric syserr("554 cannot alias non-local names"); 64616898Seric continue; 64716898Seric } 6484314Seric 6494314Seric /* 6504314Seric ** Insert alias into symbol table or DBM file 6514314Seric */ 6524314Seric 65357381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 65457381Seric makelower(al.q_user); 6554322Seric 65659673Seric lhssize = strlen(al.q_user); 65759673Seric rhssize = strlen(rhs); 65859673Seric ad->ad_class->ac_store(ad, al.q_user, rhs, e); 6594157Seric 66059673Seric if (al.q_paddr != NULL) 66159673Seric free(al.q_paddr); 66259673Seric if (al.q_host != NULL) 66359673Seric free(al.q_host); 66459673Seric if (al.q_user != NULL) 66559673Seric free(al.q_user); 6664322Seric 6674322Seric /* statistics */ 6684322Seric naliases++; 6694322Seric bytes += lhssize + rhssize; 6704322Seric if (rhssize > longest) 6714322Seric longest = rhssize; 6721515Seric } 67319784Seric 67459673Seric e->e_to = NULL; 67559673Seric FileName = NULL; 67659733Seric if (Verbose || !automatic) 67759733Seric message("%s: %d aliases, longest %d bytes, %d bytes total", 67859673Seric ad->ad_name, naliases, longest, bytes); 67959673Seric # ifdef LOG 68059673Seric if (LogLevel > 7) 68159673Seric syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total", 68259673Seric ad->ad_name, naliases, longest, bytes); 68359673Seric # endif /* LOG */ 68459673Seric } 68559673Seric /* 68659673Seric ** NDBM modules 68759673Seric */ 68859673Seric 68959673Seric #ifdef NDBM 69059673Seric 69159673Seric /* 69259673Seric ** NDBM_ALOOKUP -- look up alias in ndbm file 69359673Seric */ 69459673Seric 69559673Seric char * 69659673Seric ndbm_alookup(ad, name, e) 69759673Seric register ALIASDB *ad; 69859673Seric char *name; 69959673Seric ENVELOPE *e; 70059673Seric { 70159673Seric int i; 70259673Seric datum rhs, lhs; 70359673Seric char keybuf[MAXNAME + 1]; 70459673Seric 70559697Seric if (tTd(27, 20)) 70659697Seric printf("ndbm_lookup(%s)\n", name); 70759697Seric 70859673Seric /* create a key for fetch */ 70959673Seric i = strlen(name) + 1; 71059673Seric if (i > sizeof keybuf) 71159673Seric i = sizeof keybuf; 71259673Seric bcopy(name, keybuf, i); 71359673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 71459673Seric makelower(keybuf); 71559673Seric 71659673Seric lhs.dsize = i; 71759673Seric lhs.dptr = keybuf; 71859673Seric rhs = dbm_fetch((DBM *) ad->ad_dbp, lhs); 71959673Seric return (rhs.dptr); 72059673Seric } 72159673Seric 72259673Seric 72359673Seric /* 72459673Seric ** NDBM_ASTORE -- store a datum in the database 72559673Seric */ 72659673Seric 72759673Seric void 72859673Seric ndbm_astore(ad, lhs, rhs, e) 72959673Seric register ALIASDB *ad; 73059673Seric char *lhs; 73159673Seric char *rhs; 73259673Seric ENVELOPE *e; 73359673Seric { 73459673Seric datum key; 73559673Seric datum data; 73659673Seric int stat; 73759673Seric 73859697Seric key.dsize = strlen(lhs) + 1; 73959673Seric key.dptr = lhs; 74059673Seric 74159697Seric data.dsize = strlen(rhs) + 1; 74259673Seric data.dptr = rhs; 74359673Seric 74459673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_INSERT); 74559673Seric if (stat > 0) 74619784Seric { 74759673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 74859673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_REPLACE); 74959673Seric } 75059673Seric if (stat != 0) 75159673Seric syserr("readaliases: dbm put (%s)", lhs); 75259673Seric } 75319784Seric 75459673Seric 75559673Seric /* 75659673Seric ** NDBM_AINIT -- initialize DBM database 75759673Seric */ 75859673Seric 75959673Seric bool 76059673Seric ndbm_ainit(ad, e) 76159673Seric register ALIASDB *ad; 76259673Seric ENVELOPE *e; 76359673Seric { 76459673Seric char buf[MAXNAME]; 76559673Seric 76659697Seric if (tTd(27, 2)) 76759697Seric printf("ndbm_ainit(%s)\n", ad->ad_name); 76859697Seric 76959673Seric /* open the database */ 77059673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDONLY, DBMMODE); 77159673Seric if (ad->ad_dbp == NULL) 77259673Seric return FALSE; 77359673Seric 77459673Seric /* wait for @:@ to appear */ 77559673Seric aliaswait(ad, ".pag", e); 77659673Seric 77759673Seric return TRUE; 77859673Seric } 77959673Seric 78059673Seric 78159673Seric /* 78259673Seric ** NDBM_AREBUILD -- rebuild hash database 78359673Seric */ 78459673Seric 78559673Seric void 78659733Seric ndbm_arebuild(ad, fp, automatic, e) 78759673Seric register ALIASDB *ad; 78859673Seric FILE *fp; 78959733Seric int automatic; 79059673Seric ENVELOPE *e; 79159673Seric { 79259673Seric register DBM *db; 79359673Seric int i; 79459673Seric char buf[MAXNAME]; 79559673Seric 79659697Seric if (tTd(27, 2)) 79759697Seric printf("ndbm_arebuild(%s)\n", ad->ad_name); 79859697Seric 79959673Seric db = dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 80059673Seric if (db == NULL) 80159673Seric { 80259701Seric syserr("ndbm_arebuild: cannot create %s", buf); 80359673Seric return; 80459673Seric } 80559673Seric ad->ad_dbp = (void *) db; 80659701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 80759673Seric 80859673Seric /* read and store the aliases */ 80959733Seric readaliases(ad, fp, automatic, e); 81059673Seric } 81159673Seric 81259673Seric /* 81359673Seric ** NDBM_ACLOSE -- close the database 81459673Seric */ 81559673Seric 81659673Seric void 81759673Seric ndbm_aclose(ad, e) 81859673Seric register ALIASDB *ad; 81959673Seric ENVELOPE *e; 82059673Seric { 82159673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 82259673Seric { 82358059Seric #ifdef YPCOMPAT 82459673Seric char buf[200]; 82558846Seric 82659673Seric (void) sprintf(buf, "%010ld", curtime()); 82759673Seric ndbm_astore(ad, "YP_LAST_MODIFIED", buf, e); 82859673Seric 82959673Seric (void) myhostname(buf, sizeof buf); 83059673Seric ndbm_astore(ad, "YP_MASTER_NAME", buf, e); 83158059Seric #endif 83219784Seric 83359673Seric /* write out the distinguished alias */ 83459673Seric ndbm_astore(ad, "@", "@", e); 83519784Seric } 83659673Seric dbm_close((DBM *) ad->ad_dbp); 83759673Seric } 83819784Seric 83959673Seric #endif 84059673Seric /* 84159673Seric ** HASH (NEWDB) Modules 84259673Seric */ 84359673Seric 84459673Seric #ifdef NEWDB 84559673Seric 84659673Seric /* 84759673Seric ** HASH_ALOOKUP -- look up alias in hash file 84859673Seric */ 84959673Seric 85059673Seric char * 85159673Seric hash_alookup(ad, name, e) 85259673Seric register ALIASDB *ad; 85359673Seric char *name; 85459673Seric ENVELOPE *e; 85559673Seric { 85659673Seric int i; 85759673Seric DBT rhs, lhs; 85859673Seric int s; 85959673Seric char keybuf[MAXNAME + 1]; 86059673Seric 86159697Seric if (tTd(27, 20)) 86259697Seric printf("hash_alookup(%s)\n", name); 86359697Seric 86459673Seric /* create a key for fetch */ 86559673Seric i = strlen(name) + 1; 86659673Seric if (i > sizeof keybuf) 86759673Seric i = sizeof keybuf; 86859673Seric bcopy(name, keybuf, i); 86959673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 87059673Seric makelower(keybuf); 87159673Seric 87259673Seric lhs.size = i; 87359673Seric lhs.data = keybuf; 87459673Seric i = ad->ad_ndbp->get(ad->ad_ndbp, &lhs, &rhs, 0); 87559673Seric if (i == 0) 87659673Seric return (rhs.data); 87759673Seric return (NULL); 878292Seric } 87959673Seric 88059673Seric 88159673Seric /* 88259673Seric ** HASH_ASTORE -- store a datum in the database 88359673Seric */ 88459673Seric 88559673Seric void 88659673Seric hash_astore(ad, lhs, rhs, e) 88759673Seric register ALIASDB *ad; 88859673Seric char *lhs; 88959673Seric char *rhs; 89059673Seric ENVELOPE *e; 89159673Seric { 89259673Seric int stat; 89359673Seric DBT key; 89459673Seric DBT data; 89559673Seric 89659697Seric if (tTd(27, 20)) 89759697Seric printf("hash_astore(%s, %s)\n", lhs, rhs); 89859697Seric 89959697Seric key.size = strlen(lhs) + 1; 90059673Seric key.data = lhs; 90159673Seric 90259697Seric data.size = strlen(rhs) + 1; 90359673Seric data.data = rhs; 90459673Seric 90559673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, R_NOOVERWRITE); 90659673Seric if (stat > 0) 90759673Seric { 90859673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 90959673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, 0); 91059673Seric } 91159673Seric if (stat != 0) 91259673Seric syserr("readaliases: db put (%s)", lhs); 91359673Seric } 91459673Seric 91559673Seric 91659673Seric /* 91759673Seric ** HASH_AINIT -- initialize hash database 91859673Seric */ 91959673Seric 92059673Seric bool 92159673Seric hash_ainit(ad, e) 92259673Seric register ALIASDB *ad; 92359673Seric ENVELOPE *e; 92459673Seric { 92559673Seric char buf[MAXNAME]; 92659673Seric 92759697Seric if (tTd(27, 2)) 92859697Seric printf("hash_ainit(%s)\n", ad->ad_name); 92959697Seric 93059673Seric /* open the database */ 93159673Seric (void) strcpy(buf, ad->ad_name); 93259673Seric (void) strcat(buf, ".db"); 93359673Seric ad->ad_ndbp = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 93459673Seric if (ad->ad_ndbp == NULL) 93559673Seric return FALSE; 93659673Seric 93759673Seric /* wait for @:@ to appear */ 93859673Seric aliaswait(ad, ".db", e); 93959673Seric return TRUE; 94059673Seric } 94159673Seric 94259673Seric 94359673Seric /* 94459673Seric ** HASH_AREBUILD -- rebuild hash database 94559673Seric */ 94659673Seric 94759673Seric void 94859733Seric hash_arebuild(ad, fp, automatic, e) 94959673Seric register ALIASDB *ad; 95059673Seric FILE *fp; 95159733Seric int automatic; 95259673Seric ENVELOPE *e; 95359673Seric { 95459673Seric register DB *db; 95559673Seric char buf[MAXNAME]; 95659673Seric 95759697Seric if (tTd(27, 2)) 95859697Seric printf("hash_arebuild(%s)\n", ad->ad_name); 95959697Seric 96059701Seric (void) strcpy(buf, ad->ad_name); 96159701Seric (void) strcat(buf, ".db"); 96259673Seric db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 96359673Seric if (db == NULL) 96459673Seric { 96559701Seric syserr("hash_arebuild: cannot create %s", buf); 96659673Seric return; 96759673Seric } 96859673Seric ad->ad_ndbp = db; 96959701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 97059673Seric 97159673Seric /* read and store the aliases */ 97259733Seric readaliases(ad, fp, automatic, e); 97359673Seric } 97459673Seric 97559673Seric 97659673Seric /* 97759673Seric ** HASH_ACLOSE -- add distinguished entries and close the database 97859673Seric */ 97959673Seric 98059673Seric void 98159673Seric hash_aclose(ad, e) 98259673Seric ALIASDB *ad; 98359673Seric ENVELOPE *e; 98459673Seric { 98559697Seric if (tTd(27, 9)) 98659697Seric printf("hash_aclose(%x)\n", ad->ad_flags); 98759697Seric 98859673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 98959673Seric { 99059673Seric /* write out the distinguished alias */ 99159673Seric hash_astore(ad, "@", "@", e); 99259673Seric } 99359673Seric 99459673Seric if (ad->ad_ndbp->close(ad->ad_ndbp) != 0) 99559673Seric syserr("readaliases: db close failure"); 99659673Seric } 99759673Seric 99859673Seric #endif 999292Seric /* 100059673Seric ** STAB (Symbol Table) Modules 100159673Seric */ 100259673Seric 100359673Seric 100459673Seric /* 100559673Seric ** STAB_ALOOKUP -- look up alias in symbol table 100659673Seric */ 100759673Seric 100859673Seric char * 100959673Seric stab_alookup(ad, name, e) 101059673Seric register ALIASDB *ad; 101159673Seric char *name; 101259673Seric ENVELOPE *e; 101359673Seric { 101459673Seric register STAB *s; 101559673Seric 101659697Seric if (tTd(27, 20)) 101759697Seric printf("stab_lookup(%s)\n", name); 101859697Seric 101959673Seric s = stab(name, ST_ALIAS, ST_FIND); 102059673Seric if (s != NULL) 102159673Seric return (s->s_alias); 102259673Seric return (NULL); 102359673Seric } 102459673Seric 102559673Seric 102659673Seric /* 102759673Seric ** STAB_ASTORE -- store in symtab (actually using during init, not rebuild) 102859673Seric */ 102959673Seric 103059673Seric void 103159673Seric stab_astore(ad, lhs, rhs, e) 103259673Seric register ALIASDB *ad; 103359673Seric char *lhs; 103459673Seric char *rhs; 103559673Seric ENVELOPE *e; 103659673Seric { 103759673Seric register STAB *s; 103859673Seric 103959673Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 104059673Seric s->s_alias = newstr(rhs); 104159673Seric } 104259673Seric 104359673Seric 104459673Seric /* 104559673Seric ** STAB_AINIT -- initialize (reads data file) 104659673Seric */ 104759673Seric 104859673Seric bool 104959673Seric stab_ainit(ad, e) 105059673Seric register ALIASDB *ad; 105159673Seric ENVELOPE *e; 105259673Seric { 105359673Seric FILE *af; 105459673Seric 105559697Seric if (tTd(27, 2)) 105659697Seric printf("stab_ainit(%s)\n", ad->ad_name); 105759697Seric 105859673Seric af = fopen(ad->ad_name, "r"); 105959673Seric if (af == NULL) 106059673Seric return FALSE; 106159673Seric 106259733Seric readaliases(ad, af, TRUE, e); 106359673Seric } 106459673Seric 106559673Seric 106659673Seric /* 106759673Seric ** STAB_AREBUILD -- rebuild alias file 106859673Seric */ 106959673Seric 107059673Seric void 107159733Seric stab_arebuild(ad, fp, automatic, e) 107259673Seric ALIASDB *ad; 107359673Seric FILE *fp; 107459733Seric int automatic; 107559673Seric ENVELOPE *e; 107659673Seric { 107759697Seric if (tTd(27, 2)) 107859697Seric printf("stab_arebuild(%s)\n", ad->ad_name); 107959697Seric 108059701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 108159673Seric } 108259673Seric 108359673Seric 108459673Seric /* 108559673Seric ** STAB_ACLOSE -- close symbol table (???) 108659673Seric */ 108759673Seric 108859673Seric void 108959673Seric stab_aclose(ad, e) 109059673Seric ALIASDB *ad; 109159673Seric ENVELOPE *e; 109259673Seric { 109359673Seric /* ignore it */ 109459673Seric } 109559673Seric /* 109659673Seric ** NIS Modules 109759673Seric */ 109859673Seric 109959724Seric #ifdef NIS_ALIASES 110059673Seric 110159673Seric /* 110259673Seric ** NIS_ALOOKUP 110359673Seric */ 110459673Seric 110559673Seric char * 110659673Seric nis_alookup(ad, name, e) 110759673Seric ALIASDB *ad; 110859673Seric char *name; 110959673Seric ENVELOPE *e; 111059673Seric { 111159673Seric auto char *vp; 111259673Seric auto int vsize; 1113*59756Seric int yperr; 1114*59756Seric int keylen; 111559673Seric 111659697Seric if (tTd(27, 20)) 111759697Seric printf("nis_lookup(%s)\n", name); 111859697Seric 1119*59756Seric keylen = strlen(name); 1120*59756Seric yperr = yp_match(ad->ad_domain, ad->ad_name, name, keylen, 1121*59756Seric &vp, &vsize); 1122*59756Seric if (yperr == YPERR_KEY) 1123*59756Seric yperr = yp_match(ad->ad_domain, ad->ad_name, name, ++keylen, 1124*59756Seric &vp, &vsize); 1125*59756Seric if (yperr == 0) 1126*59756Seric return vp; 1127*59756Seric 1128*59756Seric if (tTd(27, 10)) 1129*59756Seric printf("nis_alookup: yp_match(%s, %s, %s) => %s\n", 1130*59756Seric ad->ad_domain, ad->ad_name, name, yperr_string(yperr)); 1131*59756Seric if (yperr != YPERR_KEY && yperr != YPERR_BUSY) 1132*59756Seric ad->ad_flags &= ~ADF_VALID; 1133*59756Seric return NULL; 113459673Seric } 113559673Seric 113659673Seric /* 113759673Seric ** NIS_ASTORE 113859673Seric */ 113959673Seric 114059673Seric void 114159673Seric nis_astore(ad, lhs, rhs, e) 114259673Seric ALIASDB *ad; 114359673Seric char *lhs; 114459673Seric char *rhs; 114559673Seric ENVELOPE *e; 114659673Seric { 114759673Seric /* nothing */ 114859673Seric } 114959673Seric 115059673Seric /* 115159673Seric ** NIS_AINIT 115259673Seric */ 115359673Seric 115459673Seric bool 115559673Seric nis_ainit(ad, e) 115659673Seric ALIASDB *ad; 115759673Seric ENVELOPE *e; 115859673Seric { 115959673Seric register char *p; 1160*59756Seric int yperr; 1161*59756Seric auto char *vp; 1162*59756Seric auto int vsize; 116359673Seric 116459697Seric if (tTd(27, 2)) 116559697Seric printf("nis_ainit(%s)\n", ad->ad_name); 116659697Seric 116759673Seric p = strchr(ad->ad_name, '@'); 116859673Seric if (p != NULL) 116959673Seric { 117059673Seric *p++ = '\0'; 117159673Seric if (*p != '\0') 117259673Seric ad->ad_domain = p; 117359673Seric } 117459673Seric if (ad->ad_domain == NULL) 117559673Seric yp_get_default_domain(&ad->ad_domain); 117659673Seric 117759673Seric if (*ad->ad_name == '\0') 117859673Seric ad->ad_name = "mail.aliases"; 117959673Seric 1180*59756Seric yperr = yp_match(ad->ad_domain, ad->ad_name, "@", 1, 1181*59756Seric &vp, &vsize); 1182*59756Seric if (tTd(27, 10)) 1183*59756Seric printf("nis_ainit: yp_match(%s, %s) => %s\n", 1184*59756Seric ad->ad_domain, ad->ad_name, yperr_string(yperr)); 1185*59756Seric if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY) 1186*59756Seric return TRUE; 1187*59756Seric return FALSE; 118859673Seric } 118959673Seric 119059673Seric /* 119159673Seric ** NIS_AREBUILD 119259673Seric */ 119359673Seric 119459673Seric void 119559733Seric nis_arebuild(ad, fp, automatic, e) 119659673Seric ALIASDB *ad; 119759673Seric FILE *fp; 119859733Seric int automatic; 119959673Seric ENVELOPE *e; 120059673Seric { 120159697Seric if (tTd(27, 2)) 120259697Seric printf("nis_arebuild(%s)\n", ad->ad_name); 120359673Seric } 120459673Seric 120559673Seric 120659673Seric /* 120759673Seric ** NIS_ACLOSE 120859673Seric */ 120959673Seric 121059673Seric void 121159673Seric nis_aclose(ad, e) 121259673Seric ALIASDB *ad; 121359673Seric ENVELOPE *e; 121459673Seric { 121559673Seric /* nothing */ 121659673Seric } 121759673Seric 121859724Seric #endif /* NIS_ALIASES */ 121959673Seric /* 122059673Seric ** Implicit Modules 122158059Seric ** 122259673Seric ** Tries several types. For back compatibility. 122358059Seric */ 122458059Seric 122559673Seric /* 122659673Seric ** IMPL_ALOOKUP -- lookup in best open database 122759673Seric */ 122858059Seric 122959673Seric char * 123059673Seric impl_alookup(ad, name, e) 123159673Seric ALIASDB *ad; 123259673Seric char *name; 123359673Seric ENVELOPE *e; 123458059Seric { 123559697Seric if (tTd(27, 20)) 123659697Seric printf("impl_lookup(%s)\n", name); 123759697Seric 123859673Seric #ifdef NEWDB 123959673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 124059673Seric return hash_alookup(ad, name, e); 124159673Seric #endif 124259673Seric #ifdef NDBM 124359673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 124459673Seric return ndbm_alookup(ad, name, e); 124559673Seric #endif 124659673Seric return stab_alookup(ad, name, e); 124759673Seric } 124859673Seric 124959673Seric /* 125059673Seric ** IMPL_ASTORE -- store in open databases 125159673Seric */ 125259673Seric 125359673Seric void 125459673Seric impl_astore(ad, lhs, rhs, e) 125559673Seric ALIASDB *ad; 125659673Seric char *lhs; 125759673Seric char *rhs; 125859673Seric ENVELOPE *e; 125959673Seric { 126059673Seric #ifdef NEWDB 126159673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 126259673Seric hash_astore(ad, lhs, rhs, e); 126359673Seric #endif 126459673Seric #ifdef NDBM 126559673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 126659673Seric ndbm_astore(ad, lhs, rhs, e); 126759673Seric #endif 126859673Seric stab_astore(ad, lhs, rhs, e); 126959673Seric } 127059673Seric 127159673Seric /* 127259673Seric ** IMPL_AINIT -- implicit database lookup 127359673Seric */ 127459673Seric 127559673Seric bool 127659673Seric impl_ainit(ad, e) 127759673Seric ALIASDB *ad; 127859673Seric ENVELOPE *e; 127959673Seric { 128059733Seric struct stat stb; 128159733Seric 128259697Seric if (tTd(27, 2)) 128359697Seric printf("impl_ainit(%s)\n", ad->ad_name); 128459697Seric 128559733Seric if (stat(ad->ad_name, &stb) < 0) 128659733Seric { 128759733Seric /* no alias file at all */ 128859733Seric return FALSE; 128959733Seric } 129059733Seric 129159673Seric #ifdef NEWDB 129259697Seric ad->ad_flags |= ADF_IMPLHASH; 129359673Seric if (hash_ainit(ad, e)) 129458059Seric { 129559697Seric return TRUE; 129659673Seric } 129759697Seric ad->ad_flags &= ~ADF_IMPLHASH; 129859673Seric #endif 129959673Seric #ifdef NDBM 130059697Seric ad->ad_flags |= ADF_IMPLNDBM; 130159673Seric if (ndbm_ainit(ad, e)) 130259673Seric { 130359697Seric return TRUE; 130459673Seric } 130559697Seric ad->ad_flags &= ~ADF_IMPLNDBM; 130659673Seric #endif 130758059Seric 130859733Seric if (Verbose) 130959733Seric message("WARNING: cannot open alias database %s", ad->ad_name); 131059733Seric 131159673Seric if (stab_ainit(ad, e)) 131259673Seric { 131359697Seric return TRUE; 131459673Seric } 131559697Seric 131659697Seric return FALSE; 131759673Seric } 131858059Seric 131959673Seric /* 132059673Seric ** IMPL_AREBUILD -- rebuild alias database 132159673Seric */ 132258059Seric 132359673Seric void 132459733Seric impl_arebuild(ad, fp, automatic, e) 132559673Seric ALIASDB *ad; 132659673Seric FILE *fp; 132759733Seric int automatic; 132859673Seric ENVELOPE *e; 132959673Seric { 133059673Seric #ifdef NEWDB 133159673Seric DB *ndb; 133259673Seric char buf[MAXNAME]; 133359697Seric #endif 133459673Seric 133559697Seric if (tTd(27, 2)) 133659697Seric printf("impl_arebuild(%s)\n", ad->ad_name); 133759697Seric 133859697Seric #ifdef NEWDB 133959673Seric (void) strcpy(buf, ad->ad_name); 134059673Seric (void) strcat(buf, ".db"); 134159673Seric ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 134259673Seric if (ndb == NULL) 134358059Seric { 134459673Seric syserr("rebuildaliases: cannot create %s", buf); 134558059Seric } 134659673Seric else 134759673Seric { 134859673Seric ad->ad_ndbp = ndb; 134959673Seric ad->ad_flags |= ADF_IMPLHASH; 135059673Seric #if defined(NDBM) && defined(YPCOMPAT) 135159673Seric if (access("/var/yp/Makefile", R_OK) != 0) 135259673Seric #endif 135359697Seric goto readem; 135459673Seric } 135559673Seric #endif 135659673Seric 135759673Seric #ifdef NDBM 135859673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 135959673Seric if (ad->ad_dbp == NULL) 136059673Seric { 136159673Seric syserr("rebuildaliases: cannot create %s.{pag,dir}", 136259673Seric ad->ad_name); 136359673Seric } 136459673Seric else 136559673Seric { 136659673Seric ad->ad_flags |= ADF_IMPLNDBM; 136759673Seric } 136859673Seric #endif 136959673Seric 137059673Seric if (!bitset(ADF_IMPLHASH|ADF_IMPLNDBM, ad->ad_flags)) 137159673Seric return; 137259673Seric 137359697Seric readem: 137459701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 137559673Seric 137659673Seric /* read and store aliases */ 137759733Seric readaliases(ad, fp, automatic, e); 137858059Seric } 137958059Seric 138059673Seric 138159673Seric /* 138259673Seric ** IMPL_ACLOSE -- close any open database(s) 138359673Seric */ 138459673Seric 138559673Seric void 138659673Seric impl_aclose(ad, e) 138759673Seric ALIASDB *ad; 138859673Seric ENVELOPE *e; 138959673Seric { 139059673Seric #ifdef NEWDB 139159697Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 139259697Seric hash_aclose(ad, e); 139359673Seric #endif 139459673Seric 139559673Seric #ifdef NDBM 139659697Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 139759697Seric ndbm_aclose(ad, e); 139859673Seric #endif 139959673Seric } 140058059Seric /* 140159673Seric ** SETUPALIASES -- set up aliases classes 140259673Seric */ 140359673Seric 140459673Seric #ifdef NEWDB 140559673Seric ALIASCLASS HashAClass = 140659673Seric { 140759673Seric "hash", hash_alookup, hash_astore, 140859673Seric hash_ainit, hash_arebuild, hash_aclose, 140959673Seric ACF_BUILDABLE 141059673Seric }; 141159673Seric #endif 141259673Seric 141359673Seric #ifdef NDBM 141459673Seric ALIASCLASS DbmAClass = 141559673Seric { 141659673Seric "dbm", ndbm_alookup, ndbm_astore, 141759673Seric ndbm_ainit, ndbm_arebuild, ndbm_aclose, 141859673Seric ACF_BUILDABLE 141959673Seric }; 142059673Seric #endif 142159673Seric 142259724Seric #ifdef NIS_ALIASES 142359673Seric ALIASCLASS NisAClass = 142459673Seric { 142559673Seric "nis", nis_alookup, nis_astore, 142659673Seric nis_ainit, nis_arebuild, nis_aclose, 142759673Seric 0 142859673Seric }; 142959673Seric #endif 143059673Seric 143159673Seric ALIASCLASS StabAClass = 143259673Seric { 143359673Seric "stab", stab_alookup, stab_astore, 143459673Seric stab_ainit, stab_arebuild, stab_aclose, 143559673Seric 0 143659673Seric }; 143759673Seric 143859673Seric ALIASCLASS ImplAClass = 143959673Seric { 144059673Seric "implicit", impl_alookup, impl_astore, 144159673Seric impl_ainit, impl_arebuild, impl_aclose, 144259673Seric ACF_BUILDABLE 144359673Seric }; 144459673Seric 144559673Seric setupaliases() 144659673Seric { 144759673Seric register STAB *s; 144859673Seric 144959673Seric #ifdef NEWDB 145059673Seric s = stab("hash", ST_ALIASCLASS, ST_ENTER); 145159673Seric s->s_aliasclass = &HashAClass; 145259673Seric #endif 145359673Seric 145459673Seric #ifdef NDBM 145559673Seric s = stab("dbm", ST_ALIASCLASS, ST_ENTER); 145659673Seric s->s_aliasclass = &DbmAClass; 145759673Seric #endif 145859673Seric 145959724Seric #ifdef NIS_ALIASES 146059673Seric s = stab("nis", ST_ALIASCLASS, ST_ENTER); 146159673Seric s->s_aliasclass = &NisAClass; 146259673Seric #endif 146359673Seric 146459673Seric #if !defined(NEWDB) && !defined(NDBM) 146559673Seric s = stab("stab", ST_ALIASCLASS, ST_ENTER); 146659673Seric s->s_aliasclass = &StabAClass; 146759673Seric #endif 146859673Seric 146959673Seric s = stab("implicit", ST_ALIASCLASS, ST_ENTER); 147059673Seric s->s_aliasclass = &ImplAClass; 147159673Seric } 147259673Seric /* 1473292Seric ** FORWARD -- Try to forward mail 1474292Seric ** 1475292Seric ** This is similar but not identical to aliasing. 1476292Seric ** 1477292Seric ** Parameters: 14784314Seric ** user -- the name of the user who's mail we would like 14794314Seric ** to forward to. It must have been verified -- 14804314Seric ** i.e., the q_home field must have been filled 14814314Seric ** in. 14824999Seric ** sendq -- a pointer to the head of the send queue to 14834999Seric ** put this user's aliases in. 1484292Seric ** 1485292Seric ** Returns: 14864098Seric ** none. 1487292Seric ** 1488292Seric ** Side Effects: 14893185Seric ** New names are added to send queues. 1490292Seric */ 1491292Seric 149255012Seric forward(user, sendq, e) 14932966Seric ADDRESS *user; 14944999Seric ADDRESS **sendq; 149555012Seric register ENVELOPE *e; 1496292Seric { 149757136Seric char *pp; 149857136Seric char *ep; 14994069Seric 15007671Seric if (tTd(27, 1)) 15014098Seric printf("forward(%s)\n", user->q_paddr); 15024098Seric 15034594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 15044098Seric return; 15054314Seric if (user->q_home == NULL) 150658059Seric { 150758151Seric syserr("554 forward: no home"); 150858059Seric user->q_home = "/nosuchdirectory"; 150958059Seric } 15104069Seric 15114069Seric /* good address -- look for .forward file in home */ 151255012Seric define('z', user->q_home, e); 151357136Seric define('u', user->q_user, e); 151457136Seric define('h', user->q_host, e); 151557136Seric if (ForwardPath == NULL) 151658050Seric ForwardPath = newstr("\201z/.forward"); 151757136Seric 151857136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 151957136Seric { 152058247Seric int err; 152157232Seric char buf[MAXPATHLEN+1]; 152257136Seric 152357136Seric ep = strchr(pp, ':'); 152457136Seric if (ep != NULL) 152557136Seric *ep = '\0'; 152657136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 152757136Seric if (ep != NULL) 152857136Seric *ep++ = ':'; 152957136Seric if (tTd(27, 3)) 153057136Seric printf("forward: trying %s\n", buf); 153158247Seric err = include(buf, TRUE, user, sendq, e); 153258247Seric if (err == 0) 153357136Seric break; 153458247Seric if (transienterror(err)) 153558247Seric { 153658247Seric /* we have to suspend this message */ 153759563Seric if (tTd(27, 2)) 153859563Seric printf("forward: transient error on %s\n", buf); 153959563Seric #ifdef LOG 154059563Seric if (LogLevel > 2) 154159624Seric syslog(LOG_ERR, "%s: forward %s: transient error: %s", 154259624Seric e->e_id, buf, errstring(err)); 154359563Seric #endif 154459611Seric message("%s: %s: message queued", buf, errstring(err)); 154558247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 154658247Seric return; 154758247Seric } 154857136Seric } 1549292Seric } 1550