1: #ifndef POP
2: /* bb_wtmail.c - write mail to a BBoard */
3: #else POP
4: /* po_wtmail.c - write mail for a POP subscriber */
5: #endif POP
6:
7:
8: #include "util.h"
9: #include "mmdf.h"
10: #include "bboards.h"
11: #include "cnvtdate.h"
12: #include "ch.h"
13: #include "phs.h"
14: #include <pwd.h>
15: #include <sys/stat.h>
16:
17: /* */
18:
19: #ifndef RP_DOK
20: #define submitopts "vmth%s*"
21: #else RP_DOK
22: #define submitopts "vkmth%s*"
23: #endif RP_DOK
24:
25: #ifndef POP
26: #define RP_NOPE RP_AOK
27:
28: #define MBXMODE BBMODE
29: #else POP
30: #define RP_NOPE RP_USER
31:
32: #define MBXMODE sentprotect
33:
34: extern int sentprotect;
35: #endif POP
36:
37:
38: int err_fd = NOTOK;
39:
40: int ds_address ();
41:
42: extern int errno;
43:
44: int bbrduid, bbrdgid;
45:
46: char *chnlname,
47: chnlinfo[LINESIZE];
48: #ifndef POP
49: char bbrdaddr[LINESIZE],
50: bbrdfrom[LINESIZE],
51: [LINESIZE],
52: bbrdhome[LINESIZE],
53: bbrdtime[LINESIZE];
54: #endif not POP
55:
56: extern char *qu_msgfile,
57: *delim1,
58: *delim2,
59: *lckdfldir,
60: *locname,
61: *sitesignature,
62: *supportaddr;
63:
64: struct bboard *curbb;
65:
66: extern LLog *logptr;
67:
68: FILE *lk_fopen();
69:
70: long lseek ();
71: char *index (), *rindex (), *sprintf ();
72: struct passwd *getpwnam ();
73:
74: /* */
75:
76: bb_init (chanptr)
77: Chan * chanptr;
78: {
79: int uid,
80: eid;
81: struct passwd *pw;
82:
83: #ifdef DEBUG
84: ll_log (logptr, LLOGBTR, "bb_init(chanptr=%s)", chanptr -> ch_name);
85: #endif
86:
87: chnlname = chanptr -> ch_name;
88: #ifndef notdef
89: sprintf (chnlinfo, submitopts, chnlname);
90: #else notdef /* the following is probably a BAD idea */
91: if (chanptr -> ch_host == NULL)
92: chnlinfo[0] = NULL; /* local delivery ONLY */
93: else
94: sprintf (chnlinfo, submitopts, chanptr -> ch_host);
95: #endif notdef
96:
97: #ifndef POP
98: if ((pw = getpwnam (BBOARDS)) == NULL)
99: err_abrt (RP_BHST, "no passwd entry for '%s'", BBOARDS);
100: #else POP
101: if ((pw = getpwnam (POPUID)) == NULL)
102: err_abrt (RP_BHST, "no passwd entry for '%s'", POPUID);
103: #endif POP
104:
105: bbrduid = pw -> pw_uid;
106: bbrdgid = pw -> pw_gid;
107: #ifndef POP
108: sprintf (bbrdfrom, "%s@%s", pw -> pw_name, locname);
109: #ifdef DEBUG
110: ll_log (logptr, LLOGGEN, "distributing as '%s'", bbrdfrom);
111: #endif
112: sprintf (bbrdhome, pw -> pw_dir);
113: #endif not POP
114:
115: #ifndef POP
116: if (!setbbent ())
117: err_abrt (RP_BHST, "setbbent() failed");
118: #else POP
119: if (!setpwinfo (pw, POPDB, 1))
120: err_abrt (RP_BHST, "setbbinfo(%s, %s, 1) failed",
121: pw -> pw_name, POPDB);
122: #endif POP
123:
124: getwho (&uid, &eid);
125: if (eid != 0)
126: err_abrt (RP_BHST, "not running as root");
127:
128: return RP_OK;
129: }
130:
131:
132: bb_end (result)
133: short result;
134: {
135: #ifdef DEBUG
136: ll_log (logptr, LLOGBTR, "bb_end(result=0%o)", result);
137: #endif
138:
139: return RP_OK;
140: }
141:
142: /* */
143:
144: bb_sbinit () {
145: #ifdef DEBUG
146: ll_log (logptr, LLOGBTR, "bb_sbinit()");
147: #endif
148:
149: return RP_OK;
150: }
151:
152:
153: bb_sbend () {
154: #ifdef DEBUG
155: ll_log (logptr, LLOGBTR, "bb_sbend()");
156: #endif
157:
158: return RP_OK;
159: }
160:
161: /* */
162:
163: bb_winit (info, sender)
164: char *info,
165: *sender;
166: {
167: #ifdef DEBUG
168: ll_log (logptr, LLOGBTR, "bb_winit(info='%s',sender='%s')",
169: info, sender);
170: #endif
171:
172: return RP_OK;
173: }
174:
175: /* */
176:
177: bb_wtadr (host, adr)
178: char *host,
179: *adr;
180: {
181: short count,
182: result;
183: int len,
184: md,
185: offset,
186: size;
187: long start,
188: stop,
189: pos;
190: char *cp,
191: buffer[BUFSIZE];
192:
193: #ifdef DEBUG
194: ll_log (logptr, LLOGBTR, "bb_wtadr(host=%s,adr=%s)", host, adr);
195: #endif
196:
197: if ((cp = index (adr, '@')) != NULL)
198: *cp = NULL;
199: make_lower (adr, adr);
200: if ((curbb = getbbnam (adr)) == NULL)
201: return RP_USER;
202: #ifndef POP
203: sprintf (bbrdaddr, "local-%s-request@%s", curbb -> bb_name, locname);
204: #endif not POP
205: #ifdef DEBUG
206: ll_log (logptr, LLOGGEN, "=> BBoard %s: file='%s' info='%s'",
207: curbb -> bb_name, curbb -> bb_file, curbb -> bb_info);
208: #endif
209:
210: if (curbb -> bb_file == NULL || *curbb -> bb_file == NULL)
211: return RP_NOPE;
212: #ifdef DEBUG
213: ll_log (logptr, LLOGGEN, "begin local delivery...");
214: #endif
215: printx ("\r\nperforming local delivery to file %s...\n",
216: curbb -> bb_file);
217:
218: qu_rtinit (0L);
219:
220: if ((md = mbx_open (curbb -> bb_file, bbrduid, bbrdgid, MBXMODE)) == NOTOK)
221: return RP_FIO;
222:
223: #ifndef POP
224: if (rp_isbad (result = mbx_init ())) {
225: mbx_close (curbb -> bb_file, md);
226: return result;
227: }
228: #endif not POP
229:
230: pos = lseek (md, 0L, 1);
231: count = strlen (delim1);
232: if (write (md, delim1, count) != count) {
233: ll_log (logptr, LLOGTMP, "error writing delim1");
234: result = NOTOK;
235: goto clean_up;
236: }
237: start = lseek (md, 0L, 1);
238: size = 0;
239:
240: #ifndef POP
241: count = strlen (bbrdheader);
242: if (write (md, bbrdheader, count) != count) {
243: ll_log (logptr, LLOGTMP, "error writing BBoard information");
244: result = NOTOK;
245: goto clean_up;
246: }
247: for (cp = bbrdheader; *cp; cp++, size++)
248: if (*cp == '\n')
249: size++;
250: #endif not POP
251:
252: while (rp_gval (result = qu_rtxt (buffer, &len)) == RP_OK) {
253: for (offset = 0;
254: (offset = strindex (delim1, buffer)) >= 0;
255: buffer[offset]++)
256: continue;
257: for (offset = 0;
258: (offset = strindex (delim2, buffer)) >= 0;
259: buffer[offset]++)
260: continue;
261: if (write (md, buffer, len) != len) {
262: ll_log (logptr, LLOGTMP, "error writing to file '%s'",
263: curbb -> bb_file);
264: result = NOTOK;
265: goto clean_up;
266: }
267: for (offset = 0, cp = buffer; offset < len; offset++, size++)
268: if (*cp++ == '\n')
269: size++;
270: }
271:
272: if (result < 0)
273: ll_log (logptr, LLOGTMP, "error reading from message file '%s'",
274: qu_msgfile);
275: clean_up: ;
276:
277: stop = lseek (md, 0L, 1);
278: count = strlen (delim2);
279: if (write (md, delim2, count) != count)
280: ll_log (logptr, LLOGTMP, "error writing delim2");
281: map_write (curbb -> bb_file, md, curbb -> bb_maxima, start, stop, pos,
282: size, 0);
283: #ifdef DEBUG
284: ll_log (logptr, LLOGGEN, "end local delivery...");
285: #endif
286:
287: if (result < 0)
288: mbx_close (curbb -> bb_file, md);
289: else
290: result = mbx_close (curbb -> bb_file, md);
291:
292: return (result != NOTOK ? RP_OK : RP_FIO);
293: }
294:
295: /* */
296:
297: bb_txtcpy () {
298: #ifndef POP
299: short result;
300:
301: #ifdef DEBUG
302: ll_log (logptr, LLOGBTR, "bb_txtcpy()");
303: #endif
304:
305: if (curbb -> bb_dist == NULL
306: || *curbb -> bb_dist == NULL
307: || chnlinfo[0] == NULL)
308: return RP_MOK;
309: #ifdef DEBUG
310: ll_log (logptr, LLOGGEN, "begin distribution...");
311: #endif
312: if (curbb -> bb_file == NULL || *curbb -> bb_file == NULL)
313: printx ("\r\n");
314: printx("\rperforming remote distribution\n");
315:
316: if (rp_isbad (result = dist_init ())
317: || rp_isbad (result = dist_adrs ())
318: || rp_isbad (result = dist_text ())
319: || rp_isbad (result = dist_end ()))
320: return dist_lose (result);
321: #ifdef DEBUG
322: ll_log (logptr, LLOGGEN, "end distribution...");
323: #endif
324:
325: if (err_fd != NOTOK)
326: dist_lose (RP_MOK);
327: else
328: printx ("\rmessage distributed\n");
329: #endif not POP
330:
331: return RP_MOK;
332: }
333:
334: /* */
335:
336: #ifndef POP
337: /* **************** (dist_) BBOARD DISTRIBUTION **************** */
338:
339: dist_init () {
340: short result;
341: #ifdef RP_NS
342: int len;
343: struct rp_bufstruct reply;
344: #endif RP_NS
345:
346: #ifdef DEBUG
347: ll_log (logptr, LLOGBTR, "dist_init()");
348: #endif
349:
350: if (rp_isbad (result = mm_init ()))
351: return ds_log (result, LLOGFAT, "mm_init() failed [%s]",
352: rp_valstr (result));
353: if (rp_isbad (result = mm_sbinit ()))
354: return ds_log (result, LLOGFAT, "mm_sbinit() failed [%s]",
355: rp_valstr (result));
356: if (rp_isbad (result = mm_winit (chnlname, chnlinfo, bbrdaddr)))
357: return ds_log (result, LLOGFAT,
358: "mm_winit('%s','%s','%s') failed [%s]",
359: chnlname, chnlinfo, bbrdaddr, rp_valstr (result));
360: #ifdef RP_NS
361: if (rp_isbad (result = mm_rrply (&reply, &len)))
362: return ds_log (result, LLOGFAT, "problem with sender address [%s]",
363: rp_valstr (result));
364: #endif RP_NS
365:
366: return result;
367: }
368:
369: /* */
370:
371: dist_adrs ()
372: {
373: short result;
374:
375: #ifdef DEBUG
376: ll_log (logptr, LLOGBTR, "dist_adrs()");
377: #endif
378:
379: if (getbbdist (curbb, ds_address))
380: return ds_log (RP_NO, LLOGTMP, "getbbdist failed: %s", getbberr ());
381:
382: if (rp_isbad (result = mm_waend ()))
383: return ds_log (result, LLOGFAT, "mm_waend() failed [%s]",
384: rp_valstr (result));
385:
386: return result;
387: }
388:
389: /* */
390:
391: ds_address (addr, host)
392: char *addr, /* local part */
393: *host; /* rest */
394: {
395: short result;
396: int len;
397: struct rp_bufstruct reply;
398:
399: #ifdef DEBUG
400: ll_log (logptr, LLOGBTR, "ds_address(addr='%s',host='%s')", addr, host);
401: #endif
402:
403: printx ("\rperforming distribution to %s@%s...\n", addr, host);
404: if (rp_isbad (result = mm_wadr (host, addr))) {
405: ds_log (result, LLOGFAT, "mm_wadr('%s','%s') failed [%s]",
406: host, addr, rp_valstr (result));
407: return NOTOK;
408: }
409: if (rp_isbad (result = mm_rrply (&reply, &len))) {
410: ds_log (result, LLOGFAT,
411: "mm_rrply() failed [%s] getting status of '%s@%s'",
412: rp_valstr (result), addr, host);
413: return NOTOK;
414: }
415:
416: switch (rp_gval (reply.rp_val)) {
417: case RP_AOK:
418: #ifdef RP_DOK
419: case RP_DOK:
420: #endif RP_DOK
421: #ifdef DEBUG
422: ll_log (logptr, LLOGGEN, "address '%s@%s' [%s] -- %s",
423: addr, host, rp_valstr (reply.rp_val), reply.rp_line);
424: #endif
425: return OK;
426:
427: case RP_NO:
428: #ifdef RP_NS
429: case RP_NS:
430: #endif RP_NS
431: case RP_USER:
432: case RP_NDEL:
433: case RP_AGN:
434: case RP_NOOP:
435: ds_log (reply.rp_val, LLOGTMP, "address '%s@%s' [%s] -- %s",
436: addr, host, rp_valstr (reply.rp_val), reply.rp_line);
437: return OK; /* fail-soft */
438:
439: default:
440: ds_log (reply.rp_val, LLOGFAT, "unexpected reply [%s] -- %s",
441: rp_valstr (reply.rp_val), reply.rp_line);
442: return NOTOK;
443: }
444: }
445:
446: /* */
447:
448: dist_text ()
449: {
450: short result;
451: int len;
452: char buffer[BUFSIZE];
453:
454: #ifdef DEBUG
455: ll_log (logptr, LLOGBTR, "dist_text()");
456: #endif
457:
458: qu_rtinit (0L);
459: while (rp_gval (result = qu_rtxt (buffer, &len)) == RP_OK)
460: if (rp_isbad (result = mm_wtxt (buffer, len)))
461: return ds_log (result, LLOGFAT, "mm_wtxt() failed [%s]",
462: rp_valstr (result));
463:
464: if (result < 0)
465: return ds_log (RP_FIO, LLOGTMP,
466: "error reading from message file '%s'", qu_msgfile);
467:
468: if (rp_isbad (result = mm_wtend ()))
469: return ds_log (result, LLOGFAT, "mm_wtend() failed [%s]",
470: rp_valstr (result));
471:
472: return result;
473: }
474:
475: /* */
476:
477: dist_end ()
478: {
479: short result;
480: int len;
481: struct rp_bufstruct reply;
482:
483: #ifdef DEBUG
484: ll_log (logptr, LLOGBTR, "dist_end()");
485: #endif
486:
487: if (rp_isbad (result = mm_rrply (&reply, &len)))
488: return ds_log (result, LLOGFAT,
489: "mm_rrply() failed [%s] getting final status",
490: rp_valstr (result));
491:
492: switch (rp_gval (reply.rp_val)) {
493: case RP_OK:
494: case RP_MOK:
495: #ifdef DEBUG
496: ll_log (logptr, LLOGGEN, "message [%s] -- %s",
497: rp_valstr (reply.rp_val), reply.rp_line);
498: #endif
499: mm_sbend ();
500: mm_end (OK);
501: return result;
502:
503: case RP_NO:
504: case RP_NDEL:
505: case RP_AGN:
506: case RP_NOOP:
507: return ds_log (RP_NO, LLOGTMP, "not delivered [%s] -- %s",
508: rp_valstr (reply.rp_val), reply.rp_line);
509:
510: default:
511: return ds_log (RP_RPLY, LLOGFAT,
512: "unexpected final reply [%s] -- %s",
513: rp_valstr (reply.rp_val), reply.rp_line);
514: }
515: }
516:
517: /* */
518:
519: dist_lose (result)
520: short result;
521: {
522: int i;
523: char *cp,
524: intro[BUFSIZ],
525: buffer[BUFSIZ];
526:
527: #ifdef DEBUG
528: ll_log (logptr, LLOGBTR, "dist_lose(result=0%o)", result);
529: #endif DEBUG
530:
531: mm_end (NOTOK);
532:
533: printx ("\rerrors during distribution: ");
534: if (domsg)
535: (void) fflush (stdout);
536: (void) sprintf (intro, "bboards%d distribution for %s failed [%s]\n",
537: getpid (), curbb -> bb_name, rp_valstr (result));
538: if (loseaux (bbrdaddr, bbrdfrom, intro) != OK
539: && loseaux (bbrdfrom, (char *) 0, intro) != OK) {
540: printx ("unable to post advisory.\n");
541: ll_log (logptr, LLOGFAT, "unable to post failure notice");
542: if (err_fd != NOTOK) {
543: (void) lseek (err_fd, 0L, 0);
544: if ((i = read (err_fd, buffer, sizeof buffer)) > 0) {
545: buffer[i] = NULL;
546: if (cp = index (buffer, '\n'))
547: *cp = NULL;
548: ll_log (logptr, LLOGFAT, "info: %s", buffer);
549: }
550: }
551: if (loseaux (supportaddr, (char *) 0, intro) != NOTOK)
552: ll_log (logptr, LLOGFAT, "unable to advise %s of failure!",
553: supportaddr);
554: }
555: else
556: printx ("advisory posted.\n");
557: if (domsg)
558: (void) fflush (stdout);
559:
560: if (err_fd != NOTOK) {
561: close (err_fd);
562: err_fd = NOTOK;
563: }
564: return RP_MOK;
565: }
566:
567: /* */
568:
569: int loseaux (to, cc, intro)
570: char *to,
571: *cc,
572: *intro;
573: {
574: int i;
575: char buffer[BUFSIZ];
576:
577: if (ml_init (NO, NO, sitesignature, "Re-distribution Failure") != OK
578: || ml_adr (to) != OK)
579: return NOTOK;
580: if (cc && (ml_cc () != OK || ml_adr (cc) != OK))
581: return NOTOK;
582: if (ml_aend () != OK || ml_tinit () != OK)
583: return NOTOK;
584:
585: ml_txt (intro);
586: if (err_fd != NOTOK) {
587: lseek (err_fd, 0L, 0);
588: while ((i = read (err_fd, buffer, sizeof buffer)) > 0) {
589: buffer[i] = NULL;
590: ml_txt (buffer);
591: }
592: }
593: encap ();
594:
595: return ml_end (OK);
596: }
597:
598: /* */
599:
600: /* very similar to sbr/cpydgst.c */
601:
602: #define S1 0
603: #define S2 1
604:
605: #define output(c) if (bp >= dp) {flush (); *bp++ = c;} else *bp++ = c
606: #define flush() if (bp - outbuf) \
607: *bp = NULL, ml_txt (outbuf), bp = outbuf
608:
609: static encap () {
610: register int state;
611: short result;
612: int len,
613: init;
614: register char *cp,
615: *ep;
616: char buffer[BUFSIZ];
617: register char *bp,
618: *dp;
619: char outbuf[BUFSIZ];
620:
621: qu_rtinit (0L);
622:
623: dp = (bp = outbuf) + sizeof outbuf;
624: init = 0;
625: for (state = S1; rp_gval (result = qu_rtxt (buffer, &len)) == RP_OK;)
626: for (ep = (cp = buffer) + len; cp < ep; cp++) {
627: if (*cp == NULL)
628: continue;
629: switch (state) {
630: case S1:
631: if (*cp == '-') {
632: if (init == 0) {
633: ml_txt ("\n------- Forwarded Message\n\n");
634: init++;
635: }
636: output ('-');
637: output (' ');
638: }
639: state = S2; /* fall */
640:
641: case S2:
642: if (init == 0) {
643: ml_txt ("\n------- Forwarded Message\n\n");
644: init++;
645: }
646: output (*cp);
647: if (*cp == '\n')
648: state = S1;
649: break;
650: }
651: }
652:
653: flush ();
654:
655: if (result < 0) {
656: ll_log (logptr, LLOGTMP, "error reading message when noting failure");
657: if (init)
658: ml_txt ("\n------- End of Forwarded Message\n\n");
659: ml_txt ("[ error reading message ]\n");
660: }
661: else
662: if (init)
663: ml_txt ("\n------- End of Forwarded Message\n\n");
664: else {
665: ll_log (logptr, LLOGTMP, "message empty when noting failure");
666: ml_txt ("[ message empty ]\n");
667: }
668: }
669:
670: /* */
671:
672: /* VARARGS3 */
673:
674: ds_log (result, level, fmt, a, b, c, d, e)
675: short result;
676: int level;
677: char *fmt,
678: *a,
679: *b,
680: *c,
681: *d,
682: *e;
683: {
684: int i;
685: char buffer[BUFSIZ],
686: tmpfil[BUFSIZ];
687:
688: ll_log (logptr, level, fmt, a, b, c, d, e);
689:
690: sprintf (buffer, fmt, a, b, c, d, e);
691: strcat (buffer, "\n");
692:
693: printx ("\rerror: %s", buffer);
694:
695: if (err_fd == NOTOK) {
696: unlink (mktemp (strcpy (tmpfil, "/tmp/bboardsXXXXXX")));
697: if ((err_fd = creat (tmpfil, 0600)) == NOTOK)
698: return result;
699: close (err_fd);
700: if ((err_fd = open (tmpfil, 2)) == NOTOK)
701: return result;
702: unlink (tmpfil);
703: lseek (err_fd, 0L, 0);
704: }
705: i = strlen (buffer);
706: write (err_fd, buffer, i);
707:
708: return result;
709: }
710: #endif not POP
711:
712: /* */
713:
714: /* mbx_ local mailbox routines */
715:
716: #ifndef POP
717: mbx_init () {
718: int fd,
719: clear;
720: char name[BUFSIZ];
721: FILE * fp;
722:
723: if ((fd = mbx_Xopen (curbb -> bb_info, bbrduid, bbrdgid, MBXMODE, &clear))
724: == NOTOK) {
725: if (errno == ETXTBSY) {
726: printx ("\runable to lock %s\n", curbb -> bb_info);
727: ll_err (logptr, LLOGTMP, "unable to lock %s",
728: curbb -> bb_info);
729: return RP_LOCK;
730: }
731: printx ("\runable to open '%s'", curbb -> bb_info);
732: ll_log (logptr, LLOGTMP, "unable to open '%s'", curbb -> bb_info);
733: return RP_FOPN;
734: }
735: if ((fp = fdopen (fd, "w")) == (FILE *) NULL) {
736: printx ("\runable to fdopen '%s'", curbb -> bb_info);
737: ll_err (logptr, LLOGTMP, "unable to fdopen '%s'", curbb -> bb_info);
738: mbx_close (curbb -> bb_info, fd);
739: return RP_LIO;
740: }
741:
742: strcpy (name, curbb -> bb_name);
743: if ((curbb = getbbnam (name)) == (struct bboard *) NULL) {
744: printx ("\runable to get information on BBoard %s\n", name);
745: ll_err (logptr, LLOGFAT, "unable to get info on %s", name);
746: lkfclose (fp, curbb -> bb_info);
747: return RP_LIO;
748: }
749: sprintf (bbrdheader, "BBoard-ID: %d\nBB-Posted: %s\n",
750: ++curbb -> bb_maxima, cnvtdate (TIMREG, bbrdtime));
751: fprintf (fp, "%d\n%s\n", curbb -> bb_maxima, bbrdtime);
752:
753: lkfclose (fp, curbb -> bb_info);
754:
755: return RP_OK;
756: }
757: #endif not POP