1 # include <stdio.h>
2 # include <pwd.h>
3 # include <signal.h>
4 # include <ctype.h>
5 # include <errno.h>
6 # include "sendmail.h"
7 # ifdef LOG
8 # include <syslog.h>
9 # endif LOG
10 
11 static char SccsId[] = "@(#)recipient.c	3.3	08/20/81";
12 
13 /*
14 **  SENDTO -- Designate a send list.
15 **
16 **	The parameter is a comma-separated list of people to send to.
17 **	This routine arranges to send to all of them.
18 **
19 **	Parameters:
20 **		list -- the send list.
21 **		copyf -- the copy flag; passed to parse.
22 **
23 **	Returns:
24 **		none
25 **
26 **	Side Effects:
27 **		none.
28 */
29 
30 # define MAXRCRSN	10
31 
32 sendto(list, copyf)
33 	char *list;
34 	int copyf;
35 {
36 	register char *p;
37 	register char *q;
38 	register char c;
39 	ADDRESS *a;
40 	bool more;
41 
42 	/* more keeps track of what the previous delimiter was */
43 	more = TRUE;
44 	for (p = list; more; )
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 
57 		/* parse the address */
58 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
59 			continue;
60 
61 		/* arrange to send to this person */
62 		recipient(a);
63 	}
64 	To = NULL;
65 }
66 /*
67 **  RECIPIENT -- Designate a message recipient
68 **
69 **	Saves the named person for future mailing.
70 **
71 **	Parameters:
72 **		a -- the (preparsed) address header for the recipient.
73 **
74 **	Returns:
75 **		none.
76 **
77 **	Side Effects:
78 **		none.
79 */
80 
81 recipient(a)
82 	register ADDRESS *a;
83 {
84 	register ADDRESS *q;
85 	register struct mailer *m;
86 	char buf[MAXNAME];
87 
88 	To = a->q_paddr;
89 	m = Mailer[a->q_mailer];
90 	errno = 0;
91 # ifdef DEBUG
92 	if (Debug)
93 		printf("recipient(%s)\n", To);
94 # endif DEBUG
95 
96 	/* break aliasing loops */
97 	if (AliasLevel > MAXRCRSN)
98 	{
99 		usrerr("aliasing/forwarding loop broken");
100 		return;
101 	}
102 
103 	/*
104 	**  Do sickly crude mapping for program mailing, etc.
105 	*/
106 
107 	if (a->q_mailer == M_LOCAL)
108 	{
109 		if (a->q_user[0] == '|')
110 		{
111 			a->q_mailer = M_PROG;
112 			m = Mailer[M_PROG];
113 			a->q_user++;
114 		}
115 	}
116 
117 	/*
118 	**  Look up this person in the recipient list.  If they
119 	**  are there already, return, otherwise continue.
120 	**  If the list is empty, just add it.
121 	*/
122 
123 	if (m->m_sendq == NULL)
124 	{
125 		m->m_sendq = a;
126 	}
127 	else
128 	{
129 		ADDRESS *pq;
130 
131 		for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next)
132 		{
133 			if (!ForceMail && sameaddr(q, a, FALSE))
134 			{
135 # ifdef DEBUG
136 				if (Debug)
137 					printf("(%s in sendq)\n", a->q_paddr);
138 # endif DEBUG
139 				if (Verbose && !bitset(QDONTSEND, a->q_flags))
140 					message(Arpa_Info, "duplicate supressed");
141 				return;
142 			}
143 		}
144 
145 		/* add address on list */
146 		q = pq;
147 		q->q_next = a;
148 	}
149 	a->q_next = NULL;
150 
151 	/*
152 	**  Alias the name and handle :include: specs.
153 	*/
154 
155 	if (a->q_mailer == M_LOCAL)
156 	{
157 		if (strncmp(a->q_user, ":include:", 9) == 0)
158 		{
159 			a->q_flags |= QDONTSEND;
160 			if (Verbose)
161 				message(Arpa_Info, "including file %s", &a->q_user[9]);
162 			include(&a->q_user[9], " sending");
163 		}
164 		else
165 			alias(a);
166 	}
167 
168 	/*
169 	**  If the user is local and still being sent, verify that
170 	**  the address is good.  If it is, try to forward.
171 	**  If the address is already good, we have a forwarding
172 	**  loop.  This can be broken by just sending directly to
173 	**  the user (which is probably correct anyway).
174 	*/
175 
176 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == M_LOCAL)
177 	{
178 		char buf[MAXNAME];
179 
180 		strcpy(buf, a->q_user);
181 		stripquotes(buf, TRUE);
182 
183 		/* see if this is to a file */
184 		if (index(buf, '/') != NULL)
185 		{
186 			if (access(buf, 2) < 0)
187 			{
188 				a->q_flags |= QBADADDR;
189 				giveresponse(EX_CANTCREAT, TRUE, m);
190 			}
191 		}
192 		else
193 		{
194 			register struct passwd *pw;
195 			extern struct passwd *getpwnam();
196 			pw = getpwnam(buf);
197 			if (pw == NULL)
198 			{
199 				a->q_flags |= QBADADDR;
200 				giveresponse(EX_NOUSER, TRUE, m);
201 			}
202 			else
203 			{
204 				a->q_home = newstr(pw->pw_dir);
205 				if (strcmp(buf, a->q_user) == 0)
206 					forward(a);
207 			}
208 		}
209 	}
210 }
211 /*
212 **  INCLUDE -- handle :include: specification.
213 **
214 **	Parameters:
215 **		fname -- filename to include.
216 **		msg -- message to print in verbose mode.
217 **
218 **	Returns:
219 **		none.
220 **
221 **	Side Effects:
222 **		reads the :include: file and sends to everyone
223 **		listed in that file.
224 */
225 
226 include(fname, msg)
227 	char *fname;
228 	char *msg;
229 {
230 	char buf[MAXLINE];
231 	register FILE *fp;
232 	char *oldto = To;
233 
234 	fp = fopen(fname, "r");
235 	if (fp == NULL)
236 	{
237 		usrerr("Cannot open %s", fname);
238 		return;
239 	}
240 
241 	/* read the file -- each line is a comma-separated list. */
242 	while (fgets(buf, sizeof buf, fp) != NULL)
243 	{
244 		register char *p = index(buf, '\n');
245 
246 		if (p != NULL)
247 			*p = '\0';
248 		if (buf[0] == '\0')
249 			continue;
250 		To = oldto;
251 		if (Verbose)
252 			message(Arpa_Info, "%s to %s", msg, buf);
253 		AliasLevel++;
254 		sendto(buf, 1);
255 		AliasLevel--;
256 	}
257 
258 	fclose(fp);
259 }
260