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[] = "@(#)deliver.c	3.23	08/18/81";
12 
13 /*
14 **  DELIVER -- Deliver a message to a particular address.
15 **
16 **	Parameters:
17 **		to -- the address to deliver the message to.
18 **		editfcn -- if non-NULL, we want to call this function
19 **			to output the letter (instead of just out-
20 **			putting it raw).
21 **
22 **	Returns:
23 **		zero -- successfully delivered.
24 **		else -- some failure, see ExitStat for more info.
25 **
26 **	Side Effects:
27 **		The standard input is passed off to someone.
28 */
29 
30 deliver(to, editfcn)
31 	ADDRESS *to;
32 	int (*editfcn)();
33 {
34 	char *host;
35 	char *user;
36 	char **pvp;
37 	register char **mvp;
38 	register char *p;
39 	register struct mailer *m;
40 	register int i;
41 	extern putmessage();
42 	extern bool checkcompat();
43 	char *pv[MAXPV+1];
44 	char tobuf[MAXLINE];
45 	char buf[MAXNAME];
46 	bool firstone;
47 
48 	if (bitset(QDONTSEND, to->q_flags))
49 		return (0);
50 
51 # ifdef DEBUG
52 	if (Debug)
53 		printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n",
54 			to->q_mailer, to->q_host, to->q_user);
55 # endif DEBUG
56 
57 	/*
58 	**  Do initial argv setup.
59 	**	Insert the mailer name.  Notice that $x expansion is
60 	**	NOT done on the mailer name.  Then, if the mailer has
61 	**	a picky -f flag, we insert it as appropriate.  This
62 	**	code does not check for 'pv' overflow; this places a
63 	**	manifest lower limit of 4 for MAXPV.
64 	*/
65 
66 	m = Mailer[to->q_mailer];
67 	host = to->q_host;
68 	define('g', m->m_from);		/* translated from address */
69 	define('h', host);		/* to host */
70 	Errors = 0;
71 	errno = 0;
72 	pvp = pv;
73 	*pvp++ = m->m_argv[0];
74 
75 	/* insert -f or -r flag as appropriate */
76 	if (bitset(M_FOPT|M_ROPT, m->m_flags) && FromFlag)
77 	{
78 		if (bitset(M_FOPT, m->m_flags))
79 			*pvp++ = "-f";
80 		else
81 			*pvp++ = "-r";
82 		(void) expand("$g", buf, &buf[sizeof buf - 1]);
83 		*pvp++ = newstr(buf);
84 	}
85 
86 	/*
87 	**  Append the other fixed parts of the argv.  These run
88 	**  up to the first entry containing "$u".  There can only
89 	**  be one of these, and there are only a few more slots
90 	**  in the pv after it.
91 	*/
92 
93 	for (mvp = m->m_argv; (p = *++mvp) != NULL; )
94 	{
95 		while ((p = index(p, '$')) != NULL)
96 			if (*++p == 'u')
97 				break;
98 		if (p != NULL)
99 			break;
100 
101 		/* this entry is safe -- go ahead and process it */
102 		(void) expand(*mvp, buf, &buf[sizeof buf - 1]);
103 		*pvp++ = newstr(buf);
104 		if (pvp >= &pv[MAXPV - 3])
105 		{
106 			syserr("Too many parameters to %s before $u", pv[0]);
107 			return (-1);
108 		}
109 	}
110 	if (*mvp == NULL)
111 		syserr("No $u in mailer argv for %s", pv[0]);
112 
113 	/*
114 	**  At this point *mvp points to the argument with $u.  We
115 	**  run through our address list and append all the addresses
116 	**  we can.  If we run out of space, do not fret!  We can
117 	**  always send another copy later.
118 	*/
119 
120 	tobuf[0] = '\0';
121 	firstone = TRUE;
122 	To = tobuf;
123 	for (; to != NULL; to = to->q_next)
124 	{
125 		/* avoid sending multiple recipients to dumb mailers */
126 		if (!firstone && !bitset(M_MUSER, m->m_flags))
127 			break;
128 
129 		/* if already sent or not for this host, don't send */
130 		if (bitset(QDONTSEND, to->q_flags) || strcmp(to->q_host, host) != 0)
131 			continue;
132 		user = to->q_user;
133 		To = to->q_paddr;
134 		to->q_flags |= QDONTSEND;
135 		firstone = FALSE;
136 
137 # ifdef DEBUG
138 		if (Debug)
139 			printf("   send to `%s'\n", user);
140 # endif DEBUG
141 
142 		/*
143 		**  Check to see that these people are allowed to
144 		**  talk to each other.
145 		*/
146 
147 		if (!checkcompat(to))
148 		{
149 			giveresponse(EX_UNAVAILABLE, TRUE, m);
150 			continue;
151 		}
152 
153 		/*
154 		**  Strip quote bits from names if the mailer is dumb
155 		**	about them.
156 		*/
157 
158 		if (bitset(M_STRIPQ, m->m_flags))
159 		{
160 			stripquotes(user, TRUE);
161 			stripquotes(host, TRUE);
162 		}
163 		else
164 		{
165 			stripquotes(user, FALSE);
166 			stripquotes(host, FALSE);
167 		}
168 
169 		/*
170 		**  If an error message has already been given, don't
171 		**	bother to send to this address.
172 		**
173 		**	>>>>>>>>>> This clause assumes that the local mailer
174 		**	>> NOTE >> cannot do any further aliasing; that
175 		**	>>>>>>>>>> function is subsumed by sendmail.
176 		*/
177 
178 		if (bitset(QBADADDR, to->q_flags))
179 			continue;
180 
181 		/*
182 		**  See if this user name is "special".
183 		**	If the user name has a slash in it, assume that this
184 		**	is a file -- send it off without further ado.
185 		**	Note that this means that editfcn's will not
186 		**	be applied to the message.  Also note that
187 		**	this type of addresses is not processed along
188 		**	with the others, so we fudge on the To person.
189 		*/
190 
191 		if (m == Mailer[M_LOCAL])
192 		{
193 			if (index(user, '/') != NULL)
194 			{
195 				i = mailfile(user);
196 				giveresponse(i, TRUE, m);
197 				continue;
198 			}
199 		}
200 
201 		/* create list of users for error messages */
202 		if (tobuf[0] != '\0')
203 			(void) strcat(tobuf, ",");
204 		(void) strcat(tobuf, to->q_paddr);
205 		define('u', user);		/* to user */
206 		define('z', to->q_home);	/* user's home */
207 
208 		/* expand out this user */
209 		(void) expand(user, buf, &buf[sizeof buf - 1]);
210 		*pvp++ = newstr(buf);
211 		if (pvp >= &pv[MAXPV - 2])
212 		{
213 			/* allow some space for trailing parms */
214 			break;
215 		}
216 	}
217 
218 	/* see if any addresses still exist */
219 	if (tobuf[0] == '\0')
220 		return (0);
221 
222 	/* print out messages as full list */
223 	To = tobuf;
224 
225 	/*
226 	**  Fill out any parameters after the $u parameter.
227 	*/
228 
229 	while (*++mvp != NULL)
230 	{
231 		(void) expand(*mvp, buf, &buf[sizeof buf - 1]);
232 		*pvp++ = newstr(buf);
233 		if (pvp >= &pv[MAXPV])
234 			syserr("deliver: pv overflow after $u for %s", pv[0]);
235 	}
236 	*pvp++ = NULL;
237 
238 	/*
239 	**  Call the mailer.
240 	**	The argument vector gets built, pipes
241 	**	are created as necessary, and we fork & exec as
242 	**	appropriate.
243 	**
244 	**	Notice the tacky hack to handle private mailers.
245 	*/
246 
247 	if (editfcn == NULL)
248 		editfcn = putmessage;
249 	i = sendoff(m, pv, editfcn);
250 
251 	return (i);
252 }
253 /*
254 **  SENDOFF -- send off call to mailer & collect response.
255 **
256 **	Parameters:
257 **		m -- mailer descriptor.
258 **		pvp -- parameter vector to send to it.
259 **		editfcn -- function to pipe it through.
260 **
261 **	Returns:
262 **		exit status of mailer.
263 **
264 **	Side Effects:
265 **		none.
266 */
267 
268 #define NFORKTRIES	5
269 
270 sendoff(m, pvp, editfcn)
271 	struct mailer *m;
272 	char **pvp;
273 	int (*editfcn)();
274 {
275 	auto int st;
276 	register int i;
277 	int pid;
278 	int pvect[2];
279 	FILE *mfile;
280 	extern putmessage();
281 	extern FILE *fdopen();
282 
283 # ifdef DEBUG
284 	if (Debug)
285 	{
286 		printf("Sendoff:\n");
287 		printav(pvp);
288 	}
289 # endif DEBUG
290 
291 	/* create a pipe to shove the mail through */
292 	if (pipe(pvect) < 0)
293 	{
294 		syserr("pipe");
295 		return (-1);
296 	}
297 	for (i = NFORKTRIES; i-- > 0; )
298 	{
299 # ifdef VFORK
300 		pid = vfork();
301 # else
302 		pid = fork();
303 # endif
304 		if (pid >= 0)
305 			break;
306 		sleep((unsigned) NFORKTRIES - i);
307 	}
308 	if (pid < 0)
309 	{
310 		syserr("Cannot fork");
311 		(void) close(pvect[0]);
312 		(void) close(pvect[1]);
313 		return (-1);
314 	}
315 	else if (pid == 0)
316 	{
317 		/* child -- set up input & exec mailer */
318 		/* make diagnostic output be standard output */
319 		(void) close(2);
320 		(void) dup(1);
321 		(void) signal(SIGINT, SIG_IGN);
322 		(void) close(0);
323 		if (dup(pvect[0]) < 0)
324 		{
325 			syserr("Cannot dup to zero!");
326 			_exit(EX_OSERR);
327 		}
328 		(void) close(pvect[0]);
329 		(void) close(pvect[1]);
330 		if (!bitset(M_RESTR, m->m_flags))
331 			(void) setuid(getuid());
332 # ifndef VFORK
333 		/*
334 		**  We have to be careful with vfork - we can't mung up the
335 		**  memory but we don't want the mailer to inherit any extra
336 		**  open files.  Chances are the mailer won't
337 		**  care about an extra file, but then again you never know.
338 		**  Actually, we would like to close(fileno(pwf)), but it's
339 		**  declared static so we can't.  But if we fclose(pwf), which
340 		**  is what endpwent does, it closes it in the parent too and
341 		**  the next getpwnam will be slower.  If you have a weird
342 		**  mailer that chokes on the extra file you should do the
343 		**  endpwent().
344 		**
345 		**  Similar comments apply to log.  However, openlog is
346 		**  clever enough to set the FIOCLEX mode on the file,
347 		**  so it will be closed automatically on the exec.
348 		*/
349 
350 		endpwent();
351 # ifdef LOG
352 		closelog();
353 # endif LOG
354 # endif VFORK
355 		execv(m->m_mailer, pvp);
356 		/* syserr fails because log is closed */
357 		/* syserr("Cannot exec %s", m->m_mailer); */
358 		printf("Cannot exec %s\n", m->m_mailer);
359 		(void) fflush(stdout);
360 		_exit(EX_UNAVAILABLE);
361 	}
362 
363 	/* write out message to mailer */
364 	(void) close(pvect[0]);
365 	(void) signal(SIGPIPE, SIG_IGN);
366 	mfile = fdopen(pvect[1], "w");
367 	if (editfcn == NULL)
368 		editfcn = putmessage;
369 	(*editfcn)(mfile, m);
370 	(void) fclose(mfile);
371 
372 	/*
373 	**  Wait for child to die and report status.
374 	**	We should never get fatal errors (e.g., segmentation
375 	**	violation), so we report those specially.  For other
376 	**	errors, we choose a status message (into statmsg),
377 	**	and if it represents an error, we print it.
378 	*/
379 
380 	while ((i = wait(&st)) > 0 && i != pid)
381 		continue;
382 	if (i < 0)
383 	{
384 		syserr("wait");
385 		return (-1);
386 	}
387 	if ((st & 0377) != 0)
388 	{
389 		syserr("%s: stat %o", pvp[0], st);
390 		ExitStat = EX_UNAVAILABLE;
391 		return (-1);
392 	}
393 	i = (st >> 8) & 0377;
394 	giveresponse(i, TRUE, m);
395 	return (i);
396 }
397 /*
398 **  GIVERESPONSE -- Interpret an error response from a mailer
399 **
400 **	Parameters:
401 **		stat -- the status code from the mailer (high byte
402 **			only; core dumps must have been taken care of
403 **			already).
404 **		force -- if set, force an error message output, even
405 **			if the mailer seems to like to print its own
406 **			messages.
407 **		m -- the mailer descriptor for this mailer.
408 **
409 **	Returns:
410 **		none.
411 **
412 **	Side Effects:
413 **		Errors may be incremented.
414 **		ExitStat may be set.
415 **
416 **	Called By:
417 **		deliver
418 */
419 
420 giveresponse(stat, force, m)
421 	int stat;
422 	int force;
423 	register struct mailer *m;
424 {
425 	register char *statmsg;
426 	extern char *SysExMsg[];
427 	register int i;
428 	extern int N_SysEx;
429 	extern long MsgSize;
430 	char buf[30];
431 
432 	i = stat - EX__BASE;
433 	if (i < 0 || i > N_SysEx)
434 		statmsg = NULL;
435 	else
436 		statmsg = SysExMsg[i];
437 	if (stat == 0)
438 	{
439 		if (bitset(M_FINAL, m->m_flags))
440 			statmsg = "delivered";
441 		else
442 			statmsg = "queued";
443 		if (Verbose)
444 			message(Arpa_Info, statmsg);
445 	}
446 	else
447 	{
448 		Errors++;
449 		if (statmsg == NULL && m->m_badstat != 0)
450 		{
451 			stat = m->m_badstat;
452 			i = stat - EX__BASE;
453 # ifdef DEBUG
454 			if (i < 0 || i >= N_SysEx)
455 				syserr("Bad m_badstat %d", stat);
456 			else
457 # endif DEBUG
458 			statmsg = SysExMsg[i];
459 		}
460 		if (statmsg == NULL)
461 			usrerr("unknown mailer response %d", stat);
462 		else if (force || !bitset(M_QUIET, m->m_flags) || Verbose)
463 			usrerr("%s", statmsg);
464 	}
465 
466 	/*
467 	**  Final cleanup.
468 	**	Log a record of the transaction.  Compute the new
469 	**	ExitStat -- if we already had an error, stick with
470 	**	that.
471 	*/
472 
473 	if (statmsg == NULL)
474 	{
475 		(void) sprintf(buf, "error %d", stat);
476 		statmsg = buf;
477 	}
478 
479 # ifdef LOG
480 	syslog(LOG_INFO, "%s->%s: %ld: %s", From.q_paddr, To, MsgSize, statmsg);
481 # endif LOG
482 	setstat(stat);
483 }
484 /*
485 **  PUTMESSAGE -- output a message to the final mailer.
486 **
487 **	This routine takes care of recreating the header from the
488 **	in-core copy, etc.
489 **
490 **	Parameters:
491 **		fp -- file to output onto.
492 **		m -- a mailer descriptor.
493 **
494 **	Returns:
495 **		none.
496 **
497 **	Side Effects:
498 **		The message is written onto fp.
499 */
500 
501 putmessage(fp, m)
502 	FILE *fp;
503 	struct mailer *m;
504 {
505 	char buf[BUFSIZ];
506 	register int i;
507 	HDR *h;
508 	register char *p;
509 	extern char *arpadate();
510 	bool anyheader = FALSE;
511 	extern char *capitalize();
512 
513 	/* output "From" line unless supressed */
514 	if (!bitset(M_NHDR, m->m_flags))
515 		fprintf(fp, "%s\n", FromLine);
516 
517 	/* output all header lines */
518 	for (h = Header; h != NULL; h = h->h_link)
519 	{
520 		if (bitset(H_DELETE, h->h_flags))
521 			continue;
522 		if (bitset(H_CHECK|H_ACHECK, h->h_flags) && !bitset(h->h_mflags, m->m_flags))
523 			continue;
524 		if (bitset(H_DEFAULT, h->h_flags))
525 		{
526 			(void) expand(h->h_value, buf, &buf[sizeof buf]);
527 			p = buf;
528 		}
529 		else
530 			p = h->h_value;
531 		if (*p == '\0')
532 			continue;
533 		fprintf(fp, "%s: %s\n", capitalize(h->h_field), p);
534 		h->h_flags |= H_USED;
535 		anyheader = TRUE;
536 	}
537 
538 	if (anyheader)
539 		fprintf(fp, "\n");
540 
541 	/* output the body of the message */
542 	rewind(stdin);
543 	while (!ferror(fp) && (i = fread(buf, 1, BUFSIZ, stdin)) > 0)
544 		(void) fwrite(buf, 1, i, fp);
545 
546 	if (ferror(fp) && errno != EPIPE)
547 	{
548 		syserr("putmessage: write error");
549 		setstat(EX_IOERR);
550 	}
551 	errno = 0;
552 }
553 /*
554 **  SENDTO -- Designate a send list.
555 **
556 **	The parameter is a comma-separated list of people to send to.
557 **	This routine arranges to send to all of them.
558 **
559 **	Parameters:
560 **		list -- the send list.
561 **		copyf -- the copy flag; passed to parse.
562 **
563 **	Returns:
564 **		none
565 **
566 **	Side Effects:
567 **		none.
568 */
569 
570 # define MAXRCRSN	10
571 
572 sendto(list, copyf)
573 	char *list;
574 	int copyf;
575 {
576 	register char *p;
577 	register char *q;
578 	register char c;
579 	ADDRESS *a;
580 	bool more;
581 
582 	/* more keeps track of what the previous delimiter was */
583 	more = TRUE;
584 	for (p = list; more; )
585 	{
586 		/* find the end of this address */
587 		while (*p == ' ' || *p == '\t')
588 			p++;
589 		q = p;
590 		while ((c = *p++) != '\0' && c != ',' && c != '\n')
591 			continue;
592 		more = c != '\0';
593 		*--p = '\0';
594 		if (more)
595 			p++;
596 
597 		/* parse the address */
598 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
599 			continue;
600 
601 		/* arrange to send to this person */
602 		recipient(a);
603 	}
604 	To = NULL;
605 }
606 /*
607 **  RECIPIENT -- Designate a message recipient
608 **
609 **	Saves the named person for future mailing.
610 **
611 **	Parameters:
612 **		a -- the (preparsed) address header for the recipient.
613 **
614 **	Returns:
615 **		none.
616 **
617 **	Side Effects:
618 **		none.
619 */
620 
621 recipient(a)
622 	register ADDRESS *a;
623 {
624 	register ADDRESS *q;
625 	register struct mailer *m;
626 	char buf[MAXNAME];
627 
628 	To = a->q_paddr;
629 	m = Mailer[a->q_mailer];
630 	errno = 0;
631 # ifdef DEBUG
632 	if (Debug)
633 		printf("recipient(%s)\n", To);
634 # endif DEBUG
635 
636 	/* break aliasing loops */
637 	if (AliasLevel > MAXRCRSN)
638 	{
639 		usrerr("aliasing/forwarding loop broken");
640 		return;
641 	}
642 
643 	/*
644 	**  Do sickly crude mapping for program mailing, etc.
645 	*/
646 
647 	if (a->q_mailer == M_LOCAL)
648 	{
649 		if (a->q_user[0] == '|')
650 		{
651 			a->q_mailer = M_PROG;
652 			m = Mailer[M_PROG];
653 			a->q_user++;
654 		}
655 	}
656 
657 	/*
658 	**  Look up this person in the recipient list.  If they
659 	**  are there already, return, otherwise continue.
660 	**  If the list is empty, just add it.
661 	*/
662 
663 	if (m->m_sendq == NULL)
664 	{
665 		m->m_sendq = a;
666 	}
667 	else
668 	{
669 		ADDRESS *pq;
670 
671 		for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next)
672 		{
673 			if (!ForceMail && sameaddr(q, a, FALSE))
674 			{
675 # ifdef DEBUG
676 				if (Debug)
677 					printf("(%s in sendq)\n", a->q_paddr);
678 # endif DEBUG
679 				if (Verbose && !bitset(QDONTSEND, a->q_flags))
680 					message(Arpa_Info, "duplicate supressed");
681 				return;
682 			}
683 		}
684 
685 		/* add address on list */
686 		q = pq;
687 		q->q_next = a;
688 	}
689 	a->q_next = NULL;
690 
691 	/*
692 	**  Alias the name and handle :include: specs.
693 	*/
694 
695 	if (a->q_mailer == M_LOCAL)
696 	{
697 		if (strncmp(a->q_user, ":include:", 9) == 0)
698 		{
699 			a->q_flags |= QDONTSEND;
700 			include(&a->q_user[9]);
701 		}
702 		else
703 			alias(a);
704 	}
705 
706 	/*
707 	**  If the user is local and still being sent, verify that
708 	**  the address is good.  If it is, try to forward.
709 	**  If the address is already good, we have a forwarding
710 	**  loop.  This can be broken by just sending directly to
711 	**  the user (which is probably correct anyway).
712 	*/
713 
714 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == M_LOCAL)
715 	{
716 		char buf[MAXNAME];
717 
718 		strcpy(buf, a->q_user);
719 		stripquotes(buf, TRUE);
720 
721 		/* see if this is to a file */
722 		if (index(buf, '/') != NULL)
723 		{
724 			if (access(buf, 2) < 0)
725 			{
726 				a->q_flags |= QBADADDR;
727 				giveresponse(EX_CANTCREAT, TRUE, m);
728 			}
729 		}
730 		else
731 		{
732 			register struct passwd *pw;
733 			extern struct passwd *getpwnam();
734 			pw = getpwnam(buf);
735 			if (pw == NULL)
736 			{
737 				a->q_flags |= QBADADDR;
738 				giveresponse(EX_NOUSER, TRUE, m);
739 			}
740 			else
741 			{
742 				a->q_home = newstr(pw->pw_dir);
743 				if (strcmp(buf, a->q_user) == 0)
744 					forward(a);
745 			}
746 		}
747 	}
748 }
749 /*
750 **  INCLUDE -- handle :include: specification.
751 **
752 **	Parameters:
753 **		fname -- filename to include.
754 **
755 **	Returns:
756 **		none.
757 **
758 **	Side Effects:
759 **		reads the :include: file and sends to everyone
760 **		listed in that file.
761 */
762 
763 include(fname)
764 	char *fname;
765 {
766 	char buf[MAXLINE];
767 	register FILE *fp;
768 
769 	if (Verbose)
770 		message(Arpa_Info, "Including file %s", fname);
771 	fp = fopen(fname, "r");
772 	if (fp == NULL)
773 	{
774 		usrerr("Cannot open %s", fname);
775 		return;
776 	}
777 
778 	/* read the file -- each line is a comma-separated list. */
779 	while (fgets(buf, sizeof buf, fp) != NULL)
780 	{
781 		register char *p = index(buf, '\n');
782 
783 		if (p != NULL)
784 			*p = '\0';
785 		if (buf[0] == '\0')
786 			continue;
787 		To = fname;
788 		if (Verbose)
789 			message(Arpa_Info, " >> %s", buf);
790 		sendto(buf, 1);
791 	}
792 
793 	fclose(fp);
794 }
795 /*
796 **  MAILFILE -- Send a message to a file.
797 **
798 **	Parameters:
799 **		filename -- the name of the file to send to.
800 **
801 **	Returns:
802 **		The exit code associated with the operation.
803 **
804 **	Side Effects:
805 **		none.
806 **
807 **	Called By:
808 **		deliver
809 */
810 
811 mailfile(filename)
812 	char *filename;
813 {
814 	register FILE *f;
815 
816 	f = fopen(filename, "a");
817 	if (f == NULL)
818 		return (EX_CANTCREAT);
819 
820 	putmessage(f, Mailer[1]);
821 	fputs("\n", f);
822 	(void) fclose(f);
823 	return (EX_OK);
824 }
825