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