+ switch (state)
+ {
+ case ESM_QUIET:
+ if (e->e_from.q_mailer == LocalMailer)
+ state = ESM_DEADLETTER;
+ else
+ state = ESM_MAIL;
+ break;
+
+ case ESM_REPORT:
+
+ /*
+ ** If the user is still logged in on the same terminal,
+ ** then write the error messages back to hir (sic).
+ */
+
+ p = ttypath();
+ if (p == NULL || freopen(p, "w", stdout) == NULL)
+ {
+ state = ESM_MAIL;
+ break;
+ }
+
+ expand("\201n", buf, &buf[sizeof buf - 1], e);
+ printf("\r\nMessage from %s...\r\n", buf);
+ printf("Errors occurred while sending mail.\r\n");
+ if (e->e_xfp != NULL)
+ {
+ (void) fflush(e->e_xfp);
+ fp = fopen(queuename(e, 'x'), "r");
+ }
+ else
+ fp = NULL;
+ if (fp == NULL)
+ {
+ syserr("Cannot open %s", queuename(e, 'x'));
+ printf("Transcript of session is unavailable.\r\n");
+ }
+ else
+ {
+ printf("Transcript follows:\r\n");
+ while (fgets(buf, sizeof buf, fp) != NULL &&
+ !ferror(stdout))
+ fputs(buf, stdout);
+ (void) xfclose(fp, "savemail transcript", e->e_id);
+ }
+ printf("Original message will be saved in dead.letter.\r\n");
+ state = ESM_DEADLETTER;
+ break;
+
+ case ESM_MAIL:
+ /*
+ ** If mailing back, do it.
+ ** Throw away all further output. Don't alias,
+ ** since this could cause loops, e.g., if joe
+ ** mails to joe@x, and for some reason the network
+ ** for @x is down, then the response gets sent to
+ ** joe@x, which gives a response, etc. Also force
+ ** the mail to be delivered even if a version of
+ ** it has already been sent to the sender.
+ */
+
+ if (strcmp(e->e_from.q_paddr, "<>") != 0)
+ (void) sendtolist(e->e_from.q_paddr,
+ (ADDRESS *) NULL,
+ &e->e_errorqueue, e);
+
+ /* deliver a cc: to the postmaster if desired */
+ if (PostMasterCopy != NULL)
+ {
+ auto ADDRESS *rlist = NULL;
+
+ (void) sendtolist(PostMasterCopy,
+ (ADDRESS *) NULL,
+ &rlist, e);
+ (void) returntosender(e->e_message,
+ rlist, FALSE, e);
+ }
+ q = e->e_errorqueue;
+ if (q == NULL)
+ {
+ /* this is an error-error */
+ state = ESM_POSTMASTER;
+ break;
+ }
+ if (returntosender(e->e_message,
+ q, (e->e_class >= 0), e) == 0)
+ {
+ state = ESM_DONE;
+ break;
+ }
+
+ /* didn't work -- return to postmaster */
+ state = ESM_POSTMASTER;
+ break;
+
+ case ESM_POSTMASTER:
+ /*
+ ** Similar to previous case, but to system postmaster.
+ */
+
+ q = NULL;
+ if (sendtolist("postmaster", NULL, &q, e) <= 0)
+ {
+ syserr("553 cannot parse postmaster!");
+ ExitStat = EX_SOFTWARE;
+ state = ESM_USRTMP;
+ break;
+ }
+ if (returntosender(e->e_message,
+ q, (e->e_class >= 0), e) == 0)
+ {
+ state = ESM_DONE;
+ break;
+ }
+
+ /* didn't work -- last resort */
+ state = ESM_USRTMP;
+ break;
+
+ case ESM_DEADLETTER:
+ /*
+ ** 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 UNIX users are.
+ */
+
+ p = NULL;
+ if (e->e_from.q_mailer == LocalMailer)
+ {
+ if (e->e_from.q_home != NULL)
+ p = e->e_from.q_home;
+ else if ((pw = getpwnam(e->e_from.q_user)) != NULL)
+ p = pw->pw_dir;
+ }
+ if (p == NULL)
+ {
+ /* no local directory */
+ state = ESM_MAIL;
+ break;
+ }
+ if (e->e_dfp != NULL)
+ {
+ bool oldverb = Verbose;
+
+ /* we have a home directory; open dead.letter */
+ define('z', p, e);
+ expand("\201z/dead.letter", buf, &buf[sizeof buf - 1], e);
+ Verbose = TRUE;
+ message("Saving message in %s", buf);
+ Verbose = oldverb;
+ e->e_to = buf;
+ q = NULL;
+ (void) sendtolist(buf, &e->e_from, &q, e);
+ if (deliver(e, q) == 0)
+ state = ESM_DONE;
+ else
+ state = ESM_MAIL;
+ }
+ else
+ {
+ /* no data file -- try mailing back */
+ state = ESM_MAIL;
+ }
+ break;
+
+ case ESM_USRTMP:
+ /*
+ ** Log the mail in /usr/tmp/dead.letter.
+ */
+
+ if (e->e_class < 0)
+ {
+ state = ESM_DONE;
+ break;
+ }
+
+ fp = dfopen("/usr/tmp/dead.letter",
+ O_WRONLY|O_CREAT|O_APPEND, FileMode);
+ if (fp == NULL)
+ {
+ state = ESM_PANIC;
+ break;
+ }
+
+ putfromline(fp, FileMailer, e);
+ (*e->e_puthdr)(fp, FileMailer, e);
+ putline("\n", fp, FileMailer);
+ (*e->e_putbody)(fp, FileMailer, e, NULL);
+ putline("\n", fp, FileMailer);
+ (void) fflush(fp);
+ state = ferror(fp) ? ESM_PANIC : ESM_DONE;
+ (void) xfclose(fp, "savemail", "/usr/tmp/dead.letter");
+ break;