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