1292Seric # include <stdio.h>
2292Seric # include <ctype.h>
3292Seric # include <pwd.h>
4292Seric # include "dlvrmail.h"
5292Seric 
6*1503Smark static char SccsId[] = "@(#)alias.c	1.4	10/17/80";
7402Seric 
8292Seric /*
9292Seric **  ALIAS -- Compute aliases.
10292Seric **
11*1503Smark **	Scans the file ALIASFILE for a set of aliases.
12292Seric **	If found, it arranges to deliver to them by inserting the
13*1503Smark **	new names onto the SendQ queue.  Uses libdbm database if -DDBM.
14292Seric **
15292Seric **	Parameters:
16292Seric **		none
17292Seric **
18292Seric **	Returns:
19292Seric **		none
20292Seric **
21292Seric **	Side Effects:
22292Seric **		Aliases found on SendQ are removed and put onto
23292Seric **		AliasQ; replacements are added to SendQ.  This is
24292Seric **		done until no such replacement occurs.
25292Seric **
26292Seric **	Defined Constants:
27292Seric **		MAXRCRSN -- the maximum recursion depth.
28292Seric **		ALIASFILE -- the pathname of the alias file.
29292Seric **
30292Seric **	Called By:
31292Seric **		main
32292Seric **
33292Seric **	Files:
34569Seric **		ALIASFILE -- the mail aliases.  The format is
35569Seric **			a series of lines of the form:
36569Seric **				alias:name1,name2,name3,...
37569Seric **			where 'alias' expands to all of
38569Seric **			'name[i]'.  Continuations begin with
39569Seric **			space or tab.
40*1503Smark **		ALIASFILE.pag, ALIASFILE.dir: libdbm version
41*1503Smark **			of alias file.  Keys are aliases, datums
42*1503Smark **			(data?) are name1,name2, ...
43292Seric **
44292Seric **	Notes:
45292Seric **		If NoAlias (the "-n" flag) is set, no aliasing is
46292Seric **			done.
47292Seric **
48292Seric **	Deficiencies:
49292Seric **		It should complain about names that are aliased to
50292Seric **			nothing.
51292Seric **		It is unsophisticated about line overflows.
52292Seric */
53292Seric 
54292Seric 
55292Seric # define ALIASFILE	"/usr/lib/mailaliases"
56292Seric # define MAXRCRSN	10
57292Seric 
58*1503Smark #ifdef DBM
59*1503Smark typedef struct {char *dptr; int dsize;} datum;
60*1503Smark datum lhs, rhs;
61*1503Smark datum fetch();
62*1503Smark #endif DBM
63292Seric 
64292Seric alias()
65292Seric {
66292Seric 	register addrq *q;
67292Seric 	FILE *af;
68292Seric 	char line[MAXLINE+1];
69292Seric 	register char *p;
70292Seric 	extern int errno;
71292Seric 	bool didalias;
72292Seric 	bool gotmatch;
73292Seric 	auto addrq al;
74292Seric 	extern bool sameaddr();
75292Seric 	extern addrq *parse();
76292Seric 
77292Seric 	if (NoAlias)
78292Seric 		return;
79292Seric # ifdef DEBUG
80292Seric 	if (Debug)
81292Seric 		printf("--- alias ---\n");
82292Seric # endif
83292Seric 
84292Seric 	/* open alias file if not already open */
85*1503Smark #ifndef DBM
86292Seric # ifdef DEBUG
87292Seric 	if (Debug && (af = fopen("mailaliases", "r")) != NULL)
88292Seric 		printf(" [using local alias file]\n");
89292Seric 	else
90292Seric # endif
91292Seric 	if ((af = fopen(ALIASFILE, "r")) == NULL)
92292Seric 	{
93292Seric # ifdef DEBUG
94292Seric 		if (Debug)
95292Seric 			printf("Can't open %s\n", ALIASFILE);
96292Seric # endif
97292Seric 		errno = 0;
98292Seric 		return;
99292Seric 	}
100*1503Smark #else DBM
101*1503Smark 	dbminit(ALIASFILE);
102*1503Smark #endif DBM
103292Seric 
104*1503Smark #ifndef DBM
105292Seric 	/*
106292Seric 	**  Scan alias file.
107292Seric 	**	If we find any user that any line matches any user, we
108292Seric 	**	will send to the line rather than to the user.
109292Seric 	**
110292Seric 	**	We pass through the file several times.  Didalias tells
111292Seric 	**	us if we took some alias on this pass through the file;
112292Seric 	**	when it goes false at the top of the loop we don't have
113292Seric 	**	to scan any more.  Gotmatch tells the same thing, but
114292Seric 	**	on a line-by-line basis; it is used for processing
115292Seric 	**	continuation lines.
116292Seric 	*/
117292Seric 
118*1503Smark 	do
119292Seric 	{
120292Seric 		didalias = FALSE;
121292Seric 		gotmatch = FALSE;
122292Seric 		rewind(af);
123292Seric 		while (fgets(line, sizeof line, af) != NULL)
124292Seric 		{
125292Seric 			/* comments begin with `#' */
126292Seric 			if (line[0] == '#')
127292Seric 				continue;
128292Seric 
129292Seric 			/* check for continuation lines */
130292Seric 			if (isspace(line[0]))
131292Seric 			{
132292Seric 				if (gotmatch)
133292Seric 				{
134292Seric 					sendto(line, 1);
135292Seric 				}
136292Seric 				continue;
137292Seric 			}
138292Seric 			gotmatch = FALSE;
139292Seric 
140292Seric 			/*
141292Seric 			**  Check to see if this pseudonym exists in SendQ.
142292Seric 			**	Turn the alias into canonical form.
143292Seric 			**	Then scan SendQ until you do (or do not)
144292Seric 			**	find that address.
145292Seric 			*/
146292Seric 
147292Seric 			/*  Get a canonical form for the alias. */
148292Seric 			for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
149292Seric 				continue;
150292Seric 			if (*p == '\0' || *p == '\n')
151292Seric 			{
152292Seric 			 syntaxerr:
153292Seric 				syserr("Bad alias line `%s'", line);
154292Seric 				continue;
155292Seric 			}
156292Seric 			*p++ = '\0';
157292Seric 			if (parse(line, &al, -1) == NULL)
158292Seric 			{
159292Seric 				*--p = ':';
160292Seric 				goto syntaxerr;
161292Seric 			}
162292Seric 
163292Seric 			/*  Scan SendQ for that canonical form. */
164292Seric 			for (q = &SendQ; (q = nxtinq(q)) != NULL; )
165292Seric 			{
166292Seric 				if (sameaddr(&al, q, TRUE))
167292Seric 					break;
168292Seric 			}
169292Seric 			if (q != NULL)
170292Seric 			{
171*1503Smark #else DBM
172*1503Smark 	/*
173*1503Smark 	**  Scan SendQ
174*1503Smark 	**	We pass through the queue several times.  Didalias tells
175*1503Smark 	**	us if we took some alias on this pass through the queue;
176*1503Smark 	**	when it goes false at the top of the loop we don't have
177*1503Smark 	**	to scan any more.
178*1503Smark 	*/
179*1503Smark 
180*1503Smark 	do
181*1503Smark 	{
182*1503Smark 		didalias = FALSE;
183*1503Smark 		/*  Scan SendQ for that canonical form. */
184*1503Smark 		for (q = &SendQ; (q = nxtinq(q)) != NULL; )
185*1503Smark 		{
186*1503Smark 			lhs.dptr = q -> q_paddr;
187*1503Smark 			lhs.dsize = strlen(lhs.dptr)+1;
188*1503Smark 			rhs = fetch(lhs);
189*1503Smark 			p = rhs.dptr;
190*1503Smark 			if (p != NULL)
191*1503Smark 			{
192*1503Smark #endif
193292Seric 				/*
194292Seric 				**  Match on Alias.
195292Seric 				**	Deliver to the target list.
196292Seric 				**	Remove the alias from the send queue
197292Seric 				**	  and put it on the Alias queue.
198292Seric 				*/
199292Seric 
200292Seric # ifdef DEBUG
201292Seric 				if (Debug)
202292Seric 					printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n",
203292Seric 					    q->q_paddr, q->q_host, q->q_user,
204292Seric 					    p, al.q_paddr, al.q_host, al.q_user);
205292Seric # endif
206292Seric 				tkoffq(q, &SendQ);
207292Seric 				putonq(q, &AliasQ);
208292Seric 				didalias++;
209292Seric 				gotmatch++;
210292Seric 				sendto(p, 1);
211292Seric 			}
212292Seric 		}
213*1503Smark 	} while (didalias);
214*1503Smark #ifndef DBM
215292Seric 	fclose(af);
216*1503Smark #endif
217292Seric }
218292Seric /*
219292Seric **  FORWARD -- Try to forward mail
220292Seric **
221292Seric **	This is similar but not identical to aliasing.
222292Seric **
223292Seric **	Currently it is undefined, until the protocol for userinfo
224292Seric **	databases is finalized.
225292Seric **
226292Seric **	Parameters:
227292Seric **		user -- the name of the user who's mail we
228292Seric **			would like to forward to.
229292Seric **
230292Seric **	Returns:
231292Seric **		TRUE -- we have forwarded it somewhere.
232292Seric **		FALSE -- not forwarded; go ahead & deliver.
233292Seric **
234292Seric **	Side Effects:
235292Seric **		New names are added to SendQ.
236292Seric **
237292Seric **	Called By:
238292Seric **		recipient
239292Seric */
240292Seric 
241292Seric bool
242292Seric forward(user)
243292Seric 	addrq *user;
244292Seric {
245292Seric 	return (FALSE);
246292Seric }
247