122694Sdist /* 235073Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822694Sdist 958332Seric # include "sendmail.h" 1050577Seric # include <signal.h> 1150577Seric # include <pwd.h> 1256845Seric # ifdef DBM 1356848Seric ERROR: DBM is no longer supported -- use NDBM instead. 1456845Seric # endif 1550577Seric # ifdef NEWDB 1650577Seric # include <db.h> 1750577Seric # endif 1856766Seric # ifdef NDBM 1956845Seric # include <ndbm.h> 2056766Seric # endif 2159724Seric # ifdef NIS_ALIASES 2259673Seric # include <rpcsvc/ypclnt.h> 2359673Seric # endif 2456766Seric 2533728Sbostic #ifndef lint 2651756Seric #ifdef NEWDB 2757736Seric #ifdef NDBM 28*59733Seric static char sccsid[] = "@(#)alias.c 6.43 (Berkeley) 05/04/93 (with NEWDB and NDBM)"; 2951756Seric #else 30*59733Seric static char sccsid[] = "@(#)alias.c 6.43 (Berkeley) 05/04/93 (with NEWDB)"; 3157736Seric #endif 3257736Seric #else 3356845Seric #ifdef NDBM 34*59733Seric static char sccsid[] = "@(#)alias.c 6.43 (Berkeley) 05/04/93 (with NDBM)"; 3533728Sbostic #else 36*59733Seric static char sccsid[] = "@(#)alias.c 6.43 (Berkeley) 05/04/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 */ 74*59733Seric void (*ac_rebuild)__P((ALIASDB *, FILE *, int, ENVELOPE *)); 7559673Seric /* initialization func */ 7659673Seric void (*ac_close)__P((ALIASDB *, ENVELOPE *)); 7759673Seric /* close function */ 7859673Seric short ac_flags; /* flag bits */ 7959673Seric }; 8059673Seric 8159673Seric /* bits for ac_flags */ 8259673Seric #define ACF_BUILDABLE 0x0001 /* can build a cached version */ 8359673Seric 8459673Seric 8559673Seric ALIASDB AliasDB[MAXALIASDB + 1]; /* actual database list */ 8659673Seric int NAliasDBs; /* number of alias databases */ 8759673Seric /* 88292Seric ** ALIAS -- Compute aliases. 89292Seric ** 909368Seric ** Scans the alias file for an alias for the given address. 919368Seric ** If found, it arranges to deliver to the alias list instead. 929368Seric ** Uses libdbm database if -DDBM. 93292Seric ** 94292Seric ** Parameters: 954097Seric ** a -- address to alias. 964999Seric ** sendq -- a pointer to the head of the send queue 974999Seric ** to put the aliases in. 9858092Seric ** e -- the current envelope. 99292Seric ** 100292Seric ** Returns: 101292Seric ** none 102292Seric ** 103292Seric ** Side Effects: 1043185Seric ** Aliases found are expanded. 105292Seric ** 106292Seric ** Deficiencies: 107292Seric ** It should complain about names that are aliased to 108292Seric ** nothing. 109292Seric */ 110292Seric 11155012Seric alias(a, sendq, e) 1124097Seric register ADDRESS *a; 1134999Seric ADDRESS **sendq; 11455012Seric register ENVELOPE *e; 115292Seric { 1164081Seric register char *p; 11758082Seric int naliases; 11858170Seric char *owner; 11958170Seric char obuf[MAXNAME + 6]; 1205701Seric extern char *aliaslookup(); 121292Seric 1227671Seric if (tTd(27, 1)) 1234098Seric printf("alias(%s)\n", a->q_paddr); 124292Seric 1254098Seric /* don't realias already aliased names */ 12658680Seric if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags)) 1274098Seric return; 1284098Seric 12959673Seric if (NoAlias) 13059673Seric return; 13159673Seric 13255012Seric e->e_to = a->q_paddr; 1334098Seric 1344314Seric /* 1354314Seric ** Look up this name 1364314Seric */ 1374314Seric 13859673Seric p = aliaslookup(a->q_user, e); 1394098Seric if (p == NULL) 1404098Seric return; 141292Seric 142292Seric /* 1434098Seric ** Match on Alias. 1444098Seric ** Deliver to the target list. 1451515Seric */ 1461515Seric 1477671Seric if (tTd(27, 1)) 1484098Seric printf("%s (%s, %s) aliased to %s\n", 1494098Seric a->q_paddr, a->q_host, a->q_user, p); 15058092Seric if (bitset(EF_VRFYONLY, e->e_flags)) 15158154Seric { 15258154Seric a->q_flags |= QVERIFIED; 15358884Seric e->e_nrcpts++; 15458092Seric return; 15558154Seric } 15658154Seric message("aliased to %s", p); 15757977Seric #ifdef LOG 15858020Seric if (LogLevel > 9) 15957977Seric syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p); 16057977Seric #endif 16158082Seric a->q_flags &= ~QSELFREF; 1624098Seric AliasLevel++; 16358082Seric naliases = sendtolist(p, a, sendq, e); 1644098Seric AliasLevel--; 16558082Seric if (naliases > 0 && !bitset(QSELFREF, a->q_flags)) 16658065Seric { 16758065Seric if (tTd(27, 5)) 16858065Seric { 16958065Seric printf("alias: QDONTSEND "); 17058065Seric printaddr(a, FALSE); 17158065Seric } 17258065Seric a->q_flags |= QDONTSEND; 17358065Seric } 17458170Seric 17558170Seric /* 17658170Seric ** Look for owner of alias 17758170Seric */ 17858170Seric 17958170Seric (void) strcpy(obuf, "owner-"); 18058170Seric if (strncmp(a->q_user, "owner-", 6) == 0) 18158170Seric (void) strcat(obuf, "owner"); 18258170Seric else 18358170Seric (void) strcat(obuf, a->q_user); 18458170Seric if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags)) 18558170Seric makelower(obuf); 18659673Seric owner = aliaslookup(obuf, e); 18758170Seric if (owner != NULL) 18858170Seric { 18958170Seric if (strchr(owner, ',') != NULL) 19058170Seric owner = obuf; 19158170Seric a->q_owner = newstr(owner); 19258170Seric } 1934098Seric } 1944098Seric /* 1955701Seric ** ALIASLOOKUP -- look up a name in the alias file. 1965701Seric ** 1975701Seric ** Parameters: 1985701Seric ** name -- the name to look up. 1995701Seric ** 2005701Seric ** Returns: 2015701Seric ** the value of name. 2025701Seric ** NULL if unknown. 2035701Seric ** 2045701Seric ** Side Effects: 2055701Seric ** none. 2065701Seric ** 2075701Seric ** Warnings: 2085701Seric ** The return value will be trashed across calls. 2095701Seric */ 2105701Seric 2115701Seric char * 21259673Seric aliaslookup(name, e) 2135701Seric char *name; 21459673Seric ENVELOPE *e; 2155701Seric { 21659673Seric register int dbno; 21759673Seric register ALIASDB *ad; 21859673Seric register char *p; 2195701Seric 22059673Seric for (dbno = 0; dbno < NAliasDBs; dbno++) 22159673Seric { 22259673Seric ad = &AliasDB[dbno]; 22359673Seric if (!bitset(ADF_VALID, ad->ad_flags)) 22459673Seric continue; 22559673Seric p = (*ad->ad_class->ac_lookup)(ad, name, e); 22659673Seric if (p != NULL) 22759673Seric return p; 22859673Seric } 22959673Seric return NULL; 23059673Seric } 23159673Seric /* 23259673Seric ** SETALIAS -- set up an alias map 23359673Seric ** 23459673Seric ** Called when reading configuration file. 23559673Seric ** 23659673Seric ** Parameters: 23759673Seric ** spec -- the alias specification 23859673Seric ** 23959673Seric ** Returns: 24059673Seric ** none. 24159673Seric */ 24257381Seric 24359673Seric setalias(spec) 24459673Seric char *spec; 24559673Seric { 24659673Seric register char *p; 24759673Seric register ALIASDB *ad; 24859673Seric char *class; 24959673Seric STAB *s; 25059673Seric 25159697Seric if (tTd(27, 8)) 25259697Seric printf("setalias(%s)\n", spec); 25359697Seric 25459673Seric if (NAliasDBs >= MAXALIASDB) 25551756Seric { 25659673Seric syserr("Too many alias databases defined, %d max", MAXALIASDB); 25759673Seric return; 25851756Seric } 25959673Seric ad = &AliasDB[NAliasDBs]; 26059673Seric 26159673Seric for (p = spec; *p != '\0'; p++) 26251756Seric { 26359673Seric if (strchr(" /:", *p) != NULL) 26459673Seric break; 26551756Seric } 26659673Seric 26759673Seric if (*p == ':') 26859673Seric { 26959673Seric /* explicit class listed */ 27059673Seric *p++ = '\0'; 27159673Seric class = spec; 27259673Seric spec = p; 27359673Seric } 27459673Seric else 27559673Seric { 27659673Seric /* implicit class */ 27759673Seric class = "implicit"; 27859673Seric } 27959673Seric 28059673Seric /* look up class */ 28159673Seric s = stab(class, ST_ALIASCLASS, ST_FIND); 28259673Seric if (s == NULL) 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 errno = 0; 44559673Seric return; 4468437Seric } 44759673Seric 44859673Seric /* see if someone else is rebuilding the alias file */ 44959673Seric if (!lockfile(fileno(af), ad->ad_name, LOCK_EX|LOCK_NB)) 45059673Seric { 45159673Seric /* yes, they are -- wait until done */ 45259673Seric message("Alias file %s is already being rebuilt", 45359673Seric ad->ad_name); 45459673Seric if (OpMode != MD_INITALIAS) 45559673Seric { 45659673Seric /* wait for other rebuild to complete */ 45759673Seric (void) lockfile(fileno(af), ad->ad_name, 45859673Seric LOCK_EX); 45959673Seric } 46059673Seric (void) fclose(af); 46159673Seric errno = 0; 46259673Seric return; 46359673Seric } 46459673Seric 46559673Seric oldsigint = signal(SIGINT, SIG_IGN); 46659673Seric 467*59733Seric ad->ad_class->ac_rebuild(ad, af, automatic, e); 46859673Seric 46959673Seric /* close the file, thus releasing locks */ 47059673Seric fclose(af); 47159673Seric 47259673Seric /* add distinguished entries and close the database */ 47359701Seric if (bitset(ADF_VALID, ad->ad_flags)) 47459701Seric 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. 488*59733Seric ** automatic -- set if this was an automatic rebuild. 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 500*59733Seric readaliases(ad, af, automatic, e) 50159673Seric register ALIASDB *ad; 50259673Seric FILE *af; 503*59733Seric int automatic; 50455012Seric register ENVELOPE *e; 5054157Seric { 5064098Seric register char *p; 5074098Seric char *rhs; 5084098Seric bool skipping; 50959673Seric long naliases, bytes, longest; 5104098Seric ADDRESS al, bl; 5114106Seric register STAB *s; 5129368Seric char line[BUFSIZ]; 5134098Seric 5144314Seric /* 5154314Seric ** Read and interpret lines 5164314Seric */ 5174314Seric 51859673Seric FileName = ad->ad_name; 5199368Seric LineNumber = 0; 5204322Seric naliases = bytes = longest = 0; 5214098Seric skipping = FALSE; 5224098Seric while (fgets(line, sizeof (line), af) != NULL) 5234098Seric { 5244322Seric int lhssize, rhssize; 5254322Seric 5269368Seric LineNumber++; 52756795Seric p = strchr(line, '\n'); 52825278Seric if (p != NULL) 52925278Seric *p = '\0'; 5304098Seric switch (line[0]) 5314098Seric { 5324098Seric case '#': 5334098Seric case '\0': 5344098Seric skipping = FALSE; 5354098Seric continue; 5364065Seric 5374098Seric case ' ': 5384098Seric case '\t': 5394098Seric if (!skipping) 54058151Seric syserr("554 Non-continuation line starts with space"); 5414098Seric skipping = TRUE; 5424097Seric continue; 5434098Seric } 5444098Seric skipping = FALSE; 5451874Seric 5464314Seric /* 5474314Seric ** Process the LHS 54857736Seric ** Find the colon separator, and parse the address. 54916898Seric ** It should resolve to a local name -- this will 55016898Seric ** be checked later (we want to optionally do 55116898Seric ** parsing of the RHS first to maximize error 55216898Seric ** detection). 5534314Seric */ 5544314Seric 5554098Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 5564097Seric continue; 55716898Seric if (*p++ != ':') 5584098Seric { 55958151Seric syserr("554 missing colon"); 5604097Seric continue; 5614098Seric } 56258333Seric if (parseaddr(line, &al, 1, ':', NULL, e) == NULL) 5634098Seric { 56458151Seric syserr("554 illegal alias name"); 56516898Seric continue; 5664098Seric } 5674314Seric 5684314Seric /* 5694314Seric ** Process the RHS. 5704314Seric ** 'al' is the internal form of the LHS address. 5714314Seric ** 'p' points to the text of the RHS. 5724314Seric */ 5734314Seric 57458914Seric while (isascii(*p) && isspace(*p)) 57558914Seric p++; 5764098Seric rhs = p; 5774098Seric for (;;) 5784098Seric { 5794098Seric register char c; 58058662Seric register char *nlp; 5811515Seric 58258662Seric nlp = &p[strlen(p)]; 58358662Seric if (nlp[-1] == '\n') 58458662Seric *--nlp = '\0'; 58558662Seric 58659673Seric if (CheckAliases) 5874098Seric { 5884157Seric /* do parsing & compression of addresses */ 58925278Seric while (*p != '\0') 5904098Seric { 59158333Seric auto char *delimptr; 59225278Seric 59358050Seric while ((isascii(*p) && isspace(*p)) || 59458050Seric *p == ',') 5954157Seric p++; 59625278Seric if (*p == '\0') 59725278Seric break; 59858333Seric if (parseaddr(p, &bl, -1, ',', &delimptr, e) == NULL) 59958151Seric usrerr("553 %s... bad address", p); 60058333Seric p = delimptr; 6014098Seric } 6024098Seric } 6034157Seric else 60415769Seric { 60558662Seric p = nlp; 60615769Seric } 6071515Seric 6084098Seric /* see if there should be a continuation line */ 6094106Seric c = fgetc(af); 6104106Seric if (!feof(af)) 6114314Seric (void) ungetc(c, af); 6124106Seric if (c != ' ' && c != '\t') 6134098Seric break; 6144098Seric 6154098Seric /* read continuation line */ 6164098Seric if (fgets(p, sizeof line - (p - line), af) == NULL) 6174098Seric break; 6189368Seric LineNumber++; 61957135Seric 62057135Seric /* check for line overflow */ 62157135Seric if (strchr(p, '\n') == NULL) 62257135Seric { 62358151Seric usrerr("554 alias too long"); 62457135Seric break; 62557135Seric } 6264098Seric } 62716898Seric if (al.q_mailer != LocalMailer) 62816898Seric { 62958151Seric syserr("554 cannot alias non-local names"); 63016898Seric continue; 63116898Seric } 6324314Seric 6334314Seric /* 6344314Seric ** Insert alias into symbol table or DBM file 6354314Seric */ 6364314Seric 63757381Seric if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags)) 63857381Seric makelower(al.q_user); 6394322Seric 64059673Seric lhssize = strlen(al.q_user); 64159673Seric rhssize = strlen(rhs); 64259673Seric ad->ad_class->ac_store(ad, al.q_user, rhs, e); 6434157Seric 64459673Seric if (al.q_paddr != NULL) 64559673Seric free(al.q_paddr); 64659673Seric if (al.q_host != NULL) 64759673Seric free(al.q_host); 64859673Seric if (al.q_user != NULL) 64959673Seric free(al.q_user); 6504322Seric 6514322Seric /* statistics */ 6524322Seric naliases++; 6534322Seric bytes += lhssize + rhssize; 6544322Seric if (rhssize > longest) 6554322Seric longest = rhssize; 6561515Seric } 65719784Seric 65859673Seric e->e_to = NULL; 65959673Seric FileName = NULL; 660*59733Seric if (Verbose || !automatic) 661*59733Seric message("%s: %d aliases, longest %d bytes, %d bytes total", 66259673Seric ad->ad_name, naliases, longest, bytes); 66359673Seric # ifdef LOG 66459673Seric if (LogLevel > 7) 66559673Seric syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total", 66659673Seric ad->ad_name, naliases, longest, bytes); 66759673Seric # endif /* LOG */ 66859673Seric } 66959673Seric /* 67059673Seric ** NDBM modules 67159673Seric */ 67259673Seric 67359673Seric #ifdef NDBM 67459673Seric 67559673Seric /* 67659673Seric ** NDBM_ALOOKUP -- look up alias in ndbm file 67759673Seric */ 67859673Seric 67959673Seric char * 68059673Seric ndbm_alookup(ad, name, e) 68159673Seric register ALIASDB *ad; 68259673Seric char *name; 68359673Seric ENVELOPE *e; 68459673Seric { 68559673Seric int i; 68659673Seric datum rhs, lhs; 68759673Seric char keybuf[MAXNAME + 1]; 68859673Seric 68959697Seric if (tTd(27, 20)) 69059697Seric printf("ndbm_lookup(%s)\n", name); 69159697Seric 69259673Seric /* create a key for fetch */ 69359673Seric i = strlen(name) + 1; 69459673Seric if (i > sizeof keybuf) 69559673Seric i = sizeof keybuf; 69659673Seric bcopy(name, keybuf, i); 69759673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 69859673Seric makelower(keybuf); 69959673Seric 70059673Seric lhs.dsize = i; 70159673Seric lhs.dptr = keybuf; 70259673Seric rhs = dbm_fetch((DBM *) ad->ad_dbp, lhs); 70359673Seric return (rhs.dptr); 70459673Seric } 70559673Seric 70659673Seric 70759673Seric /* 70859673Seric ** NDBM_ASTORE -- store a datum in the database 70959673Seric */ 71059673Seric 71159673Seric void 71259673Seric ndbm_astore(ad, lhs, rhs, e) 71359673Seric register ALIASDB *ad; 71459673Seric char *lhs; 71559673Seric char *rhs; 71659673Seric ENVELOPE *e; 71759673Seric { 71859673Seric datum key; 71959673Seric datum data; 72059673Seric int stat; 72159673Seric 72259697Seric key.dsize = strlen(lhs) + 1; 72359673Seric key.dptr = lhs; 72459673Seric 72559697Seric data.dsize = strlen(rhs) + 1; 72659673Seric data.dptr = rhs; 72759673Seric 72859673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_INSERT); 72959673Seric if (stat > 0) 73019784Seric { 73159673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 73259673Seric stat = dbm_store((DBM *) ad->ad_dbp, key, data, DBM_REPLACE); 73359673Seric } 73459673Seric if (stat != 0) 73559673Seric syserr("readaliases: dbm put (%s)", lhs); 73659673Seric } 73719784Seric 73859673Seric 73959673Seric /* 74059673Seric ** NDBM_AINIT -- initialize DBM database 74159673Seric */ 74259673Seric 74359673Seric bool 74459673Seric ndbm_ainit(ad, e) 74559673Seric register ALIASDB *ad; 74659673Seric ENVELOPE *e; 74759673Seric { 74859673Seric char buf[MAXNAME]; 74959673Seric 75059697Seric if (tTd(27, 2)) 75159697Seric printf("ndbm_ainit(%s)\n", ad->ad_name); 75259697Seric 75359673Seric /* open the database */ 75459673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDONLY, DBMMODE); 75559673Seric if (ad->ad_dbp == NULL) 75659673Seric return FALSE; 75759673Seric 75859673Seric /* wait for @:@ to appear */ 75959673Seric aliaswait(ad, ".pag", e); 76059673Seric 76159673Seric return TRUE; 76259673Seric } 76359673Seric 76459673Seric 76559673Seric /* 76659673Seric ** NDBM_AREBUILD -- rebuild hash database 76759673Seric */ 76859673Seric 76959673Seric void 770*59733Seric ndbm_arebuild(ad, fp, automatic, e) 77159673Seric register ALIASDB *ad; 77259673Seric FILE *fp; 773*59733Seric int automatic; 77459673Seric ENVELOPE *e; 77559673Seric { 77659673Seric register DBM *db; 77759673Seric int i; 77859673Seric char buf[MAXNAME]; 77959673Seric 78059697Seric if (tTd(27, 2)) 78159697Seric printf("ndbm_arebuild(%s)\n", ad->ad_name); 78259697Seric 78359673Seric db = dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 78459673Seric if (db == NULL) 78559673Seric { 78659701Seric syserr("ndbm_arebuild: cannot create %s", buf); 78759673Seric return; 78859673Seric } 78959673Seric ad->ad_dbp = (void *) db; 79059701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 79159673Seric 79259673Seric /* read and store the aliases */ 793*59733Seric readaliases(ad, fp, automatic, e); 79459673Seric } 79559673Seric 79659673Seric /* 79759673Seric ** NDBM_ACLOSE -- close the database 79859673Seric */ 79959673Seric 80059673Seric void 80159673Seric ndbm_aclose(ad, e) 80259673Seric register ALIASDB *ad; 80359673Seric ENVELOPE *e; 80459673Seric { 80559673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 80659673Seric { 80758059Seric #ifdef YPCOMPAT 80859673Seric char buf[200]; 80958846Seric 81059673Seric (void) sprintf(buf, "%010ld", curtime()); 81159673Seric ndbm_astore(ad, "YP_LAST_MODIFIED", buf, e); 81259673Seric 81359673Seric (void) myhostname(buf, sizeof buf); 81459673Seric ndbm_astore(ad, "YP_MASTER_NAME", buf, e); 81558059Seric #endif 81619784Seric 81759673Seric /* write out the distinguished alias */ 81859673Seric ndbm_astore(ad, "@", "@", e); 81919784Seric } 82059673Seric dbm_close((DBM *) ad->ad_dbp); 82159673Seric } 82219784Seric 82359673Seric #endif 82459673Seric /* 82559673Seric ** HASH (NEWDB) Modules 82659673Seric */ 82759673Seric 82859673Seric #ifdef NEWDB 82959673Seric 83059673Seric /* 83159673Seric ** HASH_ALOOKUP -- look up alias in hash file 83259673Seric */ 83359673Seric 83459673Seric char * 83559673Seric hash_alookup(ad, name, e) 83659673Seric register ALIASDB *ad; 83759673Seric char *name; 83859673Seric ENVELOPE *e; 83959673Seric { 84059673Seric int i; 84159673Seric DBT rhs, lhs; 84259673Seric int s; 84359673Seric char keybuf[MAXNAME + 1]; 84459673Seric 84559697Seric if (tTd(27, 20)) 84659697Seric printf("hash_alookup(%s)\n", name); 84759697Seric 84859673Seric /* create a key for fetch */ 84959673Seric i = strlen(name) + 1; 85059673Seric if (i > sizeof keybuf) 85159673Seric i = sizeof keybuf; 85259673Seric bcopy(name, keybuf, i); 85359673Seric if (!bitnset(M_USR_UPPER, LocalMailer->m_flags)) 85459673Seric makelower(keybuf); 85559673Seric 85659673Seric lhs.size = i; 85759673Seric lhs.data = keybuf; 85859673Seric i = ad->ad_ndbp->get(ad->ad_ndbp, &lhs, &rhs, 0); 85959673Seric if (i == 0) 86059673Seric return (rhs.data); 86159673Seric return (NULL); 862292Seric } 86359673Seric 86459673Seric 86559673Seric /* 86659673Seric ** HASH_ASTORE -- store a datum in the database 86759673Seric */ 86859673Seric 86959673Seric void 87059673Seric hash_astore(ad, lhs, rhs, e) 87159673Seric register ALIASDB *ad; 87259673Seric char *lhs; 87359673Seric char *rhs; 87459673Seric ENVELOPE *e; 87559673Seric { 87659673Seric int stat; 87759673Seric DBT key; 87859673Seric DBT data; 87959673Seric 88059697Seric if (tTd(27, 20)) 88159697Seric printf("hash_astore(%s, %s)\n", lhs, rhs); 88259697Seric 88359697Seric key.size = strlen(lhs) + 1; 88459673Seric key.data = lhs; 88559673Seric 88659697Seric data.size = strlen(rhs) + 1; 88759673Seric data.data = rhs; 88859673Seric 88959673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, R_NOOVERWRITE); 89059673Seric if (stat > 0) 89159673Seric { 89259673Seric usrerr("050 Warning: duplicate alias name %s", lhs); 89359673Seric stat = ad->ad_ndbp->put(ad->ad_ndbp, &key, &data, 0); 89459673Seric } 89559673Seric if (stat != 0) 89659673Seric syserr("readaliases: db put (%s)", lhs); 89759673Seric } 89859673Seric 89959673Seric 90059673Seric /* 90159673Seric ** HASH_AINIT -- initialize hash database 90259673Seric */ 90359673Seric 90459673Seric bool 90559673Seric hash_ainit(ad, e) 90659673Seric register ALIASDB *ad; 90759673Seric ENVELOPE *e; 90859673Seric { 90959673Seric char buf[MAXNAME]; 91059673Seric 91159697Seric if (tTd(27, 2)) 91259697Seric printf("hash_ainit(%s)\n", ad->ad_name); 91359697Seric 91459673Seric /* open the database */ 91559673Seric (void) strcpy(buf, ad->ad_name); 91659673Seric (void) strcat(buf, ".db"); 91759673Seric ad->ad_ndbp = dbopen(buf, O_RDONLY, DBMMODE, DB_HASH, NULL); 91859673Seric if (ad->ad_ndbp == NULL) 91959673Seric return FALSE; 92059673Seric 92159673Seric /* wait for @:@ to appear */ 92259673Seric aliaswait(ad, ".db", e); 92359673Seric return TRUE; 92459673Seric } 92559673Seric 92659673Seric 92759673Seric /* 92859673Seric ** HASH_AREBUILD -- rebuild hash database 92959673Seric */ 93059673Seric 93159673Seric void 932*59733Seric hash_arebuild(ad, fp, automatic, e) 93359673Seric register ALIASDB *ad; 93459673Seric FILE *fp; 935*59733Seric int automatic; 93659673Seric ENVELOPE *e; 93759673Seric { 93859673Seric register DB *db; 93959673Seric char buf[MAXNAME]; 94059673Seric 94159697Seric if (tTd(27, 2)) 94259697Seric printf("hash_arebuild(%s)\n", ad->ad_name); 94359697Seric 94459701Seric (void) strcpy(buf, ad->ad_name); 94559701Seric (void) strcat(buf, ".db"); 94659673Seric db = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 94759673Seric if (db == NULL) 94859673Seric { 94959701Seric syserr("hash_arebuild: cannot create %s", buf); 95059673Seric return; 95159673Seric } 95259673Seric ad->ad_ndbp = db; 95359701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 95459673Seric 95559673Seric /* read and store the aliases */ 956*59733Seric readaliases(ad, fp, automatic, e); 95759673Seric } 95859673Seric 95959673Seric 96059673Seric /* 96159673Seric ** HASH_ACLOSE -- add distinguished entries and close the database 96259673Seric */ 96359673Seric 96459673Seric void 96559673Seric hash_aclose(ad, e) 96659673Seric ALIASDB *ad; 96759673Seric ENVELOPE *e; 96859673Seric { 96959697Seric if (tTd(27, 9)) 97059697Seric printf("hash_aclose(%x)\n", ad->ad_flags); 97159697Seric 97259673Seric if (bitset(ADF_WRITABLE, ad->ad_flags)) 97359673Seric { 97459673Seric /* write out the distinguished alias */ 97559673Seric hash_astore(ad, "@", "@", e); 97659673Seric } 97759673Seric 97859673Seric if (ad->ad_ndbp->close(ad->ad_ndbp) != 0) 97959673Seric syserr("readaliases: db close failure"); 98059673Seric } 98159673Seric 98259673Seric #endif 983292Seric /* 98459673Seric ** STAB (Symbol Table) Modules 98559673Seric */ 98659673Seric 98759673Seric 98859673Seric /* 98959673Seric ** STAB_ALOOKUP -- look up alias in symbol table 99059673Seric */ 99159673Seric 99259673Seric char * 99359673Seric stab_alookup(ad, name, e) 99459673Seric register ALIASDB *ad; 99559673Seric char *name; 99659673Seric ENVELOPE *e; 99759673Seric { 99859673Seric register STAB *s; 99959673Seric 100059697Seric if (tTd(27, 20)) 100159697Seric printf("stab_lookup(%s)\n", name); 100259697Seric 100359673Seric s = stab(name, ST_ALIAS, ST_FIND); 100459673Seric if (s != NULL) 100559673Seric return (s->s_alias); 100659673Seric return (NULL); 100759673Seric } 100859673Seric 100959673Seric 101059673Seric /* 101159673Seric ** STAB_ASTORE -- store in symtab (actually using during init, not rebuild) 101259673Seric */ 101359673Seric 101459673Seric void 101559673Seric stab_astore(ad, lhs, rhs, e) 101659673Seric register ALIASDB *ad; 101759673Seric char *lhs; 101859673Seric char *rhs; 101959673Seric ENVELOPE *e; 102059673Seric { 102159673Seric register STAB *s; 102259673Seric 102359673Seric s = stab(lhs, ST_ALIAS, ST_ENTER); 102459673Seric s->s_alias = newstr(rhs); 102559673Seric } 102659673Seric 102759673Seric 102859673Seric /* 102959673Seric ** STAB_AINIT -- initialize (reads data file) 103059673Seric */ 103159673Seric 103259673Seric bool 103359673Seric stab_ainit(ad, e) 103459673Seric register ALIASDB *ad; 103559673Seric ENVELOPE *e; 103659673Seric { 103759673Seric FILE *af; 103859673Seric 103959697Seric if (tTd(27, 2)) 104059697Seric printf("stab_ainit(%s)\n", ad->ad_name); 104159697Seric 104259673Seric af = fopen(ad->ad_name, "r"); 104359673Seric if (af == NULL) 104459673Seric { 104559673Seric syserr("554 Can't open %s", ad->ad_name); 104659673Seric errno = 0; 104759673Seric return FALSE; 104859673Seric } 104959673Seric 1050*59733Seric readaliases(ad, af, TRUE, e); 105159673Seric } 105259673Seric 105359673Seric 105459673Seric /* 105559673Seric ** STAB_AREBUILD -- rebuild alias file 105659673Seric */ 105759673Seric 105859673Seric void 1059*59733Seric stab_arebuild(ad, fp, automatic, e) 106059673Seric ALIASDB *ad; 106159673Seric FILE *fp; 1062*59733Seric int automatic; 106359673Seric ENVELOPE *e; 106459673Seric { 106559697Seric if (tTd(27, 2)) 106659697Seric printf("stab_arebuild(%s)\n", ad->ad_name); 106759697Seric 106859701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 106959673Seric } 107059673Seric 107159673Seric 107259673Seric /* 107359673Seric ** STAB_ACLOSE -- close symbol table (???) 107459673Seric */ 107559673Seric 107659673Seric void 107759673Seric stab_aclose(ad, e) 107859673Seric ALIASDB *ad; 107959673Seric ENVELOPE *e; 108059673Seric { 108159673Seric /* ignore it */ 108259673Seric } 108359673Seric /* 108459673Seric ** NIS Modules 108559673Seric */ 108659673Seric 108759724Seric #ifdef NIS_ALIASES 108859673Seric 108959673Seric /* 109059673Seric ** NIS_ALOOKUP 109159673Seric */ 109259673Seric 109359673Seric char * 109459673Seric nis_alookup(ad, name, e) 109559673Seric ALIASDB *ad; 109659673Seric char *name; 109759673Seric ENVELOPE *e; 109859673Seric { 109959673Seric auto char *vp; 110059673Seric auto int vsize; 110159673Seric 110259697Seric if (tTd(27, 20)) 110359697Seric printf("nis_lookup(%s)\n", name); 110459697Seric 110559673Seric if (ypmatch(ad->ad_domain, ad->ad_name, name, strlen(name), 110659673Seric &vp, &vsize) != 0) 110759673Seric return NULL; 110859673Seric return vp; 110959673Seric } 111059673Seric 111159673Seric /* 111259673Seric ** NIS_ASTORE 111359673Seric */ 111459673Seric 111559673Seric void 111659673Seric nis_astore(ad, lhs, rhs, e) 111759673Seric ALIASDB *ad; 111859673Seric char *lhs; 111959673Seric char *rhs; 112059673Seric ENVELOPE *e; 112159673Seric { 112259673Seric /* nothing */ 112359673Seric } 112459673Seric 112559673Seric /* 112659673Seric ** NIS_AINIT 112759673Seric */ 112859673Seric 112959673Seric bool 113059673Seric nis_ainit(ad, e) 113159673Seric ALIASDB *ad; 113259673Seric ENVELOPE *e; 113359673Seric { 113459673Seric register char *p; 113559673Seric auto char *ypmaster; 113659673Seric 113759697Seric if (tTd(27, 2)) 113859697Seric printf("nis_ainit(%s)\n", ad->ad_name); 113959697Seric 114059673Seric p = strchr(ad->ad_name, '@'); 114159673Seric if (p != NULL) 114259673Seric { 114359673Seric *p++ = '\0'; 114459673Seric if (*p != '\0') 114559673Seric ad->ad_domain = p; 114659673Seric } 114759673Seric if (ad->ad_domain == NULL) 114859673Seric yp_get_default_domain(&ad->ad_domain); 114959673Seric 115059673Seric if (*ad->ad_name == '\0') 115159673Seric ad->ad_name = "mail.aliases"; 115259673Seric 115359673Seric yperr = yp_master(ad->ad_domain, ad->ad_name, &ypmaster); 115459673Seric return (yperr == 0); 115559673Seric } 115659673Seric 115759673Seric /* 115859673Seric ** NIS_AREBUILD 115959673Seric */ 116059673Seric 116159673Seric void 1162*59733Seric nis_arebuild(ad, fp, automatic, e) 116359673Seric ALIASDB *ad; 116459673Seric FILE *fp; 1165*59733Seric int automatic; 116659673Seric ENVELOPE *e; 116759673Seric { 116859697Seric if (tTd(27, 2)) 116959697Seric printf("nis_arebuild(%s)\n", ad->ad_name); 117059673Seric } 117159673Seric 117259673Seric 117359673Seric /* 117459673Seric ** NIS_ACLOSE 117559673Seric */ 117659673Seric 117759673Seric void 117859673Seric nis_aclose(ad, e) 117959673Seric ALIASDB *ad; 118059673Seric ENVELOPE *e; 118159673Seric { 118259673Seric /* nothing */ 118359673Seric } 118459673Seric 118559724Seric #endif /* NIS_ALIASES */ 118659673Seric /* 118759673Seric ** Implicit Modules 118858059Seric ** 118959673Seric ** Tries several types. For back compatibility. 119058059Seric */ 119158059Seric 119259673Seric /* 119359673Seric ** IMPL_ALOOKUP -- lookup in best open database 119459673Seric */ 119558059Seric 119659673Seric char * 119759673Seric impl_alookup(ad, name, e) 119859673Seric ALIASDB *ad; 119959673Seric char *name; 120059673Seric ENVELOPE *e; 120158059Seric { 120259697Seric if (tTd(27, 20)) 120359697Seric printf("impl_lookup(%s)\n", name); 120459697Seric 120559673Seric #ifdef NEWDB 120659673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 120759673Seric return hash_alookup(ad, name, e); 120859673Seric #endif 120959673Seric #ifdef NDBM 121059673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 121159673Seric return ndbm_alookup(ad, name, e); 121259673Seric #endif 121359673Seric return stab_alookup(ad, name, e); 121459673Seric } 121559673Seric 121659673Seric /* 121759673Seric ** IMPL_ASTORE -- store in open databases 121859673Seric */ 121959673Seric 122059673Seric void 122159673Seric impl_astore(ad, lhs, rhs, e) 122259673Seric ALIASDB *ad; 122359673Seric char *lhs; 122459673Seric char *rhs; 122559673Seric ENVELOPE *e; 122659673Seric { 122759673Seric #ifdef NEWDB 122859673Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 122959673Seric hash_astore(ad, lhs, rhs, e); 123059673Seric #endif 123159673Seric #ifdef NDBM 123259673Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 123359673Seric ndbm_astore(ad, lhs, rhs, e); 123459673Seric #endif 123559673Seric stab_astore(ad, lhs, rhs, e); 123659673Seric } 123759673Seric 123859673Seric /* 123959673Seric ** IMPL_AINIT -- implicit database lookup 124059673Seric */ 124159673Seric 124259673Seric bool 124359673Seric impl_ainit(ad, e) 124459673Seric ALIASDB *ad; 124559673Seric ENVELOPE *e; 124659673Seric { 1247*59733Seric struct stat stb; 1248*59733Seric 124959697Seric if (tTd(27, 2)) 125059697Seric printf("impl_ainit(%s)\n", ad->ad_name); 125159697Seric 1252*59733Seric if (stat(ad->ad_name, &stb) < 0) 1253*59733Seric { 1254*59733Seric /* no alias file at all */ 1255*59733Seric return FALSE; 1256*59733Seric } 1257*59733Seric 125859673Seric #ifdef NEWDB 125959697Seric ad->ad_flags |= ADF_IMPLHASH; 126059673Seric if (hash_ainit(ad, e)) 126158059Seric { 126259697Seric return TRUE; 126359673Seric } 126459697Seric ad->ad_flags &= ~ADF_IMPLHASH; 126559673Seric #endif 126659673Seric #ifdef NDBM 126759697Seric ad->ad_flags |= ADF_IMPLNDBM; 126859673Seric if (ndbm_ainit(ad, e)) 126959673Seric { 127059697Seric return TRUE; 127159673Seric } 127259697Seric ad->ad_flags &= ~ADF_IMPLNDBM; 127359673Seric #endif 127458059Seric 1275*59733Seric if (Verbose) 1276*59733Seric message("WARNING: cannot open alias database %s", ad->ad_name); 1277*59733Seric 127859673Seric if (stab_ainit(ad, e)) 127959673Seric { 128059697Seric return TRUE; 128159673Seric } 128259697Seric 128359697Seric return FALSE; 128459673Seric } 128558059Seric 128659673Seric /* 128759673Seric ** IMPL_AREBUILD -- rebuild alias database 128859673Seric */ 128958059Seric 129059673Seric void 1291*59733Seric impl_arebuild(ad, fp, automatic, e) 129259673Seric ALIASDB *ad; 129359673Seric FILE *fp; 1294*59733Seric int automatic; 129559673Seric ENVELOPE *e; 129659673Seric { 129759673Seric #ifdef NEWDB 129859673Seric DB *ndb; 129959673Seric char buf[MAXNAME]; 130059697Seric #endif 130159673Seric 130259697Seric if (tTd(27, 2)) 130359697Seric printf("impl_arebuild(%s)\n", ad->ad_name); 130459697Seric 130559697Seric #ifdef NEWDB 130659673Seric (void) strcpy(buf, ad->ad_name); 130759673Seric (void) strcat(buf, ".db"); 130859673Seric ndb = dbopen(buf, O_RDWR|O_CREAT|O_TRUNC, DBMMODE, DB_HASH, NULL); 130959673Seric if (ndb == NULL) 131058059Seric { 131159673Seric syserr("rebuildaliases: cannot create %s", buf); 131258059Seric } 131359673Seric else 131459673Seric { 131559673Seric ad->ad_ndbp = ndb; 131659673Seric ad->ad_flags |= ADF_IMPLHASH; 131759673Seric #if defined(NDBM) && defined(YPCOMPAT) 131859673Seric if (access("/var/yp/Makefile", R_OK) != 0) 131959673Seric #endif 132059697Seric goto readem; 132159673Seric } 132259673Seric #endif 132359673Seric 132459673Seric #ifdef NDBM 132559673Seric ad->ad_dbp = (void *) dbm_open(ad->ad_name, O_RDWR|O_CREAT|O_TRUNC, DBMMODE); 132659673Seric if (ad->ad_dbp == NULL) 132759673Seric { 132859673Seric syserr("rebuildaliases: cannot create %s.{pag,dir}", 132959673Seric ad->ad_name); 133059673Seric } 133159673Seric else 133259673Seric { 133359673Seric ad->ad_flags |= ADF_IMPLNDBM; 133459673Seric } 133559673Seric #endif 133659673Seric 133759673Seric if (!bitset(ADF_IMPLHASH|ADF_IMPLNDBM, ad->ad_flags)) 133859673Seric return; 133959673Seric 134059697Seric readem: 134159701Seric ad->ad_flags |= ADF_WRITABLE|ADF_VALID; 134259673Seric 134359673Seric /* read and store aliases */ 1344*59733Seric readaliases(ad, fp, automatic, e); 134558059Seric } 134658059Seric 134759673Seric 134859673Seric /* 134959673Seric ** IMPL_ACLOSE -- close any open database(s) 135059673Seric */ 135159673Seric 135259673Seric void 135359673Seric impl_aclose(ad, e) 135459673Seric ALIASDB *ad; 135559673Seric ENVELOPE *e; 135659673Seric { 135759673Seric #ifdef NEWDB 135859697Seric if (bitset(ADF_IMPLHASH, ad->ad_flags)) 135959697Seric hash_aclose(ad, e); 136059673Seric #endif 136159673Seric 136259673Seric #ifdef NDBM 136359697Seric if (bitset(ADF_IMPLNDBM, ad->ad_flags)) 136459697Seric ndbm_aclose(ad, e); 136559673Seric #endif 136659673Seric } 136758059Seric /* 136859673Seric ** SETUPALIASES -- set up aliases classes 136959673Seric */ 137059673Seric 137159673Seric #ifdef NEWDB 137259673Seric ALIASCLASS HashAClass = 137359673Seric { 137459673Seric "hash", hash_alookup, hash_astore, 137559673Seric hash_ainit, hash_arebuild, hash_aclose, 137659673Seric ACF_BUILDABLE 137759673Seric }; 137859673Seric #endif 137959673Seric 138059673Seric #ifdef NDBM 138159673Seric ALIASCLASS DbmAClass = 138259673Seric { 138359673Seric "dbm", ndbm_alookup, ndbm_astore, 138459673Seric ndbm_ainit, ndbm_arebuild, ndbm_aclose, 138559673Seric ACF_BUILDABLE 138659673Seric }; 138759673Seric #endif 138859673Seric 138959724Seric #ifdef NIS_ALIASES 139059673Seric ALIASCLASS NisAClass = 139159673Seric { 139259673Seric "nis", nis_alookup, nis_astore, 139359673Seric nis_ainit, nis_arebuild, nis_aclose, 139459673Seric 0 139559673Seric }; 139659673Seric #endif 139759673Seric 139859673Seric ALIASCLASS StabAClass = 139959673Seric { 140059673Seric "stab", stab_alookup, stab_astore, 140159673Seric stab_ainit, stab_arebuild, stab_aclose, 140259673Seric 0 140359673Seric }; 140459673Seric 140559673Seric ALIASCLASS ImplAClass = 140659673Seric { 140759673Seric "implicit", impl_alookup, impl_astore, 140859673Seric impl_ainit, impl_arebuild, impl_aclose, 140959673Seric ACF_BUILDABLE 141059673Seric }; 141159673Seric 141259673Seric setupaliases() 141359673Seric { 141459673Seric register STAB *s; 141559673Seric 141659673Seric #ifdef NEWDB 141759673Seric s = stab("hash", ST_ALIASCLASS, ST_ENTER); 141859673Seric s->s_aliasclass = &HashAClass; 141959673Seric #endif 142059673Seric 142159673Seric #ifdef NDBM 142259673Seric s = stab("dbm", ST_ALIASCLASS, ST_ENTER); 142359673Seric s->s_aliasclass = &DbmAClass; 142459673Seric #endif 142559673Seric 142659724Seric #ifdef NIS_ALIASES 142759673Seric s = stab("nis", ST_ALIASCLASS, ST_ENTER); 142859673Seric s->s_aliasclass = &NisAClass; 142959673Seric #endif 143059673Seric 143159673Seric #if !defined(NEWDB) && !defined(NDBM) 143259673Seric s = stab("stab", ST_ALIASCLASS, ST_ENTER); 143359673Seric s->s_aliasclass = &StabAClass; 143459673Seric #endif 143559673Seric 143659673Seric s = stab("implicit", ST_ALIASCLASS, ST_ENTER); 143759673Seric s->s_aliasclass = &ImplAClass; 143859673Seric } 143959673Seric /* 1440292Seric ** FORWARD -- Try to forward mail 1441292Seric ** 1442292Seric ** This is similar but not identical to aliasing. 1443292Seric ** 1444292Seric ** Parameters: 14454314Seric ** user -- the name of the user who's mail we would like 14464314Seric ** to forward to. It must have been verified -- 14474314Seric ** i.e., the q_home field must have been filled 14484314Seric ** in. 14494999Seric ** sendq -- a pointer to the head of the send queue to 14504999Seric ** put this user's aliases in. 1451292Seric ** 1452292Seric ** Returns: 14534098Seric ** none. 1454292Seric ** 1455292Seric ** Side Effects: 14563185Seric ** New names are added to send queues. 1457292Seric */ 1458292Seric 145955012Seric forward(user, sendq, e) 14602966Seric ADDRESS *user; 14614999Seric ADDRESS **sendq; 146255012Seric register ENVELOPE *e; 1463292Seric { 146457136Seric char *pp; 146557136Seric char *ep; 14664069Seric 14677671Seric if (tTd(27, 1)) 14684098Seric printf("forward(%s)\n", user->q_paddr); 14694098Seric 14704594Seric if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags)) 14714098Seric return; 14724314Seric if (user->q_home == NULL) 147358059Seric { 147458151Seric syserr("554 forward: no home"); 147558059Seric user->q_home = "/nosuchdirectory"; 147658059Seric } 14774069Seric 14784069Seric /* good address -- look for .forward file in home */ 147955012Seric define('z', user->q_home, e); 148057136Seric define('u', user->q_user, e); 148157136Seric define('h', user->q_host, e); 148257136Seric if (ForwardPath == NULL) 148358050Seric ForwardPath = newstr("\201z/.forward"); 148457136Seric 148557136Seric for (pp = ForwardPath; pp != NULL; pp = ep) 148657136Seric { 148758247Seric int err; 148857232Seric char buf[MAXPATHLEN+1]; 148957136Seric 149057136Seric ep = strchr(pp, ':'); 149157136Seric if (ep != NULL) 149257136Seric *ep = '\0'; 149357136Seric expand(pp, buf, &buf[sizeof buf - 1], e); 149457136Seric if (ep != NULL) 149557136Seric *ep++ = ':'; 149657136Seric if (tTd(27, 3)) 149757136Seric printf("forward: trying %s\n", buf); 149858247Seric err = include(buf, TRUE, user, sendq, e); 149958247Seric if (err == 0) 150057136Seric break; 150158247Seric if (transienterror(err)) 150258247Seric { 150358247Seric /* we have to suspend this message */ 150459563Seric if (tTd(27, 2)) 150559563Seric printf("forward: transient error on %s\n", buf); 150659563Seric #ifdef LOG 150759563Seric if (LogLevel > 2) 150859624Seric syslog(LOG_ERR, "%s: forward %s: transient error: %s", 150959624Seric e->e_id, buf, errstring(err)); 151059563Seric #endif 151159611Seric message("%s: %s: message queued", buf, errstring(err)); 151258247Seric user->q_flags |= QQUEUEUP|QDONTSEND; 151358247Seric return; 151458247Seric } 151557136Seric } 1516292Seric } 1517