1 # include <pwd.h>
2 # include "sendmail.h"
3 
4 static char SccsId[] = "@(#)recipient.c	3.10	09/06/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 
32 	more = TRUE;
33 	for (p = list; more; )
34 	{
35 		register char *q;
36 		register char c;
37 		ADDRESS *a;
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 	ADDRESS **pq;
79 	register struct mailer *m;
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 	for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next)
124 	{
125 		if (!ForceMail && sameaddr(q, a, FALSE))
126 		{
127 # ifdef DEBUG
128 			if (Debug)
129 				printf("(%s in sendq)\n", a->q_paddr);
130 # endif DEBUG
131 			if (Verbose && !bitset(QDONTSEND, a->q_flags))
132 				message(Arpa_Info, "duplicate supressed");
133 			return;
134 		}
135 	}
136 
137 	/* add address on list */
138 	*pq = a;
139 	a->q_next = NULL;
140 	if (DontSend)
141 		a->q_flags |= QDONTSEND;
142 
143 	/*
144 	**  Alias the name and handle :include: specs.
145 	*/
146 
147 	if (a->q_mailer == MN_LOCAL)
148 	{
149 		if (strncmp(a->q_user, ":include:", 9) == 0)
150 		{
151 			a->q_flags |= QDONTSEND;
152 			if (Verbose)
153 				message(Arpa_Info, "including file %s", &a->q_user[9]);
154 			include(&a->q_user[9], " sending");
155 		}
156 		else
157 			alias(a);
158 	}
159 
160 	/*
161 	**  If the user is local and still being sent, verify that
162 	**  the address is good.  If it is, try to forward.
163 	**  If the address is already good, we have a forwarding
164 	**  loop.  This can be broken by just sending directly to
165 	**  the user (which is probably correct anyway).
166 	*/
167 
168 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL)
169 	{
170 		char buf[MAXNAME];
171 		register char *p;
172 
173 		strcpy(buf, a->q_user);
174 		stripquotes(buf, TRUE);
175 
176 		/* see if this is to a file */
177 		if ((p = rindex(buf, '/')) != NULL)
178 		{
179 			/* check if writable or creatable */
180 			if ((access(buf, 0) >= 0) ?
181 			    (access(buf, 2) < 0) :
182 			    (*p = '\0', access(buf, 3) < 0))
183 			{
184 				a->q_flags |= QBADADDR;
185 				giveresponse(EX_CANTCREAT, TRUE, m);
186 			}
187 		}
188 		else
189 		{
190 			register struct passwd *pw;
191 			extern struct passwd *getpwnam();
192 			pw = getpwnam(buf);
193 			if (pw == NULL)
194 			{
195 				a->q_flags |= QBADADDR;
196 				giveresponse(EX_NOUSER, TRUE, m);
197 			}
198 			else
199 			{
200 				a->q_home = newstr(pw->pw_dir);
201 				a->q_uid = pw->pw_uid;
202 				if (strcmp(buf, a->q_user) == 0)
203 					forward(a);
204 			}
205 		}
206 	}
207 }
208 /*
209 **  INCLUDE -- handle :include: specification.
210 **
211 **	Parameters:
212 **		fname -- filename to include.
213 **		msg -- message to print in verbose mode.
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, msg)
224 	char *fname;
225 	char *msg;
226 {
227 	char buf[MAXLINE];
228 	register FILE *fp;
229 	char *oldto = To;
230 
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 = oldto;
248 		if (Verbose)
249 			message(Arpa_Info, "%s to %s", msg, buf);
250 		AliasLevel++;
251 		sendto(buf, 1);
252 		AliasLevel--;
253 	}
254 
255 	(void) fclose(fp);
256 }
257