|
|
1.1 root 1: /* slocal.c - MH style mailer to write to a local user's mailbox */
2:
3: /* This program implements mail delivery in the MH/MMDF style.
4:
5: Under SendMail, users should add the line
6:
7: "| /usr/local/lib/mh/slocal"
8:
9: to their $HOME/.forward file.
10:
11: Under MMDF-I, users should (symbolically) link /usr/local/lib/mh/slocal
12: to $HOME/bin/rcvmail.
13:
14: Under stand-alone MH, post will automatically run this during local
15: delivery.
16:
17: This program should be used ONLY if you have "mts sendmail" or "mts mh"
18: or "mts mmdf1" set in your MH configuration.
19: */
20:
21: /* */
22:
23: #include "../h/mh.h"
24: #include "../h/dropsbr.h"
25: #include "../h/rcvmail.h"
26: #include "../zotnet/tws.h"
27: #include "../zotnet/mts.h"
28: #include <pwd.h>
29: #include <signal.h>
30: #ifndef V7
31: #include <sys/ioctl.h>
32: #endif not V7
33: #include <sys/stat.h>
34: #include <utmp.h>
35:
36:
37: #define NVEC 100
38:
39: /* */
40:
41: static struct swit switches[] = {
42: #define ADDRSW 0
43: "addr address", 0,
44: #define USERSW 1
45: "user name", 0,
46: #define FILESW 2
47: "file file", 0,
48: #define SENDSW 3
49: "sender address", 0,
50: #define MBOXSW 4
51: "mailbox file", 0,
52: #define HOMESW 5
53: "home directory", 0,
54:
55: #define MAILSW 6
56: "maildelivery file", 0,
57:
58: #define VERBSW 7
59: "verbose", 0,
60: #define NVERBSW 8
61: "noverbose", 0,
62:
63: #define DEBUGSW 9
64: "debug", 0,
65:
66: #define HELPSW 10
67: "help", 4,
68:
69: NULL, NULL
70: };
71:
72: /* */
73:
74: static int debug = 0;
75: static int globbed = 0;
76: static int parsed = 0;
77: static int utmped = 0;
78: static int verbose = 0;
79:
80: static char *addr = NULLCP;
81: static char *user = NULLCP;
82: static char *info = NULLCP;
83: static char *file = NULLCP;
84: static char *sender = NULLCP;
85: static char *mbox = NULLCP;
86: static char *home = NULLCP;
87:
88:
89: static struct passwd *pw;
90:
91:
92: static char ddate[BUFSIZ];
93:
94: struct tws *now;
95:
96:
97: static jmp_buf myctx;
98:
99: /* */
100:
101: static struct pair {
102: char *p_name;
103: char *p_value;
104:
105: char p_flags;
106: #define P_NIL 0x00
107: #define P_ADR 0x01
108: #define P_HID 0x02
109: #define P_CHK 0x04
110: };
111:
112: struct pair *lookup ();
113:
114:
115: static struct pair hdrs[NVEC + 1] = {
116: "source", NULL, P_HID,
117: "addr", NULL, P_HID,
118:
119: "Return-Path", NULL, P_ADR,
120: "Reply-To", NULL, P_ADR,
121: "From", NULL, P_ADR,
122: "Sender", NULL, P_ADR,
123: "To", NULL, P_ADR,
124: "cc", NULL, P_ADR,
125: "Resent-Reply-To", NULL, P_ADR,
126: "Resent-From", NULL, P_ADR,
127: "Resent-Sender", NULL, P_ADR,
128: "Resent-To", NULL, P_ADR,
129: "Resent-cc", NULL, P_ADR,
130:
131: NULL
132: };
133:
134:
135: static struct pair vars[] = {
136: "sender", NULL, P_NIL,
137: "address", NULL, P_NIL,
138: "size", NULL, P_NIL,
139: "reply-to", NULL, P_CHK,
140: "info", NULL, P_NIL,
141:
142: NULL
143: };
144:
145: /* */
146:
147: extern char **environ;
148:
149: void adorn ();
150: int alrmser ();
151:
152:
153: long lseek ();
154: #ifdef SYS5
155: struct passwd *getpwnam ();
156: #endif SYS5
157:
158: /* */
159:
160: /* ARGSUSED */
161:
162: main (argc, argv, envp)
163: int argc;
164: char **argv,
165: **envp;
166: {
167: int fd;
168: FILE *fp = stdin;
169: char *cp,
170: *mdlvr = NULL,
171: buf[100],
172: from[BUFSIZ],
173: mailbox[BUFSIZ],
174: tmpfil[BUFSIZ],
175: **argp = argv + 1;
176:
177: invo_name = r1bindex (*argv, '/');
178: m_foil (NULLCP);
179: mts_init (invo_name);
180:
181: /* */
182:
183: while (cp = *argp++) {
184: if (*cp == '-')
185: switch (smatch (++cp, switches)) {
186: case AMBIGSW:
187: ambigsw (cp, switches);
188: done (1);
189: case UNKWNSW:
190: adios (NULLCP, "-%s unknown", cp);
191: case HELPSW:
192: (void) sprintf (buf, "%s [switches] [address info sender]",
193: invo_name);
194: help (buf, switches);
195: done (1);
196:
197: case ADDRSW:
198: if (!(addr = *argp++))/* allow -xyz arguments */
199: adios (NULLCP, "missing argument to %s", argp[-2]);
200: continue;
201: case USERSW:
202: if (!(user = *argp++))/* allow -xyz arguments */
203: adios (NULLCP, "missing argument to %s", argp[-2]);
204: continue;
205: case FILESW:
206: if (!(file = *argp++) || *file == '-')
207: adios (NULLCP, "missing argument to %s", argp[-2]);
208: continue;
209: case SENDSW:
210: if (!(sender = *argp++))/* allow -xyz arguments */
211: adios (NULLCP, "missing argument to %s", argp[-2]);
212: continue;
213: case MBOXSW:
214: if (!(mbox = *argp++) || *mbox == '-')
215: adios (NULLCP, "missing argument to %s", argp[-2]);
216: continue;
217: case HOMESW:
218: if (!(home = *argp++) || *home == '-')
219: adios (NULLCP, "missing argument to %s", argp[-2]);
220: continue;
221:
222: case MAILSW:
223: if (!(cp = *argp++) || *cp == '-')
224: adios (NULLCP, "missing argument to %s", argp[-2]);
225: if (mdlvr)
226: adios (NULLCP, "only one maildelivery file at a time!");
227: mdlvr = cp;
228: continue;
229:
230: case VERBSW:
231: verbose++;
232: continue;
233: case NVERBSW:
234: verbose = 0;
235: continue;
236:
237: case DEBUGSW:
238: debug++;
239: continue;
240: }
241:
242: switch (argp - (argv + 1)) {
243: case 1:
244: addr = cp;
245: break;
246:
247: case 2:
248: info = cp;
249: break;
250:
251: case 3:
252: sender = cp;
253: break;
254: }
255: }
256:
257: /* */
258:
259: if (addr == NULL)
260: addr = getusr ();
261: if (user == NULL)
262: user = (cp = index (addr, '.')) ? ++cp : addr;
263: if ((pw = getpwnam (user)) == NULL)
264: adios (NULLCP, "no such local user as %s", user);
265:
266: if (chdir (pw -> pw_dir) == NOTOK)
267: (void) chdir ("/");
268: (void) umask (0077);
269:
270: if (geteuid () == 0) {
271: #ifdef BSD41A
272: (void) inigrp (pw -> pw_name, pw -> pw_gid);
273: #endif BSD41A
274: (void) setgid (pw -> pw_gid);
275: #ifdef BSD42
276: (void) initgroups (pw -> pw_name, pw -> pw_gid);
277: #endif BSD42
278: (void) setuid (pw -> pw_uid);
279: }
280:
281: if (info == NULL)
282: info = "";
283:
284: setbuf (stdin, NULLCP);
285:
286: if (file == NULL) {
287: if ((fd = copyfile (fileno (stdin), file = tmpfil, 1)) == NOTOK)
288: adios (NULLCP, "unable to create temporary file");
289: if (debug)
290: fprintf (stderr, "temporary file \"%s\" selected\n", tmpfil);
291: else
292: (void) unlink (tmpfil);
293: if ((fp = fdopen (fd, "r+")) == NULL)
294: adios (NULLCP, "unable to access temporary file");
295: }
296: else
297: fd = fileno (stdin);
298:
299: from[0] = NULL;
300: if (sender == NULL)
301: copyinfo (fp, from);
302:
303:
304: if (mbox == NULL) {
305: (void) sprintf (mailbox, "%s/%s",
306: mmdfldir[0] ? mmdfldir : pw -> pw_dir,
307: mmdflfil[0] ? mmdflfil : pw -> pw_name);
308: mbox = mailbox;
309: }
310: if (home == NULL)
311: home = pw -> pw_dir;
312:
313: if ((now = dtwstime ()) == NULL)
314: adios (NULLCP, "unable to ascertain local time");
315: (void) sprintf (ddate, "Delivery-Date: %s\n", dtimenow ());
316:
317: if (debug) {
318: fprintf (stderr, "addr=\"%s\" user=\"%s\" info=\"%s\" file=\"%s\"\n",
319: addr, user, info, file);
320: fprintf (stderr, "sender=\"%s\" mbox=\"%s\" home=\"%s\" from=\"%s\"\n",
321: sender, mbox, home, from);
322: fprintf (stderr, "ddate=\"%s\" now=%02d:%02d\n",
323: ddate, now -> tw_hour, now -> tw_min);
324: }
325:
326: done (localmail (fd, from, mdlvr) != NOTOK ? RCV_MOK : RCV_MBX);
327: }
328:
329: /* */
330:
331: static int localmail (fd, from, mdlvr)
332: int fd;
333: char *from,
334: *mdlvr;
335: {
336: if (usr_delivery (fd, mdlvr ? mdlvr : ".maildelivery", 0) != NOTOK)
337: return OK;
338:
339: if (usr_delivery (fd, maildelivery, 1) != NOTOK)
340: return OK;
341:
342: #ifdef notdef
343: if (verbose)
344: printf ("(invoking hook)\n");
345: if (usr_hook (fd, mbox) != NOTOK)
346: return OK;
347: #endif notdef
348:
349: if (verbose)
350: printf ("(trying normal delivery)\n");
351: return usr_file (fd, mbox, from);
352: }
353:
354: /* */
355:
356: #define matches(a,b) (stringdex (b, a) >= 0)
357:
358: static int usr_delivery (fd, delivery, su)
359: int fd,
360: su;
361: char *delivery;
362: {
363: int i,
364: accept,
365: status,
366: won,
367: vecp;
368: register char *cp,
369: *action,
370: *field,
371: *pattern,
372: *string;
373: char buffer[BUFSIZ],
374: tmpbuf[BUFSIZ],
375: *vec[NVEC];
376: struct stat st;
377: register struct pair *p;
378: register FILE *fp;
379:
380: if ((fp = fopen (delivery, "r")) == NULL)
381: return NOTOK;
382: if (fstat (fileno (fp), &st) == NOTOK
383: || (st.st_uid != 0 && (su || st.st_uid != pw -> pw_uid))
384: || st.st_mode & 0022) {
385: if (verbose) {
386: printf ("%s: ownership/modes bad (%d, %d,%d,0%o)\n",
387: delivery, su, pw -> pw_uid, st.st_uid, st.st_mode);
388: (void) fflush (stdout);
389: }
390: return NOTOK;
391: }
392:
393: won = 0;
394: while (fgets (buffer, sizeof buffer, fp) != NULL) {
395: if (*buffer == '#')
396: continue;
397: if (cp = index (buffer, '\n'))
398: *cp = NULL;
399: if ((vecp = split (buffer, vec)) < 5)
400: continue;
401: if (debug)
402: for (i = 0; vec[i]; i++)
403: fprintf (stderr, "vec[%d]: \"%s\"\n", i, vec[i]);
404:
405: field = vec[0];
406: pattern = vec[1];
407: action = vec[2];
408:
409: switch (vec[3][0]) {
410: case '?':
411: if (won)
412: continue; /* else fall */
413: case 'A':
414: case 'a':
415: accept = 1;
416: break;
417:
418: case 'R':
419: case 'r':
420: default:
421: accept = 0;
422: break;
423: }
424:
425: string = vec[4];
426:
427: if (vecp > 5) {
428: if (uleq (vec[5], "select")) {
429: if (logged_in () != NOTOK)
430: continue;
431: if (vecp > 7 && timely (vec[6], vec[7]) == NOTOK)
432: continue;
433: }
434: }
435:
436: switch (*field) {
437: case '*':
438: break;
439:
440: case 'd':
441: if (uleq (field, "default")) {
442: if (won)
443: continue;
444: break;
445: } /* else fall */
446:
447: default:
448: if (!parsed && parse (fd) == NOTOK) {
449: (void) fclose (fp);
450: return NOTOK;
451: }
452: if ((p = lookup (hdrs, field)) == NULL
453: || !matches (p -> p_value, pattern))
454: continue;
455: break;
456: }
457:
458: switch (*action) {
459: case 'q':
460: if (!uleq (action, "qpipe"))
461: continue; /* else fall */
462: case '^':
463: expand (tmpbuf, string, fd);
464: if (split (tmpbuf, vec) < 1)
465: continue;
466: status = usr_pipe (fd, tmpbuf, vec[0], vec);
467: break;
468:
469: case 'p':
470: if (!uleq (action, "pipe"))
471: continue; /* else fall */
472: case '|':
473: vec[2] = "sh";
474: vec[3] = "-c";
475: expand (tmpbuf, string, fd);
476: vec[4] = tmpbuf;
477: vec[5] = NULL;
478: status = usr_pipe (fd, tmpbuf, "/bin/sh", vec + 2);
479: break;
480:
481: case 'f':
482: if (!uleq (action, "file"))
483: continue; /* else fall */
484: case '>':
485: status = usr_file (fd, string, NULLCP);
486: break;
487:
488: case 'd':
489: if (!uleq (action, "destroy"))
490: continue;
491: status = OK;
492: break;
493: }
494:
495: if (accept) {
496: if (status == NOTOK) {
497: won = 0;
498: break;
499: }
500: won++;
501: }
502: }
503:
504: (void) fclose (fp);
505: return (won ? OK : NOTOK);
506: }
507:
508: /* */
509:
510: #define QUOTE '\\'
511:
512: static int split (cp, vec)
513: char *cp,
514: **vec;
515: {
516: register int i;
517: register char *s;
518:
519: for (i = 0, s = cp; i <= NVEC;) {
520: vec[i] = NULL;
521: while (isspace (*s) || *s == ',')
522: *s++ = NULL;
523: if (*s == NULL)
524: break;
525:
526: if (*s == '"') {
527: for (vec[i++] = ++s; *s != NULL && *s != '"'; s++)
528: if (*s == QUOTE) {
529: if (*++s == '"')
530: (void) strcpy (s - 1, s);
531: s--;
532: }
533: if (*s == '"')
534: *s++ = NULL;
535: continue;
536: }
537: if (*s == QUOTE && *++s != '"')
538: s--;
539: vec[i++] = s++;
540:
541: while (*s != NULL && !isspace (*s) && *s != ',')
542: s++;
543: }
544: vec[i] = NULL;
545:
546: return i;
547: }
548:
549: /* */
550:
551: static int parse (fd)
552: register int fd;
553: {
554: register int i,
555: state;
556: int fd1;
557: register char *cp,
558: *dp,
559: *lp;
560: char name[NAMESZ],
561: field[BUFSIZ];
562: register struct pair *p,
563: *q;
564: register FILE *in;
565:
566: if (parsed++)
567: return OK;
568:
569: if ((fd1 = dup (fd)) == NOTOK)
570: return NOTOK;
571: if ((in = fdopen (fd1, "r")) == NULL) {
572: (void) close (fd1);
573: return NOTOK;
574: }
575: rewind (in);
576:
577: if (p = lookup (hdrs, "source"))
578: p -> p_value = getcpy (sender);
579: if (p = lookup (hdrs, "addr"))
580: p -> p_value = getcpy (addr);
581:
582: for (i = 0, state = FLD;;) {
583: switch (state = m_getfld (state, name, field, sizeof field, in)) {
584: case FLD:
585: case FLDEOF:
586: case FLDPLUS:
587: lp = add (field, NULLCP);
588: while (state == FLDPLUS) {
589: state = m_getfld (state, name, field, sizeof field, in);
590: lp = add (field, lp);
591: }
592: for (p = hdrs; p -> p_name; p++)
593: if (uleq (p -> p_name, name)) {
594: if (!(p -> p_flags & P_HID)) {
595: if (cp = p -> p_value)
596: if (p -> p_flags & P_ADR) {
597: dp = cp + strlen (cp) - 1;
598: if (*dp == '\n')
599: *dp = NULL;
600: cp = add (",\n\t", cp);
601: }
602: else
603: cp = add ("\t", cp);
604: p -> p_value = add (lp, cp);
605: }
606: free (lp);
607: break;
608: }
609: if (p -> p_name == NULL && i < NVEC) {
610: p -> p_name = getcpy (name);
611: p -> p_value = lp;
612: p -> p_flags = P_NIL;
613: p++, i++;
614: p -> p_name = NULL;
615: }
616: if (state != FLDEOF)
617: continue;
618: break;
619:
620: case BODY:
621: case BODYEOF:
622: case FILEEOF:
623: break;
624:
625: case LENERR:
626: case FMTERR:
627: advise (NULLCP, "format error in message");
628: break;
629:
630: default:
631: advise (NULLCP, "internal error");
632: (void) fclose (in);
633: return NOTOK;
634: }
635: break;
636: }
637: (void) fclose (in);
638:
639: if (p = lookup (vars, "reply-to")) {
640: if ((q = lookup (hdrs, "reply-to")) == NULL || q -> p_value == NULL)
641: q = lookup (hdrs, "from");
642: p -> p_value = getcpy (q ? q -> p_value : "");
643: p -> p_flags &= ~P_CHK;
644: if (debug)
645: fprintf (stderr, "vars[%d]: name=\"%s\" value=\"%s\"\n",
646: p - vars, p -> p_name, p -> p_value);
647: }
648: if (debug)
649: for (p = hdrs; p -> p_name; p++)
650: fprintf (stderr, "hdrs[%d]: name=\"%s\" value=\"%s\"\n",
651: p - hdrs, p -> p_name, p -> p_value);
652:
653: return OK;
654: }
655:
656: /* */
657:
658: #define LPAREN '('
659: #define RPAREN ')'
660:
661: static expand (s1, s2, fd)
662: register char *s1,
663: *s2;
664: int fd;
665: {
666: register char c,
667: *cp;
668: register struct pair *p;
669:
670: if (!globbed)
671: glob (fd);
672:
673: while (c = *s2++)
674: if (c != '$' || *s2 != LPAREN)
675: *s1++ = c;
676: else {
677: for (cp = ++s2; *s2 && *s2 != RPAREN; s2++)
678: continue;
679: if (*s2 != RPAREN) {
680: s2 = --cp;
681: continue;
682: }
683: *s2++ = NULL;
684: if (p = lookup (vars, cp)) {
685: if (!parsed && (p -> p_flags & P_CHK))
686: (void) parse (fd);
687:
688: (void) strcpy (s1, p -> p_value);
689: s1 += strlen (s1);
690: }
691: }
692: *s1 = NULL;
693: }
694:
695: /* */
696:
697: static glob (fd)
698: register int fd;
699: {
700: char buffer[BUFSIZ];
701: struct stat st;
702: register struct pair *p;
703:
704: if (globbed++)
705: return;
706:
707: if (p = lookup (vars, "sender"))
708: p -> p_value = getcpy (sender);
709: if (p = lookup (vars, "address"))
710: p -> p_value = getcpy (addr);
711: if (p = lookup (vars, "size")) {
712: (void) sprintf (buffer, "%d",
713: fstat (fd, &st) != NOTOK ? (int) st.st_size : 0);
714: p -> p_value = getcpy (buffer);
715: }
716: if (p = lookup (vars, "info"))
717: p -> p_value = getcpy (info);
718:
719: if (debug)
720: for (p = vars; p -> p_name; p++)
721: fprintf (stderr, "vars[%d]: name=\"%s\" value=\"%s\"\n",
722: p - vars, p -> p_name, p -> p_value);
723: }
724:
725: /* */
726:
727: static struct pair *lookup (pairs, key)
728: register struct pair *pairs;
729: register char *key;
730: {
731: register char *cp;
732:
733: for (; cp = pairs -> p_name; pairs++)
734: if (uleq (cp, key))
735: return pairs;
736:
737: return NULL;
738: }
739:
740: /* */
741:
742: static int logged_in () {
743: struct utmp ut;
744: register FILE *uf;
745:
746: if (utmped)
747: return utmped;
748:
749: if ((uf = fopen ("/etc/utmp", "r")) == NULL)
750: return NOTOK;
751:
752: while (fread ((char *) &ut, sizeof ut, 1, uf) == 1)
753: if (ut.ut_name[0] != NULL
754: && strncmp (user, ut.ut_name, sizeof ut.ut_name) == 0) {
755: if (debug)
756: continue;
757: (void) fclose (uf);
758: return (utmped = DONE);
759: }
760:
761: (void) fclose (uf);
762: return (utmped = NOTOK);
763: }
764:
765:
766: static int timely (t1, t2)
767: char *t1,
768: *t2;
769: {
770: #define check(t,a,b) if (t < a || t > b) return NOTOK
771: #define cmpar(h1,m1,h2,m2) if (h1 < h2 || (h1 == h2 && m1 < m2)) return OK
772:
773: int t1hours,
774: t1mins,
775: t2hours,
776: t2mins;
777:
778: if (sscanf (t1, "%d:%d", &t1hours, &t1mins) != 2)
779: return NOTOK;
780: check (t1hours, 0, 23);
781: check (t1mins, 0, 59);
782:
783: if (sscanf (t2, "%d:%d", &t2hours, &t2mins) != 2)
784: return NOTOK;
785: check (t2hours, 0, 23);
786: check (t2mins, 0, 59);
787:
788: cmpar (now -> tw_hour, now -> tw_min, t1hours, t1mins);
789: cmpar (t2hours, t2mins, now -> tw_hour, now -> tw_min);
790:
791: return NOTOK;
792: }
793:
794: /* */
795:
796: static int usr_file (fd, mailbox, from)
797: int fd;
798: char *mailbox,
799: *from;
800: {
801: int md,
802: mapping;
803: register char *bp;
804: char buffer[BUFSIZ];
805:
806: if (verbose)
807: printf ("\tdelivering to file \"%s\"", mailbox);
808: if (from && *from) {
809: (void) mbx_uucp ();
810: if (verbose)
811: printf (" (uucp style)");
812: (void) sprintf (buffer, "%s%s", from, ddate);
813: bp = buffer;
814: mapping = 0;
815: }
816: else {
817: bp = ddate;
818: mapping = 1;
819: }
820: if (verbose)
821: (void) fflush (stdout);
822:
823: if ((md = mbx_open (mailbox, pw -> pw_uid, pw -> pw_gid, m_gmprot ()))
824: == NOTOK) {
825: adorn ("", "unable to open:");
826: return NOTOK;
827: }
828:
829: (void) lseek (fd, 0L, 0);
830: if (mbx_copy (mailbox, md, fd, mapping, bp, verbose) == NOTOK) {
831: adorn ("", "error writing to:");
832: return NOTOK;
833: }
834:
835: (void) mbx_close (mailbox, md);
836: if (verbose) {
837: printf (", done.\n");
838: (void) fflush (stdout);
839: }
840: return OK;
841: }
842:
843: /* */
844:
845: #ifdef notdef
846: static int usr_hook (fd, mailbox)
847: int fd;
848: char *mailbox;
849: {
850: int i,
851: vecp;
852: char receive[BUFSIZ],
853: tmpfil[BUFSIZ],
854: *vec[NVEC];
855:
856: if ((fd = copyfile (fd, tmpfil, 0)) == NOTOK) {
857: if (verbose)
858: adorn ("unable to copy message; skipping hook\n");
859: return NOTOK;
860: }
861: (void) chown (tmpfil, pw -> pw_uid, pw -> pw_gid);
862:
863: vecp = 1;
864: (void) sprintf (receive, "%s/.mh_receive", pw -> pw_dir);
865: switch (access (receive, 01)) {
866: case NOTOK:
867: (void) sprintf (receive, "%s/bin/rcvmail", pw -> pw_dir);
868: if (access (receive, 01) == NOTOK) {
869: (void) unlink (tmpfil);
870: if (verbose) {
871: printf ("\tnot present\n");
872: (void) fflush (stdout);
873: }
874: return NOTOK;
875: }
876: vec[vecp++] = addr;
877: vec[vecp++] = tmpfil;
878: vec[vecp++] = sender;
879: break;
880:
881: default:
882: vec[vecp++] = tmpfil;
883: vec[vecp++] = mailbox;
884: vec[vecp++] = home;
885: vec[vecp++] = addr;
886: vec[vecp++] = sender;
887: break;
888: }
889: vec[0] = r1bindex (receive, '/');
890: vec[vecp] = NULL;
891:
892: i = usr_pipe (fd, "rcvmail", receive, vec);
893: (void) unlink (tmpfil);
894:
895: return i;
896: }
897: #endif notdef
898:
899: /* */
900:
901: static int usr_pipe (fd, cmd, pgm, vec)
902: int fd;
903: char *cmd,
904: *pgm,
905: **vec;
906: {
907: int bytes,
908: i,
909: child_id,
910: status;
911: struct stat st;
912:
913: if (verbose) {
914: printf ("\tdelivering to pipe \"%s\"", cmd);
915: (void) fflush (stdout);
916: }
917: (void) lseek (fd, 0L, 0);
918:
919: for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
920: sleep (5);
921: switch (child_id) {
922: case NOTOK:
923: adorn ("fork", "unable to");
924: return NOTOK;
925:
926: case OK:
927: if (fd != 0)
928: (void) dup2 (fd, 0);
929: (void) freopen ("/dev/null", "w", stdout);
930: (void) freopen ("/dev/null", "w", stderr);
931: if (fd != 3)
932: (void) dup2 (fd, 3);
933: closefds (4);
934: #ifdef TIOCNOTTY
935: if ((fd = open ("/dev/tty", 2)) != NOTOK) {
936: (void) ioctl (fd, TIOCNOTTY, NULLCP);
937: (void) close (fd);
938: }
939: #endif TIOCNOTTY
940: #ifdef BSD42
941: (void) setpgrp (0, getpid ());
942: #endif BSD42
943:
944: *environ = NULL;
945: (void) putenv ("USER", pw -> pw_name);
946: (void) putenv ("HOME", pw -> pw_dir);
947: (void) putenv ("SHELL", pw -> pw_shell);
948:
949: execvp (pgm, vec);
950: _exit (-1);
951:
952: default:
953: switch (setjmp (myctx)) {
954: case OK:
955: (void) signal (SIGALRM, alrmser);
956: bytes = fstat (fd, &st) != NOTOK ? (int) st.st_size : 100;
957: if (bytes <= 0)
958: bytes = 100;
959: (void) alarm ((unsigned) (bytes * 60 + 300));
960:
961: status = pidwait (child_id, OK);
962:
963: (void) alarm (0);
964: #ifdef MMDFI
965: if (status == RP_MOK || status == RP_OK)
966: status = 0;
967: #endif MMDFI
968: if (verbose) {
969: if (status == 0)
970: printf (", wins.\n");
971: else
972: if ((status & 0xff00) == 0xff00)
973: printf (", system error\n");
974: else
975: (void) pidstatus (status, stdout, ", loses");
976: (void) fflush (stdout);
977: }
978: return (status == 0 ? OK : NOTOK);
979:
980: default:
981: #ifndef BSD42
982: (void) kill (child_id, SIGKILL);
983: #else BSD42
984: (void) killpg (child_id, SIGKILL);
985: #endif BSD42
986: if (verbose) {
987: printf (", timed-out; terminated\n");
988: (void) fflush (stdout);
989: }
990: return NOTOK;
991: }
992: }
993: }
994:
995: /* */
996:
997: /* ARGSUSED */
998:
999: static int alrmser (i)
1000: int i;
1001: {
1002: longjmp (myctx, DONE);
1003: }
1004:
1005: /* */
1006:
1007: static copyinfo (fp, from)
1008: register FILE *fp;
1009: char *from;
1010: {
1011: int i;
1012: register char *cp;
1013: static char buffer[BUFSIZ];
1014:
1015: if (fgets (from, BUFSIZ, fp) == NULL)
1016: adios (NULLCP, "no message");
1017:
1018: if (strncmp (from, "From ", i = strlen ("From "))) {
1019: rewind (fp);
1020: *from = NULL;
1021: return;
1022: }
1023:
1024: (void) strcpy (buffer, from + i);
1025: if (cp = index (buffer, '\n')) {
1026: *cp = NULL;
1027: cp -= 24;
1028: if (cp < buffer)
1029: cp = buffer;
1030: }
1031: else
1032: cp = buffer;
1033: *cp = NULL;
1034:
1035: for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--)
1036: if (isspace (*cp))
1037: *cp = NULL;
1038: else
1039: break;
1040: sender = buffer;
1041: rewind (fp);
1042: }
1043:
1044: /* */
1045:
1046: static int copyfile (qd, tmpfil, fold)
1047: int qd,
1048: fold;
1049: register char *tmpfil;
1050: {
1051: register int i,
1052: fd1,
1053: fd2;
1054: char buffer[BUFSIZ];
1055: register FILE *qfp,
1056: *ffp;
1057:
1058: (void) strcpy (tmpfil, m_tmpfil (invo_name));
1059: if ((fd1 = creat (tmpfil, 0600)) == NOTOK)
1060: return NOTOK;
1061: (void) close (fd1);
1062: if ((fd1 = open (tmpfil, 2)) == NOTOK)
1063: return NOTOK;
1064:
1065: if (!fold) {
1066: while ((i = read (qd, buffer, sizeof buffer)) > 0)
1067: if (write (fd1, buffer, i) != i) {
1068: you_lose: ;
1069: (void) close (fd1);
1070: (void) unlink (tmpfil);
1071: return NOTOK;
1072: }
1073: if (i == NOTOK)
1074: goto you_lose;
1075: (void) lseek (fd1, 0L, 0);
1076: return fd1;
1077: }
1078:
1079: if ((fd2 = dup (qd)) == NOTOK) {
1080: (void) close (fd1);
1081: return NOTOK;
1082: }
1083: if ((qfp = fdopen (fd2, "r")) == NULL) {
1084: (void) close (fd1);
1085: (void) close (fd2);
1086: return NOTOK;
1087: }
1088:
1089: if ((fd2 = dup (fd1)) == NOTOK) {
1090: (void) close (fd1);
1091: (void) fclose (qfp);
1092: return NOTOK;
1093: }
1094: if ((ffp = fdopen (fd2, "r+")) == NULL) {
1095: (void) close (fd1);
1096: (void) close (fd2);
1097: (void) fclose (qfp);
1098: return NOTOK;
1099: }
1100:
1101: i = strlen ("From ");
1102: while (fgets (buffer, sizeof buffer, qfp)) {
1103: if (!strncmp (buffer, "From ", i))
1104: putc ('>', ffp);
1105: fputs (buffer, ffp);
1106: if (ferror (ffp)) {
1107: (void) close (fd1);
1108: (void) fclose (ffp);
1109: (void) fclose (qfp);
1110: return NOTOK;
1111: }
1112: }
1113:
1114: (void) fclose (ffp);
1115: if (ferror (qfp)) {
1116: (void) close (fd1);
1117: (void) fclose (qfp);
1118: return NOTOK;
1119: }
1120: (void) fclose (qfp);
1121:
1122: (void) lseek (fd1, 0L, 0);
1123:
1124: return fd1;
1125: }
1126:
1127: /* */
1128:
1129: /* VARARGS2 */
1130:
1131: static void adorn (what, fmt, a, b, c, d, e, f)
1132: char *what,
1133: *fmt,
1134: *a,
1135: *b,
1136: *c,
1137: *d,
1138: *e,
1139: *f;
1140: {
1141: char *cp = invo_name;
1142:
1143: if (!verbose)
1144: return;
1145: printf (", ");
1146:
1147: invo_name = NULL;
1148: advise (what, fmt, a, b, c, d, e, f);
1149: invo_name = cp;
1150: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.