Commit | Line | Data |
---|---|---|
b3cbe40f EA |
1 | # include <stdio.h> |
2 | # include <pwd.h> | |
96faada8 | 3 | # include "sendmail.h" |
b3cbe40f | 4 | |
fb313fb2 | 5 | static 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 |
29 | savemail() |
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 | ||
207 | errhdr(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 | } |