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*59697Seric static char sccsid[] = "@(#)alias.c 6.40 (Berkeley) 05/03/93 (with NEWDB and NDBM)"; 2951756Seric #else 30*59697Seric static char sccsid[] = "@(#)alias.c 6.40 (Berkeley) 05/03/93 (with NEWDB)"; 3157736Seric #endif 3257736Seric #else 3356845Seric #ifdef NDBM 34*59697Seric static char sccsid[] = "@(#)alias.c 6.40 (Berkeley) 05/03/93 (with NDBM)"; 3533728Sbostic #else 36*59697Seric static char sccsid[] = "@(#)alias.c 6.40 (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 251*59697Seric if (tTd(27, 8)) 252*59697Seric printf("setalias(%s)\n", spec); 253*59697Seric 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]; 321*59697Seric 322*59697Seric if (tTd(27, 2)) 323*59697Seric printf("initaliases(%s:%s)\n", 324*59697Seric ad->ad_class->ac_name, ad->ad_name); 325*59697Seric 32659673Seric if (rebuild) 32750576Seric { 32859673Seric rebuildaliases(ad, FALSE, e); 32950576Seric } 33059673Seric else 33157249Seric { 332*59697Seric if (ad->ad_class->ac_init(ad, e)) 333*59697Seric 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 353*59697Seric if (tTd(27, 3)) 354*59697Seric printf("aliaswait\n"); 355*59697Seric 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 367*59697Seric if (tTd(27, 2)) 368*59697Seric printf("aliaswait: sleeping\n"); 369*59697Seric 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 */ 47459673Seric ad->ad_class->ac_close(ad, e); 47559673Seric 47659673Seric /* restore the old signal */ 47759673Seric (void) signal(SIGINT, oldsigint); 4784157Seric } 4794157Seric /* 4804157Seric ** READALIASES -- read and process the alias file. 4814157Seric ** 4824157Seric ** This routine implements the part of initaliases that occurs 4834157Seric ** when we are not going to use the DBM stuff. 4844157Seric ** 4854157Seric ** Parameters: 48659673Seric ** ad -- the alias database descriptor. 48759673Seric ** af -- file to read the aliases from. 48859673Seric ** e -- the current alias file. 4894157Seric ** 4904157Seric ** Returns: 4914157Seric ** none. 4924157Seric ** 4934157Seric ** Side Effects: 4944157Seric ** Reads aliasfile into the symbol table. 4954157Seric ** Optionally, builds the .dir & .pag files. 4964157Seric */ 4974157Seric 4984157Seric static 49959673Seric readaliases(ad, af, e) 50059673Seric register ALIASDB *ad; 50159673Seric FILE *af; 50255012Seric register ENVELOPE *e; 5034157Seric { 5044098Seric register char *p; 5054098Seric char *rhs; 5064098Seric bool skipping; 50759673Seric long naliases, bytes, longest; 5084098Seric ADDRESS al, bl; 5094106Seric register STAB *s; 5109368Seric char line[BUFSIZ]; 5114098Seric 5124314Seric /* 5134314Seric ** Read and interpret lines 5144314Seric */ 5154314Seric 51659673Seric FileName = ad->ad_name; 5179368Seric LineNumber = 0; 5184322Seric naliases = bytes = longest = 0; 5194098Seric skipping = FALSE; 5204098Seric while (fgets(line, sizeof (line), af) != NULL) 5214098Seric { 5224322Seric int lhssize, rhssize; 5234322Seric 5249368Seric LineNumber++; 52556795Seric p = strchr(line, '\n'); 52625278Seric if (p != NULL) 52725278Seric *p = '\0'; 5284098Seric switch (line[0]) 5294098Seric { 5304098Seric case '#': 5314098Seric case '\0': 5324098Seric skipping = FALSE; 5334098Seric continue; 5344065Seric 5354098Seric case ' ': 5364098Seric case '\t': 5374098Seric if (!skipping) 53858151Seric syserr("554 Non-continuation line starts with space"); 5394098Seric skipping = TRUE; 5404097Seric continue; 5414098Seric } 5424098Seric skipping = FALSE; 5431874Seric 5444314Seric /* 5454314Seric ** Process the LHS 54657736Seric ** Find the colon separator, and parse the address. 54716898Seric ** It should resolve to a local name -- this will 54816898Seric ** be checked later (we want to optionally do 54916898Seric ** parsing of the RHS first to maximize error 55016898Seric ** detection). 5514314Seric */ 5524314Seric 5534098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5544097Seric continue; 55516898Seric if (*p++ != ':') 5564098Seric { 55758151Seric syserr("554 missing colon"); 5584097Seric continue; 5594098Seric } 56058333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 5614098Seric { 56258151Seric syserr("554 illegal alias name"); 56316898Seric continue; 5644098Seric } 5654314Seric 5664314Seric /* 5674314Seric ** Process the RHS. 5684314Seric ** 'al' is the internal form of the LHS address. 5694314Seric ** 'p' points to the text of the RHS. 5704314Seric */ 5714314Seric 57258914Seric while (isascii(*p) && isspace(*p)) 57358914Seric p++; 5744098Seric rhs = p; 5754098Seric for (;;) 5764098Seric { 5774098Seric register char c; 57858662Seric register char *nlp; 5791515Seric 58058662Seric nlp = &p[strlen(p)]; 58158662Seric if (nlp[-1] == '\n') 58258662Seric *--nlp = '\0'; 58358662Seric 58459673Seric if (CheckAliases) 5854098Seric { 5864157Seric /* do parsing & compression of addresses */ 58725278Seric while (*p != '\0') 5884098Seric { 58958333Seric auto char *delimptr; 59025278Seric 59158050Seric while ((isascii(*p) && isspace(*p)) || 59258050Seric *p == ',') 5934157Seric p++; 59425278Seric if (*p == '\0') 59525278Seric break; 59658333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 59758151Seric usrerr("553 %s... bad address", p); 59858333Seric p = delimptr; 5994098Seric } 6004098Seric } 6014157Seric else 60215769Seric { 60358662Seric p = nlp; 60415769Seric } 6051515Seric 6064098Seric /* see if there should be a continuation line */ 6074106Seric c = fgetc(af); 6084106Seric if (!feof(af)) 6094314Seric (void) ungetc(c, af); 6104106Seric if (c != ' ' && c != '\t') 6114098Seric break; 6124098Seric 6134098Seric /* read continuation line */ 6144098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6154098Seric break; 6169368Seric LineNumber++; 61757135Seric 61857135Seric /* check for line overflow */ 61957135Seric if (strchr(p, '\n') == NULL) 62057135Seric { 62158151Seric usrerr("554 alias too long"); 62257135Seric break; 62357135Seric } 6244098Seric } 62516898Seric if (al.q_mailer != LocalMailer) 62616898Seric { 62758151Seric syserr("554 cannot alias non-local names"); 62816898Seric continue; 62916898Seric } 6304314Seric 6314314Seric /* 6324314Seric ** Insert alias into symbol table or DBM file 6334314Seric */ 6344314Seric 63557381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 63657381Seric makelower(al.q_user); 6374322Seric 63859673Seric lhssize = strlen(al.q_user); 63959673Seric rhssize = strlen(rhs); 64059673Seric ad->ad_class->ac_store(ad, al.q_user, rhs, e); 6414157Seric 64259673Seric if (al.q_paddr != NULL) 64359673Seric free(al.q_paddr); 64459673Seric if (al.q_host != NULL) 64559673Seric free(al.q_host); 64659673Seric if (al.q_user != NULL) 64759673Seric free(al.q_user); 6484322Seric 6494322Seric /* statistics */ 6504322Seric naliases++; 6514322Seric bytes += lhssize + rhssize; 6524322Seric if (rhssize > longest) 6534322Seric longest = rhssize; 6541515Seric } 65519784Seric 65659673Seric e->e_to = NULL; 65759673Seric FileName = NULL; 65859673Seric message("%s: %d aliases, longest %d bytes, %d bytes total", 65959673Seric ad->ad_name, naliases, longest, bytes); 66059673Seric # ifdef LOG 66159673Seric if (LogLevel > 7) 66259673Seric syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total", 66359673Seric ad->ad_name, naliases, longest, bytes); 66459673Seric # endif /* LOG */ 66559673Seric } 66659673Seric /* 66759673Seric ** NDBM modules 66859673Seric */ 66959673Seric 67059673Seric #ifdef NDBM 67159673Seric 67259673Seric /* 67359673Seric ** NDBM_ALOOKUP -- look up alias in ndbm file 67459673Seric */ 67559673Seric 67659673Seric char * 67759673Seric ndbm_alookup(ad, name, e) 67859673Seric register ALIASDB *ad; 67959673Seric char *name; 68059673Seric ENVELOPE *e; 68159673Seric { 68259673Seric int i; 68359673Seric datum rhs, lhs; 68459673Seric char keybuf[MAXNAME + 1]; 68559673Seric 686*59697Seric if (tTd(27, 20)) 687*59697Seric printf("ndbm_lookup(%s)\n", name); 688*59697Seric 68959673Seric /* create a key for fetch */ 69059673Seric i = strlen(name) + 1; 69159673Seric if (i > sizeof keybuf) 69259673Seric i = sizeof keybuf; 69359673Seric bcopy(name, keybuf, i); 69459673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 69559673Seric makelower(keybuf); 69659673Seric 69759673Seric lhs.dsize = i; 69859673Seric lhs.dptr = keybuf; 69959673Seric rhs = dbm_fetch((DBM *) ad->ad_dbp, lhs); 70059673Seric return (rhs.dptr); 70159673Seric } 70259673Seric 70359673Seric 70459673Seric /* 70559673Seric ** NDBM_ASTORE -- store a datum in the database 70659673Seric */ 70759673Seric 70859673Seric void 70959673Seric ndbm_astore(ad, lhs, rhs, e) 71059673Seric register ALIASDB *ad; 71159673Seric char *lhs; 71259673Seric char *rhs; 71359673Seric ENVELOPE *e; 71459673Seric { 71559673Seric datum key; 71659673Seric datum data; 71759673Seric int stat; 71859673Seric 719*59697Seric key.dsize = strlen(lhs) + 1; 72059673Seric key.dptr = lhs; 72159673Seric 722*59697Seric data.dsize = strlen(rhs) + 1; 72359673Seric data.dptr = rhs; 72459673Seric 72559673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_INSERT); 72659673Seric if (stat > 0) 72719784Seric { 72859673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 72959673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_REPLACE); 73059673Seric } 73159673Seric if (stat != 0) 73259673Seric syserr("readaliases: dbm put (%s)", lhs); 73359673Seric } 73419784Seric 73559673Seric 73659673Seric /* 73759673Seric ** NDBM_AINIT -- initialize DBM database 73859673Seric */ 73959673Seric 74059673Seric bool 74159673Seric ndbm_ainit(ad, e) 74259673Seric register ALIASDB *ad; 74359673Seric ENVELOPE *e; 74459673Seric { 74559673Seric char buf[MAXNAME]; 74659673Seric 747*59697Seric if (tTd(27, 2)) 748*59697Seric printf("ndbm_ainit(%s)\n", ad->ad_name); 749*59697Seric 75059673Seric /* open the database */ 75159673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDONLY, DBMMODE); 75259673Seric if (ad->ad_dbp == NULL) 75359673Seric return FALSE; 75459673Seric 75559673Seric /* wait for @:@ to appear */ 75659673Seric aliaswait(ad, ".pag", e); 75759673Seric 75859673Seric return TRUE; 75959673Seric } 76059673Seric 76159673Seric 76259673Seric /* 76359673Seric ** NDBM_AREBUILD -- rebuild hash database 76459673Seric */ 76559673Seric 76659673Seric void 76759673Seric ndbm_arebuild(ad, fp, e) 76859673Seric register ALIASDB *ad; 76959673Seric FILE *fp; 77059673Seric ENVELOPE *e; 77159673Seric { 77259673Seric register DBM *db; 77359673Seric int i; 77459673Seric char buf[MAXNAME]; 77559673Seric 776*59697Seric if (tTd(27, 2)) 777*59697Seric printf("ndbm_arebuild(%s)\n", ad->ad_name); 778*59697Seric 77959673Seric db = dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 78059673Seric if (db == NULL) 78159673Seric { 78259673Seric syserr("readaliases: cannot create %s", buf); 78359673Seric return; 78459673Seric } 78559673Seric ad->ad_dbp = (void *) db; 786*59697Seric ad->ad_flags |= ADF_WRITABLE; 78759673Seric 78859673Seric /* read and store the aliases */ 78959673Seric readaliases(ad, fp, e); 79059673Seric } 79159673Seric 79259673Seric /* 79359673Seric ** NDBM_ACLOSE -- close the database 79459673Seric */ 79559673Seric 79659673Seric void 79759673Seric ndbm_aclose(ad, e) 79859673Seric register ALIASDB *ad; 79959673Seric ENVELOPE *e; 80059673Seric { 80159673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 80259673Seric { 80358059Seric #ifdef YPCOMPAT 80459673Seric char buf[200]; 80558846Seric 80659673Seric (void) sprintf(buf, "%010ld", curtime()); 80759673Seric ndbm_astore(ad, "YP_LAST_MODIFIED", buf, e); 80859673Seric 80959673Seric (void) myhostname(buf, sizeof buf); 81059673Seric ndbm_astore(ad, "YP_MASTER_NAME", buf, e); 81158059Seric #endif 81219784Seric 81359673Seric /* write out the distinguished alias */ 81459673Seric ndbm_astore(ad, "@", "@", e); 81519784Seric } 81659673Seric dbm_close((DBM *) ad->ad_dbp); 81759673Seric } 81819784Seric 81959673Seric #endif 82059673Seric /* 82159673Seric ** HASH (NEWDB) Modules 82259673Seric */ 82359673Seric 82459673Seric #ifdef NEWDB 82559673Seric 82659673Seric /* 82759673Seric ** HASH_ALOOKUP -- look up alias in hash file 82859673Seric */ 82959673Seric 83059673Seric char * 83159673Seric hash_alookup(ad, name, e) 83259673Seric register ALIASDB *ad; 83359673Seric char *name; 83459673Seric ENVELOPE *e; 83559673Seric { 83659673Seric int i; 83759673Seric DBT rhs, lhs; 83859673Seric int s; 83959673Seric char keybuf[MAXNAME + 1]; 84059673Seric 841*59697Seric if (tTd(27, 20)) 842*59697Seric printf("hash_alookup(%s)\n", name); 843*59697Seric 84459673Seric /* create a key for fetch */ 84559673Seric i = strlen(name) + 1; 84659673Seric if (i > sizeof keybuf) 84759673Seric i = sizeof keybuf; 84859673Seric bcopy(name, keybuf, i); 84959673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 85059673Seric makelower(keybuf); 85159673Seric 85259673Seric lhs.size = i; 85359673Seric lhs.data = keybuf; 85459673Seric i = ad->ad_ndbp->get(ad->ad_ndbp, &lhs, &rhs, 0); 85559673Seric if (i == 0) 85659673Seric return (rhs.data); 85759673Seric return (NULL); 858292Seric } 85959673Seric 86059673Seric 86159673Seric /* 86259673Seric ** HASH_ASTORE -- store a datum in the database 86359673Seric */ 86459673Seric 86559673Seric void 86659673Seric hash_astore(ad, lhs, rhs, e) 86759673Seric register ALIASDB *ad; 86859673Seric char *lhs; 86959673Seric char *rhs; 87059673Seric ENVELOPE *e; 87159673Seric { 87259673Seric int stat; 87359673Seric DBT key; 87459673Seric DBT data; 87559673Seric 876*59697Seric if (tTd(27, 20)) 877*59697Seric printf("hash_astore(%s, %s)\n", lhs, rhs); 878*59697Seric 879*59697Seric key.size = strlen(lhs) + 1; 88059673Seric key.data = lhs; 88159673Seric 882*59697Seric data.size = strlen(rhs) + 1; 88359673Seric data.data = rhs; 88459673Seric 88559673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, R_NOOVERWRITE); 88659673Seric if (stat > 0) 88759673Seric { 88859673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 88959673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, 0); 89059673Seric } 89159673Seric if (stat != 0) 89259673Seric syserr("readaliases: db put (%s)", lhs); 89359673Seric } 89459673Seric 89559673Seric 89659673Seric /* 89759673Seric ** HASH_AINIT -- initialize hash database 89859673Seric */ 89959673Seric 90059673Seric bool 90159673Seric hash_ainit(ad, e) 90259673Seric register ALIASDB *ad; 90359673Seric ENVELOPE *e; 90459673Seric { 90559673Seric char buf[MAXNAME]; 90659673Seric 907*59697Seric if (tTd(27, 2)) 908*59697Seric printf("hash_ainit(%s)\n", ad->ad_name); 909*59697Seric 91059673Seric /* open the database */ 91159673Seric (void) strcpy(buf, ad->ad_name); 91259673Seric (void) strcat(buf, ".db"); 91359673Seric ad->ad_ndbp = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 91459673Seric if (ad->ad_ndbp == NULL) 91559673Seric return FALSE; 91659673Seric 91759673Seric /* wait for @:@ to appear */ 91859673Seric aliaswait(ad, ".db", e); 91959673Seric return TRUE; 92059673Seric } 92159673Seric 92259673Seric 92359673Seric /* 92459673Seric ** HASH_AREBUILD -- rebuild hash database 92559673Seric */ 92659673Seric 92759673Seric void 92859673Seric hash_arebuild(ad, fp, e) 92959673Seric register ALIASDB *ad; 93059673Seric FILE *fp; 93159673Seric ENVELOPE *e; 93259673Seric { 93359673Seric register DB *db; 93459673Seric char buf[MAXNAME]; 93559673Seric 936*59697Seric if (tTd(27, 2)) 937*59697Seric printf("hash_arebuild(%s)\n", ad->ad_name); 938*59697Seric 93959673Seric db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 94059673Seric if (db == NULL) 94159673Seric { 94259673Seric syserr("readaliases: cannot create %s", buf); 94359673Seric return; 94459673Seric } 94559673Seric ad->ad_ndbp = db; 946*59697Seric ad->ad_flags |= ADF_WRITABLE; 94759673Seric 94859673Seric /* read and store the aliases */ 94959673Seric readaliases(ad, fp, e); 95059673Seric } 95159673Seric 95259673Seric 95359673Seric /* 95459673Seric ** HASH_ACLOSE -- add distinguished entries and close the database 95559673Seric */ 95659673Seric 95759673Seric void 95859673Seric hash_aclose(ad, e) 95959673Seric ALIASDB *ad; 96059673Seric ENVELOPE *e; 96159673Seric { 962*59697Seric if (tTd(27, 9)) 963*59697Seric printf("hash_aclose(%x)\n", ad->ad_flags); 964*59697Seric 96559673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 96659673Seric { 96759673Seric /* write out the distinguished alias */ 96859673Seric hash_astore(ad, "@", "@", e); 96959673Seric } 97059673Seric 97159673Seric if (ad->ad_ndbp->close(ad->ad_ndbp) != 0) 97259673Seric syserr("readaliases: db close failure"); 97359673Seric } 97459673Seric 97559673Seric #endif 976292Seric /* 97759673Seric ** STAB (Symbol Table) Modules 97859673Seric */ 97959673Seric 98059673Seric 98159673Seric /* 98259673Seric ** STAB_ALOOKUP -- look up alias in symbol table 98359673Seric */ 98459673Seric 98559673Seric char * 98659673Seric stab_alookup(ad, name, e) 98759673Seric register ALIASDB *ad; 98859673Seric char *name; 98959673Seric ENVELOPE *e; 99059673Seric { 99159673Seric register STAB *s; 99259673Seric 993*59697Seric if (tTd(27, 20)) 994*59697Seric printf("stab_lookup(%s)\n", name); 995*59697Seric 99659673Seric s = stab(name, ST_ALIAS, ST_FIND); 99759673Seric if (s != NULL) 99859673Seric return (s->s_alias); 99959673Seric return (NULL); 100059673Seric } 100159673Seric 100259673Seric 100359673Seric /* 100459673Seric ** STAB_ASTORE -- store in symtab (actually using during init, not rebuild) 100559673Seric */ 100659673Seric 100759673Seric void 100859673Seric stab_astore(ad, lhs, rhs, e) 100959673Seric register ALIASDB *ad; 101059673Seric char *lhs; 101159673Seric char *rhs; 101259673Seric ENVELOPE *e; 101359673Seric { 101459673Seric register STAB *s; 101559673Seric 101659673Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 101759673Seric s->s_alias = newstr(rhs); 101859673Seric } 101959673Seric 102059673Seric 102159673Seric /* 102259673Seric ** STAB_AINIT -- initialize (reads data file) 102359673Seric */ 102459673Seric 102559673Seric bool 102659673Seric stab_ainit(ad, e) 102759673Seric register ALIASDB *ad; 102859673Seric ENVELOPE *e; 102959673Seric { 103059673Seric FILE *af; 103159673Seric 1032*59697Seric if (tTd(27, 2)) 1033*59697Seric printf("stab_ainit(%s)\n", ad->ad_name); 1034*59697Seric 103559673Seric af = fopen(ad->ad_name, "r"); 103659673Seric if (af == NULL) 103759673Seric { 103859673Seric syserr("554 Can't open %s", ad->ad_name); 103959673Seric errno = 0; 104059673Seric return FALSE; 104159673Seric } 104259673Seric 104359673Seric readaliases(ad, af, e); 104459673Seric } 104559673Seric 104659673Seric 104759673Seric /* 104859673Seric ** STAB_AREBUILD -- rebuild alias file 104959673Seric */ 105059673Seric 105159673Seric void 105259673Seric stab_arebuild(ad, fp, e) 105359673Seric ALIASDB *ad; 105459673Seric FILE *fp; 105559673Seric ENVELOPE *e; 105659673Seric { 1057*59697Seric if (tTd(27, 2)) 1058*59697Seric printf("stab_arebuild(%s)\n", ad->ad_name); 1059*59697Seric 1060*59697Seric ad->ad_flags |= ADF_WRITABLE; 106159673Seric } 106259673Seric 106359673Seric 106459673Seric /* 106559673Seric ** STAB_ACLOSE -- close symbol table (???) 106659673Seric */ 106759673Seric 106859673Seric void 106959673Seric stab_aclose(ad, e) 107059673Seric ALIASDB *ad; 107159673Seric ENVELOPE *e; 107259673Seric { 107359673Seric /* ignore it */ 107459673Seric } 107559673Seric /* 107659673Seric ** NIS Modules 107759673Seric */ 107859673Seric 107959673Seric #ifdef NIS 108059673Seric 108159673Seric /* 108259673Seric ** NIS_ALOOKUP 108359673Seric */ 108459673Seric 108559673Seric char * 108659673Seric nis_alookup(ad, name, e) 108759673Seric ALIASDB *ad; 108859673Seric char *name; 108959673Seric ENVELOPE *e; 109059673Seric { 109159673Seric auto char *vp; 109259673Seric auto int vsize; 109359673Seric 1094*59697Seric if (tTd(27, 20)) 1095*59697Seric printf("nis_lookup(%s)\n", name); 1096*59697Seric 109759673Seric if (ypmatch(ad->ad_domain, ad->ad_name, name, strlen(name), 109859673Seric &vp, &vsize) != 0) 109959673Seric return NULL; 110059673Seric return vp; 110159673Seric } 110259673Seric 110359673Seric /* 110459673Seric ** NIS_ASTORE 110559673Seric */ 110659673Seric 110759673Seric void 110859673Seric nis_astore(ad, lhs, rhs, e) 110959673Seric ALIASDB *ad; 111059673Seric char *lhs; 111159673Seric char *rhs; 111259673Seric ENVELOPE *e; 111359673Seric { 111459673Seric /* nothing */ 111559673Seric } 111659673Seric 111759673Seric /* 111859673Seric ** NIS_AINIT 111959673Seric */ 112059673Seric 112159673Seric bool 112259673Seric nis_ainit(ad, e) 112359673Seric ALIASDB *ad; 112459673Seric ENVELOPE *e; 112559673Seric { 112659673Seric register char *p; 112759673Seric auto char *ypmaster; 112859673Seric 1129*59697Seric if (tTd(27, 2)) 1130*59697Seric printf("nis_ainit(%s)\n", ad->ad_name); 1131*59697Seric 113259673Seric p = strchr(ad->ad_name, '@'); 113359673Seric if (p != NULL) 113459673Seric { 113559673Seric *p++ = '\0'; 113659673Seric if (*p != '\0') 113759673Seric ad->ad_domain = p; 113859673Seric } 113959673Seric if (ad->ad_domain == NULL) 114059673Seric yp_get_default_domain(&ad->ad_domain); 114159673Seric 114259673Seric if (*ad->ad_name == '\0') 114359673Seric ad->ad_name = "mail.aliases"; 114459673Seric 114559673Seric yperr = yp_master(ad->ad_domain, ad->ad_name, &ypmaster); 114659673Seric return (yperr == 0); 114759673Seric } 114859673Seric 114959673Seric /* 115059673Seric ** NIS_AREBUILD 115159673Seric */ 115259673Seric 115359673Seric void 115459673Seric nis_arebuild(ad, fp, e) 115559673Seric ALIASDB *ad; 115659673Seric FILE *fp; 115759673Seric ENVELOPE *e; 115859673Seric { 1159*59697Seric if (tTd(27, 2)) 1160*59697Seric printf("nis_arebuild(%s)\n", ad->ad_name); 1161*59697Seric 116259673Seric /* nothing */ 116359673Seric } 116459673Seric 116559673Seric 116659673Seric /* 116759673Seric ** NIS_ACLOSE 116859673Seric */ 116959673Seric 117059673Seric void 117159673Seric nis_aclose(ad, e) 117259673Seric ALIASDB *ad; 117359673Seric ENVELOPE *e; 117459673Seric { 117559673Seric /* nothing */ 117659673Seric } 117759673Seric 117859673Seric #endif /* NIS */ 117959673Seric /* 118059673Seric ** Implicit Modules 118158059Seric ** 118259673Seric ** Tries several types. For back compatibility. 118358059Seric */ 118458059Seric 118559673Seric /* 118659673Seric ** IMPL_ALOOKUP -- lookup in best open database 118759673Seric */ 118858059Seric 118959673Seric char * 119059673Seric impl_alookup(ad, name, e) 119159673Seric ALIASDB *ad; 119259673Seric char *name; 119359673Seric ENVELOPE *e; 119458059Seric { 1195*59697Seric if (tTd(27, 20)) 1196*59697Seric printf("impl_lookup(%s)\n", name); 1197*59697Seric 119859673Seric #ifdef NEWDB 119959673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 120059673Seric return hash_alookup(ad, name, e); 120159673Seric #endif 120259673Seric #ifdef NDBM 120359673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 120459673Seric return ndbm_alookup(ad, name, e); 120559673Seric #endif 120659673Seric return stab_alookup(ad, name, e); 120759673Seric } 120859673Seric 120959673Seric /* 121059673Seric ** IMPL_ASTORE -- store in open databases 121159673Seric */ 121259673Seric 121359673Seric void 121459673Seric impl_astore(ad, lhs, rhs, e) 121559673Seric ALIASDB *ad; 121659673Seric char *lhs; 121759673Seric char *rhs; 121859673Seric ENVELOPE *e; 121959673Seric { 122059673Seric #ifdef NEWDB 122159673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 122259673Seric hash_astore(ad, lhs, rhs, e); 122359673Seric #endif 122459673Seric #ifdef NDBM 122559673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 122659673Seric ndbm_astore(ad, lhs, rhs, e); 122759673Seric #endif 122859673Seric stab_astore(ad, lhs, rhs, e); 122959673Seric } 123059673Seric 123159673Seric /* 123259673Seric ** IMPL_AINIT -- implicit database lookup 123359673Seric */ 123459673Seric 123559673Seric bool 123659673Seric impl_ainit(ad, e) 123759673Seric ALIASDB *ad; 123859673Seric ENVELOPE *e; 123959673Seric { 1240*59697Seric if (tTd(27, 2)) 1241*59697Seric printf("impl_ainit(%s)\n", ad->ad_name); 1242*59697Seric 124359673Seric /* implicit class */ 124459673Seric #ifdef NEWDB 1245*59697Seric ad->ad_flags |= ADF_IMPLHASH; 124659673Seric if (hash_ainit(ad, e)) 124758059Seric { 1248*59697Seric return TRUE; 124959673Seric } 1250*59697Seric ad->ad_flags &= ~ADF_IMPLHASH; 125159673Seric #endif 125259673Seric #ifdef NDBM 1253*59697Seric ad->ad_flags |= ADF_IMPLNDBM; 125459673Seric if (ndbm_ainit(ad, e)) 125559673Seric { 1256*59697Seric return TRUE; 125759673Seric } 1258*59697Seric ad->ad_flags &= ~ADF_IMPLNDBM; 125959673Seric #endif 126059673Seric syserr("WARNING: cannot open alias database %s", ad->ad_name); 126158059Seric 126259673Seric if (stab_ainit(ad, e)) 126359673Seric { 1264*59697Seric return TRUE; 126559673Seric } 1266*59697Seric 1267*59697Seric return FALSE; 126859673Seric } 126958059Seric 127059673Seric /* 127159673Seric ** IMPL_AREBUILD -- rebuild alias database 127259673Seric */ 127358059Seric 127459673Seric void 127559673Seric impl_arebuild(ad, fp, e) 127659673Seric ALIASDB *ad; 127759673Seric FILE *fp; 127859673Seric ENVELOPE *e; 127959673Seric { 128059673Seric #ifdef NEWDB 128159673Seric DB *ndb; 128259673Seric char buf[MAXNAME]; 1283*59697Seric #endif 128459673Seric 1285*59697Seric if (tTd(27, 2)) 1286*59697Seric printf("impl_arebuild(%s)\n", ad->ad_name); 1287*59697Seric 1288*59697Seric #ifdef NEWDB 128959673Seric (void) strcpy(buf, ad->ad_name); 129059673Seric (void) strcat(buf, ".db"); 129159673Seric ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 129259673Seric if (ndb == NULL) 129358059Seric { 129459673Seric syserr("rebuildaliases: cannot create %s", buf); 129558059Seric } 129659673Seric else 129759673Seric { 129859673Seric ad->ad_ndbp = ndb; 129959673Seric ad->ad_flags |= ADF_IMPLHASH; 130059673Seric #if defined(NDBM) && defined(YPCOMPAT) 130159673Seric if (access("/var/yp/Makefile", R_OK) != 0) 130259673Seric #endif 1303*59697Seric goto readem; 130459673Seric } 130559673Seric #endif 130659673Seric 130759673Seric #ifdef NDBM 130859673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 130959673Seric if (ad->ad_dbp == NULL) 131059673Seric { 131159673Seric syserr("rebuildaliases: cannot create %s.{pag,dir}", 131259673Seric ad->ad_name); 131359673Seric } 131459673Seric else 131559673Seric { 131659673Seric ad->ad_flags |= ADF_IMPLNDBM; 131759673Seric } 131859673Seric #endif 131959673Seric 132059673Seric if (!bitset(ADF_IMPLHASH|ADF_IMPLNDBM, ad->ad_flags)) 132159673Seric return; 132259673Seric 1323*59697Seric readem: 1324*59697Seric ad->ad_flags |= ADF_WRITABLE; 132559673Seric 132659673Seric /* read and store aliases */ 132759673Seric readaliases(ad, fp, e); 132858059Seric } 132958059Seric 133059673Seric 133159673Seric /* 133259673Seric ** IMPL_ACLOSE -- close any open database(s) 133359673Seric */ 133459673Seric 133559673Seric void 133659673Seric impl_aclose(ad, e) 133759673Seric ALIASDB *ad; 133859673Seric ENVELOPE *e; 133959673Seric { 134059673Seric #ifdef NEWDB 1341*59697Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 1342*59697Seric hash_aclose(ad, e); 134359673Seric #endif 134459673Seric 134559673Seric #ifdef NDBM 1346*59697Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 1347*59697Seric ndbm_aclose(ad, e); 134859673Seric #endif 134959673Seric } 135058059Seric /* 135159673Seric ** SETUPALIASES -- set up aliases classes 135259673Seric */ 135359673Seric 135459673Seric #ifdef NEWDB 135559673Seric ALIASCLASS HashAClass = 135659673Seric { 135759673Seric "hash", hash_alookup, hash_astore, 135859673Seric hash_ainit, hash_arebuild, hash_aclose, 135959673Seric ACF_BUILDABLE 136059673Seric }; 136159673Seric #endif 136259673Seric 136359673Seric #ifdef NDBM 136459673Seric ALIASCLASS DbmAClass = 136559673Seric { 136659673Seric "dbm", ndbm_alookup, ndbm_astore, 136759673Seric ndbm_ainit, ndbm_arebuild, ndbm_aclose, 136859673Seric ACF_BUILDABLE 136959673Seric }; 137059673Seric #endif 137159673Seric 137259673Seric #ifdef NIS 137359673Seric ALIASCLASS NisAClass = 137459673Seric { 137559673Seric "nis", nis_alookup, nis_astore, 137659673Seric nis_ainit, nis_arebuild, nis_aclose, 137759673Seric 0 137859673Seric }; 137959673Seric #endif 138059673Seric 138159673Seric ALIASCLASS StabAClass = 138259673Seric { 138359673Seric "stab", stab_alookup, stab_astore, 138459673Seric stab_ainit, stab_arebuild, stab_aclose, 138559673Seric 0 138659673Seric }; 138759673Seric 138859673Seric ALIASCLASS ImplAClass = 138959673Seric { 139059673Seric "implicit", impl_alookup, impl_astore, 139159673Seric impl_ainit, impl_arebuild, impl_aclose, 139259673Seric ACF_BUILDABLE 139359673Seric }; 139459673Seric 139559673Seric setupaliases() 139659673Seric { 139759673Seric register STAB *s; 139859673Seric 139959673Seric #ifdef NEWDB 140059673Seric s = stab("hash", ST_ALIASCLASS, ST_ENTER); 140159673Seric s->s_aliasclass = &HashAClass; 140259673Seric #endif 140359673Seric 140459673Seric #ifdef NDBM 140559673Seric s = stab("dbm", ST_ALIASCLASS, ST_ENTER); 140659673Seric s->s_aliasclass = &DbmAClass; 140759673Seric #endif 140859673Seric 140959673Seric #ifdef NIS 141059673Seric s = stab("nis", ST_ALIASCLASS, ST_ENTER); 141159673Seric s->s_aliasclass = &NisAClass; 141259673Seric #endif 141359673Seric 141459673Seric #if !defined(NEWDB) && !defined(NDBM) 141559673Seric s = stab("stab", ST_ALIASCLASS, ST_ENTER); 141659673Seric s->s_aliasclass = &StabAClass; 141759673Seric #endif 141859673Seric 141959673Seric s = stab("implicit", ST_ALIASCLASS, ST_ENTER); 142059673Seric s->s_aliasclass = &ImplAClass; 142159673Seric } 142259673Seric /* 1423292Seric ** FORWARD -- Try to forward mail 1424292Seric ** 1425292Seric ** This is similar but not identical to aliasing. 1426292Seric ** 1427292Seric ** Parameters: 14284314Seric ** user -- the name of the user who's mail we would like 14294314Seric ** to forward to. It must have been verified -- 14304314Seric ** i.e., the q_home field must have been filled 14314314Seric ** in. 14324999Seric ** sendq -- a pointer to the head of the send queue to 14334999Seric ** put this user's aliases in. 1434292Seric ** 1435292Seric ** Returns: 14364098Seric ** none. 1437292Seric ** 1438292Seric ** Side Effects: 14393185Seric ** New names are added to send queues. 1440292Seric */ 1441292Seric 144255012Seric forward(user, sendq, e) 14432966Seric ADDRESS *user; 14444999Seric ADDRESS **sendq; 144555012Seric register ENVELOPE *e; 1446292Seric { 144757136Seric char *pp; 144857136Seric char *ep; 14494069Seric 14507671Seric if (tTd(27, 1)) 14514098Seric printf("forward(%s)\n", user->q_paddr); 14524098Seric 14534594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 14544098Seric return; 14554314Seric if (user->q_home == NULL) 145658059Seric { 145758151Seric syserr("554 forward: no home"); 145858059Seric user->q_home = "/nosuchdirectory"; 145958059Seric } 14604069Seric 14614069Seric /* good address -- look for .forward file in home */ 146255012Seric define('z', user->q_home, e); 146357136Seric define('u', user->q_user, e); 146457136Seric define('h', user->q_host, e); 146557136Seric if (ForwardPath == NULL) 146658050Seric ForwardPath = newstr("\201z/.forward"); 146757136Seric 146857136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 146957136Seric { 147058247Seric int err; 147157232Seric char buf[MAXPATHLEN+1]; 147257136Seric 147357136Seric ep = strchr(pp, ':'); 147457136Seric if (ep != NULL) 147557136Seric *ep = '\0'; 147657136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 147757136Seric if (ep != NULL) 147857136Seric *ep++ = ':'; 147957136Seric if (tTd(27, 3)) 148057136Seric printf("forward: trying %s\n", buf); 148158247Seric err = include(buf, TRUE, user, sendq, e); 148258247Seric if (err == 0) 148357136Seric break; 148458247Seric if (transienterror(err)) 148558247Seric { 148658247Seric /* we have to suspend this message */ 148759563Seric if (tTd(27, 2)) 148859563Seric printf("forward: transient error on %s\n", buf); 148959563Seric #ifdef LOG 149059563Seric if (LogLevel > 2) 149159624Seric syslog(LOG_ERR, "%s: forward %s: transient error: %s", 149259624Seric e->e_id, buf, errstring(err)); 149359563Seric #endif 149459611Seric message("%s: %s: message queued", buf, errstring(err)); 149558247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 149658247Seric return; 149758247Seric } 149857136Seric } 1499292Seric } 1500