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