]>
diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/bbc.c
1 /* bbc.c - ZOTnet BBoard checker */
3 static char ident
[] = "@(#)$Id: bbc.c,v 2.13 1993/02/26 21:58:57 jromine Exp $";
7 #include "../zotnet/bboards.h"
10 #include "../zotnet/mts.h"
15 #define sigmask(s) (1 << ((s) - 1))
20 #include <sys/types.h>
25 #include <sys/resource.h>
31 #define RCFILE ".bbrc"
37 static struct swit switches
[] = {
69 "file BBoardsfile", 4,
109 struct bbcount
*left
;
110 struct bbcount
*right
;
117 static int changed
= 0;
119 static int quitting
= 0;
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;
129 static int didpop
= OK
;
131 static char *user
= BBOARDS
;
132 static char *host
= NULL
;
134 extern char response
[];
136 extern char *getusr ();
137 static char **getip ();
140 TYPESIG
sigser (), hupser ();
144 static TYPESIG
tstpser ();
147 static char *rcfile
=NULL
;
150 static struct bbcount
*bbc
= NULL
;
151 static struct bboard
*bbl
= NULL
;
153 struct bbcount
*add_count (), *seek_count ();
154 struct bboard
*getbbaux (), *getbbvis ();
155 static void bbreset();
159 extern int called_bbc
;
192 setlocale(LC_ALL
, "");
194 invo_name
= r1bindex (argv
[0], '/');
196 mts_init (invo_name
);
197 if (popbbhost
&& *popbbhost
)
199 if (popbbuser
&& *popbbuser
)
200 user
= popbbuser
, rpop
= 0;
202 if ((cp
= m_find (invo_name
)) != NULL
) {
203 ap
= brkstring (cp
= getcpy (cp
), " ", "\n");
204 ap
= copyip (ap
, arguments
);
208 (void) copyip (argv
+ 1, ap
);
211 (void) setbbent (SB_STAY
);
215 while (cp
= *argp
++) {
217 switch (smatch (++cp
, switches
)) {
219 ambigsw (cp
, switches
);
225 (void) sprintf (buffer
,
226 "%s [bboards ...] [switches] [switches for mshproc]",
228 help (buffer
, switches
);
233 checksw
= readsw
= 0;
237 readsw
= topicsw
= 0;
241 checksw
= topicsw
= 0;
268 if (!(mshproc
= *argp
++) || *mshproc
== '-')
269 adios (NULLCP
, "missing argument to %s", argp
[-2]);
273 if (!(rc
= *argp
++) || *rc
== '-')
274 adios (NULLCP
, "missing argument to %s", argp
[-2]);
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 ());
288 if (!(user
= *argp
++) || *user
== '-')
289 adios (NULLCP
, "missing argument to %s", argp
[-2]);
293 if (!(host
= *argp
++) || *host
== '-')
294 adios (NULLCP
, "missing argument to %s", argp
[-2]);
307 adios (NULLCP
, "too many bboards, starting with %s", cp
);
315 host
= NULL
, didpop
= OK
;
317 (void) setuid (getuid ());
320 if (!m_find ("path"))
321 free (path ("./", TFOLDER
));
325 for (bbp
= 0; cp
= bbs
[bbp
]; bbp
++)
346 if (didpop
!= OK
&& pop_quit () == NOTOK
)
347 adios (NULLCP
, "%s", response
);
358 register struct bboard
*bb
;
360 printf ("%16s %s %s\n", "BBoard", "Items",
361 verbosw
? "Interesting Facts" : "Last Update");
362 printf ("%16s %s %s\n", "------", "-----",
363 verbosw
? "-----------------" : "-----------");
365 for (bb
= bbl
? bbl
: getbbvis ();
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");
374 for (ap
= bb
-> bb_aka
; *ap
; ap
++)
375 cp
= add (*ap
, cp
? add (", ", cp
) : cp
);
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
);
393 printv ("Relay", bb
-> bb_relay
);
394 if (*bb
-> bb_dist
) {
396 (void) getbbdist (bb
, action
);
399 if (cp
= getbberr ())
400 printv ("Error", cp
);
402 printb (bb
-> bb_flags
& ~BB_SEEN
);
416 (void) sprintf (buffer
, "%s: ", key
);
419 printf ("%*s%-*s", 25, "", 10, buffer
);
421 printf ("%s", value
);
422 (void) putchar ('\n');
426 int action (local
, domain
)
427 register char *local
,
432 (void) sprintf (buffer
, "%s@%s", local
, domain
);
433 printv (changed
++ ? NULL
: "Dist", buffer
);
443 printv ("Flags", sprintb (buffer
, flags
, BBITS
));
449 #define grammar(a,b,c) (a == 1 ? b : c)
450 #define plural(d) grammar(d, "", "s")
453 register struct bboard
*bb
;
455 for (bb
= bbl
; bb
; bb
= bb
-> bb_link
) {
456 diff
= bb
-> bb_maxima
- bb
-> bb_count
;
459 printf ("%s -- %d item%s unseen\n",
460 bb
-> bb_name
, diff
, plural (diff
));
463 if (bb
-> bb_maxima
== 0)
464 printf ("%s -- empty\n", bb
-> bb_name
);
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 "));
472 printf ("%s -- %d item%s (all seen)\n",
473 bb
-> bb_name
, bb
-> bb_maxima
,
474 plural (bb
-> bb_maxima
));
476 printf ("%s -- %d item%s unseen\n",
477 bb
-> bb_name
, diff
, plural (diff
));
491 register struct bboard
*bb
;
493 vec
[0] = r1bindex (mshproc
, '/');
495 tstat
= signal (SIGTSTP
, tstpser
);
498 for (bb
= bbl
; bb
&& !quitting
; bb
= bb
-> bb_link
) {
499 diff
= bb
-> bb_maxima
- bb
-> bb_count
;
500 if (bb
-> bb_maxima
== 0) {
502 printf ("%s -- empty\n", bb
-> bb_name
);
508 "Oops! looks like someone reset %s -- assuming all unseen\n",
510 diff
= bb
-> bb_maxima
;
513 if (verbosw
|| archivesw
|| diff
> 0)
514 bbread (bb
, vecp
, vec
);
517 printf ("%s -- %d item%s (all seen)\n",
518 bb
-> bb_name
, bb
-> bb_maxima
,
519 plural (bb
-> bb_maxima
));
524 (void) signal (SIGTSTP
, tstat
);
543 bbread (bb
, vecp
, vec
)
544 register struct bboard
*bb
;
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
);
568 if (pop_stat (&nmsgs
, &nbytes
) == NOTOK
)
569 adios (NULLCP
, "%s", response
);
572 printf ("%s -- empty\n", bb
-> bb_name
);
575 if (pop_fd (buf4
, buf5
) == NOTOK
)
576 adios (NULLCP
, "%s", response
);
580 if (stat (archivesw
? bb
-> bb_archive
: bb
-> bb_file
, &st
) != NOTOK
585 if (pipe (pd
) == NOTOK
)
586 adios ("pipe", "unable to");
587 (void) sprintf (buf3
, "%d", getpid ());
590 switch (child_id
= fork ()) {
592 adios ("fork", "unable to");
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";
603 vec
[vecp
++] = "-idstop";
605 vec
[vecp
++] = "-idquit";
609 if (bb
-> bb_flags
& BB_REMOTE
) {
610 vec
[vecp
++] = "-popread";
612 vec
[vecp
++] = "-popwrite";
616 vec
[vecp
++] = archivesw
? bb
-> bb_archive
: bb
-> bb_file
;
618 execvp (mshproc
, vec
);
619 fprintf (stderr
, "unable to exec ");
628 (void) close (pd
[1]);
629 pgmread (pd
[0], child_id
, bb
);
632 (void) pidXwait (child_id
, mshproc
);
638 pgmread (pd
, child_id
, bb
)
641 register struct bboard
*bb
;
646 TYPESIG (*estat
) (), (*hstat
) (), (*istat
) (), (*qstat
) (), (*tstat
) ();
648 struct bbcount
*selected
;
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
);
656 while ((n
= read (pd
, buffer
, sizeof buffer
)) == NOTOK
&& errno
== EINTR
)
659 (void) pidXwait (child_id
, mshproc
);
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
);
669 if (sscanf (buffer
, "%d %d", &i
, &j
) != 2 || i
<= 0 || j
<= 0)
672 if ((selected
= seek_count (bbc
, bb
-> bb_name
)) == NULL
) {
673 bbc
= add_count (bbc
, bb
-> bb_name
, i
);
678 if (i
> selected
-> count
) {
679 selected
-> count
= i
;
684 if (bb
-> bb_maxima
> j
&& i
>= j
)/* bbl... */
686 if (i
!= selected
-> count
) {
687 selected
-> count
= i
;
700 (void) signal (i
, sigser
);
711 static int armed
= 0;
714 (void) signal (i
, hupser
);
717 if (!armed
++) /* tick tock... */
718 alarm ((unsigned int) 30);
732 if ((cp
= rc
? rc
: getenv ("MHBBRC")) && *cp
) {
733 rcfile
= path (cp
, TFILE
);
735 (void) m_putenv ("MHBBRC", rcfile
);
738 rcfile
= concat (mypath
, "/", RCFILE
, NULLCP
);
740 if ((bbrc
= fopen (rcfile
, "r")) == NULL
)
742 adios (rcfile
, "unable to read");
746 for (state
= FLD
;;) {
747 switch (state
= m_getfld (state
, key
, value
, sizeof value
, bbrc
)) {
750 make_lower (key
, key
);
751 bbc
= add_count (bbc
, key
, atoi (value
));
757 admonish (NULLCP
, "bad format: %s", rcfile
);
765 if (ferror (bbrc
) && !feof (bbrc
))
766 admonish (rcfile
, "error reading");
767 (void) fclose (bbrc
);
773 TYPESIG (*hstat
) (), (*istat
) (), (*qstat
) (), (*tstat
) ();
779 hstat
= signal (SIGHUP
, SIG_IGN
);
780 istat
= signal (SIGINT
, SIG_IGN
);
781 qstat
= signal (SIGQUIT
, SIG_IGN
);
782 tstat
= signal (SIGTERM
, SIG_IGN
);
784 if ((bbrc
= fopen (rcfile
, "w")) == NULL
)
785 adios (rcfile
, "unable to write");
789 adios (rcfile
, "error writing");
790 (void) fclose (bbrc
);
792 (void) signal (SIGHUP
, hstat
);
793 (void) signal (SIGINT
, istat
);
794 (void) signal (SIGQUIT
, qstat
);
795 (void) signal (SIGTERM
, tstat
);
803 register struct bbcount
*p
;
808 fprintf (bbrc
, "%s: %d\n", p
-> key
, p
-> count
);
809 rcput (bbrc
, p
-> left
);
810 rcput (bbrc
, p
-> right
);
816 static TYPESIG
tstpser (sig
)
820 #if defined(BSD42) && !defined(WAITINT)
829 waitpid(tstpid
, &w
, WUNTRACED
);
831 while ((pid
= wait3 (&w
, WUNTRACED
, (struct rusage
*) 0)) != NOTOK
836 (void) signal (SIGTSTP
, SIG_DFL
);
838 (void) sigsetmask (sigblock (0) & ~sigmask (SIGTSTP
));
841 (void) kill (getpid (), sig
);
844 (void) sigblock (sigmask (SIGTSTP
));
846 (void) signal (SIGTSTP
, tstpser
);
851 static void bbreset (bb
, i
)
852 register struct bboard
*bb
;
855 struct bbcount
*selected
;
858 if ((selected
= seek_count (bbc
, bb
-> bb_name
)) == NULL
)
859 bbc
= add_count (bbc
, bb
-> bb_name
, i
);
861 selected
-> count
= i
;
866 struct bbcount
*add_count (p
, w
, i
)
867 register struct bbcount
*p
;
874 p
= (struct bbcount
*) malloc (sizeof *p
);
876 adios (NULLCP
,"insufficient memory");
877 p
-> key
= getcpy (w
);
879 p
-> left
= p
-> right
= NULL
;
882 if ((cond
= strcmp (w
, p
-> key
)) < 0)
883 p
-> left
= add_count (p
-> left
, w
, i
);
886 p
-> right
= add_count (p
-> right
, w
, i
);
892 struct bbcount
*seek_count (p
, w
)
893 register struct bbcount
*p
;
898 if (p
== NULL
|| (cond
= strcmp (w
, p
-> key
)) == 0)
901 return seek_count (cond
< 0 ? p
-> left
: p
-> right
, w
);
910 register int i
= bbp
;
916 if (!archivesw
&& ((cp
= m_find ("bboards")) != NULL
)) {
918 for (ap
= brkstring (cp
= getcpy (cp
), " ", "\n"); *ap
; ap
++)
920 for (ap
= getip (cp
); *ap
; ap
++)
928 add_bb (bbs
[i
++], OK
);
934 advise (NULLCP
, "please fix the %s: entry in your %s file",
935 "bboards", mh_profile
);
939 bbs
[bbp
++] = "system";
943 add_bb ("system", NOTOK
);
945 add_bb ("general", NOTOK
);
947 add_bb ("ics.system", NOTOK
);
948 add_bb ("ics.general", NOTOK
);
966 register struct bboard
*bb
;
967 static struct bboard
*tail
= NULL
;
970 if ((bb
= getbbaux (s
)) == NULL
)
974 adios (NULLCP
, "no such bboard as '%s'", s
);
976 if (bb
-> bb_flags
& BB_SEEN
) {
978 admonish (NULLCP
, "duplicate bboard '%s'", s
);
983 bb
-> bb_flags
|= BB_SEEN
;
986 tail
-> bb_link
= bb
;
995 static struct bboard
*Bhead
= NULL
;
996 static struct bboard
*Btail
= NULL
;
1003 register struct bboard
*bb
;
1005 if (sscanf (s
, "%s %d", name
, &maxima
) != 2)
1006 adios (NULLCP
, "XTND2 botch: %s", s
);
1008 if ((bb
= (struct bboard
*) calloc (1, sizeof *bb
)) == NULL
)
1009 adios (NULLCP
, "insufficient memory");
1010 bb
-> bb_name
= getcpy (name
);
1012 if (index(name
, '.')) {
1014 bb
-> bb_aka
= getip (name
);
1015 for (cp
= *bb
-> bb_aka
; *cp
; cp
++)
1020 if ((bb
-> bb_aka
= (char **) calloc (1, sizeof *bb
-> bb_aka
)) == NULL
)
1021 adios (NULLCP
, "insufficient memory");
1022 *bb
-> bb_aka
= NULL
;
1026 bb
-> bb_file
= bb
-> bb_archive
= bb
-> bb_info
= bb
-> bb_map
= "";
1027 bb
-> bb_passwd
= "";
1029 if ((bb
-> bb_leader
= (char **) calloc (1, sizeof *bb
-> bb_leader
))
1031 adios (NULLCP
, "insufficient memory");
1032 *bb
-> bb_leader
= NULL
;
1034 bb
-> bb_leader
= getip ("usenet");
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
;
1042 bb
-> bb_maxima
= maxima
;
1044 bb
-> bb_next
= bb
-> bb_link
= bb
-> bb_chain
= NULL
;
1047 Btail
-> bb_chain
= bb
;
1057 static int xtnd3 (s
)
1060 static int bbs_int
= 0;
1061 static struct bboard
*bb
;
1063 switch (bbs_int
++) {
1065 for (bb
= Bhead
; bb
; bb
= bb
-> bb_chain
)
1066 if (strcmp (bb
-> bb_name
, s
) == 0)
1069 adios (NULLCP
, "XTND3 botch");
1071 free (bb
-> bb_name
);
1072 bb
-> bb_name
= getcpy (s
);
1076 free ((char *) bb
-> bb_aka
);
1077 bb
-> bb_aka
= getip (s
);
1080 bb
-> bb_file
= getcpy (s
);
1083 bb
-> bb_archive
= getcpy (s
);
1086 bb
-> bb_info
= getcpy (s
);
1089 bb
-> bb_map
= getcpy (s
);
1092 bb
-> bb_passwd
= getcpy (s
);
1095 if (bb
-> bb_leader
)
1096 free ((char *) bb
-> bb_leader
);
1097 bb
-> bb_leader
= getip (s
);
1100 bb
-> bb_addr
= getcpy (s
);
1103 bb
-> bb_request
= getcpy (s
);
1106 bb
-> bb_relay
= getcpy (s
);
1110 free ((char *) bb
-> bb_dist
);
1111 bb
-> bb_dist
= getip (s
);
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
;
1119 bb
-> bb_date
= getcpy (s
);
1128 static char **getip (s
)
1135 for (p
= ap
= brkstring (getcpy (s
), " ", "\n"); *p
; p
++)
1138 q
= (char **) calloc ((unsigned) (p
- ap
+ 1), sizeof *q
);
1140 adios (NULLCP
, "insufficient memory");
1142 for (p
= ap
, ap
= q
; *p
; *q
++ = *p
++)
1151 static struct bboard
*rover
= NULL
;
1153 struct bboard
*getbbpop () {
1157 register struct bboard
*bb
;
1159 if (didpop
!= NOTOK
&& ((bb
= getbbent ()) || !host
))
1162 if (Bhead
== NULL
) {
1163 snoop
= (cp
= getenv ("MHPOPDEBUG")) && *cp
;
1170 if (strcmp (user
, popbbuser
) == 0)
1173 ruserpass (host
, &user
, &pass
);
1174 if (didpop
!= NOTOK
)
1177 if (pop_init (host
, user
, pass
, snoop
, rpop
) == NOTOK
)
1178 adios (NULLCP
, "%s", response
);
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
);
1191 rover
= rover
-> bb_chain
;
1195 #define getbbent getbbpop
1200 struct bboard
*getbbaux (s
)
1204 int nlatch
= host
? 1 : 0;
1207 register struct bbcount
*selected
;
1208 register struct bboard
*bb
;
1209 static struct bboard
*head
= NULL
,
1212 for (bb
= head
; bb
; bb
= bb
-> bb_next
) {
1213 if (strcmp (bb
-> bb_name
, s
) == 0)
1215 for (ap
= bb
-> bb_aka
; *ap
; ap
++)
1216 if (strcmp (*ap
, s
) == 0)
1223 while (bb
= getbbent ()) {
1224 if ((selected
= seek_count (bbc
, bb
-> bb_name
)) != NULL
)
1225 bb
-> bb_count
= selected
-> count
;
1228 if (!(bb
-> bb_flags
& BB_REMOTE
))
1230 if ((bb
= getbbcpy (bb
)) == NULL
)
1231 adios (NULLCP
, "insufficient memory");
1233 tail
-> bb_next
= bb
;
1238 if (strcmp (bb
-> bb_name
, s
) == 0) {
1240 bb
-> bb_flags
&= ~BB_SEEN
;
1243 for (ap
= bb
-> bb_aka
; *ap
; ap
++)
1244 if (strcmp (*ap
, s
) == 0)
1249 if (nlatch
&& pop_xtnd (xtnd2
, "bboards %s", s
) != NOTOK
) {
1260 struct bboard
*getbbvis () {
1261 register struct bboard
*bb
;
1263 while (bb
= getbbent ())
1264 if (!(bb
-> bb_flags
& BB_INVIS
)
1265 && (access (bb
-> bb_file
, 04) != NOTOK
|| errno
!= EACCES
))