hansen@pegasus.UUCP (Tony L. Hansen) (01/03/86)
< From: allbery@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