Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / sbboards.c,v
1 head    1.9;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.9
9 date    93.08.25.17.27.54;      author jromine; state Exp;
10 branches;
11 next    1.8;
12
13 1.8
14 date    93.08.20.15.53.49;      author jromine; state Exp;
15 branches;
16 next    1.7;
17
18 1.7
19 date    93.02.26.21.59.44;      author jromine; state Exp;
20 branches;
21 next    1.6;
22
23 1.6
24 date    92.11.24.21.00.41;      author jromine; state Exp;
25 branches;
26 next    1.5;
27
28 1.5
29 date    92.11.04.01.01.28;      author jromine; state Exp;
30 branches;
31 next    1.4;
32
33 1.4
34 date    92.02.03.17.57.22;      author jromine; state Exp;
35 branches;
36 next    1.3;
37
38 1.3
39 date    90.04.05.15.04.02;      author sources; state Exp;
40 branches;
41 next    1.2;
42
43 1.2
44 date    90.04.02.16.35.58;      author sources; state Exp;
45 branches;
46 next    1.1;
47
48 1.1
49 date    90.04.02.16.35.41;      author sources; state Exp;
50 branches;
51 next    ;
52
53
54 desc
55 @@
56
57
58 1.9
59 log
60 @off_t fixes for BSD44
61 @
62 text
63 @#ifndef        SPOP
64 /* sbboards.c - MH style mailer to write to a ZOTnet BBoard */
65 #else   SPOP
66 /* spop.c - MH style mailer to write to a POP subscriber */
67 #endif  SPOP
68 #ifndef lint
69 static char ident[] = "@@(#)$Id: sbboards.c,v 1.8 1993/08/20 15:53:49 jromine Exp jromine $";
70 #endif  lint
71
72 #ifndef SPOP
73
74 /* This program acts like the MMDF ch_bboards channel: it does local
75    delivery to a ZOTnet BBoard and/or addition re-distribution to other
76    recipients of the BBoard.  This program can function both as a SendMail
77    mailer and an MH .mh_receive file, depending on whether SENDMTS or
78    MHMTS is set.  Currently, the MHMTS version of this program does not do
79    re-distribution.
80
81    This program should be used ONLY if you have "bboards on" set in your
82    MH configuration, and if you have "mts sendmail" or "mts mh" set as well.
83  */
84
85 #else   SPOP
86
87 /* This program acts like the MMDF-II ch_pop channel: it does local
88    delivery for non-local users.  These users are known as POP subscribers
89    and use the Post Office Protocol with a POP server in order to access
90    their maildrop.
91  */
92
93 #endif  SPOP
94
95 #undef  DISTRIBUTE
96 #ifdef  SENDMTS
97 #ifndef SPOP
98 #define DISTRIBUTE
99 #endif  not SPOP
100 #endif  SENDMTS
101
102 #include "../h/mh.h"
103 #ifndef SPOP
104 #include "../h/addrsbr.h"
105 #endif  not SPOP
106 #include "../h/dropsbr.h"
107 #include "../zotnet/bboards.h"
108 #include "../zotnet/tws.h"
109 #include <stdio.h>
110 #include "../zotnet/mts.h"
111 #include <pwd.h>
112 #ifndef SYS5
113 #include <sysexits.h>
114 #else   SYS5
115 #define EX_CANTCREAT    1
116 #define EX_IOERR        1
117 #define EX_NOINPUT      1
118 #define EX_NOUSER       1
119 #define EX_OK           0
120 #define EX_OSERR        1
121 #define EX_OSFILE       1
122 #define EX_UNAVAILABLE  1
123 #define EX_USAGE        1
124 #endif  SYS5
125 #ifdef  DISTRIBUTE
126 #include "../mts/sendmail/smail.h"
127 #endif  DISTRIBUTE
128 #ifdef LOCALE
129 #include        <locale.h>
130 #endif
131
132
133 #define NBB     100
134
135 #ifndef SPOP
136 #define ENTITY  "bboard"
137 #else   SPOP
138 #define ENTITY  "subscriber"
139 #endif  SPOP
140
141 /* \f */
142
143 static int  bb_fderr;
144
145 static int  bb_uid;
146 static int  bb_gid;
147
148 static int    dst_rcpt ();
149
150
151 #ifndef SPOP
152 static char bb_from[BUFSIZ];
153 static char bb_head[BUFSIZ];
154 static char bb_home[BUFSIZ];
155 static char bb_time[BUFSIZ];
156 #ifdef  DISTRIBUTE
157 static char bb_rept[BUFSIZ];
158 #endif  DISTRIBUTE
159 #else   SPOP
160 #define bb_head NULLCP
161 #endif  SPOP
162
163 static struct bboard  *bb[NBB];
164
165
166 off_t   lseek ();
167
168 #ifndef __STDC__
169 #ifdef  SYS5
170 struct passwd  *getpwnam ();
171 #endif  /* SYS5 */
172 #endif
173
174 #ifndef SPOP
175 static int      mbx_init();
176 #endif
177 #ifdef  DISTRIBUTE
178 static int      distribute(), notify(), encap(),
179                 dst_init(), dst_text(),
180                 dst_end(), dst_lose(), dst_adrs();
181 #endif
182
183 /* hack */
184 #define adios   my_adios
185 static  localmail(), arginit();
186 static int      lose(), copyfile();
187 static void     adios();
188 /* \f */
189
190 /* ARGSUSED */
191
192 main (argc, argv, envp)
193 int     argc;
194 char  **argv,
195       **envp;
196 {
197     int     fd;
198     char    tmpfil[BUFSIZ];
199
200 #ifdef LOCALE
201         setlocale(LC_ALL, "");
202 #endif
203 #ifdef  MHMTS
204     if (argc != 5)
205         adios (EX_USAGE, NULL, "you lose really big");
206 #endif  MHMTS
207     arginit (argv);
208
209     fflush (stdout);
210     discard (stdout);           /* XXX: reference discard to help loader */
211
212     fd = copyfile (fileno (stdin), tmpfil);
213     (void) unlink (tmpfil);
214
215     localmail (fd);
216 #ifdef  DISTRIBUTE
217     distribute (fd);
218     notify (fd);
219 #endif  DISTRIBUTE
220
221     exit (EX_OK);
222 }
223
224 /* \f */
225
226 static  localmail (fd)
227 int     fd;
228 {
229     int     i,
230             md;
231     register struct bboard  *bp;
232
233     for (i = 0; bp = bb[i]; i++)
234         if (bp -> bb_file && *bp -> bb_file) {
235             (void) lseek (fd, (off_t)0, 0);
236 #ifndef SPOP
237             if ((md = mbx_open (bp -> bb_file, bb_uid, bb_gid, BBMODE))
238 #else   SPOP
239             if ((md = mbx_open (bp -> bb_file, bb_uid, bb_gid, POMODE))
240 #endif  SPOP
241                     == NOTOK) {
242                 (void) lose ("unable to open %s", bp -> bb_file);
243                 continue;
244             }
245 #ifndef SPOP
246             if (mbx_init (bp) != NOTOK)
247 #endif  not SPOP
248                 (void) mbx_copy (bp -> bb_file, md, fd, 1, bb_head, 0);
249             (void) mbx_close (bp -> bb_file, md);
250         }
251 }
252
253 /* \f */
254
255 #ifndef SPOP
256 static int  mbx_init (bp)
257 register struct bboard  *bp;
258 {
259     int     fd,
260             clear;
261     register struct bboard  *ip;
262     register FILE *fp;
263
264     if ((fd = mbx_Xopen (bp -> bb_info, bb_uid, bb_gid, BBMODE, &clear))
265             == NOTOK)
266         return lose ("unable to lock and open %s", bp -> bb_info);
267     if ((fp = fdopen (fd, "w")) == NULL) {
268         (void) mbx_close (bp -> bb_info, fd);
269         return lose ("unable to fdopen %s", bp -> bb_info);
270     }
271
272     if ((ip = getbbnam (bp -> bb_name)) == NULL) {
273         (void) lkfclose (fp, bp -> bb_info);
274         return lose ("unable to get information on BBoard %s", bp -> bb_name);
275     }
276     (void) strcpy (bb_time, dtimenow ());
277     (void) sprintf (bb_head, "BBoard-ID: %d\nBB-Posted: %s\n",
278             bp -> bb_maxima = ++ip -> bb_maxima, bb_time);
279
280     fprintf (fp, "%d\n%s\n", bp -> bb_maxima, bb_time);
281     (void) lkfclose (fp, bp -> bb_info);
282
283     return OK;
284 }
285 #endif  not SPOP
286
287 /* \f */
288
289 #ifdef  DISTRIBUTE
290 static  distribute (fd)
291 int     fd;
292 {
293     int     i;
294     register struct bboard  *bp;
295
296     for (i = 0; bp = bb[i]; i++)
297         if (bp -> bb_dist && *bp -> bb_dist)
298             break;
299     if (bp == NULL)
300         return;
301
302     if (dst_init () == NOTOK) {
303         dst_lose ();
304         return;
305     }
306     for (i = 0; bp = bb[i]; i++)
307         if (bp -> bb_dist && *bp -> bb_dist)
308             if (dst_adrs (bp) == NOTOK) {
309                 dst_lose ();
310                 return;
311             }
312     if (dst_text (fd) == NOTOK || dst_end () == NOTOK)
313         dst_lose ();
314 }
315
316 /* \f */
317
318 static int  dst_init ()
319 {
320     int     retval;
321
322     if (rp_isbad (retval = sm_init (NULLCP, NULLCP, 0, 0, 0, 0, 0))
323             || rp_isbad (retval = sm_winit (S_MAIL, bb_from)))
324         return lose ("problem initializing SendMail; %s",
325                 rp_string (retval));
326
327     return OK;
328 }
329
330 /* \f */
331
332 static int  dst_adrs (bp)
333 register struct bboard  *bp;
334 {
335     if (getbbdist (bp, dst_rcpt))
336         return lose ("getbbdist failed: %s", getbberr ());
337
338     return OK;
339 }
340
341 /* \f */
342
343 static int  dst_rcpt (mbox, host)
344 register char   *mbox,
345                 *host;
346 {
347     int     retval;
348
349     switch (retval = sm_wadr (mbox, host, NULLCP)) {
350         case RP_OK:
351             return OK;
352
353         case RP_NO:
354         case RP_USER:
355             (void) lose ("%s@@%s: loses; %s", mbox, host, rp_string (retval));
356             return OK;          /* fail-soft */
357
358         default:
359             return lose ("%s@@%s: unexpected response; %s",
360                     mbox, host, rp_string (retval));
361     }
362 }
363
364 /* \f */
365
366 static int  dst_text (fd)
367 int     fd;
368 {
369     int     i,
370             retval;
371     char    buffer[BUFSIZ];
372
373     if (rp_isbad (retval = sm_waend ()))
374         return lose ("problem ending addresses; %s", rp_string (retval));
375
376     (void) lseek (fd, (off_t)0, 0);
377     while ((i = read (fd, buffer, sizeof buffer)) > 0)
378         if (rp_isbad (retval = sm_wtxt (buffer, i)))
379             return lose ("problem writing text; %s", rp_string (retval));
380
381     return (i != NOTOK ? OK : lose ("error reading from file"));
382 }
383
384 /* \f */
385
386 static int  dst_end ()
387 {
388     int     retval;
389
390     switch (retval = sm_wtend ()) {
391         case RP_OK:
392             (void) sm_end (OK);
393             return OK;
394
395         case RP_NO:
396         case RP_NDEL:
397             return lose ("posting failed; %s", rp_string (retval));
398
399         default:
400             return lose ("unexpected response; %s", rp_string (retval));
401     }
402 }
403
404 /* \f */
405
406 static  dst_lose ()
407 {
408     (void) sm_end (NOTOK);
409 }
410
411 /* \f */
412
413 /* VARARGS1 */
414
415 static int  lose (fmt, a, b, c, d)
416 char   *fmt,
417        *a,
418        *b,
419        *c,
420        *d;
421 {
422     int     fd,
423             i;
424     char   *bp,
425             buffer[BUFSIZ];
426
427     if (bb_fderr == NOTOK) {
428         if ((fd = open ("/dev/null", 0)) == NOTOK)
429             adios (EX_OSERR, "/dev/null", "unable to open");
430         bb_fderr = copyfile (fd, bb_rept);
431     }
432
433     (void) sprintf (bp = buffer, fmt, a, b, c, d);
434     bp += strlen (bp);
435     bp += strlen (strcpy(bp, "\n"));
436     i = bp - buffer;
437     if (write (bb_fderr, buffer, i) != i)
438         adios (EX_IOERR, bb_rept, "error writing");
439
440     return NOTOK;
441 }
442
443 /* \f */
444
445 static  notify (fd)
446 int     fd;
447 {
448     int     i;
449     char    buffer[BUFSIZ];
450
451     if (bb_fderr == NOTOK)
452         return;
453
454     if (rp_isbad (sm_init (NULLCP, NULLCP, 0, 0, 0, 0, 0))
455             || rp_isbad (sm_winit (S_MAIL, bb_from)))
456         goto sm_err;
457
458     switch (sm_wadr (bb_from, NULLCP, NULLCP)) {
459         case RP_OK:
460             for (i = 0; bb[i]; i++) {
461                 (void) sprintf (buffer, "local-%s-request", bb[i] -> bb_name);
462                 (void) sm_wadr (buffer, LocalName (), NULLCP);
463             }
464             break;
465
466         default:
467             goto sm_err;
468     }
469
470     if (rp_isbad (sm_waend ()))
471         goto sm_err;
472
473     (void) sprintf (buffer,
474             "Date: %s\nFrom: %s\nTo: %s\nSubject: BBoards Failure\n\n",
475             dtimenow (), bb_from, bb_from);
476     if (rp_isbad (sm_wtxt (buffer, strlen (buffer))))
477         goto sm_err;
478
479     for (i = 0; bb[i]; i++) {
480         (void) sprintf (buffer, "BBoard %s\n", bb[i] -> bb_name);
481         if (rp_isbad (sm_wtxt (buffer, strlen (buffer))))
482             goto sm_err;
483     }
484
485     (void) lseek (bb_fderr, (off_t)0, 0);
486     while ((i = read (bb_fderr, buffer, sizeof buffer)) > 0)
487         if (rp_isbad (sm_wtxt (buffer, i)))
488             goto sm_err;
489
490     (void) strcpy (buffer, "\n------- Forwarded Message\n\n");
491     if (rp_isbad (sm_wtxt (buffer, strlen (buffer))) || encap (fd) == NOTOK)
492         goto sm_err;
493     (void) strcpy (buffer, "\n------- End of Forwarded Message\n\n");
494     if (rp_isbad (sm_wtxt (buffer, strlen (buffer))))
495         goto sm_err;
496
497     switch (sm_wtend ()) {
498         case RP_OK:
499             (void) unlink (bb_rept);
500             (void) sm_end (OK);
501             return;
502
503         default:
504     sm_err: ;
505             adios (EX_UNAVAILABLE, NULLCP,
506                     "failed and unable to post advisory, see %s for details",
507                     bb_rept);
508     }
509 }
510
511 /* \f */
512
513 /* very similar to sbr/cpydgst.c */
514
515 #define S1      0
516 #define S2      1
517
518 #define output(c)       if (bp >= dp) flush (), *bp++ = c; else *bp++ = c
519 #define flush()         if ((j = bp - outbuf) \
520                                 && rp_isbad (sm_wtxt (outbuf, j))) \
521                             return NOTOK; \
522                         else \
523                             bp = outbuf
524
525 static int  encap (fd)
526 register int    fd;
527 {
528     register int    i,
529                     state;
530     register char  *cp,
531                    *ep;
532     char    buffer[BUFSIZ];
533     register int    j;
534     register char  *bp,
535                    *dp;
536     char    outbuf[BUFSIZ];
537
538     (void) lseek (fd, (off_t)0, 0);
539
540     dp = (bp = outbuf) + sizeof outbuf;
541     for (state = S1; (i = read (fd, buffer, sizeof buffer)) > 0;)
542         for (ep = (cp = buffer) + i; cp < ep; cp++) {
543             if (*cp == NULL)
544                 continue;
545             switch (state) {
546                 case S1: 
547                     if (*cp == '-') {
548                         output ('-');
549                         output (' ');
550                     }
551                     state = S2; /* fall */
552
553                 case S2: 
554                     output (*cp);
555                     if (*cp == '\n')
556                         state = S1;
557                     break;
558             }
559         }
560
561     if (i == NOTOK)
562         return NOTOK;
563     flush ();
564
565     return OK;
566 }
567 #endif  DISTRIBUTE
568
569 /* \f */
570
571 #ifndef DISTRIBUTE
572 /* VARARGS1 */
573
574 static int  lose (fmt, a, b, c, d)
575 char   *fmt,
576        *a,
577        *b,
578        *c,
579        *d;
580 {
581     adios (EX_UNAVAILABLE, NULLCP, fmt, a, b, c, d);/* NOTREACHED */
582 }
583 #endif  not DISTRIBUTE
584
585 /* \f */
586
587 static  arginit (vec)
588 register char  **vec;
589 {
590     register int    i;
591 #ifdef  MHMTS
592     register char  *ap;
593 #endif  MHMTS
594     char    addr[BUFSIZ];
595     register struct bboard *bp;
596     register struct passwd *pw;
597
598     invo_name = r1bindex (*vec++, '/');
599     m_foil (NULLCP);
600     mts_init (invo_name);
601
602 #ifndef SPOP
603     if ((pw = getpwnam (BBOARDS)) == NULL)
604         adios (EX_OSFILE, NULLCP, "no entry for ~%s", BBOARDS);
605 #else   SPOP
606     if ((pw = getpwnam (POPUID)) == NULL || !setpwinfo (pw, POPDB, 1))
607         adios (EX_OSFILE, NULLCP, "%s", pw ? getbberr () : "POP user-id unknown");
608 #endif  SPOP
609
610     if (pw -> pw_uid != geteuid ())
611 #ifndef SPOP
612     adios (EX_OSERR, NULLCP, "not running setuid to %s", BBOARDS);
613 #else   SPOP
614     adios (EX_OSERR, NULLCP, "not running setuid to %s", POPUID);
615 #endif  SPOP
616
617     bb_uid = pw -> pw_uid;
618     bb_gid = pw -> pw_gid;
619 #ifndef SPOP
620     (void) strcpy (bb_from, adrsprintf (pw -> pw_name, LocalName ()));
621     (void) strcpy (bb_home, pw -> pw_dir);
622 #endif  not SPOP
623
624 #ifdef  MHMTS
625     vec += 3;
626 #endif  MHMTS
627     if (*vec == NULL)
628         adios (EX_USAGE, NULLCP, "usage: %s %s [%s ...]",
629                 invo_name, ENTITY, ENTITY);
630
631     for (i = 0; *vec; vec++) {
632 #ifdef  MHMTS
633         if (ap = index (*vec, '.'))
634             *vec = ++ap;
635 #endif  MHMTS
636         make_lower (addr, *vec);
637
638         if ((bp = getbbnam (addr)) == NULL
639                 && (bp = getbbaka (addr)) == NULL)
640             adios (EX_NOUSER, NULLCP, "no such %s as %s", ENTITY, *vec);
641         if ((bb[i++] = getbbcpy (bp)) == NULL)
642             adios (EX_UNAVAILABLE, NULLCP, "insufficient memory on %s", *vec);
643
644         if (i >= NBB - 1)
645             adios (EX_USAGE, NULLCP, "too many %ss, starting with %s",
646                     ENTITY, *vec);
647     }
648     bb[i] = NULL;
649
650     (void) umask (0022);
651
652     bb_fderr = NOTOK;
653 }
654
655 /* \f */
656
657 static int  copyfile (qd, tmpfil)
658 int     qd;
659 register char   *tmpfil;
660 {
661     int     i,
662             fd;
663     char    buffer[BUFSIZ];
664
665     (void) strcpy (tmpfil, m_tmpfil (invo_name));
666     if ((fd = creat (tmpfil, 0600)) == NOTOK)
667         adios (EX_CANTCREAT, tmpfil, "unable to create");
668     (void) close (fd);
669     if ((fd = open (tmpfil, 2)) == NOTOK)
670         adios (EX_NOINPUT, tmpfil, "unable to re-open");
671
672     (void) lseek (qd, (off_t)0, 0);
673     while ((i = read (qd, buffer, sizeof buffer)) > 0)
674         if (write (fd, buffer, i) != i)
675             adios (EX_IOERR, tmpfil, "error writing");
676     if (i == NOTOK)
677         adios (EX_IOERR, "input", "error reading");
678
679     (void) lseek (fd, (off_t)0, 0);
680
681     return fd;
682 }
683
684 /* \f */
685
686 /* VARARGS3 */
687
688 #ifdef  MHMTS
689 /* ARGSUSED */
690 #endif  MHMTS
691
692 static  void adios (code, what, fmt, a, b, c, d, e, f)
693 int     code;
694 char   *what,
695        *fmt,
696        *a,
697        *b,
698        *c,
699        *d,
700        *e,
701        *f;
702 {
703     advise (what, fmt, a, b, c, d, e, f);
704 #ifdef  SENDMTS
705     done (code);
706 #endif  SENDMTS
707 #ifdef  MHMTS
708     done (1);
709 #endif  MHMTS
710 }
711 @
712
713
714 1.8
715 log
716 @fixup for onex/queued interface
717 @
718 text
719 @d7 1
720 a7 1
721 static char ident[] = "@@(#)$Id: sbboards.c,v 1.7 1993/02/26 21:59:44 jromine Exp jromine $";
722 d104 1
723 a104 1
724 long    lseek ();
725 d173 1
726 a173 1
727             (void) lseek (fd, 0L, 0);
728 d314 1
729 a314 1
730     (void) lseek (fd, 0L, 0);
731 d423 1
732 a423 1
733     (void) lseek (bb_fderr, 0L, 0);
734 d476 1
735 a476 1
736     (void) lseek (fd, 0L, 0);
737 d610 1
738 a610 1
739     (void) lseek (qd, 0L, 0);
740 d617 1
741 a617 1
742     (void) lseek (fd, 0L, 0);
743 @
744
745
746 1.7
747 log
748 @BSD44
749 @
750 text
751 @d7 1
752 a7 1
753 static char ident[] = "@@(#)$Id: sbboards.c,v 1.6 1992/11/24 21:00:41 jromine Exp jromine $";
754 d260 1
755 a260 1
756     if (rp_isbad (retval = sm_init (NULLCP, NULLCP, 0, 0, 0))
757 d392 1
758 a392 1
759     if (rp_isbad (sm_init (NULLCP, NULLCP, 0, 0, 0))
760 @
761
762
763 1.6
764 log
765 @fix decl
766 @
767 text
768 @d7 1
769 a7 1
770 static char ident[] = "@@(#)$Id: sbboards.c,v 1.5 1992/11/04 01:01:28 jromine Exp jromine $";
771 d110 9
772 @
773
774
775 1.5
776 log
777 @LOCALE
778 @
779 text
780 @d7 1
781 a7 1
782 static char ident[] = "@@(#)$Id: sbboards.c,v 1.4 1992/02/03 17:57:22 jromine Exp jromine $";
783 d86 1
784 a86 1
785 int    dst_rcpt ();
786 @
787
788
789 1.4
790 log
791 @STDC/SYS5/getpw
792 @
793 text
794 @d7 1
795 a7 1
796 static char ident[] = "@@(#)$Id: sbboards.c,v 1.3 1990/04/05 15:04:02 sources Exp jromine $";
797 d66 3
798 d129 3
799 @
800
801
802 1.3
803 log
804 @add ID
805 @
806 text
807 @d7 1
808 a7 1
809 static char ident[] = "@@(#)$Id:$";
810 d103 1
811 d106 2
812 a107 1
813 #endif  SYS5
814 @
815
816
817 1.2
818 log
819 @fix
820 @
821 text
822 @d6 3
823 @
824
825
826 1.1
827 log
828 @Initial revision
829 @
830 text
831 @d104 5
832 @