static char SccsId
[] = "@(#)savemail.c 3.14 %G%";
** SAVEMAIL -- Save mail on error
** If the MailBack flag is set, mail it back to the originator
** together with an error message; otherwise, just put it in
** dead.letter in the user's home directory (if he exists on
** Saves the letter, by writing or mailing it back to the
** sender, or by putting it in dead.letter in her home
** WARNING: the user id is reset to the original user.
register struct passwd
*pw
;
extern struct passwd
*getpwnam();
if (exclusive
++ || TempFile
== NULL
)
** In the unhappy event we don't know who to return the mail
if (From
.q_paddr
== NULL
)
if (parse("root", &From
, 0) == NULL
)
syserr("Cannot parse root!");
** If called from Eric Schmidt's network, do special mailback.
** Fundamentally, this is the mailback case except that
** it returns an OK exit status (assuming the return
** If writing back, do it.
** If the user is still logged in on the same terminal,
** then write the error messages back to hir (sic).
** If not, set the MailBack flag so that it will get
if (p
== NULL
|| freopen(p
, "w", stdout
) == NULL
)
xfile
= fopen(Transcript
, "r");
syserr("Cannot open %s", Transcript
);
(void) expand("$n", buf
, &buf
[sizeof buf
- 1]);
printf("\r\nMessage from %s...\r\n", buf
);
printf("Errors occurred while sending mail, transcript follows:\r\n");
while (fgets(buf
, sizeof buf
, xfile
) != NULL
&& !ferror(stdout
))
(void) syserr("savemail: stdout: write err");
** If mailing back, do it.
** Throw away all further output. Don't do aliases, since
** this could cause loops, e.g., if joe mails to x:joe,
** and for some reason the network for x: is down, then
** the response gets sent to x:joe, which gives a
** response, etc. Also force the mail to be delivered
** even if a version of it has already been sent to the
(void) freopen("/dev/null", "w", stdout
);
/* fake up an address header for the from person */
bmove((char *) &From
, (char *) &to_addr
, sizeof to_addr
);
(void) expand("$n", buf
, &buf
[sizeof buf
- 1]);
if (parse(buf
, &From
, -1) == NULL
)
syserr("Can't parse myself!");
i
= deliver(&to_addr
, errhdr
);
bmove((char *) &to_addr
, (char *) &From
, sizeof From
);
syserr("Can't return mail to %s", p
);
** Save the message in dead.letter.
** If we weren't mailing back, and the user is local, we
** should save the message in dead.letter so that the
** poor person doesn't have to type it over again --
** and we all know what poor typists programmers are.
if (ArpaMode
!= ARPA_NONE
)
if (From
.q_mailer
== MN_LOCAL
)
else if ((pw
= getpwnam(From
.q_user
)) != NULL
)
syserr("Can't return mail to %s", From
.q_paddr
);
/* we have a home directory; open dead.letter */
message(Arpa_Info
, "Saving message in dead.letter");
(void) expand("$z/dead.letter", buf
, &buf
[sizeof buf
- 1]);
giveresponse(i
, TRUE
, Mailer
[MN_LOCAL
]);
/* add terminator to writeback message */
** ERRHDR -- Output the header for error mail.
** This is the edit filter to error mailbacks.
** Output the transcript part.
** Output the original message.
** xfile -- the transcript file.
** fp -- the output file.
if ((xfile
= fopen(Transcript
, "r")) == NULL
)
syserr("Cannot open %s", Transcript
);
fprintf(fp
, "To: %s\n", To
);
fprintf(fp
, "Subject: Unable to deliver mail\n");
fprintf(fp
, "\n ----- Transcript of session follows -----\n");
while (fgets(buf
, sizeof buf
, xfile
) != NULL
)
fprintf(fp
, "\n ----- Unsent message follows -----\n");
putmessage(fp
, Mailer
[1]);
syserr("errhdr: I/O error");