1 # include <pwd.h>
2 # include "sendmail.h"
3 
4 static char SccsId[] = "@(#)recipient.c	3.11	09/07/81";
5 
6 /*
7 **  SENDTO -- Designate a send list.
8 **
9 **	The parameter is a comma-separated list of people to send to.
10 **	This routine arranges to send to all of them.
11 **
12 **	Parameters:
13 **		list -- the send list.
14 **		copyf -- the copy flag; passed to parse.
15 **
16 **	Returns:
17 **		none
18 **
19 **	Side Effects:
20 **		none.
21 */
22 
23 # define MAXRCRSN	10
24 
25 sendto(list, copyf)
26 	char *list;
27 	int copyf;
28 {
29 	register char *p;
30 	bool more;		/* set if more addresses to send to */
31 	ADDRESS *al;		/* list of addresses to send to */
32 
33 # ifdef DEBUG
34 	if (Debug > 1)
35 		printf("sendto: %s\n", list);
36 # endif DEBUG
37 
38 	more = TRUE;
39 	al = NULL;
40 	for (p = list; more; )
41 	{
42 		register char *q;
43 		register char c;
44 		ADDRESS *a;
45 
46 		/* find the end of this address */
47 		while (*p == ' ' || *p == '\t')
48 			p++;
49 		q = p;
50 		while ((c = *p++) != '\0' && c != ',' && c != '\n')
51 			continue;
52 		more = c != '\0';
53 		*--p = '\0';
54 		if (more)
55 			p++;
56 		if (*q == '\0')
57 			continue;
58 
59 		/* parse the address */
60 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
61 			continue;
62 
63 		/* put it on the local send list */
64 		a->q_next = al;
65 		al = a;
66 	}
67 
68 	/* arrange to send to everyone on the local send list */
69 	while (al != NULL)
70 	{
71 		register ADDRESS *a = al;
72 
73 		al = a->q_next;
74 		recipient(a);
75 	}
76 
77 	To = NULL;
78 }
79 /*
80 **  RECIPIENT -- Designate a message recipient
81 **
82 **	Saves the named person for future mailing.
83 **
84 **	Parameters:
85 **		a -- the (preparsed) address header for the recipient.
86 **
87 **	Returns:
88 **		none.
89 **
90 **	Side Effects:
91 **		none.
92 */
93 
94 recipient(a)
95 	register ADDRESS *a;
96 {
97 	register ADDRESS *q;
98 	ADDRESS **pq;
99 	register struct mailer *m;
100 
101 	To = a->q_paddr;
102 	m = Mailer[a->q_mailer];
103 	errno = 0;
104 # ifdef DEBUG
105 	if (Debug)
106 		printf("recipient(%s)\n", To);
107 # endif DEBUG
108 
109 	/* break aliasing loops */
110 	if (AliasLevel > MAXRCRSN)
111 	{
112 		usrerr("aliasing/forwarding loop broken");
113 		return;
114 	}
115 
116 	/*
117 	**  Do sickly crude mapping for program mailing, etc.
118 	*/
119 
120 	if (a->q_mailer == MN_LOCAL)
121 	{
122 		if (a->q_user[0] == '|')
123 		{
124 			a->q_mailer = MN_PROG;
125 			m = Mailer[MN_PROG];
126 			a->q_user++;
127 # ifdef PARANOID
128 			if (AliasLevel <= 0)
129 			{
130 				usrerr("Cannot mail directly to programs");
131 				a->q_flags |= QDONTSEND;
132 			}
133 # endif PARANOID
134 		}
135 	}
136 
137 	/*
138 	**  Look up this person in the recipient list.  If they
139 	**  are there already, return, otherwise continue.
140 	**  If the list is empty, just add it.
141 	*/
142 
143 	for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next)
144 	{
145 		if (!ForceMail && sameaddr(q, a, FALSE))
146 		{
147 # ifdef DEBUG
148 			if (Debug)
149 				printf("(%s in sendq)\n", a->q_paddr);
150 # endif DEBUG
151 			if (Verbose && !bitset(QDONTSEND, a->q_flags))
152 				message(Arpa_Info, "duplicate suppressed");
153 			return;
154 		}
155 	}
156 
157 	/* add address on list */
158 	*pq = a;
159 	a->q_next = NULL;
160 	if (DontSend)
161 		a->q_flags |= QDONTSEND;
162 
163 	/*
164 	**  Alias the name and handle :include: specs.
165 	*/
166 
167 	if (a->q_mailer == MN_LOCAL)
168 	{
169 		if (strncmp(a->q_user, ":include:", 9) == 0)
170 		{
171 			a->q_flags |= QDONTSEND;
172 			if (Verbose)
173 				message(Arpa_Info, "including file %s", &a->q_user[9]);
174 			include(&a->q_user[9], " sending");
175 		}
176 		else
177 			alias(a);
178 	}
179 
180 	/*
181 	**  If the user is local and still being sent, verify that
182 	**  the address is good.  If it is, try to forward.
183 	**  If the address is already good, we have a forwarding
184 	**  loop.  This can be broken by just sending directly to
185 	**  the user (which is probably correct anyway).
186 	*/
187 
188 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL)
189 	{
190 		char buf[MAXNAME];
191 		register char *p;
192 
193 		strcpy(buf, a->q_user);
194 		stripquotes(buf, TRUE);
195 
196 		/* see if this is to a file */
197 		if ((p = rindex(buf, '/')) != NULL)
198 		{
199 			/* check if writable or creatable */
200 			if ((access(buf, 0) >= 0) ?
201 			    (access(buf, 2) < 0) :
202 			    (*p = '\0', access(buf, 3) < 0))
203 			{
204 				a->q_flags |= QBADADDR;
205 				giveresponse(EX_CANTCREAT, TRUE, m);
206 			}
207 		}
208 		else
209 		{
210 			register struct passwd *pw;
211 			extern struct passwd *getpwnam();
212 			pw = getpwnam(buf);
213 			if (pw == NULL)
214 			{
215 				a->q_flags |= QBADADDR;
216 				giveresponse(EX_NOUSER, TRUE, m);
217 			}
218 			else
219 			{
220 				a->q_home = newstr(pw->pw_dir);
221 				a->q_uid = pw->pw_uid;
222 				if (strcmp(buf, a->q_user) == 0)
223 					forward(a);
224 			}
225 		}
226 	}
227 }
228 /*
229 **  INCLUDE -- handle :include: specification.
230 **
231 **	Parameters:
232 **		fname -- filename to include.
233 **		msg -- message to print in verbose mode.
234 **
235 **	Returns:
236 **		none.
237 **
238 **	Side Effects:
239 **		reads the :include: file and sends to everyone
240 **		listed in that file.
241 */
242 
243 include(fname, msg)
244 	char *fname;
245 	char *msg;
246 {
247 	char buf[MAXLINE];
248 	register FILE *fp;
249 	char *oldto = To;
250 
251 	fp = fopen(fname, "r");
252 	if (fp == NULL)
253 	{
254 		usrerr("Cannot open %s", fname);
255 		return;
256 	}
257 
258 	/* read the file -- each line is a comma-separated list. */
259 	while (fgets(buf, sizeof buf, fp) != NULL)
260 	{
261 		register char *p = index(buf, '\n');
262 
263 		if (p != NULL)
264 			*p = '\0';
265 		if (buf[0] == '\0')
266 			continue;
267 		To = oldto;
268 		if (Verbose)
269 			message(Arpa_Info, "%s to %s", msg, buf);
270 		AliasLevel++;
271 		sendto(buf, 1);
272 		AliasLevel--;
273 	}
274 
275 	(void) fclose(fp);
276 }
277 /*
278 **  SENDTOARGV -- send to an argument vector.
279 **
280 **	Parameters:
281 **		argv -- argument vector to send to.
282 **
283 **	Returns:
284 **		none.
285 **
286 **	Side Effects:
287 **		puts all addresses on the argument vector onto the
288 **			send queue.
289 */
290 
291 sendtoargv(argv)
292 	register char **argv;
293 {
294 	register char *p;
295 	extern bool sameword();
296 
297 	while ((p = *argv++) != NULL)
298 	{
299 		if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at"))
300 		{
301 			char nbuf[MAXNAME];
302 
303 			if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
304 				usrerr("address overflow");
305 			else
306 			{
307 				(void) strcpy(nbuf, p);
308 				(void) strcat(nbuf, "@");
309 				(void) strcat(nbuf, argv[1]);
310 				p = newstr(nbuf);
311 				argv += 2;
312 			}
313 		}
314 		sendto(p, 0);
315 	}
316 }
317