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