1292Seric # include <stdio.h>
2292Seric # include <ctype.h>
3292Seric # include <pwd.h>
4292Seric # include "dlvrmail.h"
5292Seric 
6*1515Seric static char SccsId[] = "@(#)alias.c	1.5	10/18/80";
7402Seric 
8292Seric /*
9292Seric **  ALIAS -- Compute aliases.
10292Seric **
111503Smark **	Scans the file ALIASFILE for a set of aliases.
12292Seric **	If found, it arranges to deliver to them by inserting the
131503Smark **	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 **
29292Seric **	Called By:
30292Seric **		main
31292Seric **
32292Seric **	Files:
33569Seric **		ALIASFILE -- the mail aliases.  The format is
34569Seric **			a series of lines of the form:
35569Seric **				alias:name1,name2,name3,...
36569Seric **			where 'alias' expands to all of
37569Seric **			'name[i]'.  Continuations begin with
38569Seric **			space or tab.
391503Smark **		ALIASFILE.pag, ALIASFILE.dir: libdbm version
401503Smark **			of alias file.  Keys are aliases, datums
411503Smark **			(data?) are name1,name2, ...
42292Seric **
43292Seric **	Notes:
44292Seric **		If NoAlias (the "-n" flag) is set, no aliasing is
45292Seric **			done.
46292Seric **
47292Seric **	Deficiencies:
48292Seric **		It should complain about names that are aliased to
49292Seric **			nothing.
50292Seric **		It is unsophisticated about line overflows.
51292Seric */
52292Seric 
53292Seric 
54292Seric # define MAXRCRSN	10
55292Seric 
561503Smark #ifdef DBM
571503Smark typedef struct {char *dptr; int dsize;} datum;
581503Smark datum lhs, rhs;
59*1515Seric extern datum fetch();
601503Smark #endif DBM
61292Seric 
62292Seric alias()
63292Seric {
64292Seric 	register addrq *q;
65292Seric 	FILE *af;
66292Seric 	char line[MAXLINE+1];
67292Seric 	register char *p;
68292Seric 	extern int errno;
69292Seric 	bool didalias;
70292Seric 	bool gotmatch;
71292Seric 	auto addrq al;
72292Seric 	extern bool sameaddr();
73292Seric 	extern addrq *parse();
74292Seric 
75292Seric 	if (NoAlias)
76292Seric 		return;
77292Seric # ifdef DEBUG
78292Seric 	if (Debug)
79292Seric 		printf("--- alias ---\n");
80292Seric # endif
81292Seric 
82292Seric 	/* open alias file if not already open */
831503Smark #ifndef DBM
84292Seric # ifdef DEBUG
85292Seric 	if (Debug && (af = fopen("mailaliases", "r")) != NULL)
86292Seric 		printf(" [using local alias file]\n");
87292Seric 	else
88292Seric # endif
89292Seric 	if ((af = fopen(ALIASFILE, "r")) == NULL)
90292Seric 	{
91292Seric # ifdef DEBUG
92292Seric 		if (Debug)
93292Seric 			printf("Can't open %s\n", ALIASFILE);
94292Seric # endif
95292Seric 		errno = 0;
96292Seric 		return;
97292Seric 	}
981503Smark #else DBM
991503Smark 	dbminit(ALIASFILE);
1001503Smark #endif DBM
101292Seric 
1021503Smark #ifndef DBM
103292Seric 	/*
104292Seric 	**  Scan alias file.
105292Seric 	**	If we find any user that any line matches any user, we
106292Seric 	**	will send to the line rather than to the user.
107292Seric 	**
108292Seric 	**	We pass through the file several times.  Didalias tells
109292Seric 	**	us if we took some alias on this pass through the file;
110292Seric 	**	when it goes false at the top of the loop we don't have
111292Seric 	**	to scan any more.  Gotmatch tells the same thing, but
112292Seric 	**	on a line-by-line basis; it is used for processing
113292Seric 	**	continuation lines.
114292Seric 	*/
115292Seric 
1161503Smark 	do
117292Seric 	{
118292Seric 		didalias = FALSE;
119292Seric 		gotmatch = FALSE;
120292Seric 		rewind(af);
121292Seric 		while (fgets(line, sizeof line, af) != NULL)
122292Seric 		{
123292Seric 			/* comments begin with `#' */
124292Seric 			if (line[0] == '#')
125292Seric 				continue;
126292Seric 
127292Seric 			/* check for continuation lines */
128292Seric 			if (isspace(line[0]))
129292Seric 			{
130292Seric 				if (gotmatch)
131292Seric 				{
132292Seric 					sendto(line, 1);
133292Seric 				}
134292Seric 				continue;
135292Seric 			}
136292Seric 			gotmatch = FALSE;
137292Seric 
138292Seric 			/*
139292Seric 			**  Check to see if this pseudonym exists in SendQ.
140292Seric 			**	Turn the alias into canonical form.
141292Seric 			**	Then scan SendQ until you do (or do not)
142292Seric 			**	find that address.
143292Seric 			*/
144292Seric 
145292Seric 			/*  Get a canonical form for the alias. */
146292Seric 			for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
147292Seric 				continue;
148292Seric 			if (*p == '\0' || *p == '\n')
149292Seric 			{
150292Seric 			 syntaxerr:
151292Seric 				syserr("Bad alias line `%s'", line);
152292Seric 				continue;
153292Seric 			}
154292Seric 			*p++ = '\0';
155292Seric 			if (parse(line, &al, -1) == NULL)
156292Seric 			{
157292Seric 				*--p = ':';
158292Seric 				goto syntaxerr;
159292Seric 			}
160292Seric 
161292Seric 			/*  Scan SendQ for that canonical form. */
162292Seric 			for (q = &SendQ; (q = nxtinq(q)) != NULL; )
163292Seric 			{
164292Seric 				if (sameaddr(&al, q, TRUE))
165292Seric 					break;
166292Seric 			}
167292Seric 			if (q != NULL)
168292Seric 			{
169292Seric 				/*
170292Seric 				**  Match on Alias.
171292Seric 				**	Deliver to the target list.
172292Seric 				**	Remove the alias from the send queue
173292Seric 				**	  and put it on the Alias queue.
174292Seric 				*/
175292Seric 
176292Seric # ifdef DEBUG
177292Seric 				if (Debug)
178292Seric 					printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n",
179292Seric 					    q->q_paddr, q->q_host, q->q_user,
180292Seric 					    p, al.q_paddr, al.q_host, al.q_user);
181292Seric # endif
182292Seric 				tkoffq(q, &SendQ);
183292Seric 				putonq(q, &AliasQ);
184292Seric 				didalias++;
185292Seric 				gotmatch++;
186292Seric 				sendto(p, 1);
187292Seric 			}
188292Seric 		}
1891503Smark 	} while (didalias);
190292Seric 	fclose(af);
191*1515Seric #else DBM
192*1515Seric 	/*
193*1515Seric 	**  Scan SendQ
194*1515Seric 	**	We only have to do this once, since anything we alias
195*1515Seric 	**	two is being put at the end of the queue we are
196*1515Seric 	**	scanning.
197*1515Seric 	*/
198*1515Seric 
199*1515Seric 	for (q = &SendQ; (q = nxtinq(q)) != NULL; )
200*1515Seric 	{
201*1515Seric 		/* only alias local users */
202*1515Seric 		if (q->q_mailer != &Mailer[0])
203*1515Seric 			continue;
204*1515Seric 
205*1515Seric 		/* create a key for fetch */
206*1515Seric 		lhs.dptr = q->q_user;
207*1515Seric 		lhs.dsize = strlen(q->q_user) + 1;
208*1515Seric 		lhs.dptr = line;
209*1515Seric 		rhs = fetch(lhs);
210*1515Seric 
211*1515Seric 		/* find this alias? */
212*1515Seric 		p = rhs.dptr;
213*1515Seric 		if (p == NULL)
214*1515Seric 			continue;
215*1515Seric 
216*1515Seric 		/*
217*1515Seric 		**  Match on Alias.
218*1515Seric 		**	Deliver to the target list.
219*1515Seric 		**	Remove the alias from the send queue
220*1515Seric 		**	  and put it on the Alias queue.
221*1515Seric 		*/
222*1515Seric 
223*1515Seric # ifdef DEBUG
224*1515Seric 		if (Debug)
225*1515Seric 			printf("%s (%s, %s) aliased to %s\n",
226*1515Seric 			    q->q_paddr, q->q_host, q->q_user, p);
227*1515Seric # endif
228*1515Seric 		tkoffq(q, &SendQ);
229*1515Seric 		putonq(q, &AliasQ);
230*1515Seric 		sendto(p, 1);
231*1515Seric 	}
232*1515Seric #endif DBM
233292Seric }
234292Seric /*
235292Seric **  FORWARD -- Try to forward mail
236292Seric **
237292Seric **	This is similar but not identical to aliasing.
238292Seric **
239292Seric **	Currently it is undefined, until the protocol for userinfo
240292Seric **	databases is finalized.
241292Seric **
242292Seric **	Parameters:
243292Seric **		user -- the name of the user who's mail we
244292Seric **			would like to forward to.
245292Seric **
246292Seric **	Returns:
247292Seric **		TRUE -- we have forwarded it somewhere.
248292Seric **		FALSE -- not forwarded; go ahead & deliver.
249292Seric **
250292Seric **	Side Effects:
251292Seric **		New names are added to SendQ.
252292Seric **
253292Seric **	Called By:
254292Seric **		recipient
255292Seric */
256292Seric 
257292Seric bool
258292Seric forward(user)
259292Seric 	addrq *user;
260292Seric {
261292Seric 	return (FALSE);
262292Seric }
263