1292Seric # include <stdio.h>
2292Seric # include <ctype.h>
3292Seric # include <pwd.h>
43309Seric # include "sendmail.h"
5292Seric 
6*4097Seric static char SccsId[] = "@(#)alias.c	3.9	08/10/81";
7402Seric 
8292Seric /*
9292Seric **  ALIAS -- Compute aliases.
10292Seric **
11*4097Seric **	Scans the file AliasFile for a set of aliases.
123185Seric **	If found, it arranges to deliver to them.  Uses libdbm
133185Seric **	database if -DDBM.
14292Seric **
15292Seric **	Parameters:
16*4097Seric **		a -- address to alias.
17292Seric **
18292Seric **	Returns:
19292Seric **		none
20292Seric **
21292Seric **	Side Effects:
223185Seric **		Aliases found are expanded.
23292Seric **
24292Seric **	Defined Constants:
25292Seric **		MAXRCRSN -- the maximum recursion depth.
26292Seric **
27292Seric **	Files:
28*4097Seric **		AliasFile -- the mail aliases.  The format is
29569Seric **			a series of lines of the form:
30569Seric **				alias:name1,name2,name3,...
31569Seric **			where 'alias' expands to all of
32569Seric **			'name[i]'.  Continuations begin with
33569Seric **			space or tab.
34*4097Seric **		AliasFile.pag, AliasFile.dir: libdbm version
351503Smark **			of alias file.  Keys are aliases, datums
361503Smark **			(data?) are name1,name2, ...
37292Seric **
38292Seric **	Notes:
39292Seric **		If NoAlias (the "-n" flag) is set, no aliasing is
40292Seric **			done.
41292Seric **
42292Seric **	Deficiencies:
43292Seric **		It should complain about names that are aliased to
44292Seric **			nothing.
45292Seric **		It is unsophisticated about line overflows.
46292Seric */
47292Seric 
48292Seric 
49292Seric # define MAXRCRSN	10
50292Seric 
511503Smark #ifdef DBM
522966Seric typedef struct
532966Seric {
542966Seric 	char	*dptr;
552966Seric 	int dsize;
562966Seric } datum;
571503Smark datum lhs, rhs;
581515Seric extern datum fetch();
591503Smark #endif DBM
60292Seric 
61*4097Seric alias(a)
62*4097Seric 	register ADDRESS *a;
63292Seric {
642966Seric 	register ADDRESS *q;
654081Seric 	register char *p;
66*4097Seric 	extern char *AliasFile;
674081Seric # ifndef DBM
68292Seric 	FILE *af;
69292Seric 	char line[MAXLINE+1];
70292Seric 	bool didalias;
71292Seric 	bool gotmatch;
722966Seric 	auto ADDRESS al;
734081Seric # endif DBM
74292Seric 
75292Seric 	if (NoAlias)
76292Seric 		return;
77292Seric # ifdef DEBUG
78292Seric 	if (Debug)
79292Seric 		printf("--- alias ---\n");
80292Seric # endif
81292Seric 
82*4097Seric # ifdef DBM
83*4097Seric 	dbminit(AliasFile);
84*4097Seric # endif DBM
85292Seric 
86292Seric 	/*
87*4097Seric 	**  Scan send queue for local mailer.
881515Seric 	**	We only have to do this once, since anything we alias
891874Seric 	**	to is being put at the end of the queue we are
90*4097Seric 	**	scanning or another queue.  This is because we only
91*4097Seric 	**	scan the local mailer queue.
921515Seric 	*/
931515Seric 
94*4097Seric 	for (q = Mailer[M_LOCAL]->m_sendq; q != NULL; q = q->q_next)
951515Seric 	{
96*4097Seric 		To = q->q_paddr;
974065Seric 
98*4097Seric 		/* don't realias already aliased names */
99*4097Seric 		if (bitset(QDONTSEND, q->q_flags))
100*4097Seric 			continue;
1011874Seric 
102*4097Seric # ifdef DBM
103*4097Seric 		/* create a key for fetch */
104*4097Seric 		lhs.dptr = q->q_user;
105*4097Seric 		lhs.dsize = strlen(q->q_user) + 1;
106*4097Seric 		rhs = fetch(lhs);
1071622Seric 
108*4097Seric 		/* find this alias? */
109*4097Seric 		p = rhs.dptr;
110*4097Seric 		if (p == NULL)
111*4097Seric 			continue;
112*4097Seric # else DBM
113*4097Seric 		s = stab(q->q_user, ST_ALIAS, ST_FIND);
114*4097Seric 		if (s == NULL)
115*4097Seric 			continue;
116*4097Seric 		p = s->s_alias;
117*4097Seric # endif DBM
1181515Seric 
119*4097Seric 		/*
120*4097Seric 		**  Match on Alias.
121*4097Seric 		**	Deliver to the target list.
122*4097Seric 		**	Remove the alias from the send queue
123*4097Seric 		**	  and put it on the Alias queue.
124*4097Seric 		*/
1251515Seric 
1261515Seric # ifdef DEBUG
127*4097Seric 		if (Debug)
128*4097Seric 			printf("%s (%s, %s) aliased to %s\n",
129*4097Seric 			    q->q_paddr, q->q_host, q->q_user, p);
1301515Seric # endif
131*4097Seric 		if (Verbose)
132*4097Seric 			message("050", "aliased to %s", p);
133*4097Seric 		q->q_flags |= QDONTSEND;
134*4097Seric 		sendto(p, 1);
1351515Seric 	}
136292Seric }
137292Seric /*
138292Seric **  FORWARD -- Try to forward mail
139292Seric **
140292Seric **	This is similar but not identical to aliasing.
141292Seric **
142292Seric **	Currently it is undefined, until the protocol for userinfo
143292Seric **	databases is finalized.
144292Seric **
145292Seric **	Parameters:
146292Seric **		user -- the name of the user who's mail we
147292Seric **			would like to forward to.
148292Seric **
149292Seric **	Returns:
150292Seric **		TRUE -- we have forwarded it somewhere.
151292Seric **		FALSE -- not forwarded; go ahead & deliver.
152292Seric **
153292Seric **	Side Effects:
1543185Seric **		New names are added to send queues.
155292Seric */
156292Seric 
157292Seric bool
158292Seric forward(user)
1592966Seric 	ADDRESS *user;
160292Seric {
1614078Seric 	char buf[60];
1624069Seric 	register FILE *fp;
1634069Seric 	register char *p;
1644069Seric 
1654078Seric 	if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags))
1664069Seric 		return (FALSE);
1674069Seric 
1684069Seric 	/* good address -- look for .forward file in home */
1694081Seric 	(void) expand("$z/.forward", buf, &buf[sizeof buf - 1]);
1704069Seric 	fp = fopen(buf, "r");
1714069Seric 	if (fp == NULL)
1724069Seric 		return (FALSE);
1734069Seric 
1744069Seric 	/* we do have an address to forward to -- do it */
1754081Seric 	(void) fgets(buf, sizeof buf, fp);
1764069Seric 	if ((p = index(buf, '\n')) != NULL)
1774069Seric 		*p = '\0';
1784081Seric 	(void) fclose(fp);
1794069Seric 	if (buf[0] == '\0')
1804069Seric 		return (FALSE);
1814069Seric 	if (Verbose)
1824069Seric 		message("050", "forwarded to %s", buf);
1834069Seric 	sendto(buf, 1);
1844069Seric 	return (TRUE);
185292Seric }
186