use <crlf> in arpanet mode
[unix-history] / usr / src / usr.sbin / sendmail / src / savemail.c
CommitLineData
b3cbe40f
EA
1# include <stdio.h>
2# include <pwd.h>
96faada8 3# include "sendmail.h"
b3cbe40f 4
fb313fb2 5static char SccsId[] = "@(#)savemail.c 3.8 %G%";
916b3375 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.
b3cbe40f
EA
27*/
28
b3cbe40f
EA
29savemail()
30{
31 register struct passwd *pw;
32 register FILE *xfile;
33 char buf[MAXLINE+1];
34 extern errhdr();
406f98bc 35 auto ADDRESS to_addr;
b3cbe40f
EA
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();
406f98bc 42 extern ADDRESS *parse();
b3cbe40f 43 static int exclusive;
7b9c35c8 44 extern char *strcpy(), *strcat();
9e3c0a28 45 extern char *expand();
b3cbe40f
EA
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 /*
3b661a43
EA
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).
b3cbe40f
EA
70 */
71
3b661a43 72 if (BerkNet)
b3cbe40f 73 {
3b661a43 74 ExitStat = EX_OK;
b3cbe40f
EA
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 {
3b661a43
EA
96 xfile = fopen(Transcript, "r");
97 if (xfile == NULL)
98 syserr("Cannot open %s", Transcript);
9e3c0a28 99 printf("\r\nMessage from %s\r\n", expand("$n", buf, &buf[sizeof buf - 1]));
b3cbe40f
EA
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");
3b661a43 105 fclose(xfile);
b3cbe40f
EA
106 }
107 }
108
b3cbe40f
EA
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
6708a5e3 120 if (MailBack)
b3cbe40f
EA
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);
9e3c0a28 128 if (parse(expand("$n", buf, &buf[sizeof buf - 1]), &From, -1) == NULL)
b3cbe40f
EA
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();
6708a5e3 153 if (From.q_mailer == 0 && (pw = getpwnam(From.q_user)) != NULL)
b3cbe40f
EA
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");
fb313fb2
EA
172 To = buf;
173 i = mailfile(buf);
174 giveresponse(i, TRUE, Mailer[0]);
b3cbe40f 175 }
b3cbe40f
EA
176
177 /* add terminator to writeback message */
178 if (WriteBack)
179 printf("-----\r\n");
180}
181\f/*
182** ERRHDR -- Output the header for error mail.
183**
184** This is the edit filter to error mailbacks.
185**
186** Algorithm:
187** Output fixed header.
188** Output the transcript part.
189** Output the original message.
190**
191** Parameters:
192** xfile -- the transcript file.
193** fp -- the output file.
194**
195** Returns:
196** none
197**
198** Side Effects:
199** input from xfile
200** output to fp
201**
b3cbe40f
EA
202** Called By:
203** deliver
b3cbe40f
EA
204*/
205
206
207errhdr(fp)
208 register FILE *fp;
209{
9e3c0a28
EA
210 char buf[MAXLINE];
211 register FILE *xfile;
b3cbe40f
EA
212 extern int errno;
213
b3cbe40f 214 fflush(stdout);
9e3c0a28
EA
215 if ((xfile = fopen(Transcript, "r")) == NULL)
216 syserr("Cannot open %s", Transcript);
b3cbe40f
EA
217 errno = 0;
218 fprintf(fp, "To: %s\n", To);
219 fprintf(fp, "Subject: Unable to deliver mail\n");
220 fprintf(fp, "\n ----- Transcript of session follows -----\n");
9e3c0a28
EA
221 while (fgets(xfile, buf, sizeof buf) != NULL)
222 fputs(buf, fp);
b3cbe40f
EA
223 fprintf(fp, "\n ----- Unsent message follows -----\n");
224 fflush(fp);
9e3c0a28 225 putmessage(fp, Mailer[1]);
b3cbe40f
EA
226 close(xfile);
227 if (errno != 0)
228 syserr("errhdr: I/O error");
229}