1 # include <pwd.h>
2 # include "sendmail.h"
3 
4 static char SccsId[] = "@(#)recipient.c	3.9	08/27/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 	register char *q;
31 	register char c;
32 	ADDRESS *a;
33 	bool more;
34 
35 	/* more keeps track of what the previous delimiter was */
36 	more = TRUE;
37 	for (p = list; more; )
38 	{
39 		/* find the end of this address */
40 		while (*p == ' ' || *p == '\t')
41 			p++;
42 		q = p;
43 		while ((c = *p++) != '\0' && c != ',' && c != '\n')
44 			continue;
45 		more = c != '\0';
46 		*--p = '\0';
47 		if (more)
48 			p++;
49 
50 		/* parse the address */
51 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
52 			continue;
53 
54 		/* arrange to send to this person */
55 		recipient(a);
56 	}
57 	To = NULL;
58 }
59 /*
60 **  RECIPIENT -- Designate a message recipient
61 **
62 **	Saves the named person for future mailing.
63 **
64 **	Parameters:
65 **		a -- the (preparsed) address header for the recipient.
66 **
67 **	Returns:
68 **		none.
69 **
70 **	Side Effects:
71 **		none.
72 */
73 
74 recipient(a)
75 	register ADDRESS *a;
76 {
77 	register ADDRESS *q;
78 	register struct mailer *m;
79 	char buf[MAXNAME];
80 
81 	To = a->q_paddr;
82 	m = Mailer[a->q_mailer];
83 	errno = 0;
84 # ifdef DEBUG
85 	if (Debug)
86 		printf("recipient(%s)\n", To);
87 # endif DEBUG
88 
89 	/* break aliasing loops */
90 	if (AliasLevel > MAXRCRSN)
91 	{
92 		usrerr("aliasing/forwarding loop broken");
93 		return;
94 	}
95 
96 	/*
97 	**  Do sickly crude mapping for program mailing, etc.
98 	*/
99 
100 	if (a->q_mailer == MN_LOCAL)
101 	{
102 		if (a->q_user[0] == '|')
103 		{
104 			a->q_mailer = MN_PROG;
105 			m = Mailer[MN_PROG];
106 			a->q_user++;
107 # ifdef PARANOID
108 			if (AliasLevel <= 0)
109 			{
110 				usrerr("Cannot mail directly to programs");
111 				a->q_flags |= QDONTSEND;
112 			}
113 # endif PARANOID
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 	if (DontSend)
151 		a->q_flags |= QDONTSEND;
152 
153 	/*
154 	**  Alias the name and handle :include: specs.
155 	*/
156 
157 	if (a->q_mailer == MN_LOCAL)
158 	{
159 		if (strncmp(a->q_user, ":include:", 9) == 0)
160 		{
161 			a->q_flags |= QDONTSEND;
162 			if (Verbose)
163 				message(Arpa_Info, "including file %s", &a->q_user[9]);
164 			include(&a->q_user[9], " sending");
165 		}
166 		else
167 			alias(a);
168 	}
169 
170 	/*
171 	**  If the user is local and still being sent, verify that
172 	**  the address is good.  If it is, try to forward.
173 	**  If the address is already good, we have a forwarding
174 	**  loop.  This can be broken by just sending directly to
175 	**  the user (which is probably correct anyway).
176 	*/
177 
178 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL)
179 	{
180 		char buf[MAXNAME];
181 		register char *p;
182 
183 		strcpy(buf, a->q_user);
184 		stripquotes(buf, TRUE);
185 
186 		/* see if this is to a file */
187 		if ((p = rindex(buf, '/')) != NULL)
188 		{
189 			/* check if writable or creatable */
190 			if ((access(buf, 0) >= 0) ?
191 			    (access(buf, 2) < 0) :
192 			    (*p = '\0', access(buf, 3) < 0))
193 			{
194 				a->q_flags |= QBADADDR;
195 				giveresponse(EX_CANTCREAT, TRUE, m);
196 			}
197 		}
198 		else
199 		{
200 			register struct passwd *pw;
201 			extern struct passwd *getpwnam();
202 			pw = getpwnam(buf);
203 			if (pw == NULL)
204 			{
205 				a->q_flags |= QBADADDR;
206 				giveresponse(EX_NOUSER, TRUE, m);
207 			}
208 			else
209 			{
210 				a->q_home = newstr(pw->pw_dir);
211 				a->q_uid = pw->pw_uid;
212 				if (strcmp(buf, a->q_user) == 0)
213 					forward(a);
214 			}
215 		}
216 	}
217 }
218 /*
219 **  INCLUDE -- handle :include: specification.
220 **
221 **	Parameters:
222 **		fname -- filename to include.
223 **		msg -- message to print in verbose mode.
224 **
225 **	Returns:
226 **		none.
227 **
228 **	Side Effects:
229 **		reads the :include: file and sends to everyone
230 **		listed in that file.
231 */
232 
233 include(fname, msg)
234 	char *fname;
235 	char *msg;
236 {
237 	char buf[MAXLINE];
238 	register FILE *fp;
239 	char *oldto = To;
240 
241 	fp = fopen(fname, "r");
242 	if (fp == NULL)
243 	{
244 		usrerr("Cannot open %s", fname);
245 		return;
246 	}
247 
248 	/* read the file -- each line is a comma-separated list. */
249 	while (fgets(buf, sizeof buf, fp) != NULL)
250 	{
251 		register char *p = index(buf, '\n');
252 
253 		if (p != NULL)
254 			*p = '\0';
255 		if (buf[0] == '\0')
256 			continue;
257 		To = oldto;
258 		if (Verbose)
259 			message(Arpa_Info, "%s to %s", msg, buf);
260 		AliasLevel++;
261 		sendto(buf, 1);
262 		AliasLevel--;
263 	}
264 
265 	fclose(fp);
266 }
267