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