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