Commit | Line | Data |
---|---|---|
0f5e4452 KS |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | # | |
3 | ||
4 | #include "rcv.h" | |
5 | ||
6 | /* | |
7 | * Mail -- a mail program | |
8 | * | |
9 | * Mail to others. | |
10 | */ | |
11 | ||
12 | /* | |
13 | * Send message described by the passed pointer to the | |
14 | * passed output buffer. Return -1 on error, but normally | |
15 | * the number of lines written. | |
16 | */ | |
17 | ||
18 | send(mailp, obuf) | |
19 | struct message *mailp; | |
20 | FILE *obuf; | |
21 | { | |
22 | register struct message *mp; | |
23 | register int t; | |
24 | unsigned int c; | |
25 | FILE *ibuf; | |
26 | int lc; | |
27 | ||
28 | mp = mailp; | |
29 | ibuf = setinput(mp); | |
30 | c = msize(mp); | |
31 | lc = 0; | |
32 | while (c-- > 0) { | |
33 | putc(t = getc(ibuf), obuf); | |
34 | if (t == '\n') | |
35 | lc++; | |
36 | if (ferror(obuf)) | |
37 | return(-1); | |
38 | } | |
39 | return(lc); | |
40 | } | |
41 | ||
42 | /* | |
43 | * Interface between the argument list and the mail1 routine | |
44 | * which does all the dirty work. | |
45 | */ | |
46 | ||
47 | mail(people) | |
48 | char **people; | |
49 | { | |
50 | register char *cp2; | |
51 | register int s; | |
52 | char *buf, **ap; | |
53 | struct header head; | |
54 | ||
55 | for (s = 0, ap = people; *ap != (char *) -1; ap++) | |
56 | s += strlen(*ap) + 1; | |
57 | buf = salloc(s+1); | |
58 | cp2 = buf; | |
59 | for (ap = people; *ap != (char *) -1; ap++) { | |
60 | cp2 = copy(*ap, cp2); | |
61 | *cp2++ = ' '; | |
62 | } | |
63 | if (cp2 != buf) | |
64 | cp2--; | |
65 | *cp2 = '\0'; | |
66 | head.h_to = buf; | |
67 | head.h_subj = NOSTR; | |
68 | head.h_cc = NOSTR; | |
69 | head.h_seq = 0; | |
70 | mail1(&head); | |
71 | return(0); | |
72 | } | |
73 | ||
74 | ||
75 | /* | |
76 | * Send mail to a bunch of user names. The interface is through | |
77 | * the mail routine below. | |
78 | */ | |
79 | ||
80 | sendmail(str) | |
81 | char *str; | |
82 | { | |
83 | register char **ap; | |
84 | char *bufp; | |
85 | register int t; | |
86 | struct header head; | |
87 | ||
88 | if (blankline(str)) | |
89 | head.h_to = NOSTR; | |
90 | else | |
91 | head.h_to = str; | |
92 | head.h_subj = NOSTR; | |
93 | head.h_cc = NOSTR; | |
94 | head.h_seq = 0; | |
95 | mail1(&head); | |
96 | return(0); | |
97 | } | |
98 | ||
99 | /* | |
100 | * Mail a message on standard input to the people indicated | |
101 | * in the passed header. (Internal interface). | |
102 | */ | |
103 | ||
104 | mail1(hp) | |
105 | struct header *hp; | |
106 | { | |
107 | register char *cp; | |
108 | int pid, i, s; | |
109 | char **namelist; | |
110 | struct name *to; | |
111 | FILE *mtf; | |
112 | ||
113 | /* | |
114 | * Collect user's mail from standard input. | |
115 | * Get the result as mtf. | |
116 | */ | |
117 | ||
118 | pid = -1; | |
119 | if (hp->h_subj == NOSTR) | |
120 | hp->h_seq = 0; | |
121 | else | |
122 | hp->h_seq = 1; | |
123 | if ((mtf = collect(hp)) == NULL) | |
124 | return(-1); | |
125 | if (fsize(mtf) == 0 && hp->h_subj == NOSTR) { | |
126 | printf("No message !?!\n"); | |
127 | goto out; | |
128 | } | |
129 | if (intty && value("askcc") != NOSTR) | |
130 | grabh(hp, GCC); | |
131 | else if (intty) { | |
132 | printf("EOT\n"); | |
133 | flush(); | |
134 | } | |
135 | ||
136 | /* | |
137 | * Now, take the user names from the combined | |
138 | * to and cc lists and do all the alias | |
139 | * processing. | |
140 | */ | |
141 | ||
142 | senderr = 0; | |
143 | to = usermap(cat(extract(hp->h_to), extract(hp->h_cc))); | |
144 | if (to == NIL) { | |
145 | printf("No recipients specified\n"); | |
146 | goto topdog; | |
147 | } | |
148 | ||
149 | /* | |
150 | * Look through the recipient list for names with /'s | |
151 | * in them which we write to as files directly. | |
152 | */ | |
153 | ||
154 | to = outof(to, mtf, hp); | |
155 | to = verify(to); | |
156 | if (senderr) { | |
157 | topdog: | |
158 | unlink(deadletter); | |
159 | exwrite(deadletter, mtf, 1); | |
160 | } | |
161 | if (to == NIL) | |
162 | goto out; | |
163 | to = elide(to); | |
164 | mechk(to); | |
165 | if (count(to) > 1) | |
166 | hp->h_seq++; | |
167 | if (hp->h_seq > 0) | |
168 | if ((mtf = infix(hp, mtf)) == NULL) { | |
169 | fprintf(stderr, ". . . message lost, sorry.\n"); | |
170 | return(-1); | |
171 | } | |
172 | namelist = unpack(to); | |
173 | if (value("record") != NOSTR) | |
174 | savemail(value("record"), hp, mtf, namelist); | |
175 | ||
176 | /* | |
177 | * Wait, to absorb a potential zombie, then | |
178 | * fork, set up the temporary mail file as standard | |
179 | * input for "mail" and exec with the user list we generated | |
180 | * far above. Return the process id to caller in case he | |
181 | * wants to await the completion of mail. | |
182 | */ | |
183 | ||
184 | wait(&s); | |
185 | rewind(mtf); | |
186 | pid = fork(); | |
187 | if (pid == -1) { | |
188 | perror("fork"); | |
189 | goto out; | |
190 | } | |
191 | if (pid == 0) { | |
192 | for (i = 1; i < 17; i++) | |
193 | signal(i, SIG_IGN); | |
194 | s = fileno(mtf); | |
195 | for (i = 3; i < 15; i++) | |
196 | if (i != s) | |
197 | close(i); | |
198 | close(0); | |
199 | dup(s); | |
200 | close(s); | |
201 | execv(MAIL, namelist); | |
202 | perror(MAIL); | |
203 | exit(1); | |
204 | } | |
205 | ||
206 | out: | |
207 | fclose(mtf); | |
208 | return(pid); | |
209 | } | |
210 | ||
211 | /* | |
212 | * Prepend a header in front of the collected stuff | |
213 | * and return the new file. | |
214 | */ | |
215 | ||
216 | FILE * | |
217 | infix(hp, fi) | |
218 | struct header *hp; | |
219 | FILE *fi; | |
220 | { | |
221 | extern char tempMail[]; | |
222 | register FILE *nfo, *nfi; | |
223 | register int c; | |
224 | ||
225 | if ((nfo = fopen(tempMail, "w")) == NULL) { | |
226 | perror(tempMail); | |
227 | return(fi); | |
228 | } | |
229 | if ((nfi = fopen(tempMail, "r")) == NULL) { | |
230 | perror(tempMail); | |
231 | fclose(nfo); | |
232 | return(fi); | |
233 | } | |
234 | unlink(tempMail); | |
235 | puthead(hp, nfo); | |
236 | c = getc(fi); | |
237 | while (c != EOF) { | |
238 | putc(c, nfo); | |
239 | c = getc(fi); | |
240 | } | |
241 | fflush(nfo); | |
242 | if (ferror(nfo)) { | |
243 | perror(tempMail); | |
244 | fclose(nfo); | |
245 | fclose(nfi); | |
246 | return(fi); | |
247 | } | |
248 | fclose(nfo); | |
249 | fclose(fi); | |
250 | rewind(nfi); | |
251 | return(nfi); | |
252 | } | |
253 | ||
254 | /* | |
255 | * Dump the to, subj, cc header on the | |
256 | * passed file buffer. | |
257 | */ | |
258 | ||
259 | puthead(hp, fo) | |
260 | struct header *hp; | |
261 | FILE *fo; | |
262 | { | |
263 | if (hp->h_to != NOSTR) | |
264 | fprintf(fo, "To: %s\n", hp->h_to); | |
265 | if (hp->h_subj != NOSTR) | |
266 | fprintf(fo, "Subj: %s\n", hp->h_subj); | |
267 | if (hp->h_cc != NOSTR) | |
268 | fprintf(fo, "Cc: %s\n", hp->h_cc); | |
269 | if (hp->h_to != NOSTR || hp->h_subj != NOSTR || hp->h_cc != NOSTR) | |
270 | putc('\n', fo); | |
271 | return(0); | |
272 | } | |
273 | ||
274 | /* | |
275 | * Save the outgoing mail on the passed file. | |
276 | */ | |
277 | ||
278 | savemail(name, hp, fi, tolist) | |
279 | char name[], **tolist; | |
280 | struct header *hp; | |
281 | FILE *fi; | |
282 | { | |
283 | register FILE *fo; | |
284 | register int c; | |
285 | long now; | |
286 | ||
287 | if ((fo = fopen(name, "a")) == NULL) { | |
288 | perror(name); | |
289 | return(-1); | |
290 | } | |
291 | time(&now); | |
292 | fprintf(fo, "From %s %s", *(tolist+1), ctime(&now)); | |
293 | rewind(fi); | |
294 | for (c = getc(fi); c != EOF; c = getc(fi)) | |
295 | putc(c, fo); | |
296 | fprintf(fo, "\n"); | |
297 | fflush(fo); | |
298 | if (ferror(fo)) | |
299 | perror(name); | |
300 | fclose(fo); | |
301 | return(0); | |
302 | } |