Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / bbc.c,v
1 head    2.13;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 2.13
9 date    93.02.26.21.58.57;      author jromine; state Exp;
10 branches;
11 next    2.12;
12
13 2.12
14 date    92.12.14.17.10.25;      author jromine; state Exp;
15 branches;
16 next    2.11;
17
18 2.11
19 date    92.11.24.18.34.21;      author jromine; state Exp;
20 branches;
21 next    2.10;
22
23 2.10
24 date    92.11.11.22.04.17;      author jromine; state Exp;
25 branches;
26 next    2.9;
27
28 2.9
29 date    92.11.04.00.39.01;      author jromine; state Exp;
30 branches;
31 next    2.8;
32
33 2.8
34 date    92.05.12.21.55.14;      author jromine; state Exp;
35 branches;
36 next    2.7;
37
38 2.7
39 date    92.02.10.19.57.26;      author jromine; state Exp;
40 branches;
41 next    2.6;
42
43 2.6
44 date    92.02.10.18.12.35;      author jromine; state Exp;
45 branches;
46 next    2.5;
47
48 2.5
49 date    90.04.05.14.56.21;      author sources; state Exp;
50 branches;
51 next    2.4;
52
53 2.4
54 date    90.03.12.14.01.42;      author sources; state Exp;
55 branches;
56 next    2.3;
57
58 2.3
59 date    90.02.08.14.22.47;      author sources; state Exp;
60 branches;
61 next    2.2;
62
63 2.2
64 date    90.02.05.14.23.59;      author sources; state Exp;
65 branches;
66 next    2.1;
67
68 2.1
69 date    90.01.10.10.49.19;      author sources; state Exp;
70 branches;
71 next    2.0;
72
73 2.0
74 date    89.11.17.16.02.21;      author sources; state Exp;
75 branches;
76 next    1.5;
77
78 1.5
79 date    89.09.22.13.50.35;      author sources; state Exp;
80 branches;
81 next    1.4;
82
83 1.4
84 date    89.09.22.13.48.40;      author sources; state Exp;
85 branches;
86 next    1.3;
87
88 1.3
89 date    89.09.20.10.36.27;      author sources; state Exp;
90 branches;
91 next    1.2;
92
93 1.2
94 date    89.06.02.12.56.11;      author sources; state Exp;
95 branches;
96 next    1.1;
97
98 1.1
99 date    89.05.05.19.41.14;      author sources; state Exp;
100 branches;
101 next    ;
102
103
104 desc
105 @@
106
107
108 2.13
109 log
110 @TYPESIG
111 @
112 text
113 @/* bbc.c - ZOTnet BBoard checker */
114 #ifndef lint
115 static char ident[] = "@@(#)$Id: bbc.c,v 2.12 1992/12/14 17:10:25 jromine Exp jromine $";
116 #endif  lint
117
118 #include "../h/mh.h"
119 #include "../zotnet/bboards.h"
120 #include <stdio.h>
121 #ifdef  BPOP
122 #include "../zotnet/mts.h"
123 #endif  BPOP
124 #include <errno.h>
125 #include <signal.h>
126 #ifndef sigmask
127 #define sigmask(s)      (1 << ((s) - 1))
128 #endif  not sigmask
129 #ifdef  ridge
130 #undef  SIGTSTP
131 #endif  ridge
132 #include <sys/types.h>
133 #include <sys/stat.h>
134 #ifdef  SIGTSTP
135 #include <sys/wait.h>
136 #include <sys/time.h>
137 #include <sys/resource.h>
138 #endif  SIGTSTP
139 #ifdef LOCALE
140 #include        <locale.h>
141 #endif
142
143 #define RCFILE  ".bbrc"
144
145 #define NBB     100
146
147 /* \f */
148
149 static struct swit switches[] = {
150 #define TOPICSW 0
151     "topics", 6,
152 #define CHECKSW 1
153     "check", 5,
154 #define READSW  2
155     "read", 4,
156
157 #define QUIETSW 3
158     "quiet", 4,
159 #define VERBOSW 4
160     "verbose", 4,
161
162 #define ARCHSW  5
163     "archive", 4,
164 #define NOARCH  6
165     "noarchive", 3,
166
167 #define PROTSW  7
168     "protocol", 4,
169 #define NPROTSW 8
170     "noprotocol", 3,
171
172 #define PROGSW  9
173     "mshproc program", 4,
174
175 #define RCSW    10
176     "rcfile rcfile", 4,
177 #define NRCSW   11
178     "norcfile", 3,
179
180 #define FILESW  12
181     "file BBoardsfile", 4,
182 #define USERSW  13
183     "user BBoardsuser",
184 #ifndef NNTP
185         4,
186 #else   NNTP
187         -4,
188 #endif  NNTP
189
190 #define HOSTSW  14
191     "host host",
192 #ifndef BPOP
193     -4,
194 #else   BPOP
195     4,
196 #endif  BPOP
197 #define RPOPSW  15
198     "rpop",
199 #ifndef RPOP
200         -4,
201 #else   RPOP
202         4,
203 #endif  RPOP
204 #define NRPOPSW 16
205     "norpop",
206 #ifndef RPOP
207         -6,
208 #else   RPOP
209         6,
210 #endif  RPOP
211
212 #define HELPSW  17
213     "help", 4,
214
215     NULL, NULL
216 };
217
218 struct bbcount {
219     char   *key;
220     int     count;
221     struct bbcount *left;
222     struct bbcount *right;
223 };
224
225 /* \f */
226
227 extern int  errno;
228
229 static int  changed = 0;
230 static int  oops = 0;
231 static int  quitting = 0;
232
233 static int  archivesw = 0;
234 static int  checksw = 0;
235 static int  protsw = 1;
236 static int  quietsw = 0;
237 static int  readsw = 0;
238 static int  topicsw = 0;
239 static int  verbosw = 0;
240
241 static int  didpop = OK;
242 static int  rpop = 1;
243 static char *user = BBOARDS;
244 static char *host = NULL;
245 #ifdef  BPOP
246 extern char response[];
247
248 extern char   *getusr ();
249 static char  **getip ();
250 #endif  BPOP
251
252 TYPESIG sigser (), hupser ();
253 int     action ();
254 #ifdef  SIGTSTP
255 int     tstpid;
256 static  TYPESIG tstpser ();
257 #endif  SIGTSTP
258
259 static char *rcfile=NULL;
260
261
262 static struct bbcount  *bbc = NULL;
263 static struct bboard   *bbl = NULL;
264
265 struct bbcount *add_count (), *seek_count ();
266 struct bboard *getbbaux (), *getbbvis ();
267 static  void    bbreset();
268
269 #ifdef  UCL
270 extern  char       *bbs[];
271 extern  int        called_bbc;
272 static  int bbp;
273 #endif  UCL
274 /* \f */
275
276 /* ARGSUSED */
277
278 main (argc, argv)
279 int     argc;
280 char  **argv;
281 {
282 #ifndef UCL
283     int     bbp = 0,
284             vecp = 1;
285 #else   UCL
286     int    vecp = 1;
287 #endif  UCL
288     char   *cp,
289            *rc=NULL,
290           **ap,
291           **argp,
292             buffer[80],
293            *arguments[MAXARGS],
294 #ifndef UCL
295            *bbs[NBB + 1],
296 #endif  UCL
297            *vec[MAXARGS];
298 #ifdef  UCL
299     called_bbc = 1;
300     bbp = 0;
301 #endif  UCL
302
303 #ifdef LOCALE
304         setlocale(LC_ALL, "");
305 #endif
306     invo_name = r1bindex (argv[0], '/');
307 #ifdef  BPOP
308     mts_init (invo_name);
309     if (popbbhost && *popbbhost)
310         host = popbbhost;
311     if (popbbuser && *popbbuser)
312         user = popbbuser, rpop = 0;
313 #endif  BPOP
314     if ((cp = m_find (invo_name)) != NULL) {
315         ap = brkstring (cp = getcpy (cp), " ", "\n");
316         ap = copyip (ap, arguments);
317     }
318     else
319         ap = arguments;
320     (void) copyip (argv + 1, ap);
321     argp = arguments;
322
323     (void) setbbent (SB_STAY);
324
325 /* \f */
326
327     while (cp = *argp++) {
328         if (*cp == '-')
329             switch (smatch (++cp, switches)) {
330                 case AMBIGSW: 
331                     ambigsw (cp, switches);
332                     done (1);
333                 case UNKWNSW: 
334                    vec[vecp++] = --cp;
335                    continue;
336                 case HELPSW: 
337                     (void) sprintf (buffer,
338                         "%s [bboards ...] [switches] [switches for mshproc]",
339                         invo_name);
340                     help (buffer, switches);
341                     done (1);
342
343                 case TOPICSW: 
344                     topicsw++;
345                     checksw = readsw = 0;
346                     continue;
347                 case CHECKSW: 
348                     checksw++;
349                     readsw = topicsw = 0;
350                     continue;
351                 case READSW: 
352                     readsw++;
353                     checksw = topicsw = 0;
354                     continue;
355
356                 case ARCHSW: 
357                     archivesw++;
358                     continue;
359                 case NOARCH: 
360                     archivesw = 0;
361                     continue;
362
363                 case PROTSW: 
364                     protsw++;
365                     continue;
366                 case NPROTSW: 
367                     protsw = 0;
368                     continue;
369
370                 case QUIETSW: 
371                     quietsw++;
372                     verbosw = 0;
373                     continue;
374                 case VERBOSW: 
375                     verbosw++;
376                     quietsw = 0;
377                     continue;
378
379                 case PROGSW:
380                     if (!(mshproc = *argp++) || *mshproc == '-')
381                         adios (NULLCP, "missing argument to %s", argp[-2]);
382                     continue;
383
384                 case RCSW:
385                     if (!(rc = *argp++) || *rc == '-')
386                         adios (NULLCP, "missing argument to %s", argp[-2]);
387                     continue;
388                 case NRCSW:
389                     rc = NULL;
390                     continue;
391
392                 case FILESW:
393                     if (!(cp = *argp++) || *cp == '-')
394                         adios (NULLCP, "missing argument to %s", argp[-2]);
395                     if (!setbbinfo (user, cp, 1))
396                         adios (NULLCP, "setbbinfo(%s, %s, 1) failed -- %s",
397                                 user, cp, getbberr ());
398                     continue;
399                 case USERSW:
400                     if (!(user = *argp++) || *user == '-')
401                         adios (NULLCP, "missing argument to %s", argp[-2]);
402                     continue;
403
404                 case HOSTSW:
405                     if (!(host = *argp++) || *host == '-')
406                         adios (NULLCP, "missing argument to %s", argp[-2]);
407                     didpop = NOTOK;
408                     continue;
409                 case RPOPSW:
410                     rpop++;
411                     continue;
412                 case NRPOPSW:
413                     rpop = 0;
414                     continue;
415             }
416         if (bbp < NBB)
417             bbs[bbp++] = cp;
418         else
419             adios (NULLCP, "too many bboards, starting with %s", cp);
420     }
421     bbs[bbp] = NULL;
422
423 /* \f */
424
425 #ifdef  BPOP
426     if (host && !*host)
427         host = NULL, didpop = OK;
428     if (!host || !rpop)
429         (void) setuid (getuid ());
430 #endif  BPOP
431
432     if (!m_find ("path"))
433         free (path ("./", TFOLDER));
434
435     rcinit (rc);
436
437     for (bbp = 0; cp = bbs[bbp]; bbp++)
438         add_bb (cp, NOTOK);
439
440 #ifdef UCL
441     if (topicsw) {
442         called_bbc = 0;
443         topics ();
444         }
445 #else
446     if (topicsw)
447         topics ();
448 #endif
449     else {
450         default_bboards ();
451         if (checksw)
452             check ();
453         else
454             process (vecp, vec);
455     }
456
457 #ifdef  BPOP
458     if (didpop != OK && pop_quit () == NOTOK)
459         adios (NULLCP, "%s", response);
460 #endif  BPOP
461
462     done (0);
463 }
464
465 /* \f */
466
467 topics () {
468     register char  *cp,
469                   **ap;
470     register struct bboard *bb;
471
472     printf ("%16s %s   %s\n", "BBoard", "Items",
473             verbosw ? "Interesting Facts" : "Last Update");
474     printf ("%16s %s   %s\n", "------", "-----",
475             verbosw ? "-----------------" : "-----------");
476
477     for (bb = bbl ? bbl : getbbvis ();
478             bb;
479             bb = bbl ? bb -> bb_link : getbbvis ()) {
480         printf ("%16s %5d   %s\n",
481                 bb -> bb_name, bb -> bb_maxima,
482                 bb -> bb_date ? bb -> bb_date : "no deliveries");
483         if (verbosw) {
484             if (*bb -> bb_aka) {
485                 cp = NULL;
486                 for (ap = bb -> bb_aka; *ap; ap++)
487                     cp = add (*ap, cp ? add (", ", cp) : cp);
488                 printv ("AKA", cp);
489                 free (cp);
490             }
491
492             printv ("Leaders", *bb -> bb_leader);
493             for (ap = bb -> bb_leader + 1; *ap; ap++)
494                 printv (NULLCP, *ap);
495             printv ("File", bb -> bb_file);
496             printv ("Archive", bb -> bb_archive);
497             printv ("Info", bb -> bb_info);
498             printv ("Map", bb -> bb_map);
499             printv ("Password", bb -> bb_passwd);
500             if (strcmp (bb -> bb_name, bb -> bb_addr))
501                 printv ("Address", bb -> bb_addr);
502             if (strcmp (*bb -> bb_leader, bb -> bb_request))
503                 printv ("Request", bb -> bb_request);
504             if (*bb -> bb_relay)
505                 printv ("Relay", bb -> bb_relay);
506             if (*bb -> bb_dist) {
507                 changed = 0;
508                 (void) getbbdist (bb, action);
509                 if (!changed)
510                     printv ("Dist", "");
511                 if (cp = getbberr ())
512                     printv ("Error", cp);
513             }
514             printb (bb -> bb_flags & ~BB_SEEN);
515         }
516     }
517 }
518
519 /* \f */
520
521 printv (key, value)
522 register char   *key,
523                 *value;
524 {
525     char    buffer[BUFSIZ];
526
527     if (key)
528         (void) sprintf (buffer, "%s: ", key);
529     else
530         buffer[0] = '\0';
531     printf ("%*s%-*s", 25, "", 10, buffer);
532     if (value && *value)
533         printf ("%s", value);
534     (void) putchar ('\n');
535 }
536
537
538 int     action (local, domain)
539 register char   *local,
540                 *domain;
541 {
542     char    buffer[BUFSIZ];
543
544     (void) sprintf (buffer, "%s@@%s", local, domain);
545     printv (changed++ ? NULL : "Dist", buffer);
546     return 0;
547 }
548
549
550 printb (flags)
551 unsigned int flags;
552 {
553     char buffer[BUFSIZ];
554
555     printv ("Flags", sprintb (buffer, flags, BBITS));
556 }
557
558 /* \f */
559
560 check () {
561 #define grammar(a,b,c)  (a == 1 ? b : c)
562 #define plural(d)       grammar(d, "", "s")
563
564     int     diff;
565     register struct bboard  *bb;
566
567     for (bb = bbl; bb; bb = bb -> bb_link) {
568         diff = bb -> bb_maxima - bb -> bb_count;
569         if (quietsw) {
570             if (diff > 0)
571                 printf ("%s -- %d item%s unseen\n",
572                         bb -> bb_name, diff, plural (diff));
573         }
574         else
575             if (bb -> bb_maxima == 0)
576                 printf ("%s -- empty\n", bb -> bb_name);
577             else
578                 if (bb -> bb_count == 0)
579                     printf ("%s -- %d item%sseen)\n",
580                             bb -> bb_name, bb -> bb_maxima,
581                             grammar (bb -> bb_maxima, " (un", "s (none "));
582                 else
583                     if (diff <= 0)
584                         printf ("%s -- %d item%s (all seen)\n",
585                                 bb -> bb_name, bb -> bb_maxima,
586                                 plural (bb -> bb_maxima));
587                     else
588                         printf ("%s -- %d item%s unseen\n",
589                                 bb -> bb_name, diff, plural (diff));
590     }
591 }
592
593 /* \f */
594
595 process (vecp, vec)
596 int     vecp;
597 char   *vec[];
598 {
599     int     diff;
600 #ifdef  SIGTSTP
601     TYPESIG         (*tstat) ();
602 #endif  SIGTSTP
603     register struct bboard *bb;
604
605     vec[0] = r1bindex (mshproc, '/');
606 #ifdef  SIGTSTP
607     tstat = signal (SIGTSTP, tstpser);
608 #endif  SIGTSTP
609
610     for (bb = bbl; bb && !quitting; bb = bb -> bb_link) {
611         diff = bb -> bb_maxima - bb -> bb_count;
612         if (bb -> bb_maxima == 0) {
613             if (!quietsw)
614                 printf ("%s -- empty\n", bb -> bb_name);
615             continue;
616         }
617         else {
618             if (diff < 0) {
619                 printf (
620                 "Oops! looks like someone reset %s -- assuming all unseen\n",
621                     bb -> bb_name);
622                 diff = bb -> bb_maxima;
623                 bbreset (bb, 0);
624             }
625             if (verbosw || archivesw || diff > 0)
626                 bbread (bb, vecp, vec);
627             else
628                 if (!quietsw)
629                     printf ("%s -- %d item%s (all seen)\n",
630                             bb -> bb_name, bb -> bb_maxima,
631                             plural (bb -> bb_maxima));
632         }
633     };
634
635 #ifdef  SIGTSTP
636     (void) signal (SIGTSTP, tstat);
637 #endif  SIGTSTP
638     rcend ();
639 }
640
641 /* \f */
642
643 #ifdef  BPOP
644 /* ARGSUSED */
645
646 static int  xtnd1 (s)
647 char   *s;
648 {
649     return OK;
650 }
651 #endif  BPOP
652
653 /* \f */
654
655 bbread (bb, vecp, vec)
656 register struct bboard  *bb;
657 int     vecp;
658 char   *vec[];
659 {
660     int     child_id,
661             pd[2];
662     char    buf1[BUFSIZ],
663             buf2[BUFSIZ],
664             buf3[BUFSIZ];
665 #ifdef  BPOP
666     int     nmsgs,
667             nbytes;
668     char    buf4[BUFSIZ],
669             buf5[BUFSIZ];
670 #endif  BPOP
671     struct stat st;
672
673 #ifdef  BPOP
674     if (bb -> bb_flags & BB_REMOTE) {
675         if (pop_xtnd (xtnd1, "%s %s", archivesw ? "archive" : "bboards",
676                         bb -> bb_name) == NOTOK) {
677             advise (NULLCP, "%s", response);
678             return;
679         }
680         if (pop_stat (&nmsgs, &nbytes) == NOTOK)
681             adios (NULLCP, "%s", response);
682         if (nmsgs == 0) {
683             if (verbosw)
684                 printf ("%s -- empty\n", bb -> bb_name);
685             return;
686         }
687         if (pop_fd (buf4, buf5) == NOTOK)
688             adios (NULLCP, "%s", response);
689     }
690     else
691 #endif  BPOP
692     if (stat (archivesw ? bb -> bb_archive : bb -> bb_file, &st) != NOTOK
693             && st.st_size == 0)
694         return;
695
696     if (protsw) {
697         if (pipe (pd) == NOTOK)
698             adios ("pipe", "unable to");
699         (void) sprintf (buf3, "%d", getpid ());
700     }
701
702     switch (child_id = fork ()) {
703         case NOTOK: 
704             adios ("fork", "unable to");
705
706         case OK: 
707             if (protsw) {
708                 (void) close (pd[0]);
709                 (void) sprintf (buf1, "%d", bb -> bb_count + 1);
710                 (void) sprintf (buf2, "%d", pd[1]);
711                 vec[vecp++] = "-idname";
712                 vec[vecp++] = bb -> bb_name;
713                 vec[vecp++] = "-idstart";
714                 vec[vecp++] = buf1;
715                 vec[vecp++] = "-idstop";
716                 vec[vecp++] = buf2;
717                 vec[vecp++] = "-idquit";
718                 vec[vecp++] = buf3;
719             }
720 #ifdef  BPOP
721             if (bb -> bb_flags & BB_REMOTE) {
722                 vec[vecp++] = "-popread";
723                 vec[vecp++] = buf4;
724                 vec[vecp++] = "-popwrite";
725                 vec[vecp++] = buf5;
726             }
727 #endif  BPOP
728             vec[vecp++] = archivesw ? bb -> bb_archive : bb -> bb_file;
729             vec[vecp] = NULL;
730             execvp (mshproc, vec);
731             fprintf (stderr, "unable to exec ");
732             perror (mshproc);
733             _exit (-1);
734
735         default: 
736 #ifdef  SIGTSTP
737             tstpid = child_id;
738 #endif  SIGTSTP
739             if (protsw) {
740                 (void) close (pd[1]);
741                 pgmread (pd[0], child_id, bb);
742             }
743             else
744                 (void) pidXwait (child_id, mshproc);
745     }
746 }
747
748 /* \f */
749
750 pgmread (pd, child_id, bb)
751 int     pd,
752         child_id;
753 register struct bboard  *bb;
754 {
755     int     i,
756             j,
757             n;
758     TYPESIG (*estat) (), (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
759     char    buffer[BUFSIZ];
760     struct bbcount *selected;
761
762     estat = signal (SIGEMT, sigser);
763     hstat = signal (SIGHUP, hupser);
764     istat = signal (SIGINT, SIG_IGN);
765     qstat = signal (SIGQUIT, SIG_IGN);
766     tstat = signal (SIGTERM, sigser);
767
768     while ((n = read (pd, buffer, sizeof buffer)) == NOTOK && errno == EINTR)
769         continue;
770     (void) close (pd);
771     (void) pidXwait (child_id, mshproc);
772
773     (void) signal (SIGEMT, estat);
774     (void) signal (SIGHUP, hstat);
775     (void) signal (SIGINT, istat);
776     (void) signal (SIGQUIT, qstat);
777     (void) signal (SIGTERM, tstat);
778
779     if (n <= 0)
780         return;
781     if (sscanf (buffer, "%d %d", &i, &j) != 2 || i <= 0 || j <= 0)
782         return;
783
784     if ((selected = seek_count (bbc, bb -> bb_name)) == NULL) {
785         bbc = add_count (bbc, bb -> bb_name, i);
786         changed++;
787     }
788     else
789         if (archivesw) {
790             if (i > selected -> count) {
791                 selected -> count = i;
792                 changed++;
793             }
794         }
795         else {
796             if (bb -> bb_maxima > j && i >= j)/* bbl... */
797                 i = bb -> bb_maxima;
798             if (i != selected -> count) {
799                 selected -> count = i;
800                 changed++;
801             }
802         }
803 }
804
805
806 /* ARGSUSED */
807
808 TYPESIG sigser (i)
809 int     i;
810 {
811 #ifndef BSD42
812     (void) signal (i, sigser);
813 #endif  not BSD42
814     quitting++;
815 }
816
817
818 /* ARGSUSED */
819
820 TYPESIG hupser (i)
821 int     i;
822 {
823     static int armed = 0;
824
825 #ifndef BSD42
826     (void) signal (i, hupser);
827 #endif
828
829     if (!armed++)               /* tick tock... */
830         alarm ((unsigned int) 30);
831 }
832
833 /* \f */
834
835 rcinit (rc)
836 register char  *rc;
837 {
838     int     state;
839     register char  *cp;
840     char    key[NAMESZ],
841             value[BUFSIZ];
842     register FILE  *bbrc;
843
844     if ((cp = rc ? rc : getenv ("MHBBRC")) && *cp) {
845         rcfile = path (cp, TFILE);
846         if (*cp != '/')
847             (void) m_putenv ("MHBBRC", rcfile);
848     }
849     else
850         rcfile = concat (mypath, "/", RCFILE, NULLCP);
851
852     if ((bbrc = fopen (rcfile, "r")) == NULL)
853         if (cp && *cp)
854             adios (rcfile, "unable to read");
855         else
856             return;
857
858     for (state = FLD;;) {
859         switch (state = m_getfld (state, key, value, sizeof value, bbrc)) {
860             case FLD: 
861             case FLDEOF: 
862                 make_lower (key, key);
863                 bbc = add_count (bbc, key, atoi (value));
864                 if (state == FLDEOF)
865                     break;
866                 continue;
867
868             default: 
869                 admonish (NULLCP, "bad format: %s", rcfile);
870             case FILEEOF:
871                 break;
872         }
873
874         break;
875     }
876
877     if (ferror (bbrc) && !feof (bbrc))
878         admonish (rcfile, "error reading");
879     (void) fclose (bbrc);
880 }
881
882 /* \f */
883
884 rcend () {
885     TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
886     register FILE *bbrc;
887
888     if (!changed)
889         return;
890
891     hstat = signal (SIGHUP, SIG_IGN);
892     istat = signal (SIGINT, SIG_IGN);
893     qstat = signal (SIGQUIT, SIG_IGN);
894     tstat = signal (SIGTERM, SIG_IGN);
895
896     if ((bbrc = fopen (rcfile, "w")) == NULL)
897         adios (rcfile, "unable to write");
898     rcput (bbrc, bbc);
899
900     if (ferror (bbrc))
901         adios (rcfile, "error writing");
902     (void) fclose (bbrc);
903
904     (void) signal (SIGHUP, hstat);
905     (void) signal (SIGINT, istat);
906     (void) signal (SIGQUIT, qstat);
907     (void) signal (SIGTERM, tstat);
908
909     changed = 0;
910 }
911
912
913 rcput (bbrc, p)
914 register FILE *bbrc;
915 register struct bbcount *p;
916 {
917     if (p == NULL)
918         return;
919
920     fprintf (bbrc, "%s: %d\n", p -> key, p -> count);
921     rcput (bbrc, p -> left);
922     rcput (bbrc, p -> right);
923 }
924
925 /* \f */
926
927 #ifdef  SIGTSTP
928 static TYPESIG  tstpser (sig)
929 int     sig;
930 {
931     int     pid;
932 #if defined(BSD42) && !defined(WAITINT)
933     union wait w;
934 #else
935     int w;
936 #endif
937
938     rcend ();
939
940 #ifdef SVR4
941     waitpid(tstpid, &w, WUNTRACED);
942 #else
943     while ((pid = wait3 (&w, WUNTRACED, (struct rusage *) 0)) != NOTOK
944             && pid != tstpid)
945         continue;
946 #endif
947
948     (void) signal (SIGTSTP, SIG_DFL);
949 #ifdef  BSD42
950     (void) sigsetmask (sigblock (0) & ~sigmask (SIGTSTP));
951 #endif  BSD42
952
953     (void) kill (getpid (), sig);
954
955 #ifdef  BSD42
956     (void) sigblock (sigmask (SIGTSTP));
957 #endif  BSD42
958     (void) signal (SIGTSTP, tstpser);
959 }
960 #endif  SIGTSTP
961
962 /* \f */
963 static  void    bbreset (bb, i)
964 register struct bboard  *bb;
965 int i;
966 {
967     struct bbcount *selected;
968
969     bb -> bb_count = i;
970     if ((selected = seek_count (bbc, bb -> bb_name)) == NULL)
971         bbc = add_count (bbc, bb -> bb_name, i);
972     else
973         selected -> count = i;
974
975     changed++;
976 }
977
978 struct bbcount *add_count (p, w, i)
979 register struct bbcount *p;
980 register char   *w;
981 int     i;
982 {
983     int     cond;
984
985     if (p == NULL) {
986         p = (struct bbcount *) malloc (sizeof *p);
987         if (p == NULL)
988             adios (NULLCP,"insufficient memory");
989         p -> key = getcpy (w);
990         p -> count = i;
991         p -> left = p -> right = NULL;
992     }
993     else
994         if ((cond = strcmp (w, p -> key)) < 0)
995             p -> left = add_count (p -> left, w, i);
996         else
997             if (cond > 0)
998                 p -> right = add_count (p -> right, w, i);
999
1000     return p;
1001 }
1002
1003
1004 struct bbcount *seek_count (p, w)
1005 register struct bbcount *p;
1006 register char   *w;
1007 {
1008     int     cond;
1009
1010     if (p == NULL || (cond = strcmp (w, p -> key)) == 0)
1011         return p;
1012     else
1013         return seek_count (cond < 0 ? p -> left : p -> right, w);
1014 }
1015
1016 /* \f */
1017
1018 default_bboards () {
1019     register char  *cp,
1020                   **ap;
1021 #ifdef  UCL
1022     register int    i = bbp;
1023 #endif  UCL
1024
1025     if (bbl != NULL)
1026         return;
1027
1028     if (!archivesw && ((cp = m_find ("bboards")) != NULL)) {
1029 #ifndef BPOP
1030         for (ap = brkstring (cp = getcpy (cp), " ", "\n"); *ap; ap++)
1031 #else   BPOP
1032         for (ap = getip (cp); *ap; ap++)
1033 #endif  BPOP
1034 #ifndef UCL
1035             add_bb (*ap, OK);
1036 #else   UCL
1037             bbs[bbp++] = *ap;
1038         bbs[bbp] = NULL;
1039         while (i < bbp)
1040             add_bb (bbs[i++], OK);
1041 #endif  UCL
1042 #ifndef BPOP
1043         free (cp);
1044 #endif  not BPOP
1045         if (oops)
1046             advise (NULLCP, "please fix the %s: entry in your %s file",
1047                 "bboards", mh_profile);
1048     }
1049     else {
1050 #ifdef  UCL
1051         bbs[bbp++] = "system";
1052         bbs[bbp] = NULL;
1053 #endif  UCL
1054 #ifndef NNTP
1055         add_bb ("system", NOTOK);
1056 #else   NNTP
1057         add_bb ("general", NOTOK);
1058 #ifdef  UCI
1059         add_bb ("ics.system", NOTOK);
1060         add_bb ("ics.general", NOTOK);
1061 #endif  UCI
1062 #endif  NNTP
1063     }
1064 #ifdef  UCL
1065     bbs[bbp] = NULL;
1066 #endif  UCL
1067
1068     if (bbl == NULL)
1069         done (1);
1070 }
1071
1072 /* \f */
1073
1074 add_bb (s, hush)
1075 register char   *s;
1076 int     hush;
1077 {
1078     register struct bboard  *bb;
1079     static struct bboard   *tail = NULL;
1080
1081     make_lower (s, s);
1082     if ((bb = getbbaux (s)) == NULL)
1083         if (hush == OK)
1084             return;
1085         else
1086             adios (NULLCP, "no such bboard as '%s'", s);
1087
1088     if (bb -> bb_flags & BB_SEEN) {
1089         if (hush == OK) {
1090             admonish (NULLCP, "duplicate bboard '%s'", s);
1091             oops++;
1092         }
1093         return;
1094     }
1095     bb -> bb_flags |= BB_SEEN;
1096
1097     if (tail != NULL)
1098         tail -> bb_link = bb;
1099     if (bbl == NULL)
1100         bbl = bb;
1101     tail = bb;
1102 }
1103
1104 /* \f */
1105
1106 #ifdef  BPOP
1107 static struct bboard   *Bhead = NULL;
1108 static struct bboard   *Btail = NULL;
1109
1110 static int xtnd2 (s)
1111 char   *s;
1112 {
1113     int     maxima;
1114     char    name[BUFSIZ];
1115     register struct bboard *bb;
1116
1117     if (sscanf (s, "%s %d", name, &maxima) != 2)
1118         adios (NULLCP, "XTND2 botch: %s", s);
1119
1120     if ((bb = (struct bboard   *) calloc (1, sizeof *bb)) == NULL)
1121         adios (NULLCP, "insufficient memory");
1122     bb -> bb_name = getcpy (name);
1123 #ifdef  NNTP
1124     if (index(name, '.')) {
1125         char *cp;
1126         bb -> bb_aka = getip (name);
1127         for (cp = *bb -> bb_aka; *cp; cp++)
1128             if (*cp == '.')
1129                 *cp = '-';
1130     } else {
1131 #endif
1132     if ((bb -> bb_aka = (char **) calloc (1, sizeof *bb -> bb_aka)) == NULL)
1133         adios (NULLCP, "insufficient memory");
1134     *bb -> bb_aka = NULL;
1135 #ifdef  NNTP
1136     }
1137 #endif  NNTP
1138     bb -> bb_file = bb -> bb_archive = bb -> bb_info = bb -> bb_map = "";
1139     bb -> bb_passwd = "";
1140 #ifndef NNTP
1141     if ((bb -> bb_leader = (char **) calloc (1, sizeof *bb -> bb_leader))
1142             == NULL)
1143         adios (NULLCP, "insufficient memory");
1144     *bb -> bb_leader = NULL;
1145 #else   NNTP
1146     bb -> bb_leader = getip ("usenet");
1147 #endif  NNTP
1148     bb -> bb_addr = bb -> bb_request = bb -> bb_relay = "";
1149     if ((bb -> bb_dist = (char **) calloc (1, sizeof *bb -> bb_dist)) == NULL)
1150         adios (NULLCP, "insufficient memory");
1151     *bb -> bb_dist = NULL;
1152     bb -> bb_flags = BB_REMOTE;
1153     bb -> bb_count = 0;
1154     bb -> bb_maxima = maxima;
1155     bb -> bb_date = "";
1156     bb -> bb_next = bb -> bb_link = bb -> bb_chain = NULL;
1157
1158     if (Btail != NULL)
1159         Btail -> bb_chain = bb;
1160     if (Bhead == NULL)
1161         Bhead = bb;
1162     Btail = bb;
1163
1164     return OK;
1165 }
1166
1167 /* \f */
1168
1169 static int xtnd3 (s)
1170 char   *s;
1171 {
1172     static int  bbs_int = 0;
1173     static struct bboard   *bb;
1174
1175     switch (bbs_int++) {
1176         case 0: 
1177             for (bb = Bhead; bb; bb = bb -> bb_chain)
1178                 if (strcmp (bb -> bb_name, s) == 0)
1179                     break;
1180             if (bb == NULL)
1181                 adios (NULLCP, "XTND3 botch");
1182
1183             free (bb -> bb_name);
1184             bb -> bb_name = getcpy (s);
1185             break;
1186         case 1: 
1187             if (bb -> bb_aka)
1188                 free ((char *) bb -> bb_aka);
1189             bb -> bb_aka = getip (s);
1190             break;
1191         case 2: 
1192             bb -> bb_file = getcpy (s);
1193             break;
1194         case 3: 
1195             bb -> bb_archive = getcpy (s);
1196             break;
1197         case 4: 
1198             bb -> bb_info = getcpy (s);
1199             break;
1200         case 5: 
1201             bb -> bb_map = getcpy (s);
1202             break;
1203         case 6: 
1204             bb -> bb_passwd = getcpy (s);
1205             break;
1206         case 7: 
1207             if (bb -> bb_leader)
1208                 free ((char *) bb -> bb_leader);
1209             bb -> bb_leader = getip (s);
1210             break;
1211         case 8: 
1212             bb -> bb_addr = getcpy (s);
1213             break;
1214         case 9: 
1215             bb -> bb_request = getcpy (s);
1216             break;
1217         case 10: 
1218             bb -> bb_relay = getcpy (s);
1219             break;
1220         case 11: 
1221             if (bb -> bb_dist)
1222                 free ((char *) bb -> bb_dist);
1223             bb -> bb_dist = getip (s);
1224             break;
1225         case 12: 
1226             bb -> bb_flags = bb -> bb_maxima = 0;
1227             (void) sscanf (s, "%o %d", &bb -> bb_flags, &bb -> bb_maxima);
1228             bb -> bb_flags |= BB_REMOTE;
1229             break;
1230         case 13: 
1231             bb -> bb_date = getcpy (s);
1232             bbs_int = 0;
1233             break;
1234     }
1235
1236     return OK;
1237 }
1238
1239
1240 static char **getip (s)
1241 char   *s;
1242 {
1243     register char **ap,
1244                   **p,
1245                   **q;
1246
1247     for (p = ap = brkstring (getcpy (s), " ", "\n"); *p; p++)
1248         continue;
1249
1250     q = (char **) calloc ((unsigned) (p - ap + 1), sizeof *q);
1251     if (q == NULL)
1252         adios (NULLCP, "insufficient memory");
1253
1254     for (p = ap, ap = q; *p; *q++ = *p++)
1255         continue;
1256     *q = NULL;
1257
1258     return ap;
1259 }
1260
1261 /* \f */
1262
1263 static struct bboard   *rover = NULL;
1264
1265 struct bboard  *getbbpop () {
1266     int     snoop;
1267     char   *cp,
1268            *pass = NULL;
1269     register struct bboard *bb;
1270
1271     if (didpop != NOTOK && ((bb = getbbent ()) || !host))
1272         return bb;
1273
1274     if (Bhead == NULL) {
1275         snoop = (cp = getenv ("MHPOPDEBUG")) && *cp;
1276         if (rpop) {
1277             if (user == NULL)
1278                 user = getusr ();
1279             pass = getusr ();
1280         }
1281         else
1282             if (strcmp (user, popbbuser) == 0)
1283                 pass = user;
1284             else
1285                 ruserpass (host, &user, &pass);
1286         if (didpop != NOTOK)
1287             didpop = DONE;
1288
1289         if (pop_init (host, user, pass, snoop, rpop) == NOTOK)
1290             adios (NULLCP, "%s", response);
1291         if (rpop)
1292             (void) setuid (getuid ());
1293         if (pop_xtnd (xtnd2, "bboards") == NOTOK)
1294             adios (NULLCP, "%s", response);
1295         if (topicsw && verbosw) /* could optimize here */
1296             for (bb = Bhead; bb; bb = bb -> bb_chain)
1297                 if (pop_xtnd (xtnd3, "x-bboards %s", bb -> bb_name) == NOTOK)
1298                     adios (NULLCP, "%s", response);
1299         rover = Bhead;
1300     }
1301
1302     if (bb = rover)
1303         rover = rover -> bb_chain;
1304     return bb;
1305 }
1306
1307 #define getbbent        getbbpop
1308 #endif  BPOP
1309
1310 /* \f */
1311
1312 struct bboard *getbbaux (s)
1313 register char   *s;
1314 {
1315 #ifdef  BPOP
1316     int     nlatch = host ? 1 : 0;
1317 #endif  BPOP
1318     register char  **ap;
1319     register struct bbcount *selected;
1320     register struct bboard *bb;
1321     static struct bboard   *head = NULL,
1322                            *tail = NULL;
1323
1324     for (bb = head; bb; bb = bb -> bb_next) {
1325         if (strcmp (bb -> bb_name, s) == 0)
1326             return bb;
1327         for (ap = bb -> bb_aka; *ap; ap++)
1328             if (strcmp (*ap, s) == 0)
1329                 return bb;
1330     }
1331
1332 #ifdef  BPOP
1333 one_more_time: ;
1334 #endif  BPOP
1335     while (bb = getbbent ()) {
1336         if ((selected = seek_count (bbc, bb -> bb_name)) != NULL)
1337             bb -> bb_count = selected -> count;
1338
1339 #ifdef  BPOP
1340         if (!(bb -> bb_flags & BB_REMOTE))
1341 #endif  BPOP
1342         if ((bb = getbbcpy (bb)) == NULL)
1343             adios (NULLCP, "insufficient memory");
1344         if (tail != NULL)
1345             tail -> bb_next = bb;
1346         if (head == NULL)
1347             head = bb;
1348         tail = bb;
1349
1350         if (strcmp (bb -> bb_name, s) == 0) {
1351 found_it: ;
1352             bb -> bb_flags &= ~BB_SEEN;
1353             return bb;
1354         }
1355         for (ap = bb -> bb_aka; *ap; ap++)
1356             if (strcmp (*ap, s) == 0)
1357                 goto found_it;
1358     }
1359
1360 #ifdef  BPOP
1361     if (nlatch && pop_xtnd (xtnd2, "bboards %s", s) != NOTOK) {
1362         rover = Bhead;
1363         nlatch = 0;
1364         goto one_more_time;
1365     }
1366 #endif  BPOP
1367
1368     return NULL;
1369 }
1370
1371
1372 struct bboard *getbbvis () {
1373     register struct bboard *bb;
1374
1375     while (bb = getbbent ())
1376         if (!(bb -> bb_flags & BB_INVIS)
1377                 && (access (bb -> bb_file, 04) != NOTOK || errno != EACCES))
1378             break;
1379
1380     return bb;
1381 }
1382 @
1383
1384
1385 2.12
1386 log
1387 @WAITINT ifdefs
1388 @
1389 text
1390 @d3 1
1391 a3 1
1392 static char ident[] = "@@(#)$Id: bbc.c,v 2.11 1992/11/24 18:34:21 jromine Exp jromine $";
1393 d140 2
1394 a141 2
1395 int     sigser (), action ();
1396 int     hupser ();
1397 d144 1
1398 a144 1
1399 static  int     tstpser ();
1400 d696 1
1401 a696 1
1402 int     sigser (i)
1403 d708 1
1404 a708 1
1405 int     hupser (i)
1406 d816 1
1407 a816 1
1408 static int  tstpser (sig)
1409 @
1410
1411
1412 2.11
1413 log
1414 @add decl
1415 @
1416 text
1417 @d3 1
1418 a3 1
1419 static char ident[] = "@@(#)$Id: bbc.c,v 2.10 1992/11/11 22:04:17 jromine Exp jromine $";
1420 d820 3
1421 a822 1
1422 #ifndef BSD42
1423 a823 2
1424 #else
1425     union wait w;
1426 @
1427
1428
1429 2.10
1430 log
1431 @use union wait under BSD42 only
1432 @
1433 text
1434 @d3 1
1435 a3 1
1436 static char ident[] = "@@(#)$Id: bbc.c,v 2.9 1992/11/04 00:39:01 jromine Exp jromine $";
1437 d136 2
1438 a137 1
1439 char   *getusr (), **getip ();
1440 d144 1
1441 a144 1
1442 int     tstpser ();
1443 @
1444
1445
1446 2.9
1447 log
1448 @putenv -> m_putenv
1449 LOCALE
1450 @
1451 text
1452 @d3 1
1453 a3 1
1454 static char ident[] = "@@(#)$Id: bbc.c,v 2.8 1992/05/12 21:55:14 jromine Exp jromine $";
1455 d819 1
1456 a819 1
1457 #ifdef SVR4
1458 @
1459
1460
1461 2.8
1462 log
1463 @move misplaced #endif
1464 @
1465 text
1466 @d3 1
1467 a3 1
1468 static char ident[] = "@@(#)$Id: bbc.c,v 2.7 1992/02/10 19:57:26 jromine Exp jromine $";
1469 d27 3
1470 a184 1
1471
1472 d189 4
1473 d734 1
1474 a734 1
1475             (void) putenv ("MHBBRC", rcfile);
1476 @
1477
1478
1479 2.7
1480 log
1481 @typo
1482 @
1483 text
1484 @d3 1
1485 a3 1
1486 static char ident[] = "@@(#)$Id: bbc.c,v 2.6 1992/02/10 18:12:35 jromine Exp $";
1487 d826 1
1488 a827 1
1489         continue;
1490 @
1491
1492
1493 2.6
1494 log
1495 @some SVR4 changes
1496 add "localdomain" tailor option
1497 @
1498 text
1499 @d3 1
1500 a3 1
1501 static char ident[] = "@@(#)$Id: bbc.c,v 2.5 1990/04/05 14:56:21 sources Exp jromine $";
1502 d823 1
1503 a823 1
1504 #endif
1505 @
1506
1507
1508 2.5
1509 log
1510 @add ID
1511 @
1512 text
1513 @d3 1
1514 a3 1
1515 static char ident[] = "@@(#)$Id:$";
1516 d813 3
1517 d817 1
1518 d821 3
1519 d826 1
1520 @
1521
1522
1523 2.4
1524 log
1525 @TYPESIG fix
1526 @
1527 text
1528 @d2 3
1529 @
1530
1531
1532 2.3
1533 log
1534 @UCL changes
1535 @
1536 text
1537 @d479 1
1538 a479 1
1539     int     (*tstat) ();
1540 @
1541
1542
1543 2.2
1544 log
1545 @TYPESIG
1546 @
1547 text
1548 @d150 5
1549 d163 1
1550 d166 3
1551 d175 1
1552 d177 1
1553 d180 4
1554 d318 6
1555 d326 1
1556 d891 3
1557 d904 1
1558 d906 6
1559 d920 4
1560 d934 3
1561 d1042 1
1562 a1042 1
1563     static int  bbs = 0;
1564 d1045 1
1565 a1045 1
1566     switch (bbs++) {
1567 d1102 1
1568 a1102 1
1569             bbs = 0;
1570 @
1571
1572
1573 2.1
1574 log
1575 @don't always add "general" to list of bbs.
1576 @
1577 text
1578 @d614 1
1579 a614 1
1580     int     (*estat) (), (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
1581 d741 1
1582 a741 1
1583     int     (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
1584 @
1585
1586
1587 2.0
1588 log
1589 @changes for SUN40 shared libraries and NNTP under bbc
1590 @
1591 text
1592 @d887 1
1593 a887 1
1594     else
1595 d897 1
1596 @
1597
1598
1599 1.5
1600 log
1601 @fix minor nntp bug
1602 @
1603 text
1604 @@
1605
1606
1607 1.4
1608 log
1609 @*** empty log message ***
1610 @
1611 text
1612 @a24 2
1613 static  char    *mshproc = "/usr/local/nmsh";
1614
1615 d148 1
1616 d473 8
1617 a480 1
1618         else
1619 d488 1
1620 a488 1
1621
1622 d538 3
1623 a540 1
1624         if (nmsgs == 0)
1625 d542 1
1626 d811 14
1627 @
1628
1629
1630 1.3
1631 log
1632 @*** empty log message ***
1633 @
1634 text
1635 @d869 4
1636 @
1637
1638
1639 1.2
1640 log
1641 @*** empty log message ***
1642 @
1643 text
1644 @d25 1
1645 d67 6
1646 a72 1
1647     "user BBoardsuser", 4,
1648 d865 1
1649 d867 3
1650 @
1651
1652
1653 1.1
1654 log
1655 @Initial revision
1656 @
1657 text
1658 @d916 9
1659 d928 3
1660 d933 1
1661 d938 3
1662 @