1 # include <pwd.h>
2 # include "sendmail.h"
3 
4 static char SccsId[] = "@(#)recipient.c	3.5	08/21/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 		}
108 	}
109 
110 	/*
111 	**  Look up this person in the recipient list.  If they
112 	**  are there already, return, otherwise continue.
113 	**  If the list is empty, just add it.
114 	*/
115 
116 	if (m->m_sendq == NULL)
117 	{
118 		m->m_sendq = a;
119 	}
120 	else
121 	{
122 		ADDRESS *pq;
123 
124 		for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next)
125 		{
126 			if (!ForceMail && sameaddr(q, a, FALSE))
127 			{
128 # ifdef DEBUG
129 				if (Debug)
130 					printf("(%s in sendq)\n", a->q_paddr);
131 # endif DEBUG
132 				if (Verbose && !bitset(QDONTSEND, a->q_flags))
133 					message(Arpa_Info, "duplicate supressed");
134 				return;
135 			}
136 		}
137 
138 		/* add address on list */
139 		q = pq;
140 		q->q_next = a;
141 	}
142 	a->q_next = NULL;
143 
144 	/*
145 	**  Alias the name and handle :include: specs.
146 	*/
147 
148 	if (a->q_mailer == MN_LOCAL)
149 	{
150 		if (strncmp(a->q_user, ":include:", 9) == 0)
151 		{
152 			a->q_flags |= QDONTSEND;
153 			if (Verbose)
154 				message(Arpa_Info, "including file %s", &a->q_user[9]);
155 			include(&a->q_user[9], " sending");
156 		}
157 		else
158 			alias(a);
159 	}
160 
161 	/*
162 	**  If the user is local and still being sent, verify that
163 	**  the address is good.  If it is, try to forward.
164 	**  If the address is already good, we have a forwarding
165 	**  loop.  This can be broken by just sending directly to
166 	**  the user (which is probably correct anyway).
167 	*/
168 
169 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL)
170 	{
171 		char buf[MAXNAME];
172 
173 		strcpy(buf, a->q_user);
174 		stripquotes(buf, TRUE);
175 
176 		/* see if this is to a file */
177 		if (index(buf, '/') != NULL)
178 		{
179 			if (access(buf, 2) < 0)
180 			{
181 				a->q_flags |= QBADADDR;
182 				giveresponse(EX_CANTCREAT, TRUE, m);
183 			}
184 		}
185 		else
186 		{
187 			register struct passwd *pw;
188 			extern struct passwd *getpwnam();
189 			pw = getpwnam(buf);
190 			if (pw == NULL)
191 			{
192 				a->q_flags |= QBADADDR;
193 				giveresponse(EX_NOUSER, TRUE, m);
194 			}
195 			else
196 			{
197 				a->q_home = newstr(pw->pw_dir);
198 				if (strcmp(buf, a->q_user) == 0)
199 					forward(a);
200 			}
201 		}
202 	}
203 }
204 /*
205 **  INCLUDE -- handle :include: specification.
206 **
207 **	Parameters:
208 **		fname -- filename to include.
209 **		msg -- message to print in verbose mode.
210 **
211 **	Returns:
212 **		none.
213 **
214 **	Side Effects:
215 **		reads the :include: file and sends to everyone
216 **		listed in that file.
217 */
218 
219 include(fname, msg)
220 	char *fname;
221 	char *msg;
222 {
223 	char buf[MAXLINE];
224 	register FILE *fp;
225 	char *oldto = To;
226 
227 	fp = fopen(fname, "r");
228 	if (fp == NULL)
229 	{
230 		usrerr("Cannot open %s", fname);
231 		return;
232 	}
233 
234 	/* read the file -- each line is a comma-separated list. */
235 	while (fgets(buf, sizeof buf, fp) != NULL)
236 	{
237 		register char *p = index(buf, '\n');
238 
239 		if (p != NULL)
240 			*p = '\0';
241 		if (buf[0] == '\0')
242 			continue;
243 		To = oldto;
244 		if (Verbose)
245 			message(Arpa_Info, "%s to %s", msg, buf);
246 		AliasLevel++;
247 		sendto(buf, 1);
248 		AliasLevel--;
249 	}
250 
251 	fclose(fp);
252 }
253