1297Seric # include <pwd.h> 23313Seric # include "sendmail.h" 3297Seric 4*4289Seric static char SccsId[] = "@(#)savemail.c 3.16 09/01/81"; 5408Seric 6297Seric /* 7297Seric ** SAVEMAIL -- Save mail on error 8297Seric ** 9297Seric ** If the MailBack flag is set, mail it back to the originator 10297Seric ** together with an error message; otherwise, just put it in 11297Seric ** dead.letter in the user's home directory (if he exists on 12297Seric ** this machine). 13297Seric ** 14297Seric ** Parameters: 15297Seric ** none 16297Seric ** 17297Seric ** Returns: 18297Seric ** none 19297Seric ** 20297Seric ** Side Effects: 21297Seric ** Saves the letter, by writing or mailing it back to the 22297Seric ** sender, or by putting it in dead.letter in her home 23297Seric ** directory. 24297Seric ** 25297Seric ** WARNING: the user id is reset to the original user. 26297Seric */ 27297Seric 28297Seric savemail() 29297Seric { 30297Seric register struct passwd *pw; 31297Seric register FILE *xfile; 32297Seric char buf[MAXLINE+1]; 33297Seric extern errhdr(); 342973Seric auto ADDRESS to_addr; 35297Seric extern struct passwd *getpwnam(); 36297Seric register char *p; 37297Seric register int i; 38297Seric extern char *ttypath(); 39297Seric static int exclusive; 40297Seric 414199Seric if (exclusive++) 42297Seric return; 43297Seric 44297Seric /* 45297Seric ** In the unhappy event we don't know who to return the mail 46297Seric ** to, make someone up. 47297Seric */ 48297Seric 49297Seric if (From.q_paddr == NULL) 50297Seric { 51297Seric if (parse("root", &From, 0) == NULL) 52297Seric { 53297Seric syserr("Cannot parse root!"); 54297Seric ExitStat = EX_SOFTWARE; 55297Seric finis(); 56297Seric } 57297Seric } 584079Seric To = NULL; 59297Seric 60297Seric /* 61401Seric ** If called from Eric Schmidt's network, do special mailback. 62401Seric ** Fundamentally, this is the mailback case except that 63401Seric ** it returns an OK exit status (assuming the return 64401Seric ** worked). 65297Seric */ 66297Seric 67401Seric if (BerkNet) 68297Seric { 69401Seric ExitStat = EX_OK; 70297Seric MailBack++; 71297Seric } 72297Seric 73297Seric /* 74297Seric ** If writing back, do it. 75297Seric ** If the user is still logged in on the same terminal, 76297Seric ** then write the error messages back to hir (sic). 77297Seric ** If not, set the MailBack flag so that it will get 78297Seric ** mailed back instead. 79297Seric */ 80297Seric 81297Seric if (WriteBack) 82297Seric { 83297Seric p = ttypath(); 84297Seric if (p == NULL || freopen(p, "w", stdout) == NULL) 85297Seric { 86297Seric MailBack++; 87297Seric errno = 0; 88297Seric } 89297Seric else 90297Seric { 91401Seric xfile = fopen(Transcript, "r"); 92401Seric if (xfile == NULL) 93401Seric syserr("Cannot open %s", Transcript); 944086Seric (void) expand("$n", buf, &buf[sizeof buf - 1]); 954162Seric printf("\r\nMessage from %s...\r\n", buf); 96297Seric printf("Errors occurred while sending mail, transcript follows:\r\n"); 974086Seric while (fgets(buf, sizeof buf, xfile) != NULL && !ferror(stdout)) 98297Seric fputs(buf, stdout); 99297Seric if (ferror(stdout)) 1004086Seric (void) syserr("savemail: stdout: write err"); 1014086Seric (void) fclose(xfile); 102297Seric } 103297Seric } 104297Seric 105297Seric /* 106297Seric ** If mailing back, do it. 107297Seric ** Throw away all further output. Don't do aliases, since 108297Seric ** this could cause loops, e.g., if joe mails to x:joe, 109297Seric ** and for some reason the network for x: is down, then 110297Seric ** the response gets sent to x:joe, which gives a 111297Seric ** response, etc. Also force the mail to be delivered 112297Seric ** even if a version of it has already been sent to the 113297Seric ** sender. 114297Seric */ 115297Seric 1163048Seric if (MailBack) 117297Seric { 1184086Seric (void) freopen("/dev/null", "w", stdout); 119297Seric NoAlias++; 120297Seric ForceMail++; 121297Seric 122297Seric /* fake up an address header for the from person */ 123297Seric bmove((char *) &From, (char *) &to_addr, sizeof to_addr); 1244086Seric (void) expand("$n", buf, &buf[sizeof buf - 1]); 1254086Seric if (parse(buf, &From, -1) == NULL) 126297Seric { 127297Seric syserr("Can't parse myself!"); 128297Seric ExitStat = EX_SOFTWARE; 129297Seric finis(); 130297Seric } 131297Seric i = deliver(&to_addr, errhdr); 132297Seric bmove((char *) &to_addr, (char *) &From, sizeof From); 133297Seric if (i != 0) 134297Seric syserr("Can't return mail to %s", p); 135297Seric else 136297Seric return; 137297Seric } 138297Seric 139297Seric /* 140297Seric ** Save the message in dead.letter. 141297Seric ** If we weren't mailing back, and the user is local, we 142297Seric ** should save the message in dead.letter so that the 143297Seric ** poor person doesn't have to type it over again -- 144297Seric ** and we all know what poor typists programmers are. 145297Seric */ 146297Seric 1474162Seric if (ArpaMode != ARPA_NONE) 1484162Seric return; 1494079Seric p = NULL; 1504196Seric if (From.q_mailer == MN_LOCAL) 151297Seric { 1524079Seric if (From.q_home != NULL) 1534079Seric p = From.q_home; 1544079Seric else if ((pw = getpwnam(From.q_user)) != NULL) 1554079Seric p = pw->pw_dir; 156297Seric } 1574079Seric if (p == NULL) 158297Seric { 1594079Seric syserr("Can't return mail to %s", From.q_paddr); 160297Seric # ifdef DEBUG 161297Seric p = "/usr/tmp"; 162297Seric # else 163297Seric p = NULL; 164297Seric # endif 165297Seric } 1664199Seric if (p != NULL && TempFile != NULL) 167297Seric { 168297Seric /* we have a home directory; open dead.letter */ 1694167Seric message(Arpa_Info, "Saving message in dead.letter"); 1704079Seric define('z', p); 1714086Seric (void) expand("$z/dead.letter", buf, &buf[sizeof buf - 1]); 1724066Seric To = buf; 1734066Seric i = mailfile(buf); 1744196Seric giveresponse(i, TRUE, Mailer[MN_LOCAL]); 175297Seric } 176297Seric 177297Seric /* add terminator to writeback message */ 178297Seric if (WriteBack) 179297Seric printf("-----\r\n"); 180297Seric } 181297Seric /* 182297Seric ** ERRHDR -- Output the header for error mail. 183297Seric ** 184297Seric ** This is the edit filter to error mailbacks. 185297Seric ** 186297Seric ** Algorithm: 187297Seric ** Output fixed header. 188297Seric ** Output the transcript part. 189297Seric ** Output the original message. 190297Seric ** 191297Seric ** Parameters: 192297Seric ** xfile -- the transcript file. 193297Seric ** fp -- the output file. 194297Seric ** 195297Seric ** Returns: 196297Seric ** none 197297Seric ** 198297Seric ** Side Effects: 199297Seric ** input from xfile 200297Seric ** output to fp 201297Seric ** 202297Seric ** Called By: 203297Seric ** deliver 204297Seric */ 205297Seric 206297Seric 207297Seric errhdr(fp) 208297Seric register FILE *fp; 209297Seric { 2103189Seric char buf[MAXLINE]; 2113189Seric register FILE *xfile; 212297Seric 2134086Seric (void) fflush(stdout); 2143189Seric if ((xfile = fopen(Transcript, "r")) == NULL) 215297Seric syserr("Cannot open %s", Transcript); 216297Seric errno = 0; 217297Seric fprintf(fp, "To: %s\n", To); 218297Seric fprintf(fp, "Subject: Unable to deliver mail\n"); 219297Seric fprintf(fp, "\n ----- Transcript of session follows -----\n"); 2204086Seric while (fgets(buf, sizeof buf, xfile) != NULL) 2213189Seric fputs(buf, fp); 222*4289Seric if (NoReturn) 223*4289Seric fprintf(fp, "\n ----- Return message suppressed -----\n\n"); 224*4289Seric else if (TempFile != NULL) 2254199Seric { 2264199Seric fprintf(fp, "\n ----- Unsent message follows -----\n"); 2274199Seric (void) fflush(fp); 2284199Seric putmessage(fp, Mailer[1]); 2294199Seric } 2304199Seric else 2314199Seric fprintf(fp, "\n ----- No message was collected -----\n\n"); 2324086Seric (void) fclose(xfile); 233297Seric if (errno != 0) 234297Seric syserr("errhdr: I/O error"); 235297Seric } 236