* Copyright (c) 1980 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of California at Berkeley. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
static char sccsid
[] = "@(#)send.c 5.5 (Berkeley) 2/18/88";
* Send message described by the passed pointer to the
* passed output buffer. Return -1 on error, but normally
* the number of lines written. Adjust the status: field
* if need be. If doign is set, suppress ignored header fields.
register struct message
*mp
;
int lc
, ishead
, infld
, ignoring
, dostat
;
dostat
= !doign
|| !isign("status");
while (count
> 0 && ishead
) {
if (fgets(line
, LINESIZE
, ibuf
) == NULL
)
count
-= length
= strlen(line
);
* First line is the From line, so no headers
} 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
} 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.
(void) putc('\n', obuf
); /* add blank line */
* If it is an ignored field and
* we care about such things, skip it.
*cp2
= 0; /* temporarily null terminate */
if (doign
&& isign(line
))
else if ((line
[0] == 's' || line
[0] == 'S') &&
icequal(line
, "status")) {
* If the field is "status," go compute
* and print the real Status: field
(void) fwrite(line
, sizeof *line
, length
, obuf
);
c
= count
< LINESIZE
? count
: LINESIZE
;
if ((c
= fread(cp
, sizeof *cp
, c
, ibuf
)) <= 0)
if (fwrite(cp
, sizeof *cp
, c
, obuf
) != c
)
if (ishead
&& (mp
->m_flag
& MSTATUS
))
printf("failed to fix up status field\n");
* Output a reasonable looking status field.
* But if "status" is ignored and doign, forget it.
register struct message
*mp
;
register char *cp
= statout
;
if ((mp
->m_flag
& MNEW
) == 0)
fprintf(obuf
, "Status: %s\n", statout
);
* Interface between the argument list and the mail1 routine
* which does all the dirty work.
for (s
= 0, ap
= people
; *ap
!= 0; ap
++)
for (ap
= people
; *ap
!= 0; ap
++) {
* Send mail to a bunch of user names. The interface is through
* the mail routine below.
* Mail a message on standard input to the people indicated
* in the passed header. (Internal interface).
char **namelist
, *deliver
;
int remote
= rflag
!= NOSTR
|| rmail
;
* Collect user's mail from standard input.
if ((mtf
= collect(hp
)) == NULL
)
if (hp
->h_subject
== NOSTR
)
if (intty
&& value("askcc") != NOSTR
)
* Now, take the user names from the combined
* to and cc lists and do all the alias
to
= usermap(cat(extract(hp
->h_bcc
, GBCC
),
cat(extract(hp
->h_to
, GTO
), extract(hp
->h_cc
, GCC
))));
printf("No recipients specified\n");
* Look through the recipient list for names with /'s
* in them which we write to as files directly.
if (senderr
&& !remote
) {
(void) remove(deadletter
);
(void) exwrite(deadletter
, mtf
, 1);
for (gotcha
= 0, np
= to
; np
!= NIL
; np
= np
->n_flink
)
if ((np
->n_type
& GDEL
) == 0) {
if (hp
->h_seq
> 0 && !remote
) {
if (hp
->h_subject
== NOSTR
)
printf("No message, no subject; hope that's ok\n");
printf("Null message body; hope that's ok\n");
if ((mtf
= infix(hp
, mtf
)) == NULL
) {
fprintf(stderr
, ". . . message lost, sorry.\n");
printf("Recipients of message:\n");
for (t
= namelist
; *t
!= NOSTR
; t
++)
if ((cp
= value("record")) != NOSTR
)
(void) savemail(expand(cp
), mtf
);
* Wait, to absorb a potential zombie, then
* fork, set up the temporary mail file as standard
* input for "mail" and exec with the user list we generated
* far above. Return the process id to caller in case he
* wants to await the completion of mail.
while (wait3(&s
, WNOHANG
, (struct timeval
*) 0) > 0)
(void) remove(deadletter
);
(void) exwrite(deadletter
, mtf
, 1);
(void) signal(SIGTSTP
, SIG_IGN
);
(void) signal(SIGTTIN
, SIG_IGN
);
(void) signal(SIGTTOU
, SIG_IGN
);
(void) signal(SIGHUP
, SIG_IGN
);
(void) signal(SIGINT
, SIG_IGN
);
(void) signal(SIGQUIT
, SIG_IGN
);
if (!stat(POSTAGE
, &sbuf
))
if ((postage
= fopen(POSTAGE
, "a")) != NULL
) {
fprintf(postage
, "%s %d %ld\n", myname
,
for (i
= getdtablesize(); --i
> 2;)
if ((deliver
= value("sendmail")) == NOSTR
)
execv(deliver
, namelist
);
if (remote
|| (value("verbose") != NOSTR
)) {
while ((p
= wait(&s
)) != pid
&& p
!= -1)
* Fix the header by glopping all of the expanded names from
* the distribution list into the appropriate fields.
* If there are any ARPA net recipients in the message,
* we must insert commas, alas.
register struct name
*np
;
for (f
= 0, np
= tolist
; np
!= NIL
; np
= np
->n_flink
)
if (any('@', np
->n_name
)) {
fprintf(stderr
, "Should be inserting commas in recip lists\n");
hp
->h_to
= detract(tolist
, GTO
|f
);
hp
->h_cc
= detract(tolist
, GCC
|f
);
* 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
|GNL
);
* Dump the to, subject, cc header on the
if (hp
->h_to
!= NOSTR
&& w
& GTO
)
fmt("To: ", hp
->h_to
, fo
), gotcha
++;
if (hp
->h_subject
!= NOSTR
&& w
& GSUBJECT
)
fprintf(fo
, "Subject: %s\n", hp
->h_subject
), gotcha
++;
if (hp
->h_cc
!= NOSTR
&& w
& GCC
)
fmt("Cc: ", hp
->h_cc
, fo
), gotcha
++;
if (hp
->h_bcc
!= NOSTR
&& w
& GBCC
)
fmt("Bcc: ", hp
->h_bcc
, fo
), gotcha
++;
* Format the given text to not exceed 72 characters.
register char *str
, *txt
;
register char *bg
, *bl
, *pt
, ch
;
while (*bl
&& !isspace(*bl
))
fprintf(fo
, "%s\n ", bg
);
* Save the outgoing mail on the passed file.
if ((fo
= fopen(name
, "a")) == NULL
) {
if ((n
= rflag
) == NOSTR
)
fprintf(fo
, "From %s %s", n
, ctime(&now
));
while ((i
= fread(buf
, 1, sizeof buf
, fi
)) > 0)
(void) fwrite(buf
, 1, i
, fo
);