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