BSD 3 development
[unix-history] / .ref-BSD-2 / src / Mail / send.c
CommitLineData
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
18send(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
47mail(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
80sendmail(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
104mail1(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) {
157topdog:
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
206out:
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
216FILE *
217infix(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
259puthead(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
278savemail(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}