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