|
|
1.1 root 1: #
2:
3: #include "rcv.h"
4: #ifdef VMUNIX
5: #include <wait.h>
6: #endif
7:
8: /*
9: * Mail -- a mail program
10: *
11: * Mail to others.
12: */
13:
14: /*
15: * Send message described by the passed pointer to the
16: * passed output buffer. Return -1 on error, but normally
17: * the number of lines written.
18: */
19:
20: send(mailp, obuf)
21: struct message *mailp;
22: FILE *obuf;
23: {
24: register struct message *mp;
25: register int t;
26: unsigned int c;
27: FILE *ibuf;
28: int lc;
29:
30: mp = mailp;
31: ibuf = setinput(mp);
32: c = msize(mp);
33: lc = 0;
34: while (c-- > 0) {
35: putc(t = getc(ibuf), obuf);
36: if (t == '\n')
37: lc++;
38: if (ferror(obuf))
39: return(-1);
40: }
41: return(lc);
42: }
43:
44: /*
45: * Interface between the argument list and the mail1 routine
46: * which does all the dirty work.
47: */
48:
49: mail(people)
50: char **people;
51: {
52: register char *cp2;
53: register int s;
54: char *buf, **ap;
55: struct header head;
56:
57: for (s = 0, ap = people; *ap != (char *) -1; ap++)
58: s += strlen(*ap) + 1;
59: buf = salloc(s+1);
60: cp2 = buf;
61: for (ap = people; *ap != (char *) -1; ap++) {
62: cp2 = copy(*ap, cp2);
63: *cp2++ = ' ';
64: }
65: if (cp2 != buf)
66: cp2--;
67: *cp2 = '\0';
68: head.h_to = buf;
69: head.h_subject = NOSTR;
70: head.h_cc = NOSTR;
71: head.h_bcc = NOSTR;
72: head.h_seq = 0;
73: mail1(&head);
74: return(0);
75: }
76:
77:
78: /*
79: * Send mail to a bunch of user names. The interface is through
80: * the mail routine below.
81: */
82:
83: sendmail(str)
84: char *str;
85: {
86: register char **ap;
87: char *bufp;
88: register int t;
89: struct header head;
90:
91: if (blankline(str))
92: head.h_to = NOSTR;
93: else
94: head.h_to = str;
95: head.h_subject = NOSTR;
96: head.h_cc = NOSTR;
97: head.h_bcc = NOSTR;
98: head.h_seq = 0;
99: mail1(&head);
100: return(0);
101: }
102:
103: /*
104: * Mail a message on standard input to the people indicated
105: * in the passed header. (Internal interface).
106: */
107:
108: mail1(hp)
109: struct header *hp;
110: {
111: register char *cp;
112: int pid, i, s, p, gotcha;
113: char **namelist;
114: struct name *to, *np;
115: FILE *mtf, *postage;
116: int remote = rflag != NOSTR || rmail;
117: char **t;
118:
119: /*
120: * Collect user's mail from standard input.
121: * Get the result as mtf.
122: */
123:
124: pid = -1;
125: if ((mtf = collect(hp)) == NULL)
126: return(-1);
127: hp->h_seq = 1;
128: if (hp->h_subject == NOSTR)
129: hp->h_subject = sflag;
130: if (fsize(mtf) == 0 && hp->h_subject == NOSTR) {
131: printf("No message !?!\n");
132: goto out;
133: }
134: if (intty && value("askcc") != NOSTR)
135: grabh(hp, GCC);
136: else if (intty) {
137: printf("EOT\n");
138: flush();
139: }
140:
141: /*
142: * Now, take the user names from the combined
143: * to and cc lists and do all the alias
144: * processing.
145: */
146:
147: senderr = 0;
148: to = usermap(cat(extract(hp->h_bcc, GBCC),
149: cat(extract(hp->h_to, GTO), extract(hp->h_cc, GCC))));
150: if (to == NIL) {
151: printf("No recipients specified\n");
152: goto topdog;
153: }
154:
155: /*
156: * Look through the recipient list for names with /'s
157: * in them which we write to as files directly.
158: */
159:
160: to = outof(to, mtf, hp);
161: rewind(mtf);
162: to = verify(to);
163: if (senderr && !remote) {
164: topdog:
165:
166: if (fsize(mtf) != 0) {
167: remove(deadletter);
168: exwrite(deadletter, mtf, 1);
169: rewind(mtf);
170: }
171: }
172: for (gotcha = 0, np = to; np != NIL; np = np->n_flink)
173: if ((np->n_type & GDEL) == 0) {
174: gotcha++;
175: break;
176: }
177: if (!gotcha)
178: goto out;
179: to = elide(to);
180: mechk(to);
181: if (count(to) > 1)
182: hp->h_seq++;
183: if (hp->h_seq > 0 && !remote) {
184: fixhead(hp, to);
185: if (fsize(mtf) == 0)
186: printf("Null message body; hope that's ok\n");
187: if ((mtf = infix(hp, mtf)) == NULL) {
188: fprintf(stderr, ". . . message lost, sorry.\n");
189: return(-1);
190: }
191: }
192: namelist = unpack(to);
193: if (debug) {
194: printf("Recipients of message:\n");
195: for (t = namelist; *t != NOSTR; t++)
196: printf(" \"%s\"", *t);
197: printf("\n");
198: fflush(stdout);
199: return;
200: }
201: if ((cp = value("record")) != NOSTR)
202: savemail(expand(cp), hp, mtf);
203:
204: /*
205: * Wait, to absorb a potential zombie, then
206: * fork, set up the temporary mail file as standard
207: * input for "mail" and exec with the user list we generated
208: * far above. Return the process id to caller in case he
209: * wants to await the completion of mail.
210: */
211:
212: #ifdef VMUNIX
213: while (wait3(&s, WNOHANG, 0) > 0)
214: ;
215: #else
216: wait(&s);
217: #endif
218: rewind(mtf);
219: pid = fork();
220: if (pid == -1) {
221: perror("fork");
222: remove(deadletter);
223: exwrite(deadletter, mtf, 1);
224: goto out;
225: }
226: if (pid == 0) {
227: #ifdef SIGTSTP
228: if (remote == 0) {
229: signal(SIGTSTP, SIG_IGN);
230: signal(SIGTTIN, SIG_IGN);
231: signal(SIGTTOU, SIG_IGN);
232: }
233: #endif
234: for (i = SIGHUP; i <= SIGQUIT; i++)
235: signal(i, SIG_IGN);
236: if ((postage = fopen("/crp/kurt/postage", "a")) != NULL) {
237: fprintf(postage, "%s %d %d\n", myname,
238: count(to), fsize(mtf));
239: fclose(postage);
240: }
241: s = fileno(mtf);
242: for (i = 3; i < 15; i++)
243: if (i != s)
244: close(i);
245: close(0);
246: dup(s);
247: close(s);
248: #ifdef CC
249: submit(getpid());
250: #endif CC
251: #ifdef DELIVERMAIL
252: execv(DELIVERMAIL, namelist);
253: #endif DELIVERMAIL
254: execv(MAIL, namelist);
255: perror(MAIL);
256: exit(1);
257: }
258:
259: out:
260: if (remote) {
261: while ((p = wait(&s)) != pid && p != -1)
262: ;
263: if (s != 0)
264: senderr++;
265: pid = 0;
266: }
267: fclose(mtf);
268: return(pid);
269: }
270:
271: /*
272: * Fix the header by glopping all of the expanded names from
273: * the distribution list into the appropriate fields.
274: * If there are any ARPA net recipients in the message,
275: * we must insert commas, alas.
276: */
277:
278: fixhead(hp, tolist)
279: struct header *hp;
280: struct name *tolist;
281: {
282: register struct name *nlist;
283: register int f;
284: register struct name *np;
285:
286: for (f = 0, np = tolist; np != NIL; np = np->n_flink)
287: if (any('@', np->n_name)) {
288: f |= GCOMMA;
289: break;
290: }
291:
292: if (debug && f & GCOMMA)
293: fprintf(stderr, "Should be inserting commas in recip lists\n");
294: hp->h_to = detract(tolist, GTO|f);
295: hp->h_cc = detract(tolist, GCC|f);
296: }
297:
298: /*
299: * Prepend a header in front of the collected stuff
300: * and return the new file.
301: */
302:
303: FILE *
304: infix(hp, fi)
305: struct header *hp;
306: FILE *fi;
307: {
308: extern char tempMail[];
309: register FILE *nfo, *nfi;
310: register int c;
311:
312: if ((nfo = fopen(tempMail, "w")) == NULL) {
313: perror(tempMail);
314: return(fi);
315: }
316: if ((nfi = fopen(tempMail, "r")) == NULL) {
317: perror(tempMail);
318: fclose(nfo);
319: return(fi);
320: }
321: remove(tempMail);
322: puthead(hp, nfo, GTO|GSUBJECT|GCC|GNL);
323: rewind(fi);
324: c = getc(fi);
325: while (c != EOF) {
326: putc(c, nfo);
327: c = getc(fi);
328: }
329: if (ferror(fi)) {
330: perror("read");
331: fprintf(stderr, "Please notify Kurt Shoens\n");
332: return(fi);
333: }
334: fflush(nfo);
335: if (ferror(nfo)) {
336: perror(tempMail);
337: fclose(nfo);
338: fclose(nfi);
339: return(fi);
340: }
341: fclose(nfo);
342: fclose(fi);
343: rewind(nfi);
344: return(nfi);
345: }
346:
347: /*
348: * Dump the to, subject, cc header on the
349: * passed file buffer.
350: */
351:
352: puthead(hp, fo, w)
353: struct header *hp;
354: FILE *fo;
355: {
356: register int gotcha;
357:
358: gotcha = 0;
359: if (hp->h_to != NOSTR && w & GTO)
360: fprintf(fo, "To: "), fmt(hp->h_to, fo), gotcha++;
361: if (hp->h_subject != NOSTR && w & GSUBJECT)
362: fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
363: if (hp->h_cc != NOSTR && w & GCC)
364: fprintf(fo, "Cc: "), fmt(hp->h_cc, fo), gotcha++;
365: if (hp->h_bcc != NOSTR && w & GBCC)
366: fprintf(fo, "Bcc: "), fmt(hp->h_bcc, fo), gotcha++;
367: if (gotcha && w & GNL)
368: putc('\n', fo);
369: return(0);
370: }
371:
372: /*
373: * Format the given text to not exceed 72 characters.
374: */
375:
376: fmt(str, fo)
377: register char *str;
378: register FILE *fo;
379: {
380: register int col;
381: register char *cp;
382:
383: cp = str;
384: col = 0;
385: while (*cp) {
386: if (*cp == ' ' && col > 65) {
387: fprintf(fo, "\n ");
388: col = 4;
389: cp++;
390: continue;
391: }
392: putc(*cp++, fo);
393: col++;
394: }
395: putc('\n', fo);
396: }
397:
398: /*
399: * Save the outgoing mail on the passed file.
400: */
401:
402: savemail(name, hp, fi)
403: char name[];
404: struct header *hp;
405: FILE *fi;
406: {
407: register FILE *fo;
408: register int c;
409: long now;
410: char *n;
411:
412: if ((fo = fopen(name, "a")) == NULL) {
413: perror(name);
414: return(-1);
415: }
416: time(&now);
417: n = rflag;
418: if (n == NOSTR)
419: n = myname;
420: fprintf(fo, "From %s %s", n, ctime(&now));
421: rewind(fi);
422: for (c = getc(fi); c != EOF; c = getc(fi))
423: putc(c, fo);
424: fprintf(fo, "\n");
425: fflush(fo);
426: if (ferror(fo))
427: perror(name);
428: fclose(fo);
429: return(0);
430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.