]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/bbc.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / bbc.c
1 /* bbc.c - ZOTnet BBoard checker */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: bbc.c,v 2.13 1993/02/26 21:58:57 jromine Exp $";
4 #endif lint
5
6 #include "../h/mh.h"
7 #include "../zotnet/bboards.h"
8 #include <stdio.h>
9 #ifdef BPOP
10 #include "../zotnet/mts.h"
11 #endif BPOP
12 #include <errno.h>
13 #include <signal.h>
14 #ifndef sigmask
15 #define sigmask(s) (1 << ((s) - 1))
16 #endif not sigmask
17 #ifdef ridge
18 #undef SIGTSTP
19 #endif ridge
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #ifdef SIGTSTP
23 #include <sys/wait.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26 #endif SIGTSTP
27 #ifdef LOCALE
28 #include <locale.h>
29 #endif
30
31 #define RCFILE ".bbrc"
32
33 #define NBB 100
34
35 /* \f */
36
37 static struct swit switches[] = {
38 #define TOPICSW 0
39 "topics", 6,
40 #define CHECKSW 1
41 "check", 5,
42 #define READSW 2
43 "read", 4,
44
45 #define QUIETSW 3
46 "quiet", 4,
47 #define VERBOSW 4
48 "verbose", 4,
49
50 #define ARCHSW 5
51 "archive", 4,
52 #define NOARCH 6
53 "noarchive", 3,
54
55 #define PROTSW 7
56 "protocol", 4,
57 #define NPROTSW 8
58 "noprotocol", 3,
59
60 #define PROGSW 9
61 "mshproc program", 4,
62
63 #define RCSW 10
64 "rcfile rcfile", 4,
65 #define NRCSW 11
66 "norcfile", 3,
67
68 #define FILESW 12
69 "file BBoardsfile", 4,
70 #define USERSW 13
71 "user BBoardsuser",
72 #ifndef NNTP
73 4,
74 #else NNTP
75 -4,
76 #endif NNTP
77
78 #define HOSTSW 14
79 "host host",
80 #ifndef BPOP
81 -4,
82 #else BPOP
83 4,
84 #endif BPOP
85 #define RPOPSW 15
86 "rpop",
87 #ifndef RPOP
88 -4,
89 #else RPOP
90 4,
91 #endif RPOP
92 #define NRPOPSW 16
93 "norpop",
94 #ifndef RPOP
95 -6,
96 #else RPOP
97 6,
98 #endif RPOP
99
100 #define HELPSW 17
101 "help", 4,
102
103 NULL, NULL
104 };
105
106 struct bbcount {
107 char *key;
108 int count;
109 struct bbcount *left;
110 struct bbcount *right;
111 };
112
113 /* \f */
114
115 extern int errno;
116
117 static int changed = 0;
118 static int oops = 0;
119 static int quitting = 0;
120
121 static int archivesw = 0;
122 static int checksw = 0;
123 static int protsw = 1;
124 static int quietsw = 0;
125 static int readsw = 0;
126 static int topicsw = 0;
127 static int verbosw = 0;
128
129 static int didpop = OK;
130 static int rpop = 1;
131 static char *user = BBOARDS;
132 static char *host = NULL;
133 #ifdef BPOP
134 extern char response[];
135
136 extern char *getusr ();
137 static char **getip ();
138 #endif BPOP
139
140 TYPESIG sigser (), hupser ();
141 int action ();
142 #ifdef SIGTSTP
143 int tstpid;
144 static TYPESIG tstpser ();
145 #endif SIGTSTP
146
147 static char *rcfile=NULL;
148
149
150 static struct bbcount *bbc = NULL;
151 static struct bboard *bbl = NULL;
152
153 struct bbcount *add_count (), *seek_count ();
154 struct bboard *getbbaux (), *getbbvis ();
155 static void bbreset();
156
157 #ifdef UCL
158 extern char *bbs[];
159 extern int called_bbc;
160 static int bbp;
161 #endif UCL
162 /* \f */
163
164 /* ARGSUSED */
165
166 main (argc, argv)
167 int argc;
168 char **argv;
169 {
170 #ifndef UCL
171 int bbp = 0,
172 vecp = 1;
173 #else UCL
174 int vecp = 1;
175 #endif UCL
176 char *cp,
177 *rc=NULL,
178 **ap,
179 **argp,
180 buffer[80],
181 *arguments[MAXARGS],
182 #ifndef UCL
183 *bbs[NBB + 1],
184 #endif UCL
185 *vec[MAXARGS];
186 #ifdef UCL
187 called_bbc = 1;
188 bbp = 0;
189 #endif UCL
190
191 #ifdef LOCALE
192 setlocale(LC_ALL, "");
193 #endif
194 invo_name = r1bindex (argv[0], '/');
195 #ifdef BPOP
196 mts_init (invo_name);
197 if (popbbhost && *popbbhost)
198 host = popbbhost;
199 if (popbbuser && *popbbuser)
200 user = popbbuser, rpop = 0;
201 #endif BPOP
202 if ((cp = m_find (invo_name)) != NULL) {
203 ap = brkstring (cp = getcpy (cp), " ", "\n");
204 ap = copyip (ap, arguments);
205 }
206 else
207 ap = arguments;
208 (void) copyip (argv + 1, ap);
209 argp = arguments;
210
211 (void) setbbent (SB_STAY);
212
213 /* \f */
214
215 while (cp = *argp++) {
216 if (*cp == '-')
217 switch (smatch (++cp, switches)) {
218 case AMBIGSW:
219 ambigsw (cp, switches);
220 done (1);
221 case UNKWNSW:
222 vec[vecp++] = --cp;
223 continue;
224 case HELPSW:
225 (void) sprintf (buffer,
226 "%s [bboards ...] [switches] [switches for mshproc]",
227 invo_name);
228 help (buffer, switches);
229 done (1);
230
231 case TOPICSW:
232 topicsw++;
233 checksw = readsw = 0;
234 continue;
235 case CHECKSW:
236 checksw++;
237 readsw = topicsw = 0;
238 continue;
239 case READSW:
240 readsw++;
241 checksw = topicsw = 0;
242 continue;
243
244 case ARCHSW:
245 archivesw++;
246 continue;
247 case NOARCH:
248 archivesw = 0;
249 continue;
250
251 case PROTSW:
252 protsw++;
253 continue;
254 case NPROTSW:
255 protsw = 0;
256 continue;
257
258 case QUIETSW:
259 quietsw++;
260 verbosw = 0;
261 continue;
262 case VERBOSW:
263 verbosw++;
264 quietsw = 0;
265 continue;
266
267 case PROGSW:
268 if (!(mshproc = *argp++) || *mshproc == '-')
269 adios (NULLCP, "missing argument to %s", argp[-2]);
270 continue;
271
272 case RCSW:
273 if (!(rc = *argp++) || *rc == '-')
274 adios (NULLCP, "missing argument to %s", argp[-2]);
275 continue;
276 case NRCSW:
277 rc = NULL;
278 continue;
279
280 case FILESW:
281 if (!(cp = *argp++) || *cp == '-')
282 adios (NULLCP, "missing argument to %s", argp[-2]);
283 if (!setbbinfo (user, cp, 1))
284 adios (NULLCP, "setbbinfo(%s, %s, 1) failed -- %s",
285 user, cp, getbberr ());
286 continue;
287 case USERSW:
288 if (!(user = *argp++) || *user == '-')
289 adios (NULLCP, "missing argument to %s", argp[-2]);
290 continue;
291
292 case HOSTSW:
293 if (!(host = *argp++) || *host == '-')
294 adios (NULLCP, "missing argument to %s", argp[-2]);
295 didpop = NOTOK;
296 continue;
297 case RPOPSW:
298 rpop++;
299 continue;
300 case NRPOPSW:
301 rpop = 0;
302 continue;
303 }
304 if (bbp < NBB)
305 bbs[bbp++] = cp;
306 else
307 adios (NULLCP, "too many bboards, starting with %s", cp);
308 }
309 bbs[bbp] = NULL;
310
311 /* \f */
312
313 #ifdef BPOP
314 if (host && !*host)
315 host = NULL, didpop = OK;
316 if (!host || !rpop)
317 (void) setuid (getuid ());
318 #endif BPOP
319
320 if (!m_find ("path"))
321 free (path ("./", TFOLDER));
322
323 rcinit (rc);
324
325 for (bbp = 0; cp = bbs[bbp]; bbp++)
326 add_bb (cp, NOTOK);
327
328 #ifdef UCL
329 if (topicsw) {
330 called_bbc = 0;
331 topics ();
332 }
333 #else
334 if (topicsw)
335 topics ();
336 #endif
337 else {
338 default_bboards ();
339 if (checksw)
340 check ();
341 else
342 process (vecp, vec);
343 }
344
345 #ifdef BPOP
346 if (didpop != OK && pop_quit () == NOTOK)
347 adios (NULLCP, "%s", response);
348 #endif BPOP
349
350 done (0);
351 }
352
353 /* \f */
354
355 topics () {
356 register char *cp,
357 **ap;
358 register struct bboard *bb;
359
360 printf ("%16s %s %s\n", "BBoard", "Items",
361 verbosw ? "Interesting Facts" : "Last Update");
362 printf ("%16s %s %s\n", "------", "-----",
363 verbosw ? "-----------------" : "-----------");
364
365 for (bb = bbl ? bbl : getbbvis ();
366 bb;
367 bb = bbl ? bb -> bb_link : getbbvis ()) {
368 printf ("%16s %5d %s\n",
369 bb -> bb_name, bb -> bb_maxima,
370 bb -> bb_date ? bb -> bb_date : "no deliveries");
371 if (verbosw) {
372 if (*bb -> bb_aka) {
373 cp = NULL;
374 for (ap = bb -> bb_aka; *ap; ap++)
375 cp = add (*ap, cp ? add (", ", cp) : cp);
376 printv ("AKA", cp);
377 free (cp);
378 }
379
380 printv ("Leaders", *bb -> bb_leader);
381 for (ap = bb -> bb_leader + 1; *ap; ap++)
382 printv (NULLCP, *ap);
383 printv ("File", bb -> bb_file);
384 printv ("Archive", bb -> bb_archive);
385 printv ("Info", bb -> bb_info);
386 printv ("Map", bb -> bb_map);
387 printv ("Password", bb -> bb_passwd);
388 if (strcmp (bb -> bb_name, bb -> bb_addr))
389 printv ("Address", bb -> bb_addr);
390 if (strcmp (*bb -> bb_leader, bb -> bb_request))
391 printv ("Request", bb -> bb_request);
392 if (*bb -> bb_relay)
393 printv ("Relay", bb -> bb_relay);
394 if (*bb -> bb_dist) {
395 changed = 0;
396 (void) getbbdist (bb, action);
397 if (!changed)
398 printv ("Dist", "");
399 if (cp = getbberr ())
400 printv ("Error", cp);
401 }
402 printb (bb -> bb_flags & ~BB_SEEN);
403 }
404 }
405 }
406
407 /* \f */
408
409 printv (key, value)
410 register char *key,
411 *value;
412 {
413 char buffer[BUFSIZ];
414
415 if (key)
416 (void) sprintf (buffer, "%s: ", key);
417 else
418 buffer[0] = '\0';
419 printf ("%*s%-*s", 25, "", 10, buffer);
420 if (value && *value)
421 printf ("%s", value);
422 (void) putchar ('\n');
423 }
424
425
426 int action (local, domain)
427 register char *local,
428 *domain;
429 {
430 char buffer[BUFSIZ];
431
432 (void) sprintf (buffer, "%s@%s", local, domain);
433 printv (changed++ ? NULL : "Dist", buffer);
434 return 0;
435 }
436
437
438 printb (flags)
439 unsigned int flags;
440 {
441 char buffer[BUFSIZ];
442
443 printv ("Flags", sprintb (buffer, flags, BBITS));
444 }
445
446 /* \f */
447
448 check () {
449 #define grammar(a,b,c) (a == 1 ? b : c)
450 #define plural(d) grammar(d, "", "s")
451
452 int diff;
453 register struct bboard *bb;
454
455 for (bb = bbl; bb; bb = bb -> bb_link) {
456 diff = bb -> bb_maxima - bb -> bb_count;
457 if (quietsw) {
458 if (diff > 0)
459 printf ("%s -- %d item%s unseen\n",
460 bb -> bb_name, diff, plural (diff));
461 }
462 else
463 if (bb -> bb_maxima == 0)
464 printf ("%s -- empty\n", bb -> bb_name);
465 else
466 if (bb -> bb_count == 0)
467 printf ("%s -- %d item%sseen)\n",
468 bb -> bb_name, bb -> bb_maxima,
469 grammar (bb -> bb_maxima, " (un", "s (none "));
470 else
471 if (diff <= 0)
472 printf ("%s -- %d item%s (all seen)\n",
473 bb -> bb_name, bb -> bb_maxima,
474 plural (bb -> bb_maxima));
475 else
476 printf ("%s -- %d item%s unseen\n",
477 bb -> bb_name, diff, plural (diff));
478 }
479 }
480
481 /* \f */
482
483 process (vecp, vec)
484 int vecp;
485 char *vec[];
486 {
487 int diff;
488 #ifdef SIGTSTP
489 TYPESIG (*tstat) ();
490 #endif SIGTSTP
491 register struct bboard *bb;
492
493 vec[0] = r1bindex (mshproc, '/');
494 #ifdef SIGTSTP
495 tstat = signal (SIGTSTP, tstpser);
496 #endif SIGTSTP
497
498 for (bb = bbl; bb && !quitting; bb = bb -> bb_link) {
499 diff = bb -> bb_maxima - bb -> bb_count;
500 if (bb -> bb_maxima == 0) {
501 if (!quietsw)
502 printf ("%s -- empty\n", bb -> bb_name);
503 continue;
504 }
505 else {
506 if (diff < 0) {
507 printf (
508 "Oops! looks like someone reset %s -- assuming all unseen\n",
509 bb -> bb_name);
510 diff = bb -> bb_maxima;
511 bbreset (bb, 0);
512 }
513 if (verbosw || archivesw || diff > 0)
514 bbread (bb, vecp, vec);
515 else
516 if (!quietsw)
517 printf ("%s -- %d item%s (all seen)\n",
518 bb -> bb_name, bb -> bb_maxima,
519 plural (bb -> bb_maxima));
520 }
521 };
522
523 #ifdef SIGTSTP
524 (void) signal (SIGTSTP, tstat);
525 #endif SIGTSTP
526 rcend ();
527 }
528
529 /* \f */
530
531 #ifdef BPOP
532 /* ARGSUSED */
533
534 static int xtnd1 (s)
535 char *s;
536 {
537 return OK;
538 }
539 #endif BPOP
540
541 /* \f */
542
543 bbread (bb, vecp, vec)
544 register struct bboard *bb;
545 int vecp;
546 char *vec[];
547 {
548 int child_id,
549 pd[2];
550 char buf1[BUFSIZ],
551 buf2[BUFSIZ],
552 buf3[BUFSIZ];
553 #ifdef BPOP
554 int nmsgs,
555 nbytes;
556 char buf4[BUFSIZ],
557 buf5[BUFSIZ];
558 #endif BPOP
559 struct stat st;
560
561 #ifdef BPOP
562 if (bb -> bb_flags & BB_REMOTE) {
563 if (pop_xtnd (xtnd1, "%s %s", archivesw ? "archive" : "bboards",
564 bb -> bb_name) == NOTOK) {
565 advise (NULLCP, "%s", response);
566 return;
567 }
568 if (pop_stat (&nmsgs, &nbytes) == NOTOK)
569 adios (NULLCP, "%s", response);
570 if (nmsgs == 0) {
571 if (verbosw)
572 printf ("%s -- empty\n", bb -> bb_name);
573 return;
574 }
575 if (pop_fd (buf4, buf5) == NOTOK)
576 adios (NULLCP, "%s", response);
577 }
578 else
579 #endif BPOP
580 if (stat (archivesw ? bb -> bb_archive : bb -> bb_file, &st) != NOTOK
581 && st.st_size == 0)
582 return;
583
584 if (protsw) {
585 if (pipe (pd) == NOTOK)
586 adios ("pipe", "unable to");
587 (void) sprintf (buf3, "%d", getpid ());
588 }
589
590 switch (child_id = fork ()) {
591 case NOTOK:
592 adios ("fork", "unable to");
593
594 case OK:
595 if (protsw) {
596 (void) close (pd[0]);
597 (void) sprintf (buf1, "%d", bb -> bb_count + 1);
598 (void) sprintf (buf2, "%d", pd[1]);
599 vec[vecp++] = "-idname";
600 vec[vecp++] = bb -> bb_name;
601 vec[vecp++] = "-idstart";
602 vec[vecp++] = buf1;
603 vec[vecp++] = "-idstop";
604 vec[vecp++] = buf2;
605 vec[vecp++] = "-idquit";
606 vec[vecp++] = buf3;
607 }
608 #ifdef BPOP
609 if (bb -> bb_flags & BB_REMOTE) {
610 vec[vecp++] = "-popread";
611 vec[vecp++] = buf4;
612 vec[vecp++] = "-popwrite";
613 vec[vecp++] = buf5;
614 }
615 #endif BPOP
616 vec[vecp++] = archivesw ? bb -> bb_archive : bb -> bb_file;
617 vec[vecp] = NULL;
618 execvp (mshproc, vec);
619 fprintf (stderr, "unable to exec ");
620 perror (mshproc);
621 _exit (-1);
622
623 default:
624 #ifdef SIGTSTP
625 tstpid = child_id;
626 #endif SIGTSTP
627 if (protsw) {
628 (void) close (pd[1]);
629 pgmread (pd[0], child_id, bb);
630 }
631 else
632 (void) pidXwait (child_id, mshproc);
633 }
634 }
635
636 /* \f */
637
638 pgmread (pd, child_id, bb)
639 int pd,
640 child_id;
641 register struct bboard *bb;
642 {
643 int i,
644 j,
645 n;
646 TYPESIG (*estat) (), (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
647 char buffer[BUFSIZ];
648 struct bbcount *selected;
649
650 estat = signal (SIGEMT, sigser);
651 hstat = signal (SIGHUP, hupser);
652 istat = signal (SIGINT, SIG_IGN);
653 qstat = signal (SIGQUIT, SIG_IGN);
654 tstat = signal (SIGTERM, sigser);
655
656 while ((n = read (pd, buffer, sizeof buffer)) == NOTOK && errno == EINTR)
657 continue;
658 (void) close (pd);
659 (void) pidXwait (child_id, mshproc);
660
661 (void) signal (SIGEMT, estat);
662 (void) signal (SIGHUP, hstat);
663 (void) signal (SIGINT, istat);
664 (void) signal (SIGQUIT, qstat);
665 (void) signal (SIGTERM, tstat);
666
667 if (n <= 0)
668 return;
669 if (sscanf (buffer, "%d %d", &i, &j) != 2 || i <= 0 || j <= 0)
670 return;
671
672 if ((selected = seek_count (bbc, bb -> bb_name)) == NULL) {
673 bbc = add_count (bbc, bb -> bb_name, i);
674 changed++;
675 }
676 else
677 if (archivesw) {
678 if (i > selected -> count) {
679 selected -> count = i;
680 changed++;
681 }
682 }
683 else {
684 if (bb -> bb_maxima > j && i >= j)/* bbl... */
685 i = bb -> bb_maxima;
686 if (i != selected -> count) {
687 selected -> count = i;
688 changed++;
689 }
690 }
691 }
692
693
694 /* ARGSUSED */
695
696 TYPESIG sigser (i)
697 int i;
698 {
699 #ifndef BSD42
700 (void) signal (i, sigser);
701 #endif not BSD42
702 quitting++;
703 }
704
705
706 /* ARGSUSED */
707
708 TYPESIG hupser (i)
709 int i;
710 {
711 static int armed = 0;
712
713 #ifndef BSD42
714 (void) signal (i, hupser);
715 #endif
716
717 if (!armed++) /* tick tock... */
718 alarm ((unsigned int) 30);
719 }
720
721 /* \f */
722
723 rcinit (rc)
724 register char *rc;
725 {
726 int state;
727 register char *cp;
728 char key[NAMESZ],
729 value[BUFSIZ];
730 register FILE *bbrc;
731
732 if ((cp = rc ? rc : getenv ("MHBBRC")) && *cp) {
733 rcfile = path (cp, TFILE);
734 if (*cp != '/')
735 (void) m_putenv ("MHBBRC", rcfile);
736 }
737 else
738 rcfile = concat (mypath, "/", RCFILE, NULLCP);
739
740 if ((bbrc = fopen (rcfile, "r")) == NULL)
741 if (cp && *cp)
742 adios (rcfile, "unable to read");
743 else
744 return;
745
746 for (state = FLD;;) {
747 switch (state = m_getfld (state, key, value, sizeof value, bbrc)) {
748 case FLD:
749 case FLDEOF:
750 make_lower (key, key);
751 bbc = add_count (bbc, key, atoi (value));
752 if (state == FLDEOF)
753 break;
754 continue;
755
756 default:
757 admonish (NULLCP, "bad format: %s", rcfile);
758 case FILEEOF:
759 break;
760 }
761
762 break;
763 }
764
765 if (ferror (bbrc) && !feof (bbrc))
766 admonish (rcfile, "error reading");
767 (void) fclose (bbrc);
768 }
769
770 /* \f */
771
772 rcend () {
773 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
774 register FILE *bbrc;
775
776 if (!changed)
777 return;
778
779 hstat = signal (SIGHUP, SIG_IGN);
780 istat = signal (SIGINT, SIG_IGN);
781 qstat = signal (SIGQUIT, SIG_IGN);
782 tstat = signal (SIGTERM, SIG_IGN);
783
784 if ((bbrc = fopen (rcfile, "w")) == NULL)
785 adios (rcfile, "unable to write");
786 rcput (bbrc, bbc);
787
788 if (ferror (bbrc))
789 adios (rcfile, "error writing");
790 (void) fclose (bbrc);
791
792 (void) signal (SIGHUP, hstat);
793 (void) signal (SIGINT, istat);
794 (void) signal (SIGQUIT, qstat);
795 (void) signal (SIGTERM, tstat);
796
797 changed = 0;
798 }
799
800
801 rcput (bbrc, p)
802 register FILE *bbrc;
803 register struct bbcount *p;
804 {
805 if (p == NULL)
806 return;
807
808 fprintf (bbrc, "%s: %d\n", p -> key, p -> count);
809 rcput (bbrc, p -> left);
810 rcput (bbrc, p -> right);
811 }
812
813 /* \f */
814
815 #ifdef SIGTSTP
816 static TYPESIG tstpser (sig)
817 int sig;
818 {
819 int pid;
820 #if defined(BSD42) && !defined(WAITINT)
821 union wait w;
822 #else
823 int w;
824 #endif
825
826 rcend ();
827
828 #ifdef SVR4
829 waitpid(tstpid, &w, WUNTRACED);
830 #else
831 while ((pid = wait3 (&w, WUNTRACED, (struct rusage *) 0)) != NOTOK
832 && pid != tstpid)
833 continue;
834 #endif
835
836 (void) signal (SIGTSTP, SIG_DFL);
837 #ifdef BSD42
838 (void) sigsetmask (sigblock (0) & ~sigmask (SIGTSTP));
839 #endif BSD42
840
841 (void) kill (getpid (), sig);
842
843 #ifdef BSD42
844 (void) sigblock (sigmask (SIGTSTP));
845 #endif BSD42
846 (void) signal (SIGTSTP, tstpser);
847 }
848 #endif SIGTSTP
849
850 /* \f */
851 static void bbreset (bb, i)
852 register struct bboard *bb;
853 int i;
854 {
855 struct bbcount *selected;
856
857 bb -> bb_count = i;
858 if ((selected = seek_count (bbc, bb -> bb_name)) == NULL)
859 bbc = add_count (bbc, bb -> bb_name, i);
860 else
861 selected -> count = i;
862
863 changed++;
864 }
865
866 struct bbcount *add_count (p, w, i)
867 register struct bbcount *p;
868 register char *w;
869 int i;
870 {
871 int cond;
872
873 if (p == NULL) {
874 p = (struct bbcount *) malloc (sizeof *p);
875 if (p == NULL)
876 adios (NULLCP,"insufficient memory");
877 p -> key = getcpy (w);
878 p -> count = i;
879 p -> left = p -> right = NULL;
880 }
881 else
882 if ((cond = strcmp (w, p -> key)) < 0)
883 p -> left = add_count (p -> left, w, i);
884 else
885 if (cond > 0)
886 p -> right = add_count (p -> right, w, i);
887
888 return p;
889 }
890
891
892 struct bbcount *seek_count (p, w)
893 register struct bbcount *p;
894 register char *w;
895 {
896 int cond;
897
898 if (p == NULL || (cond = strcmp (w, p -> key)) == 0)
899 return p;
900 else
901 return seek_count (cond < 0 ? p -> left : p -> right, w);
902 }
903
904 /* \f */
905
906 default_bboards () {
907 register char *cp,
908 **ap;
909 #ifdef UCL
910 register int i = bbp;
911 #endif UCL
912
913 if (bbl != NULL)
914 return;
915
916 if (!archivesw && ((cp = m_find ("bboards")) != NULL)) {
917 #ifndef BPOP
918 for (ap = brkstring (cp = getcpy (cp), " ", "\n"); *ap; ap++)
919 #else BPOP
920 for (ap = getip (cp); *ap; ap++)
921 #endif BPOP
922 #ifndef UCL
923 add_bb (*ap, OK);
924 #else UCL
925 bbs[bbp++] = *ap;
926 bbs[bbp] = NULL;
927 while (i < bbp)
928 add_bb (bbs[i++], OK);
929 #endif UCL
930 #ifndef BPOP
931 free (cp);
932 #endif not BPOP
933 if (oops)
934 advise (NULLCP, "please fix the %s: entry in your %s file",
935 "bboards", mh_profile);
936 }
937 else {
938 #ifdef UCL
939 bbs[bbp++] = "system";
940 bbs[bbp] = NULL;
941 #endif UCL
942 #ifndef NNTP
943 add_bb ("system", NOTOK);
944 #else NNTP
945 add_bb ("general", NOTOK);
946 #ifdef UCI
947 add_bb ("ics.system", NOTOK);
948 add_bb ("ics.general", NOTOK);
949 #endif UCI
950 #endif NNTP
951 }
952 #ifdef UCL
953 bbs[bbp] = NULL;
954 #endif UCL
955
956 if (bbl == NULL)
957 done (1);
958 }
959
960 /* \f */
961
962 add_bb (s, hush)
963 register char *s;
964 int hush;
965 {
966 register struct bboard *bb;
967 static struct bboard *tail = NULL;
968
969 make_lower (s, s);
970 if ((bb = getbbaux (s)) == NULL)
971 if (hush == OK)
972 return;
973 else
974 adios (NULLCP, "no such bboard as '%s'", s);
975
976 if (bb -> bb_flags & BB_SEEN) {
977 if (hush == OK) {
978 admonish (NULLCP, "duplicate bboard '%s'", s);
979 oops++;
980 }
981 return;
982 }
983 bb -> bb_flags |= BB_SEEN;
984
985 if (tail != NULL)
986 tail -> bb_link = bb;
987 if (bbl == NULL)
988 bbl = bb;
989 tail = bb;
990 }
991
992 /* \f */
993
994 #ifdef BPOP
995 static struct bboard *Bhead = NULL;
996 static struct bboard *Btail = NULL;
997
998 static int xtnd2 (s)
999 char *s;
1000 {
1001 int maxima;
1002 char name[BUFSIZ];
1003 register struct bboard *bb;
1004
1005 if (sscanf (s, "%s %d", name, &maxima) != 2)
1006 adios (NULLCP, "XTND2 botch: %s", s);
1007
1008 if ((bb = (struct bboard *) calloc (1, sizeof *bb)) == NULL)
1009 adios (NULLCP, "insufficient memory");
1010 bb -> bb_name = getcpy (name);
1011 #ifdef NNTP
1012 if (index(name, '.')) {
1013 char *cp;
1014 bb -> bb_aka = getip (name);
1015 for (cp = *bb -> bb_aka; *cp; cp++)
1016 if (*cp == '.')
1017 *cp = '-';
1018 } else {
1019 #endif
1020 if ((bb -> bb_aka = (char **) calloc (1, sizeof *bb -> bb_aka)) == NULL)
1021 adios (NULLCP, "insufficient memory");
1022 *bb -> bb_aka = NULL;
1023 #ifdef NNTP
1024 }
1025 #endif NNTP
1026 bb -> bb_file = bb -> bb_archive = bb -> bb_info = bb -> bb_map = "";
1027 bb -> bb_passwd = "";
1028 #ifndef NNTP
1029 if ((bb -> bb_leader = (char **) calloc (1, sizeof *bb -> bb_leader))
1030 == NULL)
1031 adios (NULLCP, "insufficient memory");
1032 *bb -> bb_leader = NULL;
1033 #else NNTP
1034 bb -> bb_leader = getip ("usenet");
1035 #endif NNTP
1036 bb -> bb_addr = bb -> bb_request = bb -> bb_relay = "";
1037 if ((bb -> bb_dist = (char **) calloc (1, sizeof *bb -> bb_dist)) == NULL)
1038 adios (NULLCP, "insufficient memory");
1039 *bb -> bb_dist = NULL;
1040 bb -> bb_flags = BB_REMOTE;
1041 bb -> bb_count = 0;
1042 bb -> bb_maxima = maxima;
1043 bb -> bb_date = "";
1044 bb -> bb_next = bb -> bb_link = bb -> bb_chain = NULL;
1045
1046 if (Btail != NULL)
1047 Btail -> bb_chain = bb;
1048 if (Bhead == NULL)
1049 Bhead = bb;
1050 Btail = bb;
1051
1052 return OK;
1053 }
1054
1055 /* \f */
1056
1057 static int xtnd3 (s)
1058 char *s;
1059 {
1060 static int bbs_int = 0;
1061 static struct bboard *bb;
1062
1063 switch (bbs_int++) {
1064 case 0:
1065 for (bb = Bhead; bb; bb = bb -> bb_chain)
1066 if (strcmp (bb -> bb_name, s) == 0)
1067 break;
1068 if (bb == NULL)
1069 adios (NULLCP, "XTND3 botch");
1070
1071 free (bb -> bb_name);
1072 bb -> bb_name = getcpy (s);
1073 break;
1074 case 1:
1075 if (bb -> bb_aka)
1076 free ((char *) bb -> bb_aka);
1077 bb -> bb_aka = getip (s);
1078 break;
1079 case 2:
1080 bb -> bb_file = getcpy (s);
1081 break;
1082 case 3:
1083 bb -> bb_archive = getcpy (s);
1084 break;
1085 case 4:
1086 bb -> bb_info = getcpy (s);
1087 break;
1088 case 5:
1089 bb -> bb_map = getcpy (s);
1090 break;
1091 case 6:
1092 bb -> bb_passwd = getcpy (s);
1093 break;
1094 case 7:
1095 if (bb -> bb_leader)
1096 free ((char *) bb -> bb_leader);
1097 bb -> bb_leader = getip (s);
1098 break;
1099 case 8:
1100 bb -> bb_addr = getcpy (s);
1101 break;
1102 case 9:
1103 bb -> bb_request = getcpy (s);
1104 break;
1105 case 10:
1106 bb -> bb_relay = getcpy (s);
1107 break;
1108 case 11:
1109 if (bb -> bb_dist)
1110 free ((char *) bb -> bb_dist);
1111 bb -> bb_dist = getip (s);
1112 break;
1113 case 12:
1114 bb -> bb_flags = bb -> bb_maxima = 0;
1115 (void) sscanf (s, "%o %d", &bb -> bb_flags, &bb -> bb_maxima);
1116 bb -> bb_flags |= BB_REMOTE;
1117 break;
1118 case 13:
1119 bb -> bb_date = getcpy (s);
1120 bbs_int = 0;
1121 break;
1122 }
1123
1124 return OK;
1125 }
1126
1127
1128 static char **getip (s)
1129 char *s;
1130 {
1131 register char **ap,
1132 **p,
1133 **q;
1134
1135 for (p = ap = brkstring (getcpy (s), " ", "\n"); *p; p++)
1136 continue;
1137
1138 q = (char **) calloc ((unsigned) (p - ap + 1), sizeof *q);
1139 if (q == NULL)
1140 adios (NULLCP, "insufficient memory");
1141
1142 for (p = ap, ap = q; *p; *q++ = *p++)
1143 continue;
1144 *q = NULL;
1145
1146 return ap;
1147 }
1148
1149 /* \f */
1150
1151 static struct bboard *rover = NULL;
1152
1153 struct bboard *getbbpop () {
1154 int snoop;
1155 char *cp,
1156 *pass = NULL;
1157 register struct bboard *bb;
1158
1159 if (didpop != NOTOK && ((bb = getbbent ()) || !host))
1160 return bb;
1161
1162 if (Bhead == NULL) {
1163 snoop = (cp = getenv ("MHPOPDEBUG")) && *cp;
1164 if (rpop) {
1165 if (user == NULL)
1166 user = getusr ();
1167 pass = getusr ();
1168 }
1169 else
1170 if (strcmp (user, popbbuser) == 0)
1171 pass = user;
1172 else
1173 ruserpass (host, &user, &pass);
1174 if (didpop != NOTOK)
1175 didpop = DONE;
1176
1177 if (pop_init (host, user, pass, snoop, rpop) == NOTOK)
1178 adios (NULLCP, "%s", response);
1179 if (rpop)
1180 (void) setuid (getuid ());
1181 if (pop_xtnd (xtnd2, "bboards") == NOTOK)
1182 adios (NULLCP, "%s", response);
1183 if (topicsw && verbosw) /* could optimize here */
1184 for (bb = Bhead; bb; bb = bb -> bb_chain)
1185 if (pop_xtnd (xtnd3, "x-bboards %s", bb -> bb_name) == NOTOK)
1186 adios (NULLCP, "%s", response);
1187 rover = Bhead;
1188 }
1189
1190 if (bb = rover)
1191 rover = rover -> bb_chain;
1192 return bb;
1193 }
1194
1195 #define getbbent getbbpop
1196 #endif BPOP
1197
1198 /* \f */
1199
1200 struct bboard *getbbaux (s)
1201 register char *s;
1202 {
1203 #ifdef BPOP
1204 int nlatch = host ? 1 : 0;
1205 #endif BPOP
1206 register char **ap;
1207 register struct bbcount *selected;
1208 register struct bboard *bb;
1209 static struct bboard *head = NULL,
1210 *tail = NULL;
1211
1212 for (bb = head; bb; bb = bb -> bb_next) {
1213 if (strcmp (bb -> bb_name, s) == 0)
1214 return bb;
1215 for (ap = bb -> bb_aka; *ap; ap++)
1216 if (strcmp (*ap, s) == 0)
1217 return bb;
1218 }
1219
1220 #ifdef BPOP
1221 one_more_time: ;
1222 #endif BPOP
1223 while (bb = getbbent ()) {
1224 if ((selected = seek_count (bbc, bb -> bb_name)) != NULL)
1225 bb -> bb_count = selected -> count;
1226
1227 #ifdef BPOP
1228 if (!(bb -> bb_flags & BB_REMOTE))
1229 #endif BPOP
1230 if ((bb = getbbcpy (bb)) == NULL)
1231 adios (NULLCP, "insufficient memory");
1232 if (tail != NULL)
1233 tail -> bb_next = bb;
1234 if (head == NULL)
1235 head = bb;
1236 tail = bb;
1237
1238 if (strcmp (bb -> bb_name, s) == 0) {
1239 found_it: ;
1240 bb -> bb_flags &= ~BB_SEEN;
1241 return bb;
1242 }
1243 for (ap = bb -> bb_aka; *ap; ap++)
1244 if (strcmp (*ap, s) == 0)
1245 goto found_it;
1246 }
1247
1248 #ifdef BPOP
1249 if (nlatch && pop_xtnd (xtnd2, "bboards %s", s) != NOTOK) {
1250 rover = Bhead;
1251 nlatch = 0;
1252 goto one_more_time;
1253 }
1254 #endif BPOP
1255
1256 return NULL;
1257 }
1258
1259
1260 struct bboard *getbbvis () {
1261 register struct bboard *bb;
1262
1263 while (bb = getbbent ())
1264 if (!(bb -> bb_flags & BB_INVIS)
1265 && (access (bb -> bb_file, 04) != NOTOK || errno != EACCES))
1266 break;
1267
1268 return bb;
1269 }