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

Defined functions

action defined in line 383; used 2 times
add_bb defined in line 842; used 3 times
add_count defined in line 775; used 5 times
bbread defined in line 493; used 1 times
check defined in line 405; used 1 times
default_bboards defined in line 815; used 1 times
getbbaux defined in line 1055; used 2 times
getbbpop defined in line 1008; used 1 times
getbbvis defined in line 1112; used 3 times
getip defined in line 983; used 5 times
main defined in line 144; never used
pgmread defined in line 585; used 1 times
printb defined in line 395; used 1 times
printv defined in line 366; used 15 times
process defined in line 440; used 1 times
rcend defined in line 703; used 2 times
rcinit defined in line 654; used 4 times
rcput defined in line 732; used 3 times
seek_count defined in line 801; used 4 times
sigser defined in line 643; used 4 times
topics defined in line 313; used 1 times
tstpser defined in line 747; used 3 times
xtnd1 defined in line 484; used 1 times
xtnd2 defined in line 869; used 2 times
xtnd3 defined in line 912; used 1 times

Defined variables

Bhead defined in line 866; used 7 times
Btail defined in line 867; used 3 times
archivesw defined in line 107; used 8 times
bbc defined in line 134; used 7 times
bbl defined in line 135; used 9 times
changed defined in line 104; used 8 times
checksw defined in line 108; used 4 times
didpop defined in line 115; used 6 times
host defined in line 118; used 10 times
protsw defined in line 109; used 5 times
quietsw defined in line 110; used 5 times
quitting defined in line 105; used 2 times
rcfile defined in line 131; used 10 times
readsw defined in line 111; used 3 times
rover defined in line 1006; used 5 times
rpop defined in line 116; used 7 times
switches defined in line 29; used 3 times
topicsw defined in line 112; used 5 times
tstpid defined in line 127; used 2 times
user defined in line 117; used 11 times
verbosw defined in line 113; used 7 times

Defined struct's

bbcount defined in line 93; used 24 times

Defined macros

ARCHSW defined in line 42; never used
CHECKSW defined in line 32; never used
FILESW defined in line 60; never used
HELPSW defined in line 87; never used
HOSTSW defined in line 65; never used
NBB defined in line 25; used 2 times
NOARCH defined in line 44; never used
NPROTSW defined in line 49; never used
NRCSW defined in line 57; never used
NRPOPSW defined in line 79; never used
PROGSW defined in line 52; never used
PROTSW defined in line 47; never used
QUIETSW defined in line 37; never used
RCFILE defined in line 23; used 1 times
RCSW defined in line 55; never used
READSW defined in line 34; never used
RPOPSW defined in line 72; never used
TOPICSW defined in line 30; never used
USERSW defined in line 62; never used
VERBOSW defined in line 39; never used
getbbent defined in line 1050; used 3 times
grammar defined in line 406; used 2 times
plural defined in line 407; used 4 times
sigmask defined in line 12; used 3 times
Last modified: 1986-04-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3388
Valid CSS Valid XHTML 1.0 Strict