|
|
1.1 root 1: #ifndef SPOP
2: /* sbboards.c - MH style mailer to write to a ZOTnet BBoard */
3: #else SPOP
4: /* spop.c - MH style mailer to write to a POP subscriber */
5: #endif SPOP
6:
7: #ifndef SPOP
8:
9: /* This program acts like the MMDF ch_bboards channel: it does local
10: delivery to a ZOTnet BBoard and/or addition re-distribution to other
11: recipients of the BBoard. This program can function both as a SendMail
12: mailer and an MH .mh_receive file, depending on whether SENDMTS or
13: MHMTS is set. Currently, the MHMTS version of this program does not do
14: re-distribution.
15:
16: This program should be used ONLY if you have "bboards on" set in your
17: MH configuration, and if you have "mts sendmail" or "mts mh" set as well.
18: */
19:
20: #else SPOP
21:
22: /* This program acts like the MMDF-II ch_pop channel: it does local
23: delivery for non-local users. These users are known as POP subscribers
24: and use the Post Office Protocol with a POP server in order to access
25: their maildrop.
26: */
27:
28: #endif SPOP
29:
30: #undef DISTRIBUTE
31: #ifdef SENDMTS
32: #ifndef SPOP
33: #define DISTRIBUTE
34: #endif not SPOP
35: #endif SENDMTS
36:
37: #include "../h/mh.h"
38: #ifndef SPOP
39: #include "../h/addrsbr.h"
40: #endif not SPOP
41: #include "../h/dropsbr.h"
42: #include "../zotnet/bboards.h"
43: #include "../zotnet/tws.h"
44: #include <stdio.h>
45: #include "../zotnet/mts.h"
46: #include <pwd.h>
47: #ifndef SYS5
48: #include <sysexits.h>
49: #else SYS5
50: #define EX_CANTCREAT 1
51: #define EX_IOERR 1
52: #define EX_NOINPUT 1
53: #define EX_NOUSER 1
54: #define EX_OK 0
55: #define EX_OSERR 1
56: #define EX_OSFILE 1
57: #define EX_UNAVAILABLE 1
58: #define EX_USAGE 1
59: #endif SYS5
60: #ifdef DISTRIBUTE
61: #include "../mts/sendmail/smail.h"
62: #endif DISTRIBUTE
63:
64:
65: #define NBB 100
66:
67: #ifndef SPOP
68: #define ENTITY "bboard"
69: #else SPOP
70: #define ENTITY "subscriber"
71: #endif SPOP
72:
73: /* */
74:
75: static int bb_fderr;
76:
77: static int bb_uid;
78: static int bb_gid;
79:
80: int dst_rcpt ();
81:
82:
83: #ifndef SPOP
84: static char bb_from[BUFSIZ];
85: static char bb_head[BUFSIZ];
86: static char bb_home[BUFSIZ];
87: static char bb_time[BUFSIZ];
88: #ifdef DISTRIBUTE
89: static char bb_rept[BUFSIZ];
90: #endif DISTRIBUTE
91: #else SPOP
92: #define bb_head NULLCP
93: #endif SPOP
94:
95: static struct bboard *bb[NBB];
96:
97:
98: long lseek ();
99:
100: #ifdef SYS5
101: struct passwd *getpwnam ();
102: #endif SYS5
103:
104: /* */
105:
106: /* ARGSUSED */
107:
108: main (argc, argv, envp)
109: int argc;
110: char **argv,
111: **envp;
112: {
113: int fd;
114: char tmpfil[BUFSIZ];
115:
116: #ifdef MHMTS
117: if (argc != 5)
118: adios (EX_USAGE, NULL, "you lose really big");
119: #endif MHMTS
120: arginit (argv);
121:
122: fd = copyfile (fileno (stdin), tmpfil);
123: (void) unlink (tmpfil);
124:
125: localmail (fd);
126: #ifdef DISTRIBUTE
127: distribute (fd);
128: notify (fd);
129: #endif DISTRIBUTE
130:
131: exit (EX_OK);
132: }
133:
134: /* */
135:
136: static localmail (fd)
137: int fd;
138: {
139: int i,
140: md;
141: register struct bboard *bp;
142:
143: for (i = 0; bp = bb[i]; i++)
144: if (bp -> bb_file && *bp -> bb_file) {
145: (void) lseek (fd, 0L, 0);
146: #ifndef SPOP
147: if ((md = mbx_open (bp -> bb_file, bb_uid, bb_gid, BBMODE))
148: #else SPOP
149: if ((md = mbx_open (bp -> bb_file, bb_uid, bb_gid, POMODE))
150: #endif SPOP
151: == NOTOK) {
152: (void) lose ("unable to open %s", bp -> bb_file);
153: continue;
154: }
155: #ifndef SPOP
156: if (mbx_init (bp) != NOTOK)
157: #endif not SPOP
158: (void) mbx_copy (bp -> bb_file, md, fd, 1, bb_head, 0);
159: (void) mbx_close (bp -> bb_file, md);
160: }
161: }
162:
163: /* */
164:
165: #ifndef SPOP
166: static int mbx_init (bp)
167: register struct bboard *bp;
168: {
169: int fd,
170: clear;
171: register struct bboard *ip;
172: register FILE *fp;
173:
174: if ((fd = mbx_Xopen (bp -> bb_info, bb_uid, bb_gid, BBMODE, &clear))
175: == NOTOK)
176: return lose ("unable to lock and open %s", bp -> bb_info);
177: if ((fp = fdopen (fd, "w")) == NULL) {
178: (void) mbx_close (bp -> bb_info, fd);
179: return lose ("unable to fdopen %s", bp -> bb_info);
180: }
181:
182: if ((ip = getbbnam (bp -> bb_name)) == NULL) {
183: (void) lkfclose (fp, bp -> bb_info);
184: return lose ("unable to get information on BBoard %s", bp -> bb_name);
185: }
186: (void) strcpy (bb_time, dtimenow ());
187: (void) sprintf (bb_head, "BBoard-ID: %d\nBB-Posted: %s\n",
188: bp -> bb_maxima = ++ip -> bb_maxima, bb_time);
189:
190: fprintf (fp, "%d\n%s\n", bp -> bb_maxima, bb_time);
191: (void) lkfclose (fp, bp -> bb_info);
192:
193: return OK;
194: }
195: #endif not SPOP
196:
197: /* */
198:
199: #ifdef DISTRIBUTE
200: static distribute (fd)
201: int fd;
202: {
203: int i;
204: register struct bboard *bp;
205:
206: for (i = 0; bp = bb[i]; i++)
207: if (bp -> bb_dist && *bp -> bb_dist)
208: break;
209: if (bp == NULL)
210: return;
211:
212: if (dst_init () == NOTOK) {
213: dst_lose ();
214: return;
215: }
216: for (i = 0; bp = bb[i]; i++)
217: if (bp -> bb_dist && *bp -> bb_dist)
218: if (dst_adrs (bp) == NOTOK) {
219: dst_lose ();
220: return;
221: }
222: if (dst_text (fd) == NOTOK || dst_end () == NOTOK)
223: dst_lose ();
224: }
225:
226: /* */
227:
228: static int dst_init ()
229: {
230: int retval;
231:
232: if (rp_isbad (retval = sm_init (NULLCP, NULLCP, 0, 0, 0))
233: || rp_isbad (retval = sm_winit (S_MAIL, bb_from)))
234: return lose ("problem initializing SendMail; %s",
235: rp_string (retval));
236:
237: return OK;
238: }
239:
240: /* */
241:
242: static int dst_adrs (bp)
243: register struct bboard *bp;
244: {
245: if (getbbdist (bp, dst_rcpt))
246: return lose ("getbbdist failed: %s", getbberr ());
247:
248: return OK;
249: }
250:
251: /* */
252:
253: static int dst_rcpt (mbox, host)
254: register char *mbox,
255: *host;
256: {
257: int retval;
258:
259: switch (retval = sm_wadr (mbox, host, NULLCP)) {
260: case RP_OK:
261: return OK;
262:
263: case RP_NO:
264: case RP_USER:
265: (void) lose ("%s@%s: loses; %s", mbox, host, rp_string (retval));
266: return OK; /* fail-soft */
267:
268: default:
269: return lose ("%s@%s: unexpected response; %s",
270: mbox, host, rp_string (retval));
271: }
272: }
273:
274: /* */
275:
276: static int dst_text (fd)
277: int fd;
278: {
279: int i,
280: retval;
281: char buffer[BUFSIZ];
282:
283: if (rp_isbad (retval = sm_waend ()))
284: return lose ("problem ending addresses; %s", rp_string (retval));
285:
286: (void) lseek (fd, 0L, 0);
287: while ((i = read (fd, buffer, sizeof buffer)) > 0)
288: if (rp_isbad (retval = sm_wtxt (buffer, i)))
289: return lose ("problem writing text; %s", rp_string (retval));
290:
291: return (i != NOTOK ? OK : lose ("error reading from file"));
292: }
293:
294: /* */
295:
296: static int dst_end ()
297: {
298: int retval;
299:
300: switch (retval = sm_wtend ()) {
301: case RP_OK:
302: (void) sm_end (OK);
303: return OK;
304:
305: case RP_NO:
306: case RP_NDEL:
307: return lose ("posting failed; %s", rp_string (retval));
308:
309: default:
310: return lose ("unexpected response; %s", rp_string (retval));
311: }
312: }
313:
314: /* */
315:
316: static dst_lose ()
317: {
318: (void) sm_end (NOTOK);
319: }
320:
321: /* */
322:
323: /* VARARGS1 */
324:
325: static int lose (fmt, a, b, c, d)
326: char *fmt,
327: *a,
328: *b,
329: *c,
330: *d;
331: {
332: int fd,
333: i;
334: char *bp,
335: buffer[BUFSIZ];
336:
337: if (bb_fderr == NOTOK) {
338: if ((fd = open ("/dev/null", 0)) == NOTOK)
339: adios (EX_OSERR, "/dev/null", "unable to open");
340: bb_fderr = copyfile (fd, bb_rept);
341: }
342:
343: (void) sprintf (bp = buffer, fmt, a, b, c, d);
344: bp += strlen (bp);
345: bp += strlen (strcpy(bp, "\n"));
346: i = bp - buffer;
347: if (write (bb_fderr, buffer, i) != i)
348: adios (EX_IOERR, bb_rept, "error writing");
349:
350: return NOTOK;
351: }
352:
353: /* */
354:
355: static notify (fd)
356: int fd;
357: {
358: int i;
359: char buffer[BUFSIZ];
360:
361: if (bb_fderr == NOTOK)
362: return;
363:
364: if (rp_isbad (sm_init (NULLCP, NULLCP, 0, 0, 0))
365: || rp_isbad (sm_winit (S_MAIL, bb_from)))
366: goto sm_err;
367:
368: switch (sm_wadr (bb_from, NULLCP, NULLCP)) {
369: case RP_OK:
370: for (i = 0; bb[i]; i++) {
371: (void) sprintf (buffer, "local-%s-request", bb[i] -> bb_name);
372: (void) sm_wadr (buffer, LocalName (), NULLCP);
373: }
374: break;
375:
376: default:
377: goto sm_err;
378: }
379:
380: if (rp_isbad (sm_waend ()))
381: goto sm_err;
382:
383: (void) sprintf (buffer,
384: "Date: %s\nFrom: %s\nTo: %s\nSubject: BBoards Failure\n\n",
385: dtimenow (), bb_from, bb_from);
386: if (rp_isbad (sm_wtxt (buffer, strlen (buffer))))
387: goto sm_err;
388:
389: for (i = 0; bb[i]; i++) {
390: (void) sprintf (buffer, "BBoard %s\n", bb[i] -> bb_name);
391: if (rp_isbad (sm_wtxt (buffer, strlen (buffer))))
392: goto sm_err;
393: }
394:
395: (void) lseek (bb_fderr, 0L, 0);
396: while ((i = read (bb_fderr, buffer, sizeof buffer)) > 0)
397: if (rp_isbad (sm_wtxt (buffer, i)))
398: goto sm_err;
399:
400: (void) strcpy (buffer, "\n------- Forwarded Message\n\n");
401: if (rp_isbad (sm_wtxt (buffer, strlen (buffer))) || encap (fd) == NOTOK)
402: goto sm_err;
403: (void) strcpy (buffer, "\n------- End of Forwarded Message\n\n");
404: if (rp_isbad (sm_wtxt (buffer, strlen (buffer))))
405: goto sm_err;
406:
407: switch (sm_wtend ()) {
408: case RP_OK:
409: (void) unlink (bb_rept);
410: (void) sm_end (OK);
411: return;
412:
413: default:
414: sm_err: ;
415: adios (EX_UNAVAILABLE, NULLCP,
416: "failed and unable to post advisory, see %s for details",
417: bb_rept);
418: }
419: }
420:
421: /* */
422:
423: /* very similar to sbr/cpydgst.c */
424:
425: #define S1 0
426: #define S2 1
427:
428: #define output(c) if (bp >= dp) flush (), *bp++ = c; else *bp++ = c
429: #define flush() if ((j = bp - outbuf) \
430: && rp_isbad (sm_wtxt (outbuf, j))) \
431: return NOTOK; \
432: else \
433: bp = outbuf
434:
435: static int encap (fd)
436: register int fd;
437: {
438: register int i,
439: state;
440: register char *cp,
441: *ep;
442: char buffer[BUFSIZ];
443: register int j;
444: register char *bp,
445: *dp;
446: char outbuf[BUFSIZ];
447:
448: (void) lseek (fd, 0L, 0);
449:
450: dp = (bp = outbuf) + sizeof outbuf;
451: for (state = S1; (i = read (fd, buffer, sizeof buffer)) > 0;)
452: for (ep = (cp = buffer) + i; cp < ep; cp++) {
453: if (*cp == NULL)
454: continue;
455: switch (state) {
456: case S1:
457: if (*cp == '-') {
458: output ('-');
459: output (' ');
460: }
461: state = S2; /* fall */
462:
463: case S2:
464: output (*cp);
465: if (*cp == '\n')
466: state = S1;
467: break;
468: }
469: }
470:
471: if (i == NOTOK)
472: return NOTOK;
473: flush ();
474:
475: return OK;
476: }
477: #endif DISTRIBUTE
478:
479: /* */
480:
481: #ifndef DISTRIBUTE
482: /* VARARGS1 */
483:
484: static int lose (fmt, a, b, c, d)
485: char *fmt,
486: *a,
487: *b,
488: *c,
489: *d;
490: {
491: adios (EX_UNAVAILABLE, NULLCP, fmt, a, b, c, d);/* NOTREACHED */
492: }
493: #endif not DISTRIBUTE
494:
495: /* */
496:
497: static arginit (vec)
498: register char **vec;
499: {
500: register int i;
501: #ifdef MHMTS
502: register char *ap;
503: #endif MHMTS
504: char addr[BUFSIZ];
505: register struct bboard *bp;
506: register struct passwd *pw;
507:
508: invo_name = r1bindex (*vec++, '/');
509: m_foil (NULLCP);
510: mts_init (invo_name);
511:
512: #ifndef SPOP
513: if ((pw = getpwnam (BBOARDS)) == NULL)
514: adios (EX_OSFILE, NULLCP, "no entry for ~%s", BBOARDS);
515: #else SPOP
516: if ((pw = getpwnam (POPUID)) == NULL || !setpwinfo (pw, POPDB, 1))
517: adios (EX_OSFILE, NULLCP, "%s", pw ? getbberr () : "POP user-id unknown");
518: #endif SPOP
519:
520: if (pw -> pw_uid != geteuid ())
521: #ifndef SPOP
522: adios (EX_OSERR, NULLCP, "not running setuid to %s", BBOARDS);
523: #else SPOP
524: adios (EX_OSERR, NULLCP, "not running setuid to %s", POPUID);
525: #endif SPOP
526:
527: bb_uid = pw -> pw_uid;
528: bb_gid = pw -> pw_gid;
529: #ifndef SPOP
530: (void) strcpy (bb_from, adrsprintf (pw -> pw_name, LocalName ()));
531: (void) strcpy (bb_home, pw -> pw_dir);
532: #endif not SPOP
533:
534: #ifdef MHMTS
535: vec += 3;
536: #endif MHMTS
537: if (*vec == NULL)
538: adios (EX_USAGE, NULLCP, "usage: %s %s [%s ...]",
539: invo_name, ENTITY, ENTITY);
540:
541: for (i = 0; *vec; vec++) {
542: #ifdef MHMTS
543: if (ap = index (*vec, '.'))
544: *vec = ++ap;
545: #endif MHMTS
546: make_lower (addr, *vec);
547:
548: if ((bp = getbbnam (addr)) == NULL
549: && (bp = getbbaka (addr)) == NULL)
550: adios (EX_NOUSER, NULLCP, "no such %s as %s", ENTITY, *vec);
551: if ((bb[i++] = getbbcpy (bp)) == NULL)
552: adios (EX_UNAVAILABLE, NULLCP, "insufficient memory on %s", *vec);
553:
554: if (i >= NBB - 1)
555: adios (EX_USAGE, NULLCP, "too many %ss, starting with %s",
556: ENTITY, *vec);
557: }
558: bb[i] = NULL;
559:
560: (void) umask (0022);
561:
562: bb_fderr = NOTOK;
563: }
564:
565: /* */
566:
567: static int copyfile (qd, tmpfil)
568: int qd;
569: register char *tmpfil;
570: {
571: int i,
572: fd;
573: char buffer[BUFSIZ];
574:
575: (void) strcpy (tmpfil, m_tmpfil (invo_name));
576: if ((fd = creat (tmpfil, 0600)) == NOTOK)
577: adios (EX_CANTCREAT, tmpfil, "unable to create");
578: (void) close (fd);
579: if ((fd = open (tmpfil, 2)) == NOTOK)
580: adios (EX_NOINPUT, tmpfil, "unable to re-open");
581:
582: (void) lseek (qd, 0L, 0);
583: while ((i = read (qd, buffer, sizeof buffer)) > 0)
584: if (write (fd, buffer, i) != i)
585: adios (EX_IOERR, tmpfil, "error writing");
586: if (i == NOTOK)
587: adios (EX_IOERR, "input", "error reading");
588:
589: (void) lseek (fd, 0L, 0);
590:
591: return fd;
592: }
593:
594: /* */
595:
596: /* VARARGS3 */
597:
598: #ifdef MHMTS
599: /* ARGSUSED */
600: #endif MHMTS
601:
602: static void adios (code, what, fmt, a, b, c, d, e, f)
603: int code;
604: char *what,
605: *fmt,
606: *a,
607: *b,
608: *c,
609: *d,
610: *e,
611: *f;
612: {
613: advise (what, fmt, a, b, c, d, e, f);
614: #ifdef SENDMTS
615: done (code);
616: #endif SENDMTS
617: #ifdef MHMTS
618: done (1);
619: #endif MHMTS
620: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.