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