Dmail under sys3 (new recmail.c included)
Tony L. Hansen
hansen at pegasus.UUCP
Sat Jan 4 06:20:37 AEST 1986
< From: allbery at ncoast.UUCP (Brandon S. Allbery)
< I have gotten dmail working under System III, by means of much hacking and
< an interface to /bin/mail (or /etc/delivermail, for that matter) which reads
< the To:, Cc:, and Bcc: lines from a message coming in on stdin (if invoked
< with -t; otherwise it execs /bin/mail), discards Bcc:'s, and adds
< sendmail-style Date: and From: lines. If anyone's interested, I'll diff the
< sources so that I can #ifdef the changes for BSD42_3, ATT3_5, and RE_V7 and
< post them, along with my mail interface.
This interface program sounds an awful lot like the recmail.c program that
comes along with the netnews programs. Wasn't that usable?
I did some hacking on the recmail.c source to make it handle Bcc: lines
properly where it didn't before. This includes ensuring that a Bcc: line is
visible, without showing other Bcc: recipients, for the Bcc: recipient to
tell them why they had gotten the message.
This version is also being passed onto Rick Adams for inclusion in 2.10.3.
Tony Hansen
ihnp4!pegasus!hansen
#!/bin/sh
# This is a shar archive.
# The rest of this file is a shell script which will extract:
# recmail.c
# Archive created: Fri Jan 3 15:18:39 EST 1986
echo x - recmail.c
sed 's/^X//' > recmail.c << '~FUNKY STUFF~'
/*
* recmail: read a mail message on stdin, grab all addresses in To and Cc
* lines, and pass the full message to all addressees. This is useful to
* send the output of a recently edited mail message (with headers edited too).
* It is similar to sendmail -t, but only assumes /bin/mail.
* To use your own mailer, e. g. nmail, compile with -DMAILER=my_mailer.
*/
#ifdef SCCSID
static char *SccsId = "@(#)recmail.c 1.11++ 12/85";
#endif /* SCCSID */
#include "params.h"
#ifndef MAILER
#define MAILER "/bin/mail"
#endif
char mailer[] = MAILER;
#define MAXRECIPS 100
char *recips[MAXRECIPS];
char *tmpf, *errf, *bccf, *progname;
int nrecips = 0;
main(argc, argv)
char **argv;
int argc;
{
FILE *fd, *errfd;
char linebuf[BUFSIZ];
int i, pid, wpid;
int exstat;
char *mypath;
int goodcnt, badcnt;
char *mktemp(), *getenv();
progname = argv[0];
tmpf = mktemp("/tmp/rmXXXXXX");
(void) close(creat(tmpf,0666));
fd = fopen(tmpf, "w");
errf = mktemp("/tmp/rmXXXXXX");
(void) close(creat(errf,0666));
errfd = fopen(errf, "w");
bccf = mktemp("/tmp/rmXXXXXX");
(void) close(creat(errf,0666));
fputs("Subject: Returned mail\n", errfd);
fputs("\n ----- Transcript of session follows -----\n", errfd);
(void) fflush(errfd);
goodcnt = badcnt = 0;
while (fgets(linebuf, sizeof linebuf, stdin) != NULL) {
if (Equal(linebuf, "BCC: ", 5))
addrecips(linebuf+5, 1);
else {
if (fputs(linebuf, fd) == EOF)
werror();
if (linebuf[0] == '\n')
break;
if (Equal(linebuf, "TO: ", 4) ||
Equal(linebuf, "CC: ", 4))
addrecips(linebuf+4, 0);
}
}
if (!feof(stdin)) {
while (fgets(linebuf, sizeof linebuf, stdin) != NULL) {
if (fputs(linebuf, fd) == EOF)
werror();
}
}
/*
* Append the contents of the .signature file (if it exists) to
* the end of the mail message
*/
{
char sigbuf[BUFSIZ];
register c;
register char *p = getenv("HOME");
FILE *infp;
if (p) {
(void) sprintf(sigbuf, "%s/%s", p, ".signature");
if (infp = fopen(sigbuf, "r")) {
fputs("---\n", fd);
while ((c = getc(infp)) != EOF)
putc(c,fd);
(void) fclose(infp);
}
}
}
(void) fclose(fd);
/*
* Force the path to only consider /bin and /usr/bin, since
* that's the version of mail we want (not /usr/ucb/mail)
*/
{
extern char **environ;
register char **p = environ;
for (;*p;p++)
if (strncmp(*p, "PATH=", 5) == 0) {
*p = "PATH=/bin:/usr/bin";
break;
}
}
/*
* We send the copies out separately, because of a bug in
* some versions of /bin/mail which will generate ANOTHER To: line,
* even though we already have one, if there are at least
* two recipients.
*/
for (i=0; i<nrecips; i++) {
/*
* mail recips[i] < tmpf
*/
pid = mailto(tmpf, bccf, errfd, recips[i]);
exstat = -1;
while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
;
if (exstat == 0)
goodcnt++;
else
badcnt++;
}
if (badcnt) {
mailback(errfd, tmpf, errf);
quit(1);
} else if (goodcnt == 0) {
fputs("recmail: no 'To:' line\n", errfd);
mailback(errfd, tmpf, errf);
quit (1);
} else
quit(0);
}
quit(exitstatus)
int exitstatus;
{
(void) unlink(tmpf);
(void) unlink(errf);
(void) unlink(bccf);
exit (exitstatus);
/* NOTREACHED */
}
/* in case of write error */
werror()
{
fprintf(stderr, "%s: write error on temp file\n", progname);
quit(2);
}
/*
compare two strings, folding case on first string
*/
Equal(s1, s2, n)
register char *s1, *s2;
register int n;
{
while (n-- > 0)
if (toupper(*s1++) != *s2++)
return 0;
return 1;
}
#define isok(c) (isprint(c) && (c) != ' ' && (c) != ',' && (c) != '\t')
/*
Add a list of recipients to the array of recipients.
If Bcc is true, then this is a blind carbon copy.
*/
addrecips(line, Bcc)
char *line;
int Bcc;
{
char *front, *back, *tail;
char *malloc();
tail = line + strlen(line);
for (front=line; front < tail; ) {
while (!isok(*front) && front < tail)
front++;
for (back=front; isok(*back); back++)
;
*back=0;
if (nrecips >= MAXRECIPS) {
fprintf(stderr, "%s: Too many destinations\n", progname);
quit(2);
}
if ((recips[nrecips] = malloc(strlen(front) + 2)) == NULL) {
fprintf(stderr, "%s: Out of space\n", progname);
quit(2);
}
recips[nrecips][0] = Bcc ? 'B' : 'T';
(void) strcpy(&recips[nrecips][1], front);
nrecips++;
front = back+1;
}
}
int
mailto(tmpf, bccf, errfd, recip)
char *tmpf, *bccf, *recip;
FILE *errfd;
{
register int pid;
if (recip[0] == 'B') { /* Bcc recipient */
/*
* Copy file into bcc tmp file with Bcc: line
* added back in (pointing only to this recipient).
*/
FILE *bccfd, *tmpfd;
char linebuf[BUFSIZ];
bccfd = fopen(bccf, "w");
tmpfd = fopen(tmpf, "r");
while (fgets(linebuf, sizeof linebuf, tmpfd) != NULL) {
if (linebuf[0] == '\n')
break;
if (fputs(linebuf, bccfd) == EOF)
werror();
}
fprintf(bccfd, "Bcc: %s\n\n", recip+1);
if (!feof(tmpfd))
while (fgets(linebuf, sizeof linebuf, tmpfd))
if (fputs(linebuf, bccfd) == EOF)
werror();
fclose(bccfd);
fclose(tmpfd);
}
/*
* mail recips < tmpf
*/
while ((pid = fork()) == -1) {
fprintf(stderr, "%s: fork failed, waiting...\r\n", progname);
sleep(60);
}
if (pid == 0) {
(void) close(0);
if (recip[0] == 'B') /* Bcc recipient */
(void) open(bccf, 0);
else /* regular To/Cc recipient */
(void) open(tmpf, 0);
if (errfd != NULL) {
(void) close(1);
(void) dup(fileno(errfd));
(void) fclose(errfd);
(void) close(2);
(void) dup(1);
}
execlp(mailer, mailer, recip+1, (char *)0);
perror(mailer);
exit(1);
}
return pid;
}
mailback(errfd, tmpf, errf)
register FILE *errfd;
char *tmpf;
char *errf;
{
register FILE *fd;
register int c;
int exstat;
register int pid, wpid;
char *logn;
char *getlogin(), *getenv();
register struct passwd *pwd;
if ((fd = fopen(tmpf, "r")) != NULL) {
fputs("\n ----- Unsent message follows -----\n", errfd);
while ((c = getc(fd)) != EOF)
putc(c, errfd);
(void) fclose(fd);
}
(void) fclose(errfd);
if ((logn = getlogin()) == NULL && (logn = getenv("USER")) == NULL) {
if ((pwd = getpwent(getuid())) == NULL)
return;
logn = pwd->pw_name;
}
pid = mailto(errf, (FILE *)NULL, logn);
while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
;
}
~FUNKY STUFF~
ls -l recmail.c
# The following exit is to ensure that extra garbage
# after the end of the shar file will be ignored.
exit 0
More information about the Comp.sources.unix
mailing list