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