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: }