BSD 3 development
[unix-history] / .ref-BSD-2 / src / Mail / send.c
/* Copyright (c) 1979 Regents of the University of California */
#
#include "rcv.h"
/*
* Mail -- a mail program
*
* Mail to others.
*/
/*
* Send message described by the passed pointer to the
* passed output buffer. Return -1 on error, but normally
* the number of lines written.
*/
send(mailp, obuf)
struct message *mailp;
FILE *obuf;
{
register struct message *mp;
register int t;
unsigned int c;
FILE *ibuf;
int lc;
mp = mailp;
ibuf = setinput(mp);
c = msize(mp);
lc = 0;
while (c-- > 0) {
putc(t = getc(ibuf), obuf);
if (t == '\n')
lc++;
if (ferror(obuf))
return(-1);
}
return(lc);
}
/*
* Interface between the argument list and the mail1 routine
* which does all the dirty work.
*/
mail(people)
char **people;
{
register char *cp2;
register int s;
char *buf, **ap;
struct header head;
for (s = 0, ap = people; *ap != (char *) -1; ap++)
s += strlen(*ap) + 1;
buf = salloc(s+1);
cp2 = buf;
for (ap = people; *ap != (char *) -1; ap++) {
cp2 = copy(*ap, cp2);
*cp2++ = ' ';
}
if (cp2 != buf)
cp2--;
*cp2 = '\0';
head.h_to = buf;
head.h_subj = NOSTR;
head.h_cc = NOSTR;
head.h_seq = 0;
mail1(&head);
return(0);
}
/*
* Send mail to a bunch of user names. The interface is through
* the mail routine below.
*/
sendmail(str)
char *str;
{
register char **ap;
char *bufp;
register int t;
struct header head;
if (blankline(str))
head.h_to = NOSTR;
else
head.h_to = str;
head.h_subj = NOSTR;
head.h_cc = NOSTR;
head.h_seq = 0;
mail1(&head);
return(0);
}
/*
* Mail a message on standard input to the people indicated
* in the passed header. (Internal interface).
*/
mail1(hp)
struct header *hp;
{
register char *cp;
int pid, i, s;
char **namelist;
struct name *to;
FILE *mtf;
/*
* Collect user's mail from standard input.
* Get the result as mtf.
*/
pid = -1;
if (hp->h_subj == NOSTR)
hp->h_seq = 0;
else
hp->h_seq = 1;
if ((mtf = collect(hp)) == NULL)
return(-1);
if (fsize(mtf) == 0 && hp->h_subj == NOSTR) {
printf("No message !?!\n");
goto out;
}
if (intty && value("askcc") != NOSTR)
grabh(hp, GCC);
else if (intty) {
printf("EOT\n");
flush();
}
/*
* Now, take the user names from the combined
* to and cc lists and do all the alias
* processing.
*/
senderr = 0;
to = usermap(cat(extract(hp->h_to), extract(hp->h_cc)));
if (to == NIL) {
printf("No recipients specified\n");
goto topdog;
}
/*
* Look through the recipient list for names with /'s
* in them which we write to as files directly.
*/
to = outof(to, mtf, hp);
to = verify(to);
if (senderr) {
topdog:
unlink(deadletter);
exwrite(deadletter, mtf, 1);
}
if (to == NIL)
goto out;
to = elide(to);
mechk(to);
if (count(to) > 1)
hp->h_seq++;
if (hp->h_seq > 0)
if ((mtf = infix(hp, mtf)) == NULL) {
fprintf(stderr, ". . . message lost, sorry.\n");
return(-1);
}
namelist = unpack(to);
if (value("record") != NOSTR)
savemail(value("record"), hp, mtf, namelist);
/*
* 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.
*/
wait(&s);
rewind(mtf);
pid = fork();
if (pid == -1) {
perror("fork");
goto out;
}
if (pid == 0) {
for (i = 1; i < 17; i++)
signal(i, SIG_IGN);
s = fileno(mtf);
for (i = 3; i < 15; i++)
if (i != s)
close(i);
close(0);
dup(s);
close(s);
execv(MAIL, namelist);
perror(MAIL);
exit(1);
}
out:
fclose(mtf);
return(pid);
}
/*
* Prepend a header in front of the collected stuff
* and return the new file.
*/
FILE *
infix(hp, fi)
struct header *hp;
FILE *fi;
{
extern char tempMail[];
register FILE *nfo, *nfi;
register int c;
if ((nfo = fopen(tempMail, "w")) == NULL) {
perror(tempMail);
return(fi);
}
if ((nfi = fopen(tempMail, "r")) == NULL) {
perror(tempMail);
fclose(nfo);
return(fi);
}
unlink(tempMail);
puthead(hp, nfo);
c = getc(fi);
while (c != EOF) {
putc(c, nfo);
c = getc(fi);
}
fflush(nfo);
if (ferror(nfo)) {
perror(tempMail);
fclose(nfo);
fclose(nfi);
return(fi);
}
fclose(nfo);
fclose(fi);
rewind(nfi);
return(nfi);
}
/*
* Dump the to, subj, cc header on the
* passed file buffer.
*/
puthead(hp, fo)
struct header *hp;
FILE *fo;
{
if (hp->h_to != NOSTR)
fprintf(fo, "To: %s\n", hp->h_to);
if (hp->h_subj != NOSTR)
fprintf(fo, "Subj: %s\n", hp->h_subj);
if (hp->h_cc != NOSTR)
fprintf(fo, "Cc: %s\n", hp->h_cc);
if (hp->h_to != NOSTR || hp->h_subj != NOSTR || hp->h_cc != NOSTR)
putc('\n', fo);
return(0);
}
/*
* Save the outgoing mail on the passed file.
*/
savemail(name, hp, fi, tolist)
char name[], **tolist;
struct header *hp;
FILE *fi;
{
register FILE *fo;
register int c;
long now;
if ((fo = fopen(name, "a")) == NULL) {
perror(name);
return(-1);
}
time(&now);
fprintf(fo, "From %s %s", *(tolist+1), ctime(&now));
rewind(fi);
for (c = getc(fi); c != EOF; c = getc(fi))
putc(c, fo);
fprintf(fo, "\n");
fflush(fo);
if (ferror(fo))
perror(name);
fclose(fo);
return(0);
}