1 # include <stdio.h>
2 # include <ctype.h>
3 # include <pwd.h>
4 # include "dlvrmail.h"
5 
6 static char SccsId[] = "@(#)alias.c	1.5	10/18/80";
7 
8 /*
9 **  ALIAS -- Compute aliases.
10 **
11 **	Scans the file ALIASFILE for a set of aliases.
12 **	If found, it arranges to deliver to them by inserting the
13 **	new names onto the SendQ queue.  Uses libdbm database if -DDBM.
14 **
15 **	Parameters:
16 **		none
17 **
18 **	Returns:
19 **		none
20 **
21 **	Side Effects:
22 **		Aliases found on SendQ are removed and put onto
23 **		AliasQ; replacements are added to SendQ.  This is
24 **		done until no such replacement occurs.
25 **
26 **	Defined Constants:
27 **		MAXRCRSN -- the maximum recursion depth.
28 **
29 **	Called By:
30 **		main
31 **
32 **	Files:
33 **		ALIASFILE -- the mail aliases.  The format is
34 **			a series of lines of the form:
35 **				alias:name1,name2,name3,...
36 **			where 'alias' expands to all of
37 **			'name[i]'.  Continuations begin with
38 **			space or tab.
39 **		ALIASFILE.pag, ALIASFILE.dir: libdbm version
40 **			of alias file.  Keys are aliases, datums
41 **			(data?) are name1,name2, ...
42 **
43 **	Notes:
44 **		If NoAlias (the "-n" flag) is set, no aliasing is
45 **			done.
46 **
47 **	Deficiencies:
48 **		It should complain about names that are aliased to
49 **			nothing.
50 **		It is unsophisticated about line overflows.
51 */
52 
53 
54 # define MAXRCRSN	10
55 
56 #ifdef DBM
57 typedef struct {char *dptr; int dsize;} datum;
58 datum lhs, rhs;
59 extern datum fetch();
60 #endif DBM
61 
62 alias()
63 {
64 	register addrq *q;
65 	FILE *af;
66 	char line[MAXLINE+1];
67 	register char *p;
68 	extern int errno;
69 	bool didalias;
70 	bool gotmatch;
71 	auto addrq al;
72 	extern bool sameaddr();
73 	extern addrq *parse();
74 
75 	if (NoAlias)
76 		return;
77 # ifdef DEBUG
78 	if (Debug)
79 		printf("--- alias ---\n");
80 # endif
81 
82 	/* open alias file if not already open */
83 #ifndef DBM
84 # ifdef DEBUG
85 	if (Debug && (af = fopen("mailaliases", "r")) != NULL)
86 		printf(" [using local alias file]\n");
87 	else
88 # endif
89 	if ((af = fopen(ALIASFILE, "r")) == NULL)
90 	{
91 # ifdef DEBUG
92 		if (Debug)
93 			printf("Can't open %s\n", ALIASFILE);
94 # endif
95 		errno = 0;
96 		return;
97 	}
98 #else DBM
99 	dbminit(ALIASFILE);
100 #endif DBM
101 
102 #ifndef DBM
103 	/*
104 	**  Scan alias file.
105 	**	If we find any user that any line matches any user, we
106 	**	will send to the line rather than to the user.
107 	**
108 	**	We pass through the file several times.  Didalias tells
109 	**	us if we took some alias on this pass through the file;
110 	**	when it goes false at the top of the loop we don't have
111 	**	to scan any more.  Gotmatch tells the same thing, but
112 	**	on a line-by-line basis; it is used for processing
113 	**	continuation lines.
114 	*/
115 
116 	do
117 	{
118 		didalias = FALSE;
119 		gotmatch = FALSE;
120 		rewind(af);
121 		while (fgets(line, sizeof line, af) != NULL)
122 		{
123 			/* comments begin with `#' */
124 			if (line[0] == '#')
125 				continue;
126 
127 			/* check for continuation lines */
128 			if (isspace(line[0]))
129 			{
130 				if (gotmatch)
131 				{
132 					sendto(line, 1);
133 				}
134 				continue;
135 			}
136 			gotmatch = FALSE;
137 
138 			/*
139 			**  Check to see if this pseudonym exists in SendQ.
140 			**	Turn the alias into canonical form.
141 			**	Then scan SendQ until you do (or do not)
142 			**	find that address.
143 			*/
144 
145 			/*  Get a canonical form for the alias. */
146 			for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
147 				continue;
148 			if (*p == '\0' || *p == '\n')
149 			{
150 			 syntaxerr:
151 				syserr("Bad alias line `%s'", line);
152 				continue;
153 			}
154 			*p++ = '\0';
155 			if (parse(line, &al, -1) == NULL)
156 			{
157 				*--p = ':';
158 				goto syntaxerr;
159 			}
160 
161 			/*  Scan SendQ for that canonical form. */
162 			for (q = &SendQ; (q = nxtinq(q)) != NULL; )
163 			{
164 				if (sameaddr(&al, q, TRUE))
165 					break;
166 			}
167 			if (q != NULL)
168 			{
169 				/*
170 				**  Match on Alias.
171 				**	Deliver to the target list.
172 				**	Remove the alias from the send queue
173 				**	  and put it on the Alias queue.
174 				*/
175 
176 # ifdef DEBUG
177 				if (Debug)
178 					printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n",
179 					    q->q_paddr, q->q_host, q->q_user,
180 					    p, al.q_paddr, al.q_host, al.q_user);
181 # endif
182 				tkoffq(q, &SendQ);
183 				putonq(q, &AliasQ);
184 				didalias++;
185 				gotmatch++;
186 				sendto(p, 1);
187 			}
188 		}
189 	} while (didalias);
190 	fclose(af);
191 #else DBM
192 	/*
193 	**  Scan SendQ
194 	**	We only have to do this once, since anything we alias
195 	**	two is being put at the end of the queue we are
196 	**	scanning.
197 	*/
198 
199 	for (q = &SendQ; (q = nxtinq(q)) != NULL; )
200 	{
201 		/* only alias local users */
202 		if (q->q_mailer != &Mailer[0])
203 			continue;
204 
205 		/* create a key for fetch */
206 		lhs.dptr = q->q_user;
207 		lhs.dsize = strlen(q->q_user) + 1;
208 		lhs.dptr = line;
209 		rhs = fetch(lhs);
210 
211 		/* find this alias? */
212 		p = rhs.dptr;
213 		if (p == NULL)
214 			continue;
215 
216 		/*
217 		**  Match on Alias.
218 		**	Deliver to the target list.
219 		**	Remove the alias from the send queue
220 		**	  and put it on the Alias queue.
221 		*/
222 
223 # ifdef DEBUG
224 		if (Debug)
225 			printf("%s (%s, %s) aliased to %s\n",
226 			    q->q_paddr, q->q_host, q->q_user, p);
227 # endif
228 		tkoffq(q, &SendQ);
229 		putonq(q, &AliasQ);
230 		sendto(p, 1);
231 	}
232 #endif DBM
233 }
234 /*
235 **  FORWARD -- Try to forward mail
236 **
237 **	This is similar but not identical to aliasing.
238 **
239 **	Currently it is undefined, until the protocol for userinfo
240 **	databases is finalized.
241 **
242 **	Parameters:
243 **		user -- the name of the user who's mail we
244 **			would like to forward to.
245 **
246 **	Returns:
247 **		TRUE -- we have forwarded it somewhere.
248 **		FALSE -- not forwarded; go ahead & deliver.
249 **
250 **	Side Effects:
251 **		New names are added to SendQ.
252 **
253 **	Called By:
254 **		recipient
255 */
256 
257 bool
258 forward(user)
259 	addrq *user;
260 {
261 	return (FALSE);
262 }
263