2006-10-31 23:07:32 +03:00
|
|
|
/* $NetBSD: send.c,v 1.27 2006/10/31 20:07:32 christos Exp $ */
|
1996-06-08 23:48:09 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-06-29 09:09:04 +04:00
|
|
|
* Copyright (c) 1980, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 15:13:06 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-03-21 12:45:37 +03:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
1997-10-19 09:02:57 +04:00
|
|
|
#include <sys/cdefs.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef lint
|
1996-06-08 23:48:09 +04:00
|
|
|
#if 0
|
|
|
|
static char sccsid[] = "@(#)send.c 8.1 (Berkeley) 6/6/93";
|
|
|
|
#else
|
2006-10-31 23:07:32 +03:00
|
|
|
__RCSID("$NetBSD: send.c,v 1.27 2006/10/31 20:07:32 christos Exp $");
|
1996-06-08 23:48:09 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include "rcv.h"
|
1994-06-29 09:09:04 +04:00
|
|
|
#include "extern.h"
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
#include "mime.h"
|
|
|
|
#endif
|
|
|
|
|
2006-10-31 23:07:32 +03:00
|
|
|
#ifdef SMOPTS_CMD
|
|
|
|
#include <db.h>
|
|
|
|
|
|
|
|
static int
|
|
|
|
namecmp(struct name *np1, struct name *np2)
|
|
|
|
{
|
|
|
|
for (/*EMPTY*/; np1 && np2; np1 = np1->n_flink, np2 = np2->n_flink) {
|
|
|
|
if (strcmp(np1->n_name, np2->n_name) != 0)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return np1 || np2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct name *
|
|
|
|
get_smopts(struct name *to)
|
|
|
|
{
|
|
|
|
struct smopts_s *sp;
|
|
|
|
struct name *smargs, *np;
|
|
|
|
smargs = NULL;
|
|
|
|
for (np = to; np; np = np->n_flink) {
|
|
|
|
if ((sp = findsmopts(np->n_name, 0)) == NULL)
|
|
|
|
continue;
|
|
|
|
if (smargs == NULL)
|
|
|
|
smargs = sp->s_smopts;
|
|
|
|
else if (namecmp(smargs, sp->s_smopts) != 0)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (smargs &&
|
|
|
|
smargs->n_flink == NULL &&
|
|
|
|
(smargs->n_name == NULL || smargs->n_name[0] == '\0'))
|
|
|
|
return NULL;
|
|
|
|
return smargs;
|
|
|
|
}
|
|
|
|
#endif /* SMOPTS_CMD */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Mail -- a mail program
|
|
|
|
*
|
|
|
|
* Mail to others.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send message described by the passed pointer to the
|
|
|
|
* passed output buffer. Return -1 on error.
|
|
|
|
* Adjust the status: field if need be.
|
|
|
|
* If doign is given, suppress ignored header fields.
|
|
|
|
* prefix is a string to prepend to each output line.
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
int
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
|
|
|
|
const char *prefix, struct mime_info *mip)
|
|
|
|
#else
|
2002-03-02 17:59:35 +03:00
|
|
|
sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
|
2005-07-19 05:38:38 +04:00
|
|
|
const char *prefix)
|
2006-10-22 01:37:20 +04:00
|
|
|
#endif /* MIME_SUPPORT */
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-07-20 03:07:10 +04:00
|
|
|
off_t len;
|
1997-10-19 09:02:57 +04:00
|
|
|
FILE *ibuf;
|
1993-03-21 12:45:37 +03:00
|
|
|
char line[LINESIZE];
|
2002-03-02 18:27:51 +03:00
|
|
|
int isheadflag, infld, ignoring = 0, dostat, firstline;
|
1997-10-19 09:02:57 +04:00
|
|
|
char *cp, *cp2;
|
|
|
|
int c = 0;
|
2005-07-20 03:07:10 +04:00
|
|
|
size_t length;
|
|
|
|
size_t prefixlen = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute the prefix string, without trailing whitespace
|
|
|
|
*/
|
2002-03-04 06:07:25 +03:00
|
|
|
if (prefix != NULL) {
|
2005-07-19 05:38:38 +04:00
|
|
|
const char *dp, *dp2 = NULL;
|
|
|
|
for (dp = prefix; *dp; dp++)
|
|
|
|
if (*dp != ' ' && *dp != '\t')
|
|
|
|
dp2 = dp;
|
|
|
|
prefixlen = dp2 == 0 ? 0 : dp2 - prefix + 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
ibuf = setinput(mp);
|
2002-03-02 18:27:51 +03:00
|
|
|
len = mp->m_size;
|
|
|
|
isheadflag = 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
dostat = doign == 0 || !isign("status", doign);
|
|
|
|
infld = 0;
|
|
|
|
firstline = 1;
|
|
|
|
/*
|
|
|
|
* Process headers first
|
|
|
|
*/
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
if (mip)
|
|
|
|
obuf = mime_decode_header(mip);
|
|
|
|
#endif
|
2002-03-02 18:27:51 +03:00
|
|
|
while (len > 0 && isheadflag) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (fgets(line, LINESIZE, ibuf) == NULL)
|
|
|
|
break;
|
2002-03-02 18:27:51 +03:00
|
|
|
len -= length = strlen(line);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (firstline) {
|
|
|
|
/*
|
|
|
|
* First line is the From line, so no headers
|
|
|
|
* there to worry about
|
|
|
|
*/
|
|
|
|
firstline = 0;
|
|
|
|
ignoring = doign == ignoreall;
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
/* XXX - ignore multipart boundary lines! */
|
|
|
|
if (line[0] == '-' && line[1] == '-')
|
|
|
|
ignoring = 1;
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
} else if (line[0] == '\n') {
|
|
|
|
/*
|
|
|
|
* If line is blank, we've reached end of
|
|
|
|
* headers, so force out status: field
|
|
|
|
* and note that we are no longer in header
|
|
|
|
* fields
|
|
|
|
*/
|
|
|
|
if (dostat) {
|
|
|
|
statusput(mp, obuf, prefix);
|
|
|
|
dostat = 0;
|
|
|
|
}
|
2002-03-02 18:27:51 +03:00
|
|
|
isheadflag = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
ignoring = doign == ignoreall;
|
|
|
|
} else if (infld && (line[0] == ' ' || line[0] == '\t')) {
|
|
|
|
/*
|
|
|
|
* If this line is a continuation (via space or tab)
|
|
|
|
* of a previous header field, just echo it
|
|
|
|
* (unless the field should be ignored).
|
|
|
|
* In other words, nothing to do.
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Pick up the header field if we have one.
|
|
|
|
*/
|
|
|
|
for (cp = line; (c = *cp++) && c != ':' && !isspace(c);)
|
|
|
|
;
|
|
|
|
cp2 = --cp;
|
1998-12-19 19:34:38 +03:00
|
|
|
while (isspace((unsigned char)*cp++))
|
1993-03-21 12:45:37 +03:00
|
|
|
;
|
|
|
|
if (cp[-1] != ':') {
|
|
|
|
/*
|
|
|
|
* Not a header line, force out status:
|
|
|
|
* This happens in uucp style mail where
|
|
|
|
* there are no headers at all.
|
|
|
|
*/
|
|
|
|
if (dostat) {
|
|
|
|
statusput(mp, obuf, prefix);
|
|
|
|
dostat = 0;
|
|
|
|
}
|
|
|
|
if (doign != ignoreall)
|
|
|
|
/* add blank line */
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)putc('\n', obuf);
|
2002-03-02 18:27:51 +03:00
|
|
|
isheadflag = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
ignoring = 0;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If it is an ignored field and
|
|
|
|
* we care about such things, skip it.
|
|
|
|
*/
|
|
|
|
*cp2 = 0; /* temporarily null terminate */
|
|
|
|
if (doign && isign(line, doign))
|
|
|
|
ignoring = 1;
|
|
|
|
else if ((line[0] == 's' || line[0] == 'S') &&
|
|
|
|
strcasecmp(line, "status") == 0) {
|
|
|
|
/*
|
|
|
|
* If the field is "status," go compute
|
|
|
|
* and print the real Status: field
|
|
|
|
*/
|
|
|
|
if (dostat) {
|
|
|
|
statusput(mp, obuf, prefix);
|
|
|
|
dostat = 0;
|
|
|
|
}
|
|
|
|
ignoring = 1;
|
|
|
|
} else {
|
|
|
|
ignoring = 0;
|
|
|
|
*cp2 = c; /* restore */
|
|
|
|
}
|
|
|
|
infld = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ignoring) {
|
|
|
|
/*
|
|
|
|
* Strip trailing whitespace from prefix
|
|
|
|
* if line is blank.
|
|
|
|
*/
|
2002-03-04 06:07:25 +03:00
|
|
|
if (prefix != NULL) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (length > 1)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fputs(prefix, obuf);
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)fwrite(prefix, sizeof *prefix,
|
1993-03-21 12:45:37 +03:00
|
|
|
prefixlen, obuf);
|
1998-08-26 00:59:36 +04:00
|
|
|
}
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)fwrite(line, sizeof *line, length, obuf);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ferror(obuf))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Copy out message body
|
|
|
|
*/
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
if (mip) {
|
|
|
|
obuf = mime_decode_body(mip);
|
|
|
|
if (obuf == NULL) /* XXX - early out */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
if (doign == ignoreall)
|
2002-03-02 18:27:51 +03:00
|
|
|
len--; /* skip final blank line */
|
2002-03-04 06:07:25 +03:00
|
|
|
if (prefix != NULL)
|
2002-03-02 18:27:51 +03:00
|
|
|
while (len > 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (fgets(line, LINESIZE, ibuf) == NULL) {
|
|
|
|
c = 0;
|
|
|
|
break;
|
|
|
|
}
|
2002-03-02 18:27:51 +03:00
|
|
|
len -= c = strlen(line);
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Strip trailing whitespace from prefix
|
|
|
|
* if line is blank.
|
|
|
|
*/
|
|
|
|
if (c > 1)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fputs(prefix, obuf);
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)fwrite(prefix, sizeof *prefix,
|
1993-03-21 12:45:37 +03:00
|
|
|
prefixlen, obuf);
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fwrite(line, sizeof *line, (size_t)c, obuf);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ferror(obuf))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
2002-03-02 18:27:51 +03:00
|
|
|
while (len > 0) {
|
2005-07-20 03:07:10 +04:00
|
|
|
c = (int)(len < LINESIZE ? len : LINESIZE);
|
|
|
|
if ((c = fread(line, sizeof *line, (size_t)c, ibuf)) <= 0)
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
2002-03-02 18:27:51 +03:00
|
|
|
len -= c;
|
2005-07-20 03:07:10 +04:00
|
|
|
if (fwrite(line, sizeof *line, (size_t)c, obuf) != c)
|
1993-03-21 12:45:37 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (doign == ignoreall && c > 0 && line[c - 1] != '\n')
|
|
|
|
/* no final blank line */
|
|
|
|
if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF)
|
2006-10-22 01:37:20 +04:00
|
|
|
return -1;
|
1993-03-21 12:45:37 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Output a reasonable looking status field.
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
void
|
2005-07-19 05:38:38 +04:00
|
|
|
statusput(struct message *mp, FILE *obuf, const char *prefix)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
char statout[3];
|
1997-10-19 09:02:57 +04:00
|
|
|
char *cp = statout;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
if (mp->m_flag & MREAD)
|
|
|
|
*cp++ = 'R';
|
|
|
|
if ((mp->m_flag & MNEW) == 0)
|
|
|
|
*cp++ = 'O';
|
|
|
|
*cp = 0;
|
|
|
|
if (statout[0])
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fprintf(obuf, "%sStatus: %s\n",
|
2002-03-04 06:07:25 +03:00
|
|
|
prefix == NULL ? "" : prefix, statout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Interface between the argument list and the mail1 routine
|
|
|
|
* which does all the dirty work.
|
|
|
|
*/
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
int
|
|
|
|
mail(struct name *to, struct name *cc, struct name *bcc,
|
|
|
|
struct name *smopts, char *subject, struct attachment *attach)
|
|
|
|
#else
|
1994-06-29 09:09:04 +04:00
|
|
|
int
|
2002-03-02 17:59:35 +03:00
|
|
|
mail(struct name *to, struct name *cc, struct name *bcc,
|
|
|
|
struct name *smopts, char *subject)
|
2006-10-22 01:37:20 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
struct header head;
|
|
|
|
|
|
|
|
head.h_to = to;
|
|
|
|
head.h_subject = subject;
|
|
|
|
head.h_cc = cc;
|
|
|
|
head.h_bcc = bcc;
|
|
|
|
head.h_smopts = smopts;
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
head.h_attach = attach;
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
mail1(&head, 0);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send mail to a bunch of user names. The interface is through
|
|
|
|
* the mail routine below.
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
int
|
2002-03-02 17:59:35 +03:00
|
|
|
sendmail(void *v)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1996-06-08 23:48:09 +04:00
|
|
|
char *str = v;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct header head;
|
|
|
|
|
|
|
|
head.h_to = extract(str, GTO);
|
2002-03-04 06:07:25 +03:00
|
|
|
head.h_subject = NULL;
|
2002-03-04 06:16:10 +03:00
|
|
|
head.h_cc = NULL;
|
|
|
|
head.h_bcc = NULL;
|
|
|
|
head.h_smopts = NULL;
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
head.h_attach = NULL;
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
mail1(&head, 0);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mail a message on standard input to the people indicated
|
|
|
|
* in the passed header. (Internal interface).
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
void
|
2002-03-02 17:59:35 +03:00
|
|
|
mail1(struct header *hp, int printheaders)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-07-19 05:38:38 +04:00
|
|
|
const char *cp;
|
1993-03-21 12:45:37 +03:00
|
|
|
int pid;
|
2005-07-19 05:38:38 +04:00
|
|
|
const char **namelist;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct name *to;
|
|
|
|
FILE *mtf;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Collect user's mail from standard input.
|
|
|
|
* Get the result as mtf.
|
|
|
|
*/
|
|
|
|
if ((mtf = collect(hp, printheaders)) == NULL)
|
|
|
|
return;
|
2002-03-04 06:07:25 +03:00
|
|
|
if (value("interactive") != NULL) {
|
|
|
|
if (value("askcc") != NULL || value("askbcc") != NULL) {
|
|
|
|
if (value("askcc") != NULL)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)grabh(hp, GCC);
|
2002-03-04 06:07:25 +03:00
|
|
|
if (value("askbcc") != NULL)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)grabh(hp, GBCC);
|
1993-08-28 00:31:51 +04:00
|
|
|
} else {
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)printf("EOT\n");
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1998-08-26 00:59:36 +04:00
|
|
|
}
|
|
|
|
if (fsize(mtf) == 0) {
|
2002-03-04 06:07:25 +03:00
|
|
|
if (value("dontsendempty") != NULL)
|
2000-09-19 05:12:48 +04:00
|
|
|
goto out;
|
2002-03-04 06:07:25 +03:00
|
|
|
if (hp->h_subject == NULL)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)printf("No message, no subject; hope that's ok\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)printf("Null message body; hope that's ok\n");
|
1998-08-26 00:59:36 +04:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Now, take the user names from the combined
|
|
|
|
* to and cc lists and do all the alias
|
|
|
|
* processing.
|
|
|
|
*/
|
|
|
|
senderr = 0;
|
|
|
|
to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
|
2002-03-04 06:16:10 +03:00
|
|
|
if (to == NULL) {
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)printf("No recipients specified\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
senderr++;
|
|
|
|
}
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
/*
|
|
|
|
* If there are attachments, repackage the mail as a
|
|
|
|
* multi-part MIME message.
|
|
|
|
*/
|
|
|
|
if (hp->h_attach || value(ENAME_MIME_ENCODE_MSG))
|
|
|
|
mtf = mime_encode(mtf, hp);
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Look through the recipient list for names with /'s
|
|
|
|
* in them which we write to as files directly.
|
|
|
|
*/
|
|
|
|
to = outof(to, mtf, hp);
|
|
|
|
if (senderr)
|
|
|
|
savedeadletter(mtf);
|
|
|
|
to = elide(to);
|
|
|
|
if (count(to) == 0)
|
|
|
|
goto out;
|
|
|
|
fixhead(hp, to);
|
|
|
|
if ((mtf = infix(hp, mtf)) == NULL) {
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fprintf(stderr, ". . . message lost, sorry.\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
2006-10-31 23:07:32 +03:00
|
|
|
#ifdef SMOPTS_CMD
|
|
|
|
if (hp->h_smopts == NULL) {
|
|
|
|
hp->h_smopts = get_smopts(to);
|
|
|
|
if (hp->h_smopts != NULL &&
|
|
|
|
hp->h_smopts->n_name[0] != '\0' &&
|
|
|
|
value(ENAME_SMOPTS_VERIFY) != NULL)
|
|
|
|
if (grabh(hp, GSMOPTS)) {
|
|
|
|
(void)printf("mail aborted!\n");
|
|
|
|
savedeadletter(mtf);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if 0 /* XXX - for debugging - remove me!!!! */
|
|
|
|
printf("to: '%s' flink: %p\n", to->n_name, to->n_flink);
|
|
|
|
void showname(struct name *);
|
|
|
|
printf("smopts:\n");
|
|
|
|
void showname(struct name *);
|
|
|
|
showname(hp->h_smopts);
|
|
|
|
exit(0);
|
|
|
|
#endif
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
namelist = unpack(cat(hp->h_smopts, to));
|
|
|
|
if (debug) {
|
2005-07-19 05:38:38 +04:00
|
|
|
const char **t;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)printf("Sendmail arguments:");
|
2002-03-04 06:07:25 +03:00
|
|
|
for (t = namelist; *t != NULL; t++)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)printf(" \"%s\"", *t);
|
|
|
|
(void)printf("\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
goto out;
|
|
|
|
}
|
2006-10-31 23:07:32 +03:00
|
|
|
if ((cp = value(ENAME_RECORD)) != NULL)
|
|
|
|
(void)savemail(expand(cp), mtf);
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Fork, set up the temporary mail file as standard
|
|
|
|
* input for "mail", and exec with the user list we generated
|
|
|
|
* far above.
|
|
|
|
*/
|
|
|
|
pid = fork();
|
|
|
|
if (pid == -1) {
|
2002-03-06 00:29:30 +03:00
|
|
|
warn("fork");
|
1993-03-21 12:45:37 +03:00
|
|
|
savedeadletter(mtf);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (pid == 0) {
|
1996-06-08 23:48:09 +04:00
|
|
|
sigset_t nset;
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)sigemptyset(&nset);
|
|
|
|
(void)sigaddset(&nset, SIGHUP);
|
|
|
|
(void)sigaddset(&nset, SIGINT);
|
|
|
|
(void)sigaddset(&nset, SIGQUIT);
|
|
|
|
(void)sigaddset(&nset, SIGTSTP);
|
|
|
|
(void)sigaddset(&nset, SIGTTIN);
|
|
|
|
(void)sigaddset(&nset, SIGTTOU);
|
1996-06-08 23:48:09 +04:00
|
|
|
prepare_child(&nset, fileno(mtf), -1);
|
2002-03-04 06:07:25 +03:00
|
|
|
if ((cp = value("sendmail")) != NULL)
|
1993-03-21 12:45:37 +03:00
|
|
|
cp = expand(cp);
|
|
|
|
else
|
|
|
|
cp = _PATH_SENDMAIL;
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)execv(cp, (char *const *)__UNCONST(namelist));
|
2002-03-06 00:29:30 +03:00
|
|
|
warn("%s", cp);
|
1993-03-21 12:45:37 +03:00
|
|
|
_exit(1);
|
|
|
|
}
|
2002-03-04 06:07:25 +03:00
|
|
|
if (value("verbose") != NULL)
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)wait_child(pid);
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
|
|
|
free_child(pid);
|
|
|
|
out:
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)Fclose(mtf);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fix the header by glopping all of the expanded names from
|
|
|
|
* the distribution list into the appropriate fields.
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
void
|
2002-03-02 17:59:35 +03:00
|
|
|
fixhead(struct header *hp, struct name *tolist)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-19 09:02:57 +04:00
|
|
|
struct name *np;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2002-03-04 06:16:10 +03:00
|
|
|
hp->h_to = NULL;
|
|
|
|
hp->h_cc = NULL;
|
|
|
|
hp->h_bcc = NULL;
|
|
|
|
for (np = tolist; np != NULL; np = np->n_flink) {
|
1997-11-25 20:55:52 +03:00
|
|
|
if (np->n_type & GDEL)
|
|
|
|
continue; /* Don't copy deleted addresses to the header */
|
1993-03-21 12:45:37 +03:00
|
|
|
if ((np->n_type & GMASK) == GTO)
|
|
|
|
hp->h_to =
|
|
|
|
cat(hp->h_to, nalloc(np->n_name, np->n_type));
|
|
|
|
else if ((np->n_type & GMASK) == GCC)
|
|
|
|
hp->h_cc =
|
|
|
|
cat(hp->h_cc, nalloc(np->n_name, np->n_type));
|
|
|
|
else if ((np->n_type & GMASK) == GBCC)
|
|
|
|
hp->h_bcc =
|
|
|
|
cat(hp->h_bcc, nalloc(np->n_name, np->n_type));
|
1997-11-25 20:55:52 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepend a header in front of the collected stuff
|
|
|
|
* and return the new file.
|
|
|
|
*/
|
|
|
|
FILE *
|
2002-03-02 17:59:35 +03:00
|
|
|
infix(struct header *hp, FILE *fi)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-19 09:02:57 +04:00
|
|
|
FILE *nfo, *nfi;
|
2002-03-06 20:36:44 +03:00
|
|
|
int c, fd;
|
|
|
|
char tempname[PATHSIZE];
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2002-03-06 20:36:44 +03:00
|
|
|
(void)snprintf(tempname, sizeof(tempname),
|
|
|
|
"%s/mail.RsXXXXXXXXXX", tmpdir);
|
|
|
|
if ((fd = mkstemp(tempname)) == -1 ||
|
|
|
|
(nfo = Fdopen(fd, "w")) == NULL) {
|
|
|
|
if (fd != -1)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)close(fd);
|
2002-03-06 20:36:44 +03:00
|
|
|
warn("%s", tempname);
|
1993-03-21 12:45:37 +03:00
|
|
|
return(fi);
|
|
|
|
}
|
2002-03-06 20:36:44 +03:00
|
|
|
if ((nfi = Fopen(tempname, "r")) == NULL) {
|
|
|
|
warn("%s", tempname);
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)Fclose(nfo);
|
2002-03-06 20:36:44 +03:00
|
|
|
(void)rm(tempname);
|
1993-03-21 12:45:37 +03:00
|
|
|
return(fi);
|
|
|
|
}
|
2002-03-06 20:36:44 +03:00
|
|
|
(void)rm(tempname);
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
(void)puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GMIME|GNL|GCOMMA);
|
|
|
|
#else
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GNL|GCOMMA);
|
2006-10-22 01:37:20 +04:00
|
|
|
#endif
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
c = getc(fi);
|
|
|
|
while (c != EOF) {
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)putc(c, nfo);
|
1993-03-21 12:45:37 +03:00
|
|
|
c = getc(fi);
|
|
|
|
}
|
|
|
|
if (ferror(fi)) {
|
2002-03-06 00:29:30 +03:00
|
|
|
warn("read");
|
1993-03-21 12:45:37 +03:00
|
|
|
rewind(fi);
|
|
|
|
return(fi);
|
|
|
|
}
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)fflush(nfo);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ferror(nfo)) {
|
2002-03-06 20:36:44 +03:00
|
|
|
warn("%s", tempname);
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)Fclose(nfo);
|
|
|
|
(void)Fclose(nfi);
|
1993-03-21 12:45:37 +03:00
|
|
|
rewind(fi);
|
|
|
|
return(fi);
|
|
|
|
}
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)Fclose(nfo);
|
|
|
|
(void)Fclose(fi);
|
1993-03-21 12:45:37 +03:00
|
|
|
rewind(nfi);
|
|
|
|
return(nfi);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Dump the to, subject, cc header on the
|
|
|
|
* passed file buffer.
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
int
|
2002-03-02 17:59:35 +03:00
|
|
|
puthead(struct header *hp, FILE *fo, int w)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-19 09:02:57 +04:00
|
|
|
int gotcha;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
gotcha = 0;
|
2002-03-04 06:16:10 +03:00
|
|
|
if (hp->h_to != NULL && w & GTO)
|
2006-10-31 23:07:32 +03:00
|
|
|
fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
|
2002-03-04 06:07:25 +03:00
|
|
|
if (hp->h_subject != NULL && w & GSUBJECT)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
|
Jumbo mail patch from our anonymous user:
1) Use editline [optional]:
Most of this code was borrowed from src/usr.bin/ftp. It does the
appropriate editing, history, and completion for all mail commands
(from cmdtab[]) and also does editing on header strings ('~h' inside
the mail editor).
2) '-B' flag:
This will suppress the "To:" line passed to sendmail. In most
configurations it will lead to sendmail adding "To: undisclosed
recipients;". Currently, AFAIK mail requires at least one exposed
recipient address.
3) Comments in rcfile:
Currently, comments in .mailrc are only supported if the first
(non-white) character on a line is '#' followed by white space,
i.e., '#' is a 'nop' command. This (trivial) patch allows the more
normal/expected use of '#' as a comment character. It does not
respect quoting, so that might be an objection which I should fix.
4) Sendmail option editing:
This adds the sendmail option string to the strings editable by the
'~h' command within the mail editor. Currently, you can only set
this string from the command-line, which is particularly annoying
when replying to mail.
5) Reply from:
When replying to a message, grab the "To:" address from the message
and, if there is only one such address and it does not match a list of
allowed addresses (set in the "ReplyFrom" variable), pass it to
sendmail as the "From:" address for the reply (with the '-f' option).
I often make aliases for myself so that my primary address is not
given out; if the alias gets out, I know who to blame. Unfortunately,
a reply to such a message would normally use the primary address
without this patch. A warning is displayed when this is going to
happen so that it can be modified with '~h'.
6) CC and BCC lists:
Allow '-c' and '-b' to accept white-space or ',' delimited lists.
Currently, a white-space delimited list of addresses work, but a
list of aliases will not get expanded. For example, currently:
mail -c "foo bar" christos
will fail to send mail to 'foo' and 'bar' if these are mail aliases
(in ~/.mailrc); sendmail aliases (in /etc/aliases) do work.
7) pipe command:
This pipes the current message into a shell command. I use this for
quick decoding of uuencoded mail, but I can imagine it might be
useful for decrypting encrypted mail, too.
8) show command:
This command takes a list of variables and shows their values. It
is probably stupid as the 'set' command without any argument
displays all variable values. Of course, if there are a lot of
variables you have to sift through the list for the one(s) you want.
2006-09-18 23:46:21 +04:00
|
|
|
if (hp->h_smopts != NULL && w & GSMOPTS)
|
|
|
|
(void)fprintf(fo, "(sendmail options: %s)\n", detract(hp->h_smopts, GSMOPTS)), gotcha++;
|
2002-03-04 06:16:10 +03:00
|
|
|
if (hp->h_cc != NULL && w & GCC)
|
1993-03-21 12:45:37 +03:00
|
|
|
fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++;
|
2002-03-04 06:16:10 +03:00
|
|
|
if (hp->h_bcc != NULL && w & GBCC)
|
1993-03-21 12:45:37 +03:00
|
|
|
fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++;
|
2006-10-22 01:37:20 +04:00
|
|
|
#ifdef MIME_SUPPORT
|
|
|
|
if (w & GMIME && (hp->h_attach || value(ENAME_MIME_ENCODE_MSG)))
|
|
|
|
mime_putheader(fo, hp), gotcha++;
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
if (gotcha && w & GNL)
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)putc('\n', fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Format the given header line to not exceed 72 characters.
|
|
|
|
*/
|
1994-06-29 09:09:04 +04:00
|
|
|
void
|
2005-07-19 05:38:38 +04:00
|
|
|
fmt(const char *str, struct name *np, FILE *fo, int comma)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-19 09:02:57 +04:00
|
|
|
int col, len;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
comma = comma ? 1 : 0;
|
|
|
|
col = strlen(str);
|
|
|
|
if (col)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fputs(str, fo);
|
2002-03-04 06:16:10 +03:00
|
|
|
for (; np != NULL; np = np->n_flink) {
|
|
|
|
if (np->n_flink == NULL)
|
1993-03-21 12:45:37 +03:00
|
|
|
comma = 0;
|
|
|
|
len = strlen(np->n_name);
|
|
|
|
col++; /* for the space */
|
|
|
|
if (col + len + comma > 72 && col > 4) {
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fputs("\n ", fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
col = 4;
|
|
|
|
} else
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)putc(' ', fo);
|
|
|
|
(void)fputs(np->n_name, fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (comma)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)putc(',', fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
col += len + comma;
|
|
|
|
}
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)putc('\n', fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save the outgoing mail on the passed file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
1994-06-29 09:09:04 +04:00
|
|
|
int
|
2006-10-31 23:07:32 +03:00
|
|
|
savemail(const char name[], FILE *fi)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-10-19 09:02:57 +04:00
|
|
|
FILE *fo;
|
1993-03-21 12:45:37 +03:00
|
|
|
char buf[BUFSIZ];
|
1997-10-19 09:02:57 +04:00
|
|
|
int i;
|
1996-06-08 23:48:09 +04:00
|
|
|
time_t now;
|
2006-03-03 18:07:00 +03:00
|
|
|
mode_t m;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-03-03 18:07:00 +03:00
|
|
|
m = umask(077);
|
|
|
|
fo = Fopen(name, "a");
|
|
|
|
(void)umask(m);
|
|
|
|
if (fo == NULL) {
|
2002-03-06 00:29:30 +03:00
|
|
|
warn("%s", name);
|
1993-03-21 12:45:37 +03:00
|
|
|
return (-1);
|
|
|
|
}
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)time(&now);
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fprintf(fo, "From %s %s", myname, ctime(&now));
|
1993-03-21 12:45:37 +03:00
|
|
|
while ((i = fread(buf, 1, sizeof buf, fi)) > 0)
|
2005-07-20 03:07:10 +04:00
|
|
|
(void)fwrite(buf, 1, (size_t)i, fo);
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)putc('\n', fo);
|
|
|
|
(void)fflush(fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ferror(fo))
|
2002-03-06 00:29:30 +03:00
|
|
|
warn("%s", name);
|
2002-03-06 00:18:14 +03:00
|
|
|
(void)Fclose(fo);
|
1993-03-21 12:45:37 +03:00
|
|
|
rewind(fi);
|
|
|
|
return (0);
|
|
|
|
}
|