|
|
1.1 root 1: /* rmail.c - replacement for /bin/rmail */
2:
3: /* This program has a long, long history. It started as UCB's rmail, and
4: was then modified by OBrien@Rand-Unix to run with MMDF. Then DpK@Brl
5: re-wrote it, and SmB@Unc hacked it up a bit. After that
6: MRose.UCI@Rand-Relay upgraded it to use the nifty MF (mail filtering)
7: system. Finally, the latter stripped it down to work with MH.
8:
9: This program should be used ONLY if you have both "mts mh" and "uucp on"
10: set in your MH configuration.
11: */
12:
13:
14: #include "../h/mh.h"
15: #include "../h/addrsbr.h"
16: #include "../zotnet/mf.h"
17: #include "../zotnet/tws.h"
18: #include <stdio.h>
19: #include "../zotnet/mts.h"
20: #include <signal.h>
21:
22:
23: #define ADDROK 0 /* okay to use post to deliver message */
24: #define UUCP 1 /* okay to use uux to deliver message */
25: #define RETURN 2 /* message loses */
26:
27: /* */
28: int pbroke; /* broken-pipe flag */
29: int rtnflag; /* note was sent back */
30:
31: char date[BUFSIZ]; /* date of origination from uucp header */
32: char from[BUFSIZ]; /* accumulated path of sender */
33: char origsys[BUFSIZ]; /* originating system */
34: char origpath[BUFSIZ]; /* path from us to originating system */
35: char usrfrm[BUFSIZ]; /* the 822 version of from[] */
36: char Mailsys[BUFSIZ]; /* address of the mail agent */
37: char overseer[BUFSIZ]; /* address of the watchdog */
38:
39: char mmdf[BUFSIZ]; /* filtered mail file */
40:
41: char *rtnmessage[] = {
42: " Your message has been intercepted trying to access\n",
43: "a restricted access host (e.g. an ARPANET host). A copy\n",
44: "of your message has been sent to the system administrators.\n",
45: "The text of your message follows.\n\n",
46: NULL
47: };
48:
49: char rtnbegin[] =
50: " ---------------- Returned Mail Follows --------------\n";
51: char rtnend[] =
52: " --------------- End of Returned Mail ---------------\n";
53:
54: char *oopsmessage[] = {
55: "\n\n\tThe system administrators (%s) have been informed of\n",
56: "the problem, but have not been given a copy of your message.\n\n",
57: NULL
58: };
59:
60: FILE * fromf; /* UUCP "From lines */
61: FILE * msgf; /* message text */
62: FILE * pipef; /* output for "post" or "uux" */
63:
64:
65: int pipeser ();
66:
67:
68: long lseek ();
69:
70: /* */
71:
72: main (argc, argv)
73: int argc;
74: char **argv;
75: {
76: int cpyback;
77: char *cp,
78: *fromptr,
79: fromwhom[BUFSIZ],
80: linebuf[BUFSIZ],
81: sys[BUFSIZ];
82:
83: invo_name = r1bindex (*argv, '/');
84: m_foil (NULLCP);
85: mts_init (invo_name);
86:
87: if (argc < 2)
88: adios (NULLCP, "usage: %s user [user ...]", invo_name);
89: (void) umask (0);
90: (void) setgid (1);
91: (void) setuid (1);
92:
93: (void) sprintf (Mailsys, "%s@%s", Mailer, LocalName ());
94: if (Overseer == NULL)
95: Overseer = Mailsys;
96: if (index (Overseer, '@') == NULL) {
97: (void) sprintf (overseer, "%s@%s", Overseer, LocalName ());
98: Overseer = overseer;
99: }
100:
101: (void) mktemp (Errtmp);
102: if (freopen (Errtmp, "w", stderr) == NULL)
103: adios (Errtmp, "unable to create");
104: (void) dup2 (fileno (stderr), fileno (stdout));
105:
106: (void) mktemp (Msgtmp);
107: if ((msgf = fdopen (creat (Msgtmp, Tmpmode), "w")) == NULL)
108: adios (Msgtmp, "unable to create");
109:
110: (void) mktemp (Fromtmp);
111: if ((fromf = fdopen (creat (Fromtmp, Tmpmode), "w")) == NULL)
112: adios (Fromtmp, "unable to create");
113:
114: /* */
115:
116: for (;;) {
117: if (fgets (linebuf, sizeof linebuf, stdin) == NULL)
118: break;
119: if (strncmp (linebuf, "From ", 5)
120: && strncmp (linebuf, ">From ", 6))
121: break;
122:
123: if (linebuf[0] != '>')
124: fputs (">", fromf);
125: fputs (linebuf, fromf);
126: cp = index (linebuf, ' ');
127: fromptr = ++cp;
128: cp = index (cp, ' ');
129: *cp++ = NULL;
130: (void) strcpy (fromwhom, fromptr);
131: (void) strncpy (date, cp, 24);
132:
133: for (;;) {
134: if ((cp = index (cp + 1, 'r')) == NULL) {
135: if ((cp = rindex (fromwhom, '!')) != NULL) {
136: char *p;
137: *cp = NULL;
138: if ((p = rindex (fromwhom, '!')) != NULL)
139: (void) strcpy (origsys, p + 1);
140: else
141: (void) strcpy (origsys, fromwhom);
142: (void) strcat (from, fromwhom);
143: (void) strcat (from, "!");
144: (void) strcpy (fromwhom, cp + 1);
145: goto out;
146: }
147: (void) strcpy (sys, SystemName ());
148: (void) strcat (from, sys);
149: (void) strcpy (origsys, sys);
150: (void) strcat (from, "!");
151: goto out;
152: }
153: if (strncmp (cp, "remote from ", 12) == 0)
154: break;
155: }
156:
157: (void) sscanf (cp, "remote from %s", sys);
158: (void) strcat (from, sys);
159: (void) strcpy (origsys, sys);
160: (void) strcat (from, "!");
161: out: ;
162: }
163: if (fromwhom[0] == NULL)
164: adios (NULLCP, "no from line");
165:
166: /* */
167:
168: (void) strcpy (origpath, from);
169: (void) strcat (from, fromwhom);
170: get_mmdf_addr (from, usrfrm);
171: if ((cp = rindex (usrfrm, '<')) != NULL) {
172: (void) strcpy (usrfrm, ++cp); /* sigh */
173: if ((cp = rindex (usrfrm, '>')) != NULL)
174: *cp = NULL;
175: }
176: if (usrfrm[0] == NULL)
177: (void) sprintf (usrfrm, "%s!%s%%%s@%s%c",
178: SystemName (), from, UucpChan (), LocalName (), NULL);
179:
180: fputs (linebuf, msgf);
181: if (txtcpy (stdin, msgf) == NOTOK)
182: fputs ("\n *** Problem during receipt from UUCP ***\n", msgf);
183:
184: (void) freopen (Msgtmp, "r", msgf);
185: (void) freopen (Fromtmp, "r", fromf);
186: (void) unlink (Fromtmp);
187: mmdf[0] = NULL;
188:
189: cpyback = 0;
190: for (argv++; --argc > 0;) {
191: rewind (fromf);
192: rewind (msgf);
193: rtnflag = 0;
194: if (deliver (*argv++) == NOTOK && !rtnflag)
195: cpyback++;
196: }
197:
198: (void) fflush (stderr);
199: (void) fflush (stdout);
200:
201: if (cpyback) {
202: rcpy ();
203: zcpy ();
204: }
205:
206: (void) unlink (Msgtmp);
207: if (mmdf[0])
208: (void) unlink (mmdf);
209: (void) unlink (Errtmp);
210:
211: exit (0);
212: }
213:
214: /* */
215:
216: deliver (to)
217: char *to;
218: {
219: int i,
220: replyval;
221: char tmpfil[BUFSIZ];
222:
223: switch (adrcheck (to)) {
224: case ADDROK:
225: if (mmdf[0] == NULL && filter () == NOTOK)
226: (void) strcpy (mmdf, Msgtmp);
227: replyval = xpost (to, mmdf);
228: break;
229:
230: case UUCP:
231: if ((replyval = xuucp (to)) == NOTOK)
232: break;
233:
234: if ((replyval = txtcpy (fromf, pipef)) != NOTOK)
235: replyval = txtcpy (msgf, pipef);
236: i = (pclose (pipef) >> 8) & 0xff;
237: if (replyval != NOTOK)
238: replyval = (i != 0 ? NOTOK : OK);
239: break;
240:
241: /* */
242:
243: case RETURN:
244: rtnflag++;
245: switch (adrcheck (from)) {
246: case ADDROK:
247: case RETURN:
248: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
249: (void) unlink (mktemp (tmpfil));
250: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
251: return NOTOK;
252:
253: fprintf (pipef, "Date: %s\nFrom: %s\n",
254: dtimenow (), Mailsys);
255: fprintf (pipef, "To: %s\ncc: %s\n", from, Overseer);
256: rtnmesg (to);
257: (void) fclose (pipef);
258:
259: replyval = xpost (from, tmpfil);
260: (void) unlink (tmpfil);
261: break;
262:
263: case UUCP:
264: if ((replyval = xuucp (from)) == NOTOK)
265: break;
266:
267: fprintf (pipef, "To: %s\ncc: %s\n", from, Overseer);
268: rtnmesg (to);
269: i = (pclose (pipef) >> 8) & 0xff;
270: if (replyval != NOTOK)
271: replyval = (i != 0 ? NOTOK : OK);
272: break;
273: }
274: if (Syscpy) {
275: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
276: (void) unlink (mktemp (tmpfil));
277: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
278: return NOTOK;
279:
280: fprintf (pipef, "Date: %s\nFrom: %s\n",
281: dtimenow (), Mailsys);
282: fprintf (pipef, "To: %s\ncc: %s\n", usrfrm, Overseer);
283: rtnmesg (to);
284: (void) fclose (pipef);
285:
286: replyval = xpost (Overseer, tmpfil);
287: (void) unlink (tmpfil);
288: }
289: break;
290: }
291:
292: return replyval;
293: }
294:
295: /* */
296:
297: adrcheck (adr)
298: char *adr;
299: {
300: int type;
301: char *cp,
302: host[BUFSIZ];
303: struct mailname *mp;
304:
305: if ((cp = getname (adr)) == NULL)
306: return RETURN;
307: mp = getm (cp, NULLCP, 0, AD_HOST, NULLCP);
308: while (getname (""))
309: continue;
310: if (mp == NULL)
311: return RETURN;
312:
313: type = mp -> m_type;
314: (void) strcpy (host, mp -> m_host);
315: mnfree (mp);
316: if (mp -> m_mbox == NULL)
317: return RETURN;
318:
319: switch (type) {
320: case LOCALHOST:
321: return ADDROK;
322:
323: case UUCPHOST:
324: return (strcmp (host, SystemName ()) ? UUCP : ADDROK);
325:
326: default:
327: if (lookup (origsys, Okhosts) == OK)
328: return ADDROK;
329: return (okhost (host) == NOTOK ? RETURN : ADDROK);
330: }
331: }
332:
333: /* */
334:
335: okhost (host)
336: char *host;
337: {
338: return (lookup (origsys, Okhosts) == OK
339: || lookup (host, Okhosts) == OK
340: || lookup (host, Okdests) == OK ? OK : NOTOK);
341: }
342:
343:
344: lookup (what, where)
345: char *what,
346: *where;
347: {
348: char *cp,
349: entry[BUFSIZ];
350: FILE * lookf;
351:
352: if ((lookf = fopen (where, "r")) == NULL)
353: return NOTOK;
354: while (fgets (entry, sizeof entry, lookf) != NULL) {
355: cp = entry;
356: while (*cp != '\n' && *cp != ' ' && *cp != '\t')
357: cp++;
358: *cp = NULL;
359: if (uleq (what, entry)) {
360: (void) fclose (lookf);
361: return OK;
362: }
363: }
364: (void) fclose (lookf);
365:
366: return NOTOK;
367: }
368:
369:
370: /* */
371:
372: rtnmesg (badadr)
373: char *badadr;
374: {
375: int i;
376:
377: fprintf (pipef, "Subject: Illegal Address (%s)\n\n", badadr);
378: for (i = 0; rtnmessage[i]; i++)
379: fputs (rtnmessage[i], pipef);
380: fputs (rtnbegin, pipef);
381:
382: rewind (fromf);
383: (void) txtcpy (fromf, pipef);
384: rewind (msgf);
385: (void) txtcpy (msgf, pipef);
386:
387: fputs (rtnend, pipef);
388: }
389:
390:
391: txtcpy (frm, to)
392: FILE * frm, *to;
393: {
394: int nread;
395: char buffer[BUFSIZ];
396:
397: while (!pbroke
398: && (nread = fread (buffer, sizeof (*buffer), BUFSIZ, frm)) > 0)
399: (void) fwrite (buffer, sizeof (*buffer), nread, to);
400:
401: return (ferror (frm) ? NOTOK : OK);
402: }
403:
404: /* */
405:
406: xpost (addr, file)
407: char *addr,
408: *file;
409: {
410: int i,
411: child_id;
412:
413: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
414: sleep (5);
415: switch (child_id) {
416: case NOTOK:
417: return NOTOK;
418:
419: case OK:
420: execlp (postproc, r1bindex (postproc, '/'),
421: "-deliver", addr, file, NULLCP);
422: fprintf (stderr, "unable to exec ");
423: perror (postproc);
424: _exit (1);
425:
426: default:
427: return (pidwait (child_id, OK) ? NOTOK : OK);
428: }
429: }
430:
431: /* */
432:
433: xuucp (to)
434: char *to;
435: {
436: char *cp,
437: buffer[BUFSIZ],
438: cmdstr[BUFSIZ];
439:
440: (void) strcpy (buffer, to);
441: if (cp = index (buffer, '!'))
442: *cp++ = NULL;
443: else {
444: fprintf (stderr, "internal error -- %s has no host\n", to);
445: return NOTOK;
446: }
447: (void) sprintf (cmdstr, "uux -p %s!rmail \\(%s\\)", buffer, cp);
448:
449: if ((pipef = popen (cmdstr, "w")) == NULL)
450: return NOTOK;
451:
452: (void) signal (SIGPIPE, pipeser);
453: pbroke = 0;
454:
455: return OK;
456: }
457:
458: /* */
459:
460: #ifdef BSD42
461: /* ARGSUSED */
462: #endif BSD42
463:
464: static int pipeser (i)
465: int i;
466: {
467: #ifndef BSD42
468: (void) signal (i, SIG_IGN);
469: #endif BSD42
470:
471: pbroke = 1;
472: }
473:
474: /* */
475:
476: rcpy () {
477: int i;
478: char buffer[BUFSIZ],
479: tmpfil[BUFSIZ];
480: FILE * fp;
481:
482: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
483: (void) unlink (mktemp (tmpfil));
484: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
485: return;
486:
487: fprintf (pipef, "Date: %s\nFrom: %s\n", dtimenow (), Mailsys);
488: fprintf (pipef, "To: %s\n", usrfrm);
489: fprintf (pipef, "\nProblems sending mail:\n\n");
490: i = 0;
491: if ((fp = fopen (Errtmp, "r")) != NULL) {
492: while (fgets (buffer, sizeof buffer, fp) != NULL) {
493: if (ferror (pipef))
494: break;
495: fputs (buffer, pipef);
496: i++;
497: }
498: }
499: if (i == 0)
500: fprintf (pipef, "\tunknown problem\n");
501: for (i = 0; oopsmessage[i]; i++)
502: fprintf (pipef, oopsmessage[i], Overseer);
503: fputs (rtnbegin, pipef);
504:
505: rewind (fromf);
506: (void) txtcpy (fromf, pipef);
507: rewind (msgf);
508: (void) txtcpy (msgf, pipef);
509:
510: fputs (rtnend, pipef);
511: (void) fclose (pipef);
512:
513: (void) xpost (usrfrm, tmpfil);
514: (void) unlink (tmpfil);
515: }
516:
517: /* */
518:
519: zcpy () {
520: int i;
521: char buffer[BUFSIZ],
522: tmpfil[BUFSIZ];
523: FILE * fp;
524:
525: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
526: (void) unlink (mktemp (tmpfil));
527: if ((pipef = fdopen (creat (tmpfil, Tmpmode), "w")) == NULL)
528: return;
529:
530: fprintf (pipef, "Date: %s\nFrom: %s\n", dtimenow (), Mailsys);
531: fprintf (pipef, "To: %s\n", Mailsys);
532: fprintf (pipef, "\nProblems sending mail for %s (aka %s):\n\n",
533: from, usrfrm);
534:
535: i = 0;
536: if ((fp = fopen (Errtmp, "r")) != NULL) {
537: while (fgets (buffer, sizeof buffer, fp) != NULL) {
538: if (ferror (pipef))
539: break;
540: fputs (buffer, pipef);
541: i = 1;
542: }
543: (void) fclose (fp);
544: if (i == 0)
545: fprintf (pipef, "\tunknown problem\n");
546: }
547: else
548: fprintf (pipef, "\tunable to open %s\n", Errtmp);
549: (void) fclose (pipef);
550:
551: (void) xpost (Mailsys, tmpfil);
552: (void) unlink (tmpfil);
553: }
554:
555: /* */
556:
557: filter () {
558: int i,
559: fd,
560: td;
561: char tmpfil[BUFSIZ],
562: mmdfil[BUFSIZ];
563: FILE * out;
564:
565: (void) strcpy (tmpfil, "/tmp/rmailXXXXXX");
566: (void) unlink (mktemp (tmpfil));
567: if ((fd = creat (tmpfil, Tmpmode)) == NOTOK)
568: return NOTOK;
569: (void) close (fd);
570: if ((fd = open (tmpfil, 2)) == NOTOK)
571: return NOTOK;
572: if ((out = fdopen (fd, "w")) == NULL) {
573: (void) close (fd);
574: return NOTOK;
575: }
576: if ((td = dup (fd)) == NOTOK) {
577: (void) close (fd);
578: return NOTOK;
579: }
580:
581: fprintf (out, "From %s %s\n", from, date);
582: if (txtcpy (msgf, out) == NOTOK) {
583: (void) close (fd);
584: (void) close (td);
585: return NOTOK;
586: }
587: (void) fclose (out);
588: (void) lseek (td, 0L, 0);
589:
590: (void) strcpy (mmdfil, "/tmp/mmdfXXXXXX");
591: (void) unlink (mktemp (mmdfil));
592: if ((fd = creat (mmdfil, Tmpmode)) == NOTOK) {
593: (void) close (td);
594: (void) unlink (tmpfil);
595: return NOTOK;
596: }
597: if ((fd = open (mmdfil, 2)) == NOTOK) {
598: (void) close (td);
599: (void) unlink (tmpfil);
600: return NOTOK;
601: }
602:
603: /* */
604:
605: switch (i = uucp2mmdf (td, fd, TRUE)) {
606: case OK:
607: (void) strcpy (mmdf, mmdfil);
608: break;
609:
610: default:
611: mmdf[0] = NULL;
612: break;
613: }
614: (void) close (td);
615: (void) unlink (tmpfil);
616: (void) close (fd);
617:
618: return (i != OK ? NOTOK : OK);
619: }
620:
621: /* */
622:
623: get_mmdf_addr (addr, to)
624: char *addr,
625: *to;
626: {
627: struct adrx *adrxp;
628:
629: *to = NULL;
630: if ((adrxp = seekadrx (addr)) == NULL)
631: return;
632:
633: addr_convert (adrxp, to, TRUE);
634: while (seekadrx (NULLCP))
635: continue;
636: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.