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.1	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 			include(&a->q_user[9]);
161 		}
162 		else
163 			alias(a);
164 	}
165 
166 	/*
167 	**  If the user is local and still being sent, verify that
168 	**  the address is good.  If it is, try to forward.
169 	**  If the address is already good, we have a forwarding
170 	**  loop.  This can be broken by just sending directly to
171 	**  the user (which is probably correct anyway).
172 	*/
173 
174 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == M_LOCAL)
175 	{
176 		char buf[MAXNAME];
177 
178 		strcpy(buf, a->q_user);
179 		stripquotes(buf, TRUE);
180 
181 		/* see if this is to a file */
182 		if (index(buf, '/') != NULL)
183 		{
184 			if (access(buf, 2) < 0)
185 			{
186 				a->q_flags |= QBADADDR;
187 				giveresponse(EX_CANTCREAT, TRUE, m);
188 			}
189 		}
190 		else
191 		{
192 			register struct passwd *pw;
193 			extern struct passwd *getpwnam();
194 			pw = getpwnam(buf);
195 			if (pw == NULL)
196 			{
197 				a->q_flags |= QBADADDR;
198 				giveresponse(EX_NOUSER, TRUE, m);
199 			}
200 			else
201 			{
202 				a->q_home = newstr(pw->pw_dir);
203 				if (strcmp(buf, a->q_user) == 0)
204 					forward(a);
205 			}
206 		}
207 	}
208 }
209 /*
210 **  INCLUDE -- handle :include: specification.
211 **
212 **	Parameters:
213 **		fname -- filename to include.
214 **
215 **	Returns:
216 **		none.
217 **
218 **	Side Effects:
219 **		reads the :include: file and sends to everyone
220 **		listed in that file.
221 */
222 
223 include(fname)
224 	char *fname;
225 {
226 	char buf[MAXLINE];
227 	register FILE *fp;
228 
229 	if (Verbose)
230 		message(Arpa_Info, "Including file %s", fname);
231 	fp = fopen(fname, "r");
232 	if (fp == NULL)
233 	{
234 		usrerr("Cannot open %s", fname);
235 		return;
236 	}
237 
238 	/* read the file -- each line is a comma-separated list. */
239 	while (fgets(buf, sizeof buf, fp) != NULL)
240 	{
241 		register char *p = index(buf, '\n');
242 
243 		if (p != NULL)
244 			*p = '\0';
245 		if (buf[0] == '\0')
246 			continue;
247 		To = fname;
248 		if (Verbose)
249 			message(Arpa_Info, " >> %s", buf);
250 		sendto(buf, 1);
251 	}
252 
253 	fclose(fp);
254 }
255