* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 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
static char sccsid
[] = "@(#)send.c 8.1 (Berkeley) 6/6/93";
* 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.
send(mp
, obuf
, doign
, prefix
)
register struct message
*mp
;
int ishead
, infld
, ignoring
, dostat
, firstline
;
* Compute the prefix string, without trailing whitespace
for (cp
= prefix
; *cp
; cp
++)
if (*cp
!= ' ' && *cp
!= '\t')
prefixlen
= cp2
== 0 ? 0 : cp2
- prefix
+ 1;
dostat
= doign
== 0 || !isign("status", doign
);
while (count
> 0 && ishead
) {
if (fgets(line
, LINESIZE
, ibuf
) == NULL
)
count
-= length
= strlen(line
);
* First line is the From line, so no headers
ignoring
= doign
== ignoreall
;
} 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
statusput(mp
, obuf
, prefix
);
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.
* Pick up the header field if we have one.
for (cp
= line
; (c
= *cp
++) && c
!= ':' && !isspace(c
);)
* Not a header line, force out status:
* This happens in uucp style mail where
* there are no headers at all.
statusput(mp
, obuf
, prefix
);
* If it is an ignored field and
* we care about such things, skip it.
*cp2
= 0; /* temporarily null terminate */
if (doign
&& isign(line
, doign
))
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
statusput(mp
, obuf
, prefix
);
* Strip trailing whitespace from prefix
(void) fwrite(prefix
, sizeof *prefix
,
(void) fwrite(line
, sizeof *line
, length
, obuf
);
count
--; /* skip final blank line */
if (fgets(line
, LINESIZE
, ibuf
) == NULL
) {
count
-= c
= strlen(line
);
* Strip trailing whitespace from prefix
(void) fwrite(prefix
, sizeof *prefix
,
(void) fwrite(line
, sizeof *line
, c
, obuf
);
c
= count
< LINESIZE
? count
: LINESIZE
;
if ((c
= fread(line
, sizeof *line
, c
, ibuf
)) <= 0)
if (fwrite(line
, sizeof *line
, c
, obuf
) != c
)
if (doign
== ignoreall
&& c
> 0 && line
[c
- 1] != '\n')
/* no final blank line */
if ((c
= getc(ibuf
)) != EOF
&& putc(c
, obuf
) == EOF
)
* Output a reasonable looking status field.
statusput(mp
, obuf
, prefix
)
register struct message
*mp
;
register char *cp
= statout
;
if ((mp
->m_flag
& MNEW
) == 0)
fprintf(obuf
, "%sStatus: %s\n",
prefix
== NOSTR
? "" : prefix
, statout
);
* Interface between the argument list and the mail1 routine
* which does all the dirty work.
mail(to
, cc
, bcc
, smopts
, subject
)
struct name
*to
, *cc
, *bcc
, *smopts
;
head
.h_subject
= subject
;
* Send mail to a bunch of user names. The interface is through
* the mail routine below.
head
.h_to
= extract(str
, GTO
);
* Mail a message on standard input to the people indicated
* in the passed header. (Internal interface).
* Collect user's mail from standard input.
if ((mtf
= collect(hp
, printheaders
)) == NULL
)
if (value("interactive") != NOSTR
)
if (value("askcc") != NOSTR
)
if (hp
->h_subject
== NOSTR
)
printf("No message, no subject; hope that's ok\n");
printf("Null message body; hope that's ok\n");
* Now, take the user names from the combined
* to and cc lists and do all the alias
to
= usermap(cat(hp
->h_bcc
, cat(hp
->h_to
, hp
->h_cc
)));
printf("No recipients specified\n");
* Look through the recipient list for names with /'s
* in them which we write to as files directly.
if ((mtf
= infix(hp
, mtf
)) == NULL
) {
fprintf(stderr
, ". . . message lost, sorry.\n");
namelist
= unpack(cat(hp
->h_smopts
, to
));
printf("Sendmail arguments:");
for (t
= namelist
; *t
!= NOSTR
; t
++)
if ((cp
= value("record")) != NOSTR
)
(void) savemail(expand(cp
), mtf
);
* Fork, set up the temporary mail file as standard
* input for "mail", and exec with the user list we generated
prepare_child(sigmask(SIGHUP
)|sigmask(SIGINT
)|sigmask(SIGQUIT
)|
sigmask(SIGTSTP
)|sigmask(SIGTTIN
)|sigmask(SIGTTOU
),
if ((cp
= value("sendmail")) != NOSTR
)
if (value("verbose") != NOSTR
)
* Fix the header by glopping all of the expanded names from
* the distribution list into the appropriate fields.
register struct name
*np
;
for (np
= tolist
; np
!= NIL
; np
= np
->n_flink
)
if ((np
->n_type
& GMASK
) == GTO
)
cat(hp
->h_to
, nalloc(np
->n_name
, np
->n_type
));
else if ((np
->n_type
& GMASK
) == GCC
)
cat(hp
->h_cc
, nalloc(np
->n_name
, np
->n_type
));
else if ((np
->n_type
& GMASK
) == GBCC
)
cat(hp
->h_bcc
, nalloc(np
->n_name
, np
->n_type
));
* Prepend a header in front of the collected stuff
* and return the new file.
register FILE *nfo
, *nfi
;
if ((nfo
= Fopen(tempMail
, "w")) == NULL
) {
if ((nfi
= Fopen(tempMail
, "r")) == NULL
) {
(void) puthead(hp
, nfo
, GTO
|GSUBJECT
|GCC
|GBCC
|GNL
|GCOMMA
);
* Dump the to, subject, cc header on the
if (hp
->h_to
!= NIL
&& w
& GTO
)
fmt("To:", hp
->h_to
, fo
, w
&GCOMMA
), gotcha
++;
if (hp
->h_subject
!= NOSTR
&& w
& GSUBJECT
)
fprintf(fo
, "Subject: %s\n", hp
->h_subject
), gotcha
++;
if (hp
->h_cc
!= NIL
&& w
& GCC
)
fmt("Cc:", hp
->h_cc
, fo
, w
&GCOMMA
), gotcha
++;
if (hp
->h_bcc
!= NIL
&& w
& GBCC
)
fmt("Bcc:", hp
->h_bcc
, fo
, w
&GCOMMA
), gotcha
++;
* Format the given header line to not exceed 72 characters.
register struct name
*np
;
for (; np
!= NIL
; np
= np
->n_flink
) {
len
= strlen(np
->n_name
);
col
++; /* for the space */
if (col
+ len
+ comma
> 72 && col
> 4) {
* Save the outgoing mail on the passed file.
if ((fo
= Fopen(name
, "a")) == NULL
) {
fprintf(fo
, "From %s %s", myname
, ctime(&now
));
while ((i
= fread(buf
, 1, sizeof buf
, fi
)) > 0)
(void) fwrite(buf
, 1, i
, fo
);