1: # include <stdio.h> 2: # include <pwd.h> 3: # include "dlvrmail.h" 4: 5: static char SccsId[] = "@(#)savemail.c 2.2 1/10/81"; 6: 7: /* 8: ** SAVEMAIL -- Save mail on error 9: ** 10: ** If the MailBack flag is set, mail it back to the originator 11: ** together with an error message; otherwise, just put it in 12: ** dead.letter in the user's home directory (if he exists on 13: ** this machine). 14: ** 15: ** Parameters: 16: ** none 17: ** 18: ** Returns: 19: ** none 20: ** 21: ** Side Effects: 22: ** Saves the letter, by writing or mailing it back to the 23: ** sender, or by putting it in dead.letter in her home 24: ** directory. 25: ** 26: ** WARNING: the user id is reset to the original user. 27: */ 28: 29: savemail() 30: { 31: register struct passwd *pw; 32: register FILE *xfile; 33: char buf[MAXLINE+1]; 34: extern errhdr(); 35: auto addrq to_addr; 36: extern struct passwd *getpwnam(); 37: register char *p; 38: register int i; 39: auto long tim; 40: extern int errno; 41: extern char *ttypath(); 42: extern char *ctime(); 43: extern addrq *parse(); 44: static int exclusive; 45: extern char *DaemonName; 46: 47: if (exclusive++) 48: return; 49: 50: /* 51: ** In the unhappy event we don't know who to return the mail 52: ** to, make someone up. 53: */ 54: 55: if (From.q_paddr == NULL) 56: { 57: if (parse("root", &From, 0) == NULL) 58: { 59: syserr("Cannot parse root!"); 60: ExitStat = EX_SOFTWARE; 61: finis(); 62: } 63: } 64: 65: /* 66: ** If called from Eric Schmidt's network, do special mailback. 67: ** Fundamentally, this is the mailback case except that 68: ** it returns an OK exit status (assuming the return 69: ** worked). 70: */ 71: 72: if (BerkNet) 73: { 74: ExitStat = EX_OK; 75: MailBack++; 76: } 77: 78: /* 79: ** If writing back, do it. 80: ** If the user is still logged in on the same terminal, 81: ** then write the error messages back to hir (sic). 82: ** If not, set the MailBack flag so that it will get 83: ** mailed back instead. 84: */ 85: 86: if (WriteBack) 87: { 88: p = ttypath(); 89: if (p == NULL || freopen(p, "w", stdout) == NULL) 90: { 91: MailBack++; 92: errno = 0; 93: } 94: else 95: { 96: xfile = fopen(Transcript, "r"); 97: if (xfile == NULL) 98: syserr("Cannot open %s", Transcript); 99: printf("\r\nMessage from %s\r\n", DaemonName); 100: printf("Errors occurred while sending mail, transcript follows:\r\n"); 101: while (fgets(buf, sizeof buf, xfile) && !ferror(stdout)) 102: fputs(buf, stdout); 103: if (ferror(stdout)) 104: syserr("savemail: stdout: write err"); 105: fclose(xfile); 106: } 107: } 108: 109: /* 110: ** If mailing back, do it. 111: ** Throw away all further output. Don't do aliases, since 112: ** this could cause loops, e.g., if joe mails to x:joe, 113: ** and for some reason the network for x: is down, then 114: ** the response gets sent to x:joe, which gives a 115: ** response, etc. Also force the mail to be delivered 116: ** even if a version of it has already been sent to the 117: ** sender. 118: */ 119: 120: if (MailBack || From.q_mailer != &Mailer[0]) 121: { 122: freopen("/dev/null", "w", stdout); 123: NoAlias++; 124: ForceMail++; 125: 126: /* fake up an address header for the from person */ 127: bmove((char *) &From, (char *) &to_addr, sizeof to_addr); 128: if (parse(DaemonName, &From, -1) == NULL) 129: { 130: syserr("Can't parse myself!"); 131: ExitStat = EX_SOFTWARE; 132: finis(); 133: } 134: i = deliver(&to_addr, errhdr); 135: bmove((char *) &to_addr, (char *) &From, sizeof From); 136: if (i != 0) 137: syserr("Can't return mail to %s", p); 138: else 139: return; 140: } 141: 142: /* 143: ** Save the message in dead.letter. 144: ** If we weren't mailing back, and the user is local, we 145: ** should save the message in dead.letter so that the 146: ** poor person doesn't have to type it over again -- 147: ** and we all know what poor typists programmers are. 148: */ 149: 150: setuid(getuid()); 151: setgid(getgid()); 152: setpwent(); 153: if (From.q_mailer == &Mailer[0] && (pw = getpwnam(From.q_user)) != NULL) 154: { 155: /* user has a home directory */ 156: p = pw->pw_dir; 157: } 158: else 159: { 160: syserr("Can't return mail to %s (pw=%u)", From.q_paddr, pw); 161: # ifdef DEBUG 162: p = "/usr/tmp"; 163: # else 164: p = NULL; 165: # endif 166: } 167: if (p != NULL) 168: { 169: /* we have a home directory; open dead.letter */ 170: strcpy(buf, p); 171: strcat(buf, "/dead.letter"); 172: xfile = fopen(buf, "a"); 173: if (xfile == NULL) 174: printf("Cannot save mail, sorry\n"); 175: else 176: { 177: rewind(stdin); 178: errno = 0; 179: time(&tim); 180: fprintf(xfile, "----- Mail saved at %s", ctime(&tim)); 181: while (fgets(buf, sizeof buf, stdin) && !ferror(xfile)) 182: fputs(buf, xfile); 183: fputs("\n", xfile); 184: if (ferror(xfile)) 185: syserr("savemail: dead.letter: write err"); 186: fclose(xfile); 187: printf("Letter saved in dead.letter\n"); 188: } 189: } 190: else 191: 192: /* add terminator to writeback message */ 193: if (WriteBack) 194: printf("-----\r\n"); 195: } 196: /* 197: ** ERRHDR -- Output the header for error mail. 198: ** 199: ** This is the edit filter to error mailbacks. 200: ** 201: ** Algorithm: 202: ** Output fixed header. 203: ** Output the transcript part. 204: ** Output the original message. 205: ** 206: ** Parameters: 207: ** xfile -- the transcript file. 208: ** fp -- the output file. 209: ** 210: ** Returns: 211: ** none 212: ** 213: ** Side Effects: 214: ** input from xfile 215: ** output to fp 216: ** 217: ** Called By: 218: ** deliver 219: */ 220: 221: 222: errhdr(fp) 223: register FILE *fp; 224: { 225: char copybuf[512]; 226: register int i; 227: register int xfile; 228: extern int errno; 229: 230: if ((xfile = open(Transcript, 0)) < 0) 231: syserr("Cannot open %s", Transcript); 232: fflush(stdout); 233: errno = 0; 234: fprintf(fp, "To: %s\n", To); 235: fprintf(fp, "Subject: Unable to deliver mail\n"); 236: fprintf(fp, "\n ----- Transcript of session follows -----\n"); 237: fflush(fp); 238: while ((i = read(xfile, copybuf, sizeof copybuf)) > 0) 239: write(fileno(fp), copybuf, i); 240: fprintf(fp, "\n ----- Unsent message follows -----\n"); 241: fflush(fp); 242: rewind(stdin); 243: while ((i = read(fileno(stdin), copybuf, sizeof copybuf)) > 0) 244: write(fileno(fp), copybuf, i); 245: close(xfile); 246: if (errno != 0) 247: syserr("errhdr: I/O error"); 248: }