xref: /illumos-gate/usr/src/cmd/mail/sendlist.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 
24 
25 /*
26  * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include "mail.h"
33 /*
34  *  NAME
35  *	sendlist - send copy to specified users
36  *
37  *  SYNOPSIS
38  *	int sendlist(reciplist *list, int letnum, int level)
39  *
40  *  DESCRIPTION
41  *	sendlist() will traverse the current recipient list and
42  *	send a copy of the given letter to each user specified,
43  *	invoking send() to do the sending. It returns
44  *	1 if the sending fails, 0 otherwise.
45  */
46 
47 
48 /*
49  * mailx and mailtool read the SENDMAIL from an environment, since few
50  *  people use /bin/mail as their user agent and since /bin/mail is often
51  *  called as root or made setuid it's safer to leave this hardwired.
52  */
53 
54 static char *sendmail_prog = SENDMAIL;
55 
56 int
57 sendlist(list, letnum, level)
58 reciplist	*list;
59 int		letnum;
60 int		level;
61 {
62 	recip *to;
63 	int rc = 0;
64 	FILE *fp;
65 	int nargs = 4;			/* "sendmail", "-oi", "--", .. NULL */
66 	char **argv;
67 	char **p;
68 
69 	/* Deliver mail directly to a mailbox */
70 	if (deliverflag) {
71 		/*
72 		 * Note failure to deliver to any one of the recipients
73 		 * should be considered a failure, so that the user
74 		 * get's an indication of that failure.
75 		 */
76 		for (to = &(list->recip_list); to; to = to->next) {
77 			if (to->name)
78 				if (!send_mbox(to->name, letnum))
79 					rc = 1;
80 		}
81 		return (rc);
82 	}
83 
84 	/*
85 	 * build argv list, allowing for arbitrarily long deliver lists
86 	 * and then  hand the message off to sendmail
87 	 */
88 
89 	if (!ismail)
90 		nargs += 2;	/* for "-f", "Rpath" */
91 
92 	for (to = &(list->recip_list); to; to = to->next)
93 		if (to->name)
94 			nargs++;
95 
96 	argv = malloc(nargs * sizeof (char *));
97 
98 	if (argv == NULL)
99 		return (1);
100 
101 	p = argv;
102 
103 	*p++ = sendmail_prog;
104 
105 	/* If we're rmail add "-f", "Rpath" to the the command line */
106 	if (!ismail) {
107 		*p++ = "-f";
108 		*p++ = Rpath;
109 	}
110 
111 	*p++ = "-oi";
112 	*p++ = "--";		/* extra protection: end of argument list */
113 
114 	for (to = &(list->recip_list); to; to = to->next)
115 		if (to->name)
116 			*p++ = to->name;
117 
118 	*p = NULL;
119 
120 	fp = popenvp(sendmail_prog, argv, "w", 0);
121 
122 	free(argv);
123 
124 	if (fp == NULL)
125 		return (1);
126 
127 	copylet(letnum, fp, ORDINARY);
128 	rc = pclosevp(fp);
129 	if (!rc)
130 		return (0);
131 	else
132 		return (1);
133 }
134 
135 /*
136  * send_mbox(user, letnum)  Sends the letter specified by letnum to the
137  *	"user"'s mailbox. It returns 1 if the sending fails;
138  *	0 on success.
139  */
140 
141 
142 
143 int
144 send_mbox(mbox, letnum)
145 char	*mbox;
146 int	letnum;
147 {
148 	char file[PATH_MAX];
149 	char biffmsg[PATH_MAX];
150 	int mbfd;
151 	FILE *malf;
152 	int rc;
153 	uid_t useruid, saved_uid;
154 	void (*istat)(), (*qstat)(), (*hstat)();
155 
156 	if (!islocal(mbox, &useruid))
157 		return (1);
158 	(void) strlcpy(file, maildir, sizeof (file));
159 	if (strlcat(file, mbox, sizeof (file)) >= sizeof (file)) {
160 		rc = FALSE;
161 		goto done;
162 	}
163 
164 	/*
165 	 * We need to setgid and seteuid here since the users's mail box
166 	 * might be NFS mounted and since root can't write across NFS.
167 	 * Note this won't work with Secure NFS/RPC's.  Since delivering to
168 	 * NFS mounted directories isn't really supported that's OK for now.
169 	 */
170 	setgid(mailgrp);
171 	saved_uid = geteuid();
172 	seteuid(useruid);
173 	lock(mbox);
174 
175 	/* ignore signals */
176 	istat = signal(SIGINT, SIG_IGN);
177 	qstat = signal(SIGQUIT, SIG_IGN);
178 	hstat = signal(SIGHUP, SIG_IGN);
179 	/* now access mail box */
180 	mbfd = accessmf(file);
181 	if (mbfd == -1) {	/* mail box access failed, bail out */
182 		unlock();
183 		rc = FALSE;
184 		sav_errno = EACCES;
185 		goto done;
186 	} else {
187 				/* mail box is ok, now do append */
188 		if ((malf = fdopen(mbfd, "a")) != NULL) {
189 			(void) snprintf(biffmsg, sizeof (biffmsg),
190 			    "%s@%d\n", mbox, ftell(malf));
191 			rc = copylet(letnum, malf, ORDINARY);
192 			fclose(malf);
193 		}
194 	}
195 
196 	if (rc == FALSE)
197 		fprintf(stderr, "%s: Cannot append to %s\n", program, file);
198 	else
199 		notifybiff(biffmsg);
200 
201 done:
202 	/* restore signal */
203 	(void) signal(SIGINT, istat);
204 	(void) signal(SIGQUIT, qstat);
205 	(void) signal(SIGHUP, hstat);
206 	unlock();
207 	seteuid(saved_uid);
208 	return (rc);
209 }
210 
211 #include <sys/socket.h>
212 #include <netinet/in.h>
213 
214 notifybiff(msg)
215 	char *msg;
216 {
217 	static struct sockaddr_in addr;
218 	static int f = -1;
219 
220 	if (addr.sin_family == 0) {
221 		addr.sin_family = AF_INET;
222 		addr.sin_addr.s_addr = INADDR_LOOPBACK;
223 		addr.sin_port = htons(IPPORT_BIFFUDP);
224 	}
225 	if (f < 0)
226 		f = socket(AF_INET, SOCK_DGRAM, 0);
227 	sendto(f, msg, strlen(msg)+1, 0, (struct sockaddr *)&addr,
228 		sizeof (addr));
229 }
230