14174Seric # include <pwd.h>
24174Seric # include "sendmail.h"
34174Seric 
4*4247Seric static char SccsId[] = "@(#)recipient.c	3.9	08/27/81";
54174Seric 
64174Seric /*
74174Seric **  SENDTO -- Designate a send list.
84174Seric **
94174Seric **	The parameter is a comma-separated list of people to send to.
104174Seric **	This routine arranges to send to all of them.
114174Seric **
124174Seric **	Parameters:
134174Seric **		list -- the send list.
144174Seric **		copyf -- the copy flag; passed to parse.
154174Seric **
164174Seric **	Returns:
174174Seric **		none
184174Seric **
194174Seric **	Side Effects:
204174Seric **		none.
214174Seric */
224174Seric 
234174Seric # define MAXRCRSN	10
244174Seric 
254174Seric sendto(list, copyf)
264174Seric 	char *list;
274174Seric 	int copyf;
284174Seric {
294174Seric 	register char *p;
304174Seric 	register char *q;
314174Seric 	register char c;
324174Seric 	ADDRESS *a;
334174Seric 	bool more;
344174Seric 
354174Seric 	/* more keeps track of what the previous delimiter was */
364174Seric 	more = TRUE;
374174Seric 	for (p = list; more; )
384174Seric 	{
394174Seric 		/* find the end of this address */
404174Seric 		while (*p == ' ' || *p == '\t')
414174Seric 			p++;
424174Seric 		q = p;
434174Seric 		while ((c = *p++) != '\0' && c != ',' && c != '\n')
444174Seric 			continue;
454174Seric 		more = c != '\0';
464174Seric 		*--p = '\0';
474174Seric 		if (more)
484174Seric 			p++;
494174Seric 
504174Seric 		/* parse the address */
514174Seric 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
524174Seric 			continue;
534174Seric 
544174Seric 		/* arrange to send to this person */
554174Seric 		recipient(a);
564174Seric 	}
574174Seric 	To = NULL;
584174Seric }
594174Seric /*
604174Seric **  RECIPIENT -- Designate a message recipient
614174Seric **
624174Seric **	Saves the named person for future mailing.
634174Seric **
644174Seric **	Parameters:
654174Seric **		a -- the (preparsed) address header for the recipient.
664174Seric **
674174Seric **	Returns:
684174Seric **		none.
694174Seric **
704174Seric **	Side Effects:
714174Seric **		none.
724174Seric */
734174Seric 
744174Seric recipient(a)
754174Seric 	register ADDRESS *a;
764174Seric {
774174Seric 	register ADDRESS *q;
784174Seric 	register struct mailer *m;
794174Seric 	char buf[MAXNAME];
804174Seric 
814174Seric 	To = a->q_paddr;
824174Seric 	m = Mailer[a->q_mailer];
834174Seric 	errno = 0;
844174Seric # ifdef DEBUG
854174Seric 	if (Debug)
864174Seric 		printf("recipient(%s)\n", To);
874174Seric # endif DEBUG
884174Seric 
894174Seric 	/* break aliasing loops */
904174Seric 	if (AliasLevel > MAXRCRSN)
914174Seric 	{
924174Seric 		usrerr("aliasing/forwarding loop broken");
934174Seric 		return;
944174Seric 	}
954174Seric 
964174Seric 	/*
974174Seric 	**  Do sickly crude mapping for program mailing, etc.
984174Seric 	*/
994174Seric 
1004197Seric 	if (a->q_mailer == MN_LOCAL)
1014174Seric 	{
1024174Seric 		if (a->q_user[0] == '|')
1034174Seric 		{
1044197Seric 			a->q_mailer = MN_PROG;
1054197Seric 			m = Mailer[MN_PROG];
1064174Seric 			a->q_user++;
1074217Seric # ifdef PARANOID
1084217Seric 			if (AliasLevel <= 0)
1094217Seric 			{
1104217Seric 				usrerr("Cannot mail directly to programs");
1114217Seric 				a->q_flags |= QDONTSEND;
1124217Seric 			}
1134217Seric # endif PARANOID
1144174Seric 		}
1154174Seric 	}
1164174Seric 
1174174Seric 	/*
1184174Seric 	**  Look up this person in the recipient list.  If they
1194174Seric 	**  are there already, return, otherwise continue.
1204174Seric 	**  If the list is empty, just add it.
1214174Seric 	*/
1224174Seric 
1234174Seric 	if (m->m_sendq == NULL)
1244174Seric 	{
1254174Seric 		m->m_sendq = a;
1264174Seric 	}
1274174Seric 	else
1284174Seric 	{
1294174Seric 		ADDRESS *pq;
1304174Seric 
1314174Seric 		for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next)
1324174Seric 		{
1334174Seric 			if (!ForceMail && sameaddr(q, a, FALSE))
1344174Seric 			{
1354174Seric # ifdef DEBUG
1364174Seric 				if (Debug)
1374174Seric 					printf("(%s in sendq)\n", a->q_paddr);
1384174Seric # endif DEBUG
1394174Seric 				if (Verbose && !bitset(QDONTSEND, a->q_flags))
1404174Seric 					message(Arpa_Info, "duplicate supressed");
1414174Seric 				return;
1424174Seric 			}
1434174Seric 		}
1444174Seric 
1454174Seric 		/* add address on list */
1464174Seric 		q = pq;
1474174Seric 		q->q_next = a;
1484174Seric 	}
1494174Seric 	a->q_next = NULL;
150*4247Seric 	if (DontSend)
151*4247Seric 		a->q_flags |= QDONTSEND;
1524174Seric 
1534174Seric 	/*
1544174Seric 	**  Alias the name and handle :include: specs.
1554174Seric 	*/
1564174Seric 
1574197Seric 	if (a->q_mailer == MN_LOCAL)
1584174Seric 	{
1594174Seric 		if (strncmp(a->q_user, ":include:", 9) == 0)
1604174Seric 		{
1614174Seric 			a->q_flags |= QDONTSEND;
1624176Seric 			if (Verbose)
1634176Seric 				message(Arpa_Info, "including file %s", &a->q_user[9]);
1644176Seric 			include(&a->q_user[9], " sending");
1654174Seric 		}
1664174Seric 		else
1674174Seric 			alias(a);
1684174Seric 	}
1694174Seric 
1704174Seric 	/*
1714174Seric 	**  If the user is local and still being sent, verify that
1724174Seric 	**  the address is good.  If it is, try to forward.
1734174Seric 	**  If the address is already good, we have a forwarding
1744174Seric 	**  loop.  This can be broken by just sending directly to
1754174Seric 	**  the user (which is probably correct anyway).
1764174Seric 	*/
1774174Seric 
1784197Seric 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL)
1794174Seric 	{
1804174Seric 		char buf[MAXNAME];
1814201Seric 		register char *p;
1824174Seric 
1834174Seric 		strcpy(buf, a->q_user);
1844174Seric 		stripquotes(buf, TRUE);
1854174Seric 
1864174Seric 		/* see if this is to a file */
1874201Seric 		if ((p = rindex(buf, '/')) != NULL)
1884174Seric 		{
1894201Seric 			/* check if writable or creatable */
1904201Seric 			if ((access(buf, 0) >= 0) ?
1914201Seric 			    (access(buf, 2) < 0) :
1924201Seric 			    (*p = '\0', access(buf, 3) < 0))
1934174Seric 			{
1944174Seric 				a->q_flags |= QBADADDR;
1954174Seric 				giveresponse(EX_CANTCREAT, TRUE, m);
1964174Seric 			}
1974174Seric 		}
1984174Seric 		else
1994174Seric 		{
2004174Seric 			register struct passwd *pw;
2014174Seric 			extern struct passwd *getpwnam();
2024174Seric 			pw = getpwnam(buf);
2034174Seric 			if (pw == NULL)
2044174Seric 			{
2054174Seric 				a->q_flags |= QBADADDR;
2064174Seric 				giveresponse(EX_NOUSER, TRUE, m);
2074174Seric 			}
2084174Seric 			else
2094174Seric 			{
2104174Seric 				a->q_home = newstr(pw->pw_dir);
2114213Seric 				a->q_uid = pw->pw_uid;
2124174Seric 				if (strcmp(buf, a->q_user) == 0)
2134174Seric 					forward(a);
2144174Seric 			}
2154174Seric 		}
2164174Seric 	}
2174174Seric }
2184174Seric /*
2194174Seric **  INCLUDE -- handle :include: specification.
2204174Seric **
2214174Seric **	Parameters:
2224174Seric **		fname -- filename to include.
2234176Seric **		msg -- message to print in verbose mode.
2244174Seric **
2254174Seric **	Returns:
2264174Seric **		none.
2274174Seric **
2284174Seric **	Side Effects:
2294174Seric **		reads the :include: file and sends to everyone
2304174Seric **		listed in that file.
2314174Seric */
2324174Seric 
2334176Seric include(fname, msg)
2344174Seric 	char *fname;
2354176Seric 	char *msg;
2364174Seric {
2374174Seric 	char buf[MAXLINE];
2384174Seric 	register FILE *fp;
2394178Seric 	char *oldto = To;
2404174Seric 
2414174Seric 	fp = fopen(fname, "r");
2424174Seric 	if (fp == NULL)
2434174Seric 	{
2444174Seric 		usrerr("Cannot open %s", fname);
2454174Seric 		return;
2464174Seric 	}
2474174Seric 
2484174Seric 	/* read the file -- each line is a comma-separated list. */
2494174Seric 	while (fgets(buf, sizeof buf, fp) != NULL)
2504174Seric 	{
2514174Seric 		register char *p = index(buf, '\n');
2524174Seric 
2534174Seric 		if (p != NULL)
2544174Seric 			*p = '\0';
2554174Seric 		if (buf[0] == '\0')
2564174Seric 			continue;
2574178Seric 		To = oldto;
2584174Seric 		if (Verbose)
2594176Seric 			message(Arpa_Info, "%s to %s", msg, buf);
2604176Seric 		AliasLevel++;
2614174Seric 		sendto(buf, 1);
2624176Seric 		AliasLevel--;
2634174Seric 	}
2644174Seric 
2654174Seric 	fclose(fp);
2664174Seric }
267