changed "deled" to "deledit" for wnj
[unix-history] / usr / src / usr.sbin / sendmail / src / savemail.c
CommitLineData
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
60savemail()
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
277errhdr(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}