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 2159673Seric # ifdef NIS 2259673Seric # include <rpcsvc/ypclnt.h> 2359673Seric # endif 2456766Seric 2533728Sbostic #ifndef lint 2651756Seric #ifdef NEWDB 2757736Seric #ifdef NDBM 28*59701Seric static char sccsid[] = "@(#)alias.c 6.41 (Berkeley) 05/03/93 (with NEWDB and NDBM)"; 2951756Seric #else 30*59701Seric static char sccsid[] = "@(#)alias.c 6.41 (Berkeley) 05/03/93 (with NEWDB)"; 3157736Seric #endif 3257736Seric #else 3356845Seric #ifdef NDBM 34*59701Seric static char sccsid[] = "@(#)alias.c 6.41 (Berkeley) 05/03/93 (with NDBM)"; 3533728Sbostic #else 36*59701Seric static char sccsid[] = "@(#)alias.c 6.41 (Berkeley) 05/03/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 */ 7459673Seric void (*ac_rebuild)__P((ALIASDB *, FILE *, 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) 28359673Seric syserr("Unknown alias class %s", class); 28459673Seric else 28559673Seric { 28659673Seric ad->ad_class = s->s_aliasclass; 28759673Seric ad->ad_name = newstr(spec); 28859673Seric NAliasDBs++; 28959673Seric } 2905701Seric } 2915701Seric /* 2924098Seric ** INITALIASES -- initialize for aliasing 2934098Seric ** 29456845Seric ** Very different depending on whether we are running NDBM or not. 2954098Seric ** 2964098Seric ** Parameters: 29759673Seric ** rebuild -- if TRUE, this rebuilds the cached versions. 29859673Seric ** e -- current envelope. 2994098Seric ** 3004098Seric ** Returns: 3014098Seric ** none. 3024098Seric ** 3034098Seric ** Side Effects: 3044098Seric ** initializes aliases: 30556845Seric ** if NDBM: opens the database. 30656845Seric ** if ~NDBM: reads the aliases into the symbol table. 3074098Seric */ 3084098Seric 30940559Sbostic # define DBMMODE 0644 3104157Seric 31159673Seric initaliases(rebuild, e) 31259673Seric bool rebuild; 31355012Seric register ENVELOPE *e; 3144098Seric { 31559673Seric int dbno; 31659673Seric register ALIASDB *ad; 3174322Seric 31859673Seric for (dbno = 0; dbno < NAliasDBs; dbno++) 3198437Seric { 32059673Seric ad = &AliasDB[dbno]; 32159697Seric 32259697Seric if (tTd(27, 2)) 32359697Seric printf("initaliases(%s:%s)\n", 32459697Seric ad->ad_class->ac_name, ad->ad_name); 32559697Seric 32659673Seric if (rebuild) 32750576Seric { 32859673Seric rebuildaliases(ad, FALSE, e); 32950576Seric } 33059673Seric else 33157249Seric { 33259697Seric if (ad->ad_class->ac_init(ad, e)) 33359697Seric ad->ad_flags |= ADF_VALID; 33457249Seric } 33550575Seric } 33659673Seric } 33759673Seric /* 33859673Seric ** ALIASWAIT -- wait for distinguished @:@ token to appear. 33959673Seric ** 34059673Seric ** This can decide to reopen or rebuild the alias file 34159673Seric */ 34259673Seric 34359673Seric aliaswait(ad, ext, e) 34459673Seric ALIASDB *ad; 34559673Seric char *ext; 34659673Seric ENVELOPE *e; 34759673Seric { 34859673Seric int atcnt; 34959673Seric time_t mtime; 35059673Seric struct stat stb; 35159673Seric char buf[MAXNAME]; 35259673Seric 35359697Seric if (tTd(27, 3)) 35459697Seric printf("aliaswait\n"); 35559697Seric 35617471Seric atcnt = SafeAlias * 2; 35717471Seric if (atcnt > 0) 35817471Seric { 35959673Seric while (atcnt-- >= 0 && 36059673Seric ad->ad_class->ac_lookup(ad, "@", e) == NULL) 36125689Seric { 36225689Seric /* 36359673Seric ** Close and re-open the alias database in case 36459673Seric ** the one is mv'ed instead of cp'ed in. 36525689Seric */ 36625689Seric 36759697Seric if (tTd(27, 2)) 36859697Seric printf("aliaswait: sleeping\n"); 36959697Seric 37059673Seric ad->ad_class->ac_close(ad, e); 37117471Seric sleep(30); 37259673Seric ad->ad_class->ac_init(ad, e); 37325689Seric } 37417471Seric } 3758437Seric 37659673Seric /* see if we need to go into auto-rebuild mode */ 37759673Seric if (stat(ad->ad_name, &stb) < 0) 37859673Seric return; 37959673Seric mtime = stb.st_mtime; 38059673Seric (void) strcpy(buf, ad->ad_name); 38159673Seric (void) strcat(buf, ext); 38259673Seric if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || atcnt < 0) 3834322Seric { 38459673Seric /* database is out of date */ 38540559Sbostic if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid()) 3864322Seric { 38759673Seric message("auto-rebuilding alias database %s", 38859673Seric ad->ad_name); 38959673Seric rebuildaliases(ad, TRUE, e); 3904322Seric } 3914322Seric else 3924322Seric { 39319039Seric #ifdef LOG 39458020Seric if (LogLevel > 3) 39559673Seric syslog(LOG_INFO, "alias database %s out of date", 39659673Seric ad->ad_name); 39756795Seric #endif /* LOG */ 39859673Seric message("Warning: alias database %s out of date", 39959673Seric ad->ad_name); 4004322Seric } 4014322Seric } 40259673Seric } 40359673Seric /* 40459673Seric ** REBUILDALIASES -- rebuild the alias database. 40559673Seric ** 40659673Seric ** Parameters: 40759673Seric ** ad -- the database to rebuild. 40859673Seric ** automatic -- set if this was automatically generated. 40959673Seric ** e -- current envelope. 41059673Seric ** 41159673Seric ** Returns: 41259673Seric ** none. 41359673Seric ** 41459673Seric ** Side Effects: 41559673Seric ** Reads the text version of the database, builds the 41659673Seric ** DBM or DB version. 41759673Seric */ 4184322Seric 41959673Seric rebuildaliases(ad, automatic, e) 42059673Seric register ALIASDB *ad; 42159673Seric bool automatic; 42259673Seric register ENVELOPE *e; 42359673Seric { 42459673Seric FILE *af; 42559673Seric void (*oldsigint)(); 4264322Seric 42759673Seric if (!bitset(ACF_BUILDABLE, ad->ad_class->ac_flags)) 42859673Seric return; 4294322Seric 43059673Seric #ifdef LOG 43159673Seric if (LogLevel > 7) 4328437Seric { 43359673Seric extern char *username(); 43425522Seric 43559673Seric syslog(LOG_NOTICE, "alias database %s %srebuilt by %s", 43659673Seric ad->ad_name, automatic ? "auto" : "", username()); 43759673Seric } 43856795Seric #endif /* LOG */ 43959673Seric 44059673Seric /* try to lock the source file */ 44159673Seric if ((af = fopen(ad->ad_name, "r+")) == NULL) 44259673Seric { 44359673Seric syserr("554 Can't open %s", ad->ad_name); 44459673Seric printf("Can't open %s\n", ad->ad_name); 44559673Seric errno = 0; 44659673Seric return; 4478437Seric } 44859673Seric 44959673Seric /* see if someone else is rebuilding the alias file */ 45059673Seric if (!lockfile(fileno(af), ad->ad_name, LOCK_EX|LOCK_NB)) 45159673Seric { 45259673Seric /* yes, they are -- wait until done */ 45359673Seric message("Alias file %s is already being rebuilt", 45459673Seric ad->ad_name); 45559673Seric if (OpMode != MD_INITALIAS) 45659673Seric { 45759673Seric /* wait for other rebuild to complete */ 45859673Seric (void) lockfile(fileno(af), ad->ad_name, 45959673Seric LOCK_EX); 46059673Seric } 46159673Seric (void) fclose(af); 46259673Seric errno = 0; 46359673Seric return; 46459673Seric } 46559673Seric 46659673Seric oldsigint = signal(SIGINT, SIG_IGN); 46759673Seric 46859673Seric ad->ad_class->ac_rebuild(ad, af, e); 46959673Seric 47059673Seric /* close the file, thus releasing locks */ 47159673Seric fclose(af); 47259673Seric 47359673Seric /* add distinguished entries and close the database */ 474*59701Seric if (bitset(ADF_VALID, ad->ad_flags)) 475*59701Seric ad->ad_class->ac_close(ad, e); 47659673Seric 47759673Seric /* restore the old signal */ 47859673Seric (void) signal(SIGINT, oldsigint); 4794157Seric } 4804157Seric /* 4814157Seric ** READALIASES -- read and process the alias file. 4824157Seric ** 4834157Seric ** This routine implements the part of initaliases that occurs 4844157Seric ** when we are not going to use the DBM stuff. 4854157Seric ** 4864157Seric ** Parameters: 48759673Seric ** ad -- the alias database descriptor. 48859673Seric ** af -- file to read the aliases from. 48959673Seric ** e -- the current alias file. 4904157Seric ** 4914157Seric ** Returns: 4924157Seric ** none. 4934157Seric ** 4944157Seric ** Side Effects: 4954157Seric ** Reads aliasfile into the symbol table. 4964157Seric ** Optionally, builds the .dir & .pag files. 4974157Seric */ 4984157Seric 4994157Seric static 50059673Seric readaliases(ad, af, e) 50159673Seric register ALIASDB *ad; 50259673Seric FILE *af; 50355012Seric register ENVELOPE *e; 5044157Seric { 5054098Seric register char *p; 5064098Seric char *rhs; 5074098Seric bool skipping; 50859673Seric long naliases, bytes, longest; 5094098Seric ADDRESS al, bl; 5104106Seric register STAB *s; 5119368Seric char line[BUFSIZ]; 5124098Seric 5134314Seric /* 5144314Seric ** Read and interpret lines 5154314Seric */ 5164314Seric 51759673Seric FileName = ad->ad_name; 5189368Seric LineNumber = 0; 5194322Seric naliases = bytes = longest = 0; 5204098Seric skipping = FALSE; 5214098Seric while (fgets(line, sizeof (line), af) != NULL) 5224098Seric { 5234322Seric int lhssize, rhssize; 5244322Seric 5259368Seric LineNumber++; 52656795Seric p = strchr(line, '\n'); 52725278Seric if (p != NULL) 52825278Seric *p = '\0'; 5294098Seric switch (line[0]) 5304098Seric { 5314098Seric case '#': 5324098Seric case '\0': 5334098Seric skipping = FALSE; 5344098Seric continue; 5354065Seric 5364098Seric case ' ': 5374098Seric case '\t': 5384098Seric if (!skipping) 53958151Seric syserr("554 Non-continuation line starts with space"); 5404098Seric skipping = TRUE; 5414097Seric continue; 5424098Seric } 5434098Seric skipping = FALSE; 5441874Seric 5454314Seric /* 5464314Seric ** Process the LHS 54757736Seric ** Find the colon separator, and parse the address. 54816898Seric ** It should resolve to a local name -- this will 54916898Seric ** be checked later (we want to optionally do 55016898Seric ** parsing of the RHS first to maximize error 55116898Seric ** detection). 5524314Seric */ 5534314Seric 5544098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5554097Seric continue; 55616898Seric if (*p++ != ':') 5574098Seric { 55858151Seric syserr("554 missing colon"); 5594097Seric continue; 5604098Seric } 56158333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 5624098Seric { 56358151Seric syserr("554 illegal alias name"); 56416898Seric continue; 5654098Seric } 5664314Seric 5674314Seric /* 5684314Seric ** Process the RHS. 5694314Seric ** 'al' is the internal form of the LHS address. 5704314Seric ** 'p' points to the text of the RHS. 5714314Seric */ 5724314Seric 57358914Seric while (isascii(*p) && isspace(*p)) 57458914Seric p++; 5754098Seric rhs = p; 5764098Seric for (;;) 5774098Seric { 5784098Seric register char c; 57958662Seric register char *nlp; 5801515Seric 58158662Seric nlp = &p[strlen(p)]; 58258662Seric if (nlp[-1] == '\n') 58358662Seric *--nlp = '\0'; 58458662Seric 58559673Seric if (CheckAliases) 5864098Seric { 5874157Seric /* do parsing & compression of addresses */ 58825278Seric while (*p != '\0') 5894098Seric { 59058333Seric auto char *delimptr; 59125278Seric 59258050Seric while ((isascii(*p) && isspace(*p)) || 59358050Seric *p == ',') 5944157Seric p++; 59525278Seric if (*p == '\0') 59625278Seric break; 59758333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 59858151Seric usrerr("553 %s... bad address", p); 59958333Seric p = delimptr; 6004098Seric } 6014098Seric } 6024157Seric else 60315769Seric { 60458662Seric p = nlp; 60515769Seric } 6061515Seric 6074098Seric /* see if there should be a continuation line */ 6084106Seric c = fgetc(af); 6094106Seric if (!feof(af)) 6104314Seric (void) ungetc(c, af); 6114106Seric if (c != ' ' && c != '\t') 6124098Seric break; 6134098Seric 6144098Seric /* read continuation line */ 6154098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6164098Seric break; 6179368Seric LineNumber++; 61857135Seric 61957135Seric /* check for line overflow */ 62057135Seric if (strchr(p, '\n') == NULL) 62157135Seric { 62258151Seric usrerr("554 alias too long"); 62357135Seric break; 62457135Seric } 6254098Seric } 62616898Seric if (al.q_mailer != LocalMailer) 62716898Seric { 62858151Seric syserr("554 cannot alias non-local names"); 62916898Seric continue; 63016898Seric } 6314314Seric 6324314Seric /* 6334314Seric ** Insert alias into symbol table or DBM file 6344314Seric */ 6354314Seric 63657381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 63757381Seric makelower(al.q_user); 6384322Seric 63959673Seric lhssize = strlen(al.q_user); 64059673Seric rhssize = strlen(rhs); 64159673Seric ad->ad_class->ac_store(ad, al.q_user, rhs, e); 6424157Seric 64359673Seric if (al.q_paddr != NULL) 64459673Seric free(al.q_paddr); 64559673Seric if (al.q_host != NULL) 64659673Seric free(al.q_host); 64759673Seric if (al.q_user != NULL) 64859673Seric free(al.q_user); 6494322Seric 6504322Seric /* statistics */ 6514322Seric naliases++; 6524322Seric bytes += lhssize + rhssize; 6534322Seric if (rhssize > longest) 6544322Seric longest = rhssize; 6551515Seric } 65619784Seric 65759673Seric e->e_to = NULL; 65859673Seric FileName = NULL; 65959673Seric message("%s: %d aliases, longest %d bytes, %d bytes total", 66059673Seric ad->ad_name, naliases, longest, bytes); 66159673Seric # ifdef LOG 66259673Seric if (LogLevel > 7) 66359673Seric syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total", 66459673Seric ad->ad_name, naliases, longest, bytes); 66559673Seric # endif /* LOG */ 66659673Seric } 66759673Seric /* 66859673Seric ** NDBM modules 66959673Seric */ 67059673Seric 67159673Seric #ifdef NDBM 67259673Seric 67359673Seric /* 67459673Seric ** NDBM_ALOOKUP -- look up alias in ndbm file 67559673Seric */ 67659673Seric 67759673Seric char * 67859673Seric ndbm_alookup(ad, name, e) 67959673Seric register ALIASDB *ad; 68059673Seric char *name; 68159673Seric ENVELOPE *e; 68259673Seric { 68359673Seric int i; 68459673Seric datum rhs, lhs; 68559673Seric char keybuf[MAXNAME + 1]; 68659673Seric 68759697Seric if (tTd(27, 20)) 68859697Seric printf("ndbm_lookup(%s)\n", name); 68959697Seric 69059673Seric /* create a key for fetch */ 69159673Seric i = strlen(name) + 1; 69259673Seric if (i > sizeof keybuf) 69359673Seric i = sizeof keybuf; 69459673Seric bcopy(name, keybuf, i); 69559673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 69659673Seric makelower(keybuf); 69759673Seric 69859673Seric lhs.dsize = i; 69959673Seric lhs.dptr = keybuf; 70059673Seric rhs = dbm_fetch((DBM *) ad->ad_dbp, lhs); 70159673Seric return (rhs.dptr); 70259673Seric } 70359673Seric 70459673Seric 70559673Seric /* 70659673Seric ** NDBM_ASTORE -- store a datum in the database 70759673Seric */ 70859673Seric 70959673Seric void 71059673Seric ndbm_astore(ad, lhs, rhs, e) 71159673Seric register ALIASDB *ad; 71259673Seric char *lhs; 71359673Seric char *rhs; 71459673Seric ENVELOPE *e; 71559673Seric { 71659673Seric datum key; 71759673Seric datum data; 71859673Seric int stat; 71959673Seric 72059697Seric key.dsize = strlen(lhs) + 1; 72159673Seric key.dptr = lhs; 72259673Seric 72359697Seric data.dsize = strlen(rhs) + 1; 72459673Seric data.dptr = rhs; 72559673Seric 72659673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_INSERT); 72759673Seric if (stat > 0) 72819784Seric { 72959673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 73059673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_REPLACE); 73159673Seric } 73259673Seric if (stat != 0) 73359673Seric syserr("readaliases: dbm put (%s)", lhs); 73459673Seric } 73519784Seric 73659673Seric 73759673Seric /* 73859673Seric ** NDBM_AINIT -- initialize DBM database 73959673Seric */ 74059673Seric 74159673Seric bool 74259673Seric ndbm_ainit(ad, e) 74359673Seric register ALIASDB *ad; 74459673Seric ENVELOPE *e; 74559673Seric { 74659673Seric char buf[MAXNAME]; 74759673Seric 74859697Seric if (tTd(27, 2)) 74959697Seric printf("ndbm_ainit(%s)\n", ad->ad_name); 75059697Seric 75159673Seric /* open the database */ 75259673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDONLY, DBMMODE); 75359673Seric if (ad->ad_dbp == NULL) 75459673Seric return FALSE; 75559673Seric 75659673Seric /* wait for @:@ to appear */ 75759673Seric aliaswait(ad, ".pag", e); 75859673Seric 75959673Seric return TRUE; 76059673Seric } 76159673Seric 76259673Seric 76359673Seric /* 76459673Seric ** NDBM_AREBUILD -- rebuild hash database 76559673Seric */ 76659673Seric 76759673Seric void 76859673Seric ndbm_arebuild(ad, fp, e) 76959673Seric register ALIASDB *ad; 77059673Seric FILE *fp; 77159673Seric ENVELOPE *e; 77259673Seric { 77359673Seric register DBM *db; 77459673Seric int i; 77559673Seric char buf[MAXNAME]; 77659673Seric 77759697Seric if (tTd(27, 2)) 77859697Seric printf("ndbm_arebuild(%s)\n", ad->ad_name); 77959697Seric 78059673Seric db = dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 78159673Seric if (db == NULL) 78259673Seric { 783*59701Seric syserr("ndbm_arebuild: cannot create %s", buf); 78459673Seric return; 78559673Seric } 78659673Seric ad->ad_dbp = (void *) db; 787*59701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 78859673Seric 78959673Seric /* read and store the aliases */ 79059673Seric readaliases(ad, fp, e); 79159673Seric } 79259673Seric 79359673Seric /* 79459673Seric ** NDBM_ACLOSE -- close the database 79559673Seric */ 79659673Seric 79759673Seric void 79859673Seric ndbm_aclose(ad, e) 79959673Seric register ALIASDB *ad; 80059673Seric ENVELOPE *e; 80159673Seric { 80259673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 80359673Seric { 80458059Seric #ifdef YPCOMPAT 80559673Seric char buf[200]; 80658846Seric 80759673Seric (void) sprintf(buf, "%010ld", curtime()); 80859673Seric ndbm_astore(ad, "YP_LAST_MODIFIED", buf, e); 80959673Seric 81059673Seric (void) myhostname(buf, sizeof buf); 81159673Seric ndbm_astore(ad, "YP_MASTER_NAME", buf, e); 81258059Seric #endif 81319784Seric 81459673Seric /* write out the distinguished alias */ 81559673Seric ndbm_astore(ad, "@", "@", e); 81619784Seric } 81759673Seric dbm_close((DBM *) ad->ad_dbp); 81859673Seric } 81919784Seric 82059673Seric #endif 82159673Seric /* 82259673Seric ** HASH (NEWDB) Modules 82359673Seric */ 82459673Seric 82559673Seric #ifdef NEWDB 82659673Seric 82759673Seric /* 82859673Seric ** HASH_ALOOKUP -- look up alias in hash file 82959673Seric */ 83059673Seric 83159673Seric char * 83259673Seric hash_alookup(ad, name, e) 83359673Seric register ALIASDB *ad; 83459673Seric char *name; 83559673Seric ENVELOPE *e; 83659673Seric { 83759673Seric int i; 83859673Seric DBT rhs, lhs; 83959673Seric int s; 84059673Seric char keybuf[MAXNAME + 1]; 84159673Seric 84259697Seric if (tTd(27, 20)) 84359697Seric printf("hash_alookup(%s)\n", name); 84459697Seric 84559673Seric /* create a key for fetch */ 84659673Seric i = strlen(name) + 1; 84759673Seric if (i > sizeof keybuf) 84859673Seric i = sizeof keybuf; 84959673Seric bcopy(name, keybuf, i); 85059673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 85159673Seric makelower(keybuf); 85259673Seric 85359673Seric lhs.size = i; 85459673Seric lhs.data = keybuf; 85559673Seric i = ad->ad_ndbp->get(ad->ad_ndbp, &lhs, &rhs, 0); 85659673Seric if (i == 0) 85759673Seric return (rhs.data); 85859673Seric return (NULL); 859292Seric } 86059673Seric 86159673Seric 86259673Seric /* 86359673Seric ** HASH_ASTORE -- store a datum in the database 86459673Seric */ 86559673Seric 86659673Seric void 86759673Seric hash_astore(ad, lhs, rhs, e) 86859673Seric register ALIASDB *ad; 86959673Seric char *lhs; 87059673Seric char *rhs; 87159673Seric ENVELOPE *e; 87259673Seric { 87359673Seric int stat; 87459673Seric DBT key; 87559673Seric DBT data; 87659673Seric 87759697Seric if (tTd(27, 20)) 87859697Seric printf("hash_astore(%s, %s)\n", lhs, rhs); 87959697Seric 88059697Seric key.size = strlen(lhs) + 1; 88159673Seric key.data = lhs; 88259673Seric 88359697Seric data.size = strlen(rhs) + 1; 88459673Seric data.data = rhs; 88559673Seric 88659673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, R_NOOVERWRITE); 88759673Seric if (stat > 0) 88859673Seric { 88959673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 89059673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, 0); 89159673Seric } 89259673Seric if (stat != 0) 89359673Seric syserr("readaliases: db put (%s)", lhs); 89459673Seric } 89559673Seric 89659673Seric 89759673Seric /* 89859673Seric ** HASH_AINIT -- initialize hash database 89959673Seric */ 90059673Seric 90159673Seric bool 90259673Seric hash_ainit(ad, e) 90359673Seric register ALIASDB *ad; 90459673Seric ENVELOPE *e; 90559673Seric { 90659673Seric char buf[MAXNAME]; 90759673Seric 90859697Seric if (tTd(27, 2)) 90959697Seric printf("hash_ainit(%s)\n", ad->ad_name); 91059697Seric 91159673Seric /* open the database */ 91259673Seric (void) strcpy(buf, ad->ad_name); 91359673Seric (void) strcat(buf, ".db"); 91459673Seric ad->ad_ndbp = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 91559673Seric if (ad->ad_ndbp == NULL) 91659673Seric return FALSE; 91759673Seric 91859673Seric /* wait for @:@ to appear */ 91959673Seric aliaswait(ad, ".db", e); 92059673Seric return TRUE; 92159673Seric } 92259673Seric 92359673Seric 92459673Seric /* 92559673Seric ** HASH_AREBUILD -- rebuild hash database 92659673Seric */ 92759673Seric 92859673Seric void 92959673Seric hash_arebuild(ad, fp, e) 93059673Seric register ALIASDB *ad; 93159673Seric FILE *fp; 93259673Seric ENVELOPE *e; 93359673Seric { 93459673Seric register DB *db; 93559673Seric char buf[MAXNAME]; 93659673Seric 93759697Seric if (tTd(27, 2)) 93859697Seric printf("hash_arebuild(%s)\n", ad->ad_name); 93959697Seric 940*59701Seric (void) strcpy(buf, ad->ad_name); 941*59701Seric (void) strcat(buf, ".db"); 94259673Seric db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 94359673Seric if (db == NULL) 94459673Seric { 945*59701Seric syserr("hash_arebuild: cannot create %s", buf); 94659673Seric return; 94759673Seric } 94859673Seric ad->ad_ndbp = db; 949*59701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 95059673Seric 95159673Seric /* read and store the aliases */ 95259673Seric readaliases(ad, fp, e); 95359673Seric } 95459673Seric 95559673Seric 95659673Seric /* 95759673Seric ** HASH_ACLOSE -- add distinguished entries and close the database 95859673Seric */ 95959673Seric 96059673Seric void 96159673Seric hash_aclose(ad, e) 96259673Seric ALIASDB *ad; 96359673Seric ENVELOPE *e; 96459673Seric { 96559697Seric if (tTd(27, 9)) 96659697Seric printf("hash_aclose(%x)\n", ad->ad_flags); 96759697Seric 96859673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 96959673Seric { 97059673Seric /* write out the distinguished alias */ 97159673Seric hash_astore(ad, "@", "@", e); 97259673Seric } 97359673Seric 97459673Seric if (ad->ad_ndbp->close(ad->ad_ndbp) != 0) 97559673Seric syserr("readaliases: db close failure"); 97659673Seric } 97759673Seric 97859673Seric #endif 979292Seric /* 98059673Seric ** STAB (Symbol Table) Modules 98159673Seric */ 98259673Seric 98359673Seric 98459673Seric /* 98559673Seric ** STAB_ALOOKUP -- look up alias in symbol table 98659673Seric */ 98759673Seric 98859673Seric char * 98959673Seric stab_alookup(ad, name, e) 99059673Seric register ALIASDB *ad; 99159673Seric char *name; 99259673Seric ENVELOPE *e; 99359673Seric { 99459673Seric register STAB *s; 99559673Seric 99659697Seric if (tTd(27, 20)) 99759697Seric printf("stab_lookup(%s)\n", name); 99859697Seric 99959673Seric s = stab(name, ST_ALIAS, ST_FIND); 100059673Seric if (s != NULL) 100159673Seric return (s->s_alias); 100259673Seric return (NULL); 100359673Seric } 100459673Seric 100559673Seric 100659673Seric /* 100759673Seric ** STAB_ASTORE -- store in symtab (actually using during init, not rebuild) 100859673Seric */ 100959673Seric 101059673Seric void 101159673Seric stab_astore(ad, lhs, rhs, e) 101259673Seric register ALIASDB *ad; 101359673Seric char *lhs; 101459673Seric char *rhs; 101559673Seric ENVELOPE *e; 101659673Seric { 101759673Seric register STAB *s; 101859673Seric 101959673Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 102059673Seric s->s_alias = newstr(rhs); 102159673Seric } 102259673Seric 102359673Seric 102459673Seric /* 102559673Seric ** STAB_AINIT -- initialize (reads data file) 102659673Seric */ 102759673Seric 102859673Seric bool 102959673Seric stab_ainit(ad, e) 103059673Seric register ALIASDB *ad; 103159673Seric ENVELOPE *e; 103259673Seric { 103359673Seric FILE *af; 103459673Seric 103559697Seric if (tTd(27, 2)) 103659697Seric printf("stab_ainit(%s)\n", ad->ad_name); 103759697Seric 103859673Seric af = fopen(ad->ad_name, "r"); 103959673Seric if (af == NULL) 104059673Seric { 104159673Seric syserr("554 Can't open %s", ad->ad_name); 104259673Seric errno = 0; 104359673Seric return FALSE; 104459673Seric } 104559673Seric 104659673Seric readaliases(ad, af, e); 104759673Seric } 104859673Seric 104959673Seric 105059673Seric /* 105159673Seric ** STAB_AREBUILD -- rebuild alias file 105259673Seric */ 105359673Seric 105459673Seric void 105559673Seric stab_arebuild(ad, fp, e) 105659673Seric ALIASDB *ad; 105759673Seric FILE *fp; 105859673Seric ENVELOPE *e; 105959673Seric { 106059697Seric if (tTd(27, 2)) 106159697Seric printf("stab_arebuild(%s)\n", ad->ad_name); 106259697Seric 1063*59701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 106459673Seric } 106559673Seric 106659673Seric 106759673Seric /* 106859673Seric ** STAB_ACLOSE -- close symbol table (???) 106959673Seric */ 107059673Seric 107159673Seric void 107259673Seric stab_aclose(ad, e) 107359673Seric ALIASDB *ad; 107459673Seric ENVELOPE *e; 107559673Seric { 107659673Seric /* ignore it */ 107759673Seric } 107859673Seric /* 107959673Seric ** NIS Modules 108059673Seric */ 108159673Seric 108259673Seric #ifdef NIS 108359673Seric 108459673Seric /* 108559673Seric ** NIS_ALOOKUP 108659673Seric */ 108759673Seric 108859673Seric char * 108959673Seric nis_alookup(ad, name, e) 109059673Seric ALIASDB *ad; 109159673Seric char *name; 109259673Seric ENVELOPE *e; 109359673Seric { 109459673Seric auto char *vp; 109559673Seric auto int vsize; 109659673Seric 109759697Seric if (tTd(27, 20)) 109859697Seric printf("nis_lookup(%s)\n", name); 109959697Seric 110059673Seric if (ypmatch(ad->ad_domain, ad->ad_name, name, strlen(name), 110159673Seric &vp, &vsize) != 0) 110259673Seric return NULL; 110359673Seric return vp; 110459673Seric } 110559673Seric 110659673Seric /* 110759673Seric ** NIS_ASTORE 110859673Seric */ 110959673Seric 111059673Seric void 111159673Seric nis_astore(ad, lhs, rhs, e) 111259673Seric ALIASDB *ad; 111359673Seric char *lhs; 111459673Seric char *rhs; 111559673Seric ENVELOPE *e; 111659673Seric { 111759673Seric /* nothing */ 111859673Seric } 111959673Seric 112059673Seric /* 112159673Seric ** NIS_AINIT 112259673Seric */ 112359673Seric 112459673Seric bool 112559673Seric nis_ainit(ad, e) 112659673Seric ALIASDB *ad; 112759673Seric ENVELOPE *e; 112859673Seric { 112959673Seric register char *p; 113059673Seric auto char *ypmaster; 113159673Seric 113259697Seric if (tTd(27, 2)) 113359697Seric printf("nis_ainit(%s)\n", ad->ad_name); 113459697Seric 113559673Seric p = strchr(ad->ad_name, '@'); 113659673Seric if (p != NULL) 113759673Seric { 113859673Seric *p++ = '\0'; 113959673Seric if (*p != '\0') 114059673Seric ad->ad_domain = p; 114159673Seric } 114259673Seric if (ad->ad_domain == NULL) 114359673Seric yp_get_default_domain(&ad->ad_domain); 114459673Seric 114559673Seric if (*ad->ad_name == '\0') 114659673Seric ad->ad_name = "mail.aliases"; 114759673Seric 114859673Seric yperr = yp_master(ad->ad_domain, ad->ad_name, &ypmaster); 114959673Seric return (yperr == 0); 115059673Seric } 115159673Seric 115259673Seric /* 115359673Seric ** NIS_AREBUILD 115459673Seric */ 115559673Seric 115659673Seric void 115759673Seric nis_arebuild(ad, fp, e) 115859673Seric ALIASDB *ad; 115959673Seric FILE *fp; 116059673Seric ENVELOPE *e; 116159673Seric { 116259697Seric if (tTd(27, 2)) 116359697Seric printf("nis_arebuild(%s)\n", ad->ad_name); 116459673Seric } 116559673Seric 116659673Seric 116759673Seric /* 116859673Seric ** NIS_ACLOSE 116959673Seric */ 117059673Seric 117159673Seric void 117259673Seric nis_aclose(ad, e) 117359673Seric ALIASDB *ad; 117459673Seric ENVELOPE *e; 117559673Seric { 117659673Seric /* nothing */ 117759673Seric } 117859673Seric 117959673Seric #endif /* NIS */ 118059673Seric /* 118159673Seric ** Implicit Modules 118258059Seric ** 118359673Seric ** Tries several types. For back compatibility. 118458059Seric */ 118558059Seric 118659673Seric /* 118759673Seric ** IMPL_ALOOKUP -- lookup in best open database 118859673Seric */ 118958059Seric 119059673Seric char * 119159673Seric impl_alookup(ad, name, e) 119259673Seric ALIASDB *ad; 119359673Seric char *name; 119459673Seric ENVELOPE *e; 119558059Seric { 119659697Seric if (tTd(27, 20)) 119759697Seric printf("impl_lookup(%s)\n", name); 119859697Seric 119959673Seric #ifdef NEWDB 120059673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 120159673Seric return hash_alookup(ad, name, e); 120259673Seric #endif 120359673Seric #ifdef NDBM 120459673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 120559673Seric return ndbm_alookup(ad, name, e); 120659673Seric #endif 120759673Seric return stab_alookup(ad, name, e); 120859673Seric } 120959673Seric 121059673Seric /* 121159673Seric ** IMPL_ASTORE -- store in open databases 121259673Seric */ 121359673Seric 121459673Seric void 121559673Seric impl_astore(ad, lhs, rhs, e) 121659673Seric ALIASDB *ad; 121759673Seric char *lhs; 121859673Seric char *rhs; 121959673Seric ENVELOPE *e; 122059673Seric { 122159673Seric #ifdef NEWDB 122259673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 122359673Seric hash_astore(ad, lhs, rhs, e); 122459673Seric #endif 122559673Seric #ifdef NDBM 122659673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 122759673Seric ndbm_astore(ad, lhs, rhs, e); 122859673Seric #endif 122959673Seric stab_astore(ad, lhs, rhs, e); 123059673Seric } 123159673Seric 123259673Seric /* 123359673Seric ** IMPL_AINIT -- implicit database lookup 123459673Seric */ 123559673Seric 123659673Seric bool 123759673Seric impl_ainit(ad, e) 123859673Seric ALIASDB *ad; 123959673Seric ENVELOPE *e; 124059673Seric { 124159697Seric if (tTd(27, 2)) 124259697Seric printf("impl_ainit(%s)\n", ad->ad_name); 124359697Seric 124459673Seric /* implicit class */ 124559673Seric #ifdef NEWDB 124659697Seric ad->ad_flags |= ADF_IMPLHASH; 124759673Seric if (hash_ainit(ad, e)) 124858059Seric { 124959697Seric return TRUE; 125059673Seric } 125159697Seric ad->ad_flags &= ~ADF_IMPLHASH; 125259673Seric #endif 125359673Seric #ifdef NDBM 125459697Seric ad->ad_flags |= ADF_IMPLNDBM; 125559673Seric if (ndbm_ainit(ad, e)) 125659673Seric { 125759697Seric return TRUE; 125859673Seric } 125959697Seric ad->ad_flags &= ~ADF_IMPLNDBM; 126059673Seric #endif 126159673Seric syserr("WARNING: cannot open alias database %s", ad->ad_name); 126258059Seric 126359673Seric if (stab_ainit(ad, e)) 126459673Seric { 126559697Seric return TRUE; 126659673Seric } 126759697Seric 126859697Seric return FALSE; 126959673Seric } 127058059Seric 127159673Seric /* 127259673Seric ** IMPL_AREBUILD -- rebuild alias database 127359673Seric */ 127458059Seric 127559673Seric void 127659673Seric impl_arebuild(ad, fp, e) 127759673Seric ALIASDB *ad; 127859673Seric FILE *fp; 127959673Seric ENVELOPE *e; 128059673Seric { 128159673Seric #ifdef NEWDB 128259673Seric DB *ndb; 128359673Seric char buf[MAXNAME]; 128459697Seric #endif 128559673Seric 128659697Seric if (tTd(27, 2)) 128759697Seric printf("impl_arebuild(%s)\n", ad->ad_name); 128859697Seric 128959697Seric #ifdef NEWDB 129059673Seric (void) strcpy(buf, ad->ad_name); 129159673Seric (void) strcat(buf, ".db"); 129259673Seric ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 129359673Seric if (ndb == NULL) 129458059Seric { 129559673Seric syserr("rebuildaliases: cannot create %s", buf); 129658059Seric } 129759673Seric else 129859673Seric { 129959673Seric ad->ad_ndbp = ndb; 130059673Seric ad->ad_flags |= ADF_IMPLHASH; 130159673Seric #if defined(NDBM) && defined(YPCOMPAT) 130259673Seric if (access("/var/yp/Makefile", R_OK) != 0) 130359673Seric #endif 130459697Seric goto readem; 130559673Seric } 130659673Seric #endif 130759673Seric 130859673Seric #ifdef NDBM 130959673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 131059673Seric if (ad->ad_dbp == NULL) 131159673Seric { 131259673Seric syserr("rebuildaliases: cannot create %s.{pag,dir}", 131359673Seric ad->ad_name); 131459673Seric } 131559673Seric else 131659673Seric { 131759673Seric ad->ad_flags |= ADF_IMPLNDBM; 131859673Seric } 131959673Seric #endif 132059673Seric 132159673Seric if (!bitset(ADF_IMPLHASH|ADF_IMPLNDBM, ad->ad_flags)) 132259673Seric return; 132359673Seric 132459697Seric readem: 1325*59701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 132659673Seric 132759673Seric /* read and store aliases */ 132859673Seric readaliases(ad, fp, e); 132958059Seric } 133058059Seric 133159673Seric 133259673Seric /* 133359673Seric ** IMPL_ACLOSE -- close any open database(s) 133459673Seric */ 133559673Seric 133659673Seric void 133759673Seric impl_aclose(ad, e) 133859673Seric ALIASDB *ad; 133959673Seric ENVELOPE *e; 134059673Seric { 134159673Seric #ifdef NEWDB 134259697Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 134359697Seric hash_aclose(ad, e); 134459673Seric #endif 134559673Seric 134659673Seric #ifdef NDBM 134759697Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 134859697Seric ndbm_aclose(ad, e); 134959673Seric #endif 135059673Seric } 135158059Seric /* 135259673Seric ** SETUPALIASES -- set up aliases classes 135359673Seric */ 135459673Seric 135559673Seric #ifdef NEWDB 135659673Seric ALIASCLASS HashAClass = 135759673Seric { 135859673Seric "hash", hash_alookup, hash_astore, 135959673Seric hash_ainit, hash_arebuild, hash_aclose, 136059673Seric ACF_BUILDABLE 136159673Seric }; 136259673Seric #endif 136359673Seric 136459673Seric #ifdef NDBM 136559673Seric ALIASCLASS DbmAClass = 136659673Seric { 136759673Seric "dbm", ndbm_alookup, ndbm_astore, 136859673Seric ndbm_ainit, ndbm_arebuild, ndbm_aclose, 136959673Seric ACF_BUILDABLE 137059673Seric }; 137159673Seric #endif 137259673Seric 137359673Seric #ifdef NIS 137459673Seric ALIASCLASS NisAClass = 137559673Seric { 137659673Seric "nis", nis_alookup, nis_astore, 137759673Seric nis_ainit, nis_arebuild, nis_aclose, 137859673Seric 0 137959673Seric }; 138059673Seric #endif 138159673Seric 138259673Seric ALIASCLASS StabAClass = 138359673Seric { 138459673Seric "stab", stab_alookup, stab_astore, 138559673Seric stab_ainit, stab_arebuild, stab_aclose, 138659673Seric 0 138759673Seric }; 138859673Seric 138959673Seric ALIASCLASS ImplAClass = 139059673Seric { 139159673Seric "implicit", impl_alookup, impl_astore, 139259673Seric impl_ainit, impl_arebuild, impl_aclose, 139359673Seric ACF_BUILDABLE 139459673Seric }; 139559673Seric 139659673Seric setupaliases() 139759673Seric { 139859673Seric register STAB *s; 139959673Seric 140059673Seric #ifdef NEWDB 140159673Seric s = stab("hash", ST_ALIASCLASS, ST_ENTER); 140259673Seric s->s_aliasclass = &HashAClass; 140359673Seric #endif 140459673Seric 140559673Seric #ifdef NDBM 140659673Seric s = stab("dbm", ST_ALIASCLASS, ST_ENTER); 140759673Seric s->s_aliasclass = &DbmAClass; 140859673Seric #endif 140959673Seric 141059673Seric #ifdef NIS 141159673Seric s = stab("nis", ST_ALIASCLASS, ST_ENTER); 141259673Seric s->s_aliasclass = &NisAClass; 141359673Seric #endif 141459673Seric 141559673Seric #if !defined(NEWDB) && !defined(NDBM) 141659673Seric s = stab("stab", ST_ALIASCLASS, ST_ENTER); 141759673Seric s->s_aliasclass = &StabAClass; 141859673Seric #endif 141959673Seric 142059673Seric s = stab("implicit", ST_ALIASCLASS, ST_ENTER); 142159673Seric s->s_aliasclass = &ImplAClass; 142259673Seric } 142359673Seric /* 1424292Seric ** FORWARD -- Try to forward mail 1425292Seric ** 1426292Seric ** This is similar but not identical to aliasing. 1427292Seric ** 1428292Seric ** Parameters: 14294314Seric ** user -- the name of the user who's mail we would like 14304314Seric ** to forward to. It must have been verified -- 14314314Seric ** i.e., the q_home field must have been filled 14324314Seric ** in. 14334999Seric ** sendq -- a pointer to the head of the send queue to 14344999Seric ** put this user's aliases in. 1435292Seric ** 1436292Seric ** Returns: 14374098Seric ** none. 1438292Seric ** 1439292Seric ** Side Effects: 14403185Seric ** New names are added to send queues. 1441292Seric */ 1442292Seric 144355012Seric forward(user, sendq, e) 14442966Seric ADDRESS *user; 14454999Seric ADDRESS **sendq; 144655012Seric register ENVELOPE *e; 1447292Seric { 144857136Seric char *pp; 144957136Seric char *ep; 14504069Seric 14517671Seric if (tTd(27, 1)) 14524098Seric printf("forward(%s)\n", user->q_paddr); 14534098Seric 14544594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 14554098Seric return; 14564314Seric if (user->q_home == NULL) 145758059Seric { 145858151Seric syserr("554 forward: no home"); 145958059Seric user->q_home = "/nosuchdirectory"; 146058059Seric } 14614069Seric 14624069Seric /* good address -- look for .forward file in home */ 146355012Seric define('z', user->q_home, e); 146457136Seric define('u', user->q_user, e); 146557136Seric define('h', user->q_host, e); 146657136Seric if (ForwardPath == NULL) 146758050Seric ForwardPath = newstr("\201z/.forward"); 146857136Seric 146957136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 147057136Seric { 147158247Seric int err; 147257232Seric char buf[MAXPATHLEN+1]; 147357136Seric 147457136Seric ep = strchr(pp, ':'); 147557136Seric if (ep != NULL) 147657136Seric *ep = '\0'; 147757136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 147857136Seric if (ep != NULL) 147957136Seric *ep++ = ':'; 148057136Seric if (tTd(27, 3)) 148157136Seric printf("forward: trying %s\n", buf); 148258247Seric err = include(buf, TRUE, user, sendq, e); 148358247Seric if (err == 0) 148457136Seric break; 148558247Seric if (transienterror(err)) 148658247Seric { 148758247Seric /* we have to suspend this message */ 148859563Seric if (tTd(27, 2)) 148959563Seric printf("forward: transient error on %s\n", buf); 149059563Seric #ifdef LOG 149159563Seric if (LogLevel > 2) 149259624Seric syslog(LOG_ERR, "%s: forward %s: transient error: %s", 149359624Seric e->e_id, buf, errstring(err)); 149459563Seric #endif 149559611Seric message("%s: %s: message queued", buf, errstring(err)); 149658247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 149758247Seric return; 149858247Seric } 149957136Seric } 1500292Seric } 1501