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