1297Seric # include <stdio.h> 2297Seric # include <pwd.h> 3297Seric # include "dlvrmail.h" 4297Seric 5297Seric /* 6297Seric ** SAVEMAIL -- Save mail on error 7297Seric ** 8297Seric ** If the MailBack flag is set, mail it back to the originator 9297Seric ** together with an error message; otherwise, just put it in 10297Seric ** dead.letter in the user's home directory (if he exists on 11297Seric ** this machine). 12297Seric ** 13297Seric ** Parameters: 14297Seric ** none 15297Seric ** 16297Seric ** Returns: 17297Seric ** none 18297Seric ** 19297Seric ** Side Effects: 20297Seric ** Saves the letter, by writing or mailing it back to the 21297Seric ** sender, or by putting it in dead.letter in her home 22297Seric ** directory. 23297Seric ** 24297Seric ** WARNING: the user id is reset to the original user. 25297Seric ** 26297Seric ** Requires: 27297Seric ** fopen (sys) 28297Seric ** bmove 29297Seric ** parse 30297Seric ** deliver 31297Seric ** strcpy (sys) 32297Seric ** strcat (sys) 33297Seric ** fclose (sys) 34297Seric ** fgets (sys) 35297Seric ** fputs (sys) 36297Seric ** setpwent (sys) 37297Seric ** getuid (sys) 38297Seric ** setuid (sys) 39297Seric ** getgid (sys) 40297Seric ** setgid (sys) 41297Seric ** getpwnam (sys) 42297Seric ** fprintf (sys) 43297Seric ** ttypath 44297Seric ** freopen (sys) 45297Seric ** printf (sys) 46297Seric ** syserr 47297Seric ** rewind (sys) 48297Seric ** time (sys) 49297Seric ** ferror (sys) 50297Seric ** 51297Seric ** Called By: 52297Seric ** finis 53297Seric ** 54297Seric ** History: 55297Seric ** 12/30/79 -- written. 56297Seric */ 57297Seric 58297Seric # define MY_NAME "~MAILER~DAEMON~" 59297Seric 60297Seric savemail() 61297Seric { 62297Seric register struct passwd *pw; 63297Seric register FILE *xfile; 64297Seric char buf[MAXLINE+1]; 65297Seric extern errhdr(); 66297Seric auto addrq to_addr; 67297Seric extern struct passwd *getpwnam(); 68297Seric register char *p; 69297Seric register int i; 70297Seric auto long tim; 71297Seric extern int errno; 72297Seric extern char *ttypath(); 73297Seric extern char *ctime(); 74297Seric extern addrq *parse(); 75297Seric static int exclusive; 76297Seric 77297Seric if (exclusive++) 78297Seric return; 79297Seric 80297Seric /* 81297Seric ** In the unhappy event we don't know who to return the mail 82297Seric ** to, make someone up. 83297Seric */ 84297Seric 85297Seric if (From.q_paddr == NULL) 86297Seric { 87297Seric if (parse("root", &From, 0) == NULL) 88297Seric { 89297Seric syserr("Cannot parse root!"); 90297Seric ExitStat = EX_SOFTWARE; 91297Seric finis(); 92297Seric } 93297Seric } 94297Seric 95297Seric /* 96*401Seric ** If called from Eric Schmidt's network, do special mailback. 97*401Seric ** Fundamentally, this is the mailback case except that 98*401Seric ** it returns an OK exit status (assuming the return 99*401Seric ** worked). 100297Seric */ 101297Seric 102*401Seric if (BerkNet) 103297Seric { 104*401Seric ExitStat = EX_OK; 105297Seric MailBack++; 106297Seric } 107297Seric 108297Seric /* 109297Seric ** If writing back, do it. 110297Seric ** If the user is still logged in on the same terminal, 111297Seric ** then write the error messages back to hir (sic). 112297Seric ** If not, set the MailBack flag so that it will get 113297Seric ** mailed back instead. 114297Seric */ 115297Seric 116297Seric if (WriteBack) 117297Seric { 118297Seric p = ttypath(); 119297Seric if (p == NULL || freopen(p, "w", stdout) == NULL) 120297Seric { 121297Seric MailBack++; 122297Seric errno = 0; 123297Seric } 124297Seric else 125297Seric { 126*401Seric xfile = fopen(Transcript, "r"); 127*401Seric if (xfile == NULL) 128*401Seric syserr("Cannot open %s", Transcript); 129297Seric printf("\r\nMessage from %s\r\n", MY_NAME); 130297Seric printf("Errors occurred while sending mail, transcript follows:\r\n"); 131297Seric while (fgets(buf, sizeof buf, xfile) && !ferror(stdout)) 132297Seric fputs(buf, stdout); 133297Seric if (ferror(stdout)) 134297Seric syserr("savemail: stdout: write err"); 135*401Seric fclose(xfile); 136297Seric } 137297Seric } 138297Seric 139297Seric /* 140297Seric ** If mailing back, do it. 141297Seric ** Throw away all further output. Don't do aliases, since 142297Seric ** this could cause loops, e.g., if joe mails to x:joe, 143297Seric ** and for some reason the network for x: is down, then 144297Seric ** the response gets sent to x:joe, which gives a 145297Seric ** response, etc. Also force the mail to be delivered 146297Seric ** even if a version of it has already been sent to the 147297Seric ** sender. 148297Seric */ 149297Seric 150297Seric if (MailBack || From.q_mailer != &Mailer[0]) 151297Seric { 152297Seric freopen("/dev/null", "w", stdout); 153297Seric NoAlias++; 154297Seric ForceMail++; 155297Seric 156297Seric /* fake up an address header for the from person */ 157297Seric bmove((char *) &From, (char *) &to_addr, sizeof to_addr); 158297Seric if (parse(MY_NAME, &From, -1) == NULL) 159297Seric { 160297Seric syserr("Can't parse myself!"); 161297Seric ExitStat = EX_SOFTWARE; 162297Seric finis(); 163297Seric } 164297Seric i = deliver(&to_addr, errhdr); 165297Seric bmove((char *) &to_addr, (char *) &From, sizeof From); 166297Seric if (i != 0) 167297Seric syserr("Can't return mail to %s", p); 168297Seric else 169297Seric return; 170297Seric } 171297Seric 172297Seric /* 173297Seric ** Save the message in dead.letter. 174297Seric ** If we weren't mailing back, and the user is local, we 175297Seric ** should save the message in dead.letter so that the 176297Seric ** poor person doesn't have to type it over again -- 177297Seric ** and we all know what poor typists programmers are. 178297Seric */ 179297Seric 180297Seric setuid(getuid()); 181297Seric setgid(getgid()); 182297Seric setpwent(); 183297Seric if (From.q_mailer == &Mailer[0] && (pw = getpwnam(From.q_user)) != NULL) 184297Seric { 185297Seric /* user has a home directory */ 186297Seric p = pw->pw_dir; 187297Seric } 188297Seric else 189297Seric { 190297Seric syserr("Can't return mail to %s (pw=%u)", From.q_paddr, pw); 191297Seric # ifdef DEBUG 192297Seric p = "/usr/tmp"; 193297Seric # else 194297Seric p = NULL; 195297Seric # endif 196297Seric } 197297Seric if (p != NULL) 198297Seric { 199297Seric /* we have a home directory; open dead.letter */ 200297Seric strcpy(buf, p); 201297Seric strcat(buf, "/dead.letter"); 202297Seric xfile = fopen(buf, "a"); 203297Seric if (xfile == NULL) 204297Seric printf("Cannot save mail, sorry\n"); 205297Seric else 206297Seric { 207297Seric rewind(stdin); 208297Seric errno = 0; 209297Seric time(&tim); 210297Seric fprintf(xfile, "----- Mail saved at %s", ctime(&tim)); 211297Seric while (fgets(buf, sizeof buf, stdin) && !ferror(xfile)) 212297Seric fputs(buf, xfile); 213297Seric fputs("\n", xfile); 214297Seric if (ferror(xfile)) 215297Seric syserr("savemail: dead.letter: write err"); 216297Seric fclose(xfile); 217297Seric printf("Letter saved in dead.letter\n"); 218297Seric } 219297Seric } 220297Seric else 221297Seric 222297Seric /* add terminator to writeback message */ 223297Seric if (WriteBack) 224297Seric printf("-----\r\n"); 225297Seric } 226297Seric /* 227297Seric ** ERRHDR -- Output the header for error mail. 228297Seric ** 229297Seric ** This is the edit filter to error mailbacks. 230297Seric ** 231297Seric ** Algorithm: 232297Seric ** Output fixed header. 233297Seric ** Output the transcript part. 234297Seric ** Output the original message. 235297Seric ** 236297Seric ** Parameters: 237297Seric ** xfile -- the transcript file. 238297Seric ** fp -- the output file. 239297Seric ** 240297Seric ** Returns: 241297Seric ** none 242297Seric ** 243297Seric ** Side Effects: 244297Seric ** input from xfile 245297Seric ** output to fp 246297Seric ** 247297Seric ** Requires: 248297Seric ** read (sys) 249297Seric ** write (sys) 250297Seric ** open (sys) 251297Seric ** close (sys) 252297Seric ** syserr 253297Seric ** rewind (sys) 254297Seric ** fflush (sys) 255297Seric ** fprintf (sys) 256297Seric ** fileno (sys) 257297Seric ** 258297Seric ** Called By: 259297Seric ** deliver 260297Seric ** 261297Seric ** History: 262297Seric ** 12/28/79 -- written. 263297Seric */ 264297Seric 265297Seric 266297Seric errhdr(fp) 267297Seric register FILE *fp; 268297Seric { 269297Seric char copybuf[512]; 270297Seric register int i; 271297Seric register int xfile; 272297Seric extern int errno; 273297Seric 274297Seric if ((xfile = open(Transcript, 0)) < 0) 275297Seric syserr("Cannot open %s", Transcript); 276297Seric fflush(stdout); 277297Seric errno = 0; 278297Seric fprintf(fp, "To: %s\n", To); 279297Seric fprintf(fp, "Subject: Unable to deliver mail\n"); 280297Seric fprintf(fp, "\n ----- Transcript of session follows -----\n"); 281297Seric fflush(fp); 282297Seric while ((i = read(xfile, copybuf, sizeof copybuf)) > 0) 283297Seric write(fileno(fp), copybuf, i); 284297Seric fprintf(fp, "\n ----- Unsent message follows -----\n"); 285297Seric fflush(fp); 286297Seric rewind(stdin); 287297Seric while ((i = read(fileno(stdin), copybuf, sizeof copybuf)) > 0) 288297Seric write(fileno(fp), copybuf, i); 289297Seric close(xfile); 290297Seric if (errno != 0) 291297Seric syserr("errhdr: I/O error"); 292297Seric } 293