1: /* $Header: rcstuff.c,v 4.3.1.3 85/05/29 09:13:25 lwall Exp $ 2: * 3: * $Log: rcstuff.c,v $ 4: * Revision 4.3.1.3 85/05/29 09:13:25 lwall 5: * %d that should be %ld. 6: * 7: * Revision 4.3.1.2 85/05/17 11:40:08 lwall 8: * Sped up "rn -c" by not mallocing unnecessarily. 9: * 10: * Revision 4.3.1.1 85/05/10 11:37:18 lwall 11: * Branch for patches. 12: * 13: * Revision 4.3 85/05/01 11:45:56 lwall 14: * Baseline for release with 4.3bsd. 15: * 16: */ 17: 18: #include "EXTERN.h" 19: #include "common.h" 20: #include "util.h" 21: #include "ngdata.h" 22: #include "term.h" 23: #include "final.h" 24: #include "rn.h" 25: #include "intrp.h" 26: #include "only.h" 27: #include "rcln.h" 28: #include "server.h" 29: #include "INTERN.h" 30: #include "rcstuff.h" 31: 32: char *rcname INIT(Nullch); /* path name of .newsrc file */ 33: char *rctname INIT(Nullch); /* path name of temp .newsrc file */ 34: char *rcbname INIT(Nullch); /* path name of backup .newsrc file */ 35: char *softname INIT(Nullch); /* path name of .rnsoft file */ 36: FILE *rcfp INIT(Nullfp); /* .newsrc file pointer */ 37: 38: #ifdef HASHNG 39: short hashtbl[HASHSIZ]; 40: #endif 41: 42: bool 43: rcstuff_init() 44: { 45: register NG_NUM newng; 46: register char *s; 47: register int i; 48: register bool foundany = FALSE; 49: char *some_buf; 50: long length; 51: #ifdef SERVER 52: char *cp; 53: #endif 54: 55: #ifdef HASHNG 56: for (i=0; i<HASHSIZ; i++) 57: hashtbl[i] = -1; 58: #endif 59: 60: /* make filenames */ 61: 62: #ifdef SERVER 63: if (cp = getenv("NEWSRC")) 64: rcname = savestr(filexp(cp)); 65: else 66: rcname = savestr(filexp(RCNAME)); 67: #else /* not SERVER */ 68: rcname = savestr(filexp(RCNAME)); 69: #endif 70: rctname = savestr(filexp(RCTNAME)); 71: rcbname = savestr(filexp(RCBNAME)); 72: softname = savestr(filexp(SOFTNAME)); 73: 74: /* make sure the .newsrc file exists */ 75: 76: newsrc_check(); 77: 78: /* open .rnsoft file containing soft ptrs to active file */ 79: 80: tmpfp = fopen(softname,"r"); 81: if (tmpfp == Nullfp) 82: writesoft = TRUE; 83: 84: /* read in the .newsrc file */ 85: 86: for (nextrcline = 0; 87: (some_buf = get_a_line(buf,LBUFLEN,rcfp)) != Nullch; 88: nextrcline++) { 89: /* for each line in .newsrc */ 90: char tmpbuf[10]; 91: 92: newng = nextrcline; /* get it into a register */ 93: length = len_last_line_got; /* side effect of get_a_line */ 94: if (length <= 1) { /* only a newline??? */ 95: nextrcline--; /* compensate for loop increment */ 96: continue; 97: } 98: if (newng >= MAXRCLINE) { /* check for overflow */ 99: fputs("Too many lines in .newsrc\n",stdout) FLUSH; 100: finalize(1); 101: } 102: if (tmpfp != Nullfp && fgets(tmpbuf,10,tmpfp) != Nullch) 103: softptr[newng] = atoi(tmpbuf); 104: else 105: softptr[newng] = 0; 106: some_buf[--length] = '\0'; /* wipe out newline */ 107: if (checkflag) /* no extra mallocs for -c */ 108: rcline[newng] = some_buf; 109: else if (some_buf == buf) { 110: rcline[newng] = savestr(some_buf); 111: /* make a semipermanent copy */ 112: } 113: else { 114: /*NOSTRICT*/ 115: #ifndef lint 116: some_buf = saferealloc(some_buf,(MEM_SIZE)(length+1)); 117: #endif lint 118: rcline[newng] = some_buf; 119: } 120: #ifdef NOTDEF 121: if (strnEQ(some_buf,"to.",3)) { /* is this a non-newsgroup? */ 122: nextrcline--; /* destroy this line */ 123: continue; 124: } 125: #endif 126: if (*some_buf == ' ' || 127: *some_buf == '\t' || 128: strnEQ(some_buf,"options",7)) { /* non-useful line? */ 129: toread[newng] = TR_JUNK; 130: rcchar[newng] = ' '; 131: rcnums[newng] = 0; 132: continue; 133: } 134: for (s = rcline[newng]; *s && *s != ':' && *s != NEGCHAR; s++) ; 135: if (!*s && !checkflag) { 136: #ifndef lint 137: rcline[newng] = saferealloc(rcline[newng],(MEM_SIZE)length+2); 138: #endif lint 139: s = rcline[newng] + length; 140: *s = ':'; 141: *(s+1) = '\0'; 142: } 143: rcchar[newng] = *s; /* salt away the : or ! */ 144: rcnums[newng] = (char)(s - rcline[newng]); 145: rcnums[newng]++; /* remember where it was */ 146: *s = '\0'; /* null terminate newsgroup name */ 147: #ifdef HASHNG 148: if (!checkflag) 149: sethash(newng); 150: #endif 151: if (rcchar[newng] == NEGCHAR) { 152: toread[newng] = TR_UNSUB; 153: continue; 154: } 155: 156: /* now find out how much there is to read */ 157: 158: if (!inlist(buf) || (suppress_cn && foundany && !paranoid)) 159: toread[newng] = TR_NONE; /* no need to calculate now */ 160: else 161: set_toread(newng); 162: #ifdef VERBOSE 163: if (!checkflag && softmisses == 1) { 164: softmisses++; /* lie a little */ 165: fputs("(Revising soft pointers--be patient.)\n",stdout) FLUSH; 166: } 167: #endif 168: if (toread[newng] > TR_NONE) { /* anything unread? */ 169: if (!foundany) { 170: starthere = newng; 171: foundany = TRUE; /* remember that fact*/ 172: } 173: if (suppress_cn) { /* if no listing desired */ 174: if (checkflag) { /* if that is all they wanted */ 175: finalize(1); /* then bomb out */ 176: } 177: } 178: else { 179: #ifdef VERBOSE 180: IF(verbose) 181: printf("Unread news in %-20s %5ld article%s\n", 182: rcline[newng],(long)toread[newng], 183: toread[newng]==TR_ONE ? nullstr : "s") FLUSH; 184: ELSE 185: #endif 186: #ifdef TERSE 187: printf("%s: %ld article%s\n", 188: rcline[newng],(long)toread[newng], 189: toread[newng]==TR_ONE ? nullstr : "s") FLUSH; 190: #endif 191: if (int_count) { 192: countdown = 1; 193: int_count = 0; 194: } 195: if (countdown) { 196: if (! --countdown) { 197: fputs("etc.\n",stdout) FLUSH; 198: if (checkflag) 199: finalize(1); 200: suppress_cn = TRUE; 201: } 202: } 203: } 204: } 205: } 206: fclose(rcfp); /* close .newsrc */ 207: if (tmpfp != Nullfp) 208: fclose(tmpfp); /* close .rnsoft */ 209: if (checkflag) { /* were we just checking? */ 210: finalize(foundany); /* tell them what we found */ 211: } 212: if (paranoid) 213: cleanup_rc(); 214: 215: #ifdef DEBUGGING 216: if (debug & DEB_HASH) { 217: page_init(); 218: for (i=0; i<HASHSIZ; i++) { 219: sprintf(buf,"%d %d",i,hashtbl[i]); 220: print_lines(buf,NOMARKING); 221: } 222: } 223: #endif 224: 225: return foundany; 226: } 227: 228: /* try to find or add an explicitly specified newsgroup */ 229: /* returns TRUE if found or added, FALSE if not. */ 230: /* assumes that we are chdir'ed to SPOOL */ 231: 232: bool 233: get_ng(what,do_reloc) 234: char *what; 235: bool do_reloc; 236: { 237: char *ntoforget; 238: char promptbuf[128]; 239: #ifdef SERVER 240: char ser_line[256]; 241: #endif 242: 243: #ifdef VERBOSE 244: IF(verbose) 245: ntoforget = "Type n to forget about this newsgroup.\n"; 246: ELSE 247: #endif 248: #ifdef TERSE 249: ntoforget = "n to forget it.\n"; 250: #endif 251: if (index(what,'/')) { 252: dingaling(); 253: printf("\nBad newsgroup name.\n") FLUSH; 254: return FALSE; 255: } 256: set_ngname(what); 257: ng = find_ng(ngname); 258: if (ng == nextrcline) { /* not in .newsrc? */ 259: #ifndef SERVER 260: if (eaccess(ngdir,0) || 261: (softptr[ng] = findact(buf,ngname,strlen(ngname),0L)) < 0 ) { 262: #else /* SERVER */ 263: sprintf(ser_line, "GROUP %s", ngname); 264: put_server(ser_line); 265: if (get_server(ser_line, sizeof(ser_line)) < 0) { 266: fprintf(stderr, "rrn: Unexpected close of server socket.\n"); 267: finalize(1); 268: } 269: if (*ser_line != CHAR_OK) { 270: #endif /* SERVER */ 271: dingaling(); 272: #ifdef VERBOSE 273: IF(verbose) 274: printf("\nNewsgroup %s does not exist!\n",ngname) FLUSH; 275: ELSE 276: #endif 277: #ifdef TERSE 278: printf("\nNo %s!\n",ngname) FLUSH; 279: #endif 280: sleep(2); 281: return FALSE; 282: } 283: #ifdef VERBOSE 284: IF(verbose) 285: sprintf(promptbuf,"\nNewsgroup %s not in .newsrc--add? [yn] ",ngname); 286: ELSE 287: #endif 288: #ifdef TERSE 289: sprintf(promptbuf,"\nAdd %s? [yn] ",ngname); 290: #endif 291: reask_add: 292: in_char(promptbuf); 293: putchar('\n') FLUSH; 294: setdef(buf,"y"); 295: #ifdef VERIFY 296: printcmd(); 297: #endif 298: if (*buf == 'h') { 299: #ifdef VERBOSE 300: IF(verbose) 301: printf("Type y or SP to add %s to your .newsrc.\n", ngname) 302: FLUSH; 303: ELSE 304: #endif 305: #ifdef TERSE 306: fputs("y or SP to add\n",stdout) FLUSH; 307: #endif 308: fputs(ntoforget,stdout) FLUSH; 309: goto reask_add; 310: } 311: else if (*buf == 'n' || *buf == 'q') { 312: return FALSE; 313: } 314: else if (*buf == 'y') { 315: ng = add_newsgroup(ngname); 316: do_reloc = FALSE; 317: } 318: else { 319: fputs(hforhelp,stdout) FLUSH; 320: settle_down(); 321: goto reask_add; 322: } 323: } 324: else if (rcchar[ng] == NEGCHAR) { /* unsubscribed? */ 325: #ifdef VERBOSE 326: IF(verbose) 327: sprintf(promptbuf, 328: "\nNewsgroup %s is currently unsubscribed to--resubscribe? [yn] ",ngname) 329: FLUSH; 330: ELSE 331: #endif 332: #ifdef TERSE 333: sprintf(promptbuf,"\n%s unsubscribed--resubscribe? [yn] ",ngname) 334: FLUSH; 335: #endif 336: reask_unsub: 337: in_char(promptbuf); 338: putchar('\n') FLUSH; 339: setdef(buf,"y"); 340: #ifdef VERIFY 341: printcmd(); 342: #endif 343: if (*buf == 'h') { 344: #ifdef VERBOSE 345: IF(verbose) 346: printf("Type y or SP to resubscribe to %s.\n", ngname) FLUSH; 347: ELSE 348: #endif 349: #ifdef TERSE 350: fputs("y or SP to resubscribe.\n",stdout) FLUSH; 351: #endif 352: fputs(ntoforget,stdout) FLUSH; 353: goto reask_unsub; 354: } 355: else if (*buf == 'n' || *buf == 'q') { 356: return FALSE; 357: } 358: else if (*buf == 'y') { 359: rcchar[ng] = ':'; 360: } 361: else { 362: fputs(hforhelp,stdout) FLUSH; 363: settle_down(); 364: goto reask_unsub; 365: } 366: } 367: 368: /* now calculate how many unread articles in newsgroup */ 369: 370: set_toread(ng); 371: #ifdef RELOCATE 372: if (do_reloc) 373: ng = relocate_newsgroup(ng,-1); 374: #endif 375: return toread[ng] >= TR_NONE; 376: } 377: 378: /* add a newsgroup to the .newsrc file (eventually) */ 379: 380: NG_NUM 381: add_newsgroup(ngn) 382: char *ngn; 383: { 384: register NG_NUM newng = nextrcline++; 385: /* increment max rcline index */ 386: 387: rcnums[newng] = strlen(ngn) + 1; 388: rcline[newng] = safemalloc((MEM_SIZE)(rcnums[newng] + 1)); 389: strcpy(rcline[newng],ngn); /* and copy over the name */ 390: *(rcline[newng] + rcnums[newng]) = '\0'; 391: rcchar[newng] = ':'; /* call it subscribed */ 392: toread[newng] = TR_NONE; /* just for prettiness */ 393: #ifdef HASHNG 394: sethash(newng); /* so we can find it again */ 395: #endif 396: #ifdef RELOCATE 397: return relocate_newsgroup(newng,-1); 398: #else 399: return newng; 400: #endif 401: } 402: 403: #ifdef RELOCATE 404: NG_NUM 405: relocate_newsgroup(ngx,newng) 406: NG_NUM ngx; 407: NG_NUM newng; 408: { 409: char *dflt = (ngx!=current_ng ? "$^.L" : "$^L"); 410: char *tmprcline; 411: ART_UNREAD tmptoread; 412: char tmprcchar; 413: char tmprcnums; 414: ACT_POS tmpsoftptr; 415: register NG_NUM i; 416: #ifdef DEBUGGING 417: ART_NUM tmpngmax; 418: #endif 419: #ifdef CACHEFIRST 420: ART_NUM tmpabs1st; 421: #endif 422: 423: starthere = 0; /* Disable this optimization */ 424: writesoft = TRUE; /* Update soft pointer file */ 425: if (ngx < nextrcline-1) { 426: #ifdef HASHNG 427: for (i=0; i<HASHSIZ; i++) { 428: if (hashtbl[i] > ngx) 429: --hashtbl[i]; 430: else if (hashtbl[i] == ngx) 431: hashtbl[i] = nextrcline-1; 432: } 433: #endif 434: tmprcline = rcline[ngx]; 435: tmptoread = toread[ngx]; 436: tmprcchar = rcchar[ngx]; 437: tmprcnums = rcnums[ngx]; 438: tmpsoftptr = softptr[ngx]; 439: #ifdef DEBUGGING 440: tmpngmax = ngmax[ngx]; 441: #endif 442: #ifdef CACHEFIRST 443: tmpabs1st = abs1st[ngx]; 444: #endif 445: for (i=ngx+1; i<nextrcline; i++) { 446: rcline[i-1] = rcline[i]; 447: toread[i-1] = toread[i]; 448: rcchar[i-1] = rcchar[i]; 449: rcnums[i-1] = rcnums[i]; 450: softptr[i-1] = softptr[i]; 451: #ifdef DEBUGGING 452: ngmax[i-1] = ngmax[i]; 453: #endif 454: #ifdef CACHEFIRST 455: abs1st[i-1] = abs1st[i]; 456: #endif 457: } 458: rcline[nextrcline-1] = tmprcline; 459: toread[nextrcline-1] = tmptoread; 460: rcchar[nextrcline-1] = tmprcchar; 461: rcnums[nextrcline-1] = tmprcnums; 462: softptr[nextrcline-1] = tmpsoftptr; 463: #ifdef DEBUGGING 464: ngmax[nextrcline-1] = tmpngmax; 465: #endif 466: #ifdef CACHEFIRST 467: abs1st[nextrcline-1] = tmpabs1st; 468: #endif 469: } 470: if (current_ng > ngx) 471: current_ng--; 472: if (newng < 0) { 473: reask_reloc: 474: unflush_output(); /* disable any ^O in effect */ 475: #ifdef VERBOSE 476: IF(verbose) 477: printf("\nPut newsgroup where? [%s] ", dflt); 478: ELSE 479: #endif 480: #ifdef TERSE 481: printf("\nPut where? [%s] ", dflt); 482: #endif 483: fflush(stdout); 484: reinp_reloc: 485: eat_typeahead(); 486: getcmd(buf); 487: if (errno || *buf == '\f') { 488: /* if return from stop signal */ 489: goto reask_reloc; /* give them a prompt again */ 490: } 491: setdef(buf,dflt); 492: #ifdef VERIFY 493: printcmd(); 494: #endif 495: if (*buf == 'h') { 496: #ifdef VERBOSE 497: IF(verbose) { 498: printf("\n\n\ 499: Type ^ to put the newsgroup first (position 0).\n\ 500: Type $ to put the newsgroup last (position %d).\n", nextrcline-1); 501: printf("\ 502: Type . to put it before the current newsgroup (position %d).\n", current_ng); 503: printf("\ 504: Type -newsgroup name to put it before that newsgroup.\n\ 505: Type +newsgroup name to put it after that newsgroup.\n\ 506: Type a number between 0 and %d to put it at that position.\n", nextrcline-1); 507: printf("\ 508: Type L for a listing of newsgroups and their positions.\n") FLUSH; 509: } 510: ELSE 511: #endif 512: #ifdef TERSE 513: { 514: printf("\n\n\ 515: ^ to put newsgroup first (pos 0).\n\ 516: $ to put last (pos %d).\n", nextrcline-1); 517: printf("\ 518: . to put before current newsgroup (pos %d).\n", current_ng); 519: printf("\ 520: -newsgroup to put before newsgroup.\n\ 521: +newsgroup to put after.\n\ 522: number in 0-%d to put at that pos.\n", nextrcline-1); 523: printf("\ 524: L for list of .newsrc.\n") FLUSH; 525: } 526: #endif 527: goto reask_reloc; 528: } 529: else if (*buf == 'L') { 530: putchar('\n') FLUSH; 531: list_newsgroups(); 532: goto reask_reloc; 533: } 534: else if (isdigit(*buf)) { 535: if (!finish_command(TRUE)) /* get rest of command */ 536: goto reinp_reloc; 537: newng = atoi(buf); 538: if (newng < 0) 539: newng = 0; 540: if (newng >= nextrcline) 541: return nextrcline-1; 542: } 543: else if (*buf == '^') { 544: putchar('\n') FLUSH; 545: newng = 0; 546: } 547: else if (*buf == '$') { 548: putchar('\n') FLUSH; 549: return nextrcline-1; 550: } 551: else if (*buf == '.') { 552: putchar('\n') FLUSH; 553: newng = current_ng; 554: } 555: else if (*buf == '-' || *buf == '+') { 556: if (!finish_command(TRUE)) /* get rest of command */ 557: goto reinp_reloc; 558: newng = find_ng(buf+1); 559: if (newng == nextrcline) { 560: fputs("Not found.",stdout) FLUSH; 561: goto reask_reloc; 562: } 563: if (*buf == '+') 564: newng++; 565: } 566: else { 567: printf("\n%s",hforhelp) FLUSH; 568: settle_down(); 569: goto reask_reloc; 570: } 571: } 572: if (newng < nextrcline-1) { 573: #ifdef HASHNG 574: for (i=0; i<HASHSIZ; i++) { 575: if (hashtbl[i] == nextrcline-1) 576: hashtbl[i] = newng; 577: else if (hashtbl[i] >= newng) 578: ++hashtbl[i]; 579: } 580: #endif 581: tmprcline = rcline[nextrcline-1]; 582: tmptoread = toread[nextrcline-1]; 583: tmprcchar = rcchar[nextrcline-1]; 584: tmprcnums = rcnums[nextrcline-1]; 585: tmpsoftptr = softptr[nextrcline-1]; 586: #ifdef DEBUGGING 587: tmpngmax = ngmax[nextrcline-1]; 588: #endif 589: #ifdef CACHEFIRST 590: tmpabs1st = abs1st[nextrcline-1]; 591: #endif 592: for (i=nextrcline-2; i>=newng; i--) { 593: rcline[i+1] = rcline[i]; 594: toread[i+1] = toread[i]; 595: rcchar[i+1] = rcchar[i]; 596: rcnums[i+1] = rcnums[i]; 597: softptr[i+1] = softptr[i]; 598: #ifdef DEBUGGING 599: ngmax[i+1] = ngmax[i]; 600: #endif 601: #ifdef CACHEFIRST 602: abs1st[i+1] = abs1st[i]; 603: #endif 604: } 605: rcline[newng] = tmprcline; 606: toread[newng] = tmptoread; 607: rcchar[newng] = tmprcchar; 608: rcnums[newng] = tmprcnums; 609: softptr[newng] = tmpsoftptr; 610: #ifdef DEBUGGING 611: ngmax[newng] = tmpngmax; 612: #endif 613: #ifdef CACHEFIRST 614: abs1st[newng] = tmpabs1st; 615: #endif 616: } 617: if (current_ng >= newng) 618: current_ng++; 619: return newng; 620: } 621: #endif 622: 623: /* List out the newsrc with annotations */ 624: 625: void 626: list_newsgroups() 627: { 628: register NG_NUM i; 629: char tmpbuf[2048]; 630: static char *status[] = {"(READ)","(UNSUB)","(BOGUS)","(JUNK)"}; 631: int cmd; 632: 633: page_init(); 634: print_lines("\ 635: # Status Newsgroup\n\ 636: ",STANDOUT); 637: for (i=0; i<nextrcline && !int_count; i++) { 638: if (toread[i] >= 0) 639: set_toread(i); 640: *(rcline[i] + rcnums[i] - 1) = rcchar[i]; 641: if (toread[i] > 0) 642: sprintf(tmpbuf,"%3d %6ld ",i,(long)toread[i]); 643: else 644: sprintf(tmpbuf,"%3d %7s ",i,status[-toread[i]]); 645: safecpy(tmpbuf+13,rcline[i],2034); 646: *(rcline[i] + rcnums[i] - 1) = '\0'; 647: if (cmd = print_lines(tmpbuf,NOMARKING)) { 648: if (cmd > 0) 649: pushchar(cmd); 650: break; 651: } 652: } 653: int_count = 0; 654: } 655: 656: /* find a newsgroup in .newsrc */ 657: 658: NG_NUM 659: find_ng(ngnam) 660: char *ngnam; 661: { 662: register NG_NUM ngnum; 663: #ifdef HASHNG 664: register int hashix = hash(ngnam); 665: register int incr = 1; 666: 667: while ((ngnum = hashtbl[hashix]) >= 0) { 668: if (strEQ(rcline[ngnum], ngnam) && toread[ngnum] >= TR_UNSUB) 669: return ngnum; 670: hashix = (hashix + incr) % HASHSIZ; 671: incr += 2; /* offsets from original are in n*2 */ 672: } 673: return nextrcline; /* = notfound */ 674: 675: #else /* just do linear search */ 676: 677: for (ngnum = 0; ngnum < nextrcline; ngnum++) { 678: if (strEQ(rcline[ngnum],ngnam)) 679: break; 680: } 681: return ngnum; 682: #endif 683: } 684: 685: void 686: cleanup_rc() 687: { 688: register NG_NUM ngx; 689: register NG_NUM bogosity = 0; 690: 691: #ifdef VERBOSE 692: IF(verbose) 693: fputs("Checking out your .newsrc--hang on a second...\n",stdout) 694: FLUSH; 695: ELSE 696: #endif 697: #ifdef TERSE 698: fputs("Checking .newsrc--hang on...\n",stdout) FLUSH; 699: #endif 700: for (ngx = 0; ngx < nextrcline; ngx++) { 701: if (toread[ngx] >= TR_UNSUB) { 702: set_toread(ngx); /* this may reset newsgroup */ 703: /* or declare it bogus */ 704: } 705: if (toread[ngx] == TR_BOGUS) 706: bogosity++; 707: } 708: for (ngx = nextrcline-1; ngx >= 0 && toread[ngx] == TR_BOGUS; ngx--) 709: bogosity--; /* discount already moved ones */ 710: if (nextrcline > 5 && bogosity > nextrcline / 2) { 711: fputs( 712: "It looks like the active file is messed up. Contact your news administrator,\n\ 713: ",stdout); 714: fputs( 715: "leave the \"bogus\" groups alone, and they may come back to normal. Maybe.\n\ 716: ",stdout) FLUSH; 717: } 718: #ifdef RELOCATE 719: else if (bogosity) { 720: #ifdef VERBOSE 721: IF(verbose) 722: fputs("Moving bogus newsgroups to the end of your .newsrc.\n", 723: stdout) FLUSH; 724: ELSE 725: #endif 726: #ifdef TERSE 727: fputs("Moving boguses to the end.\n",stdout) FLUSH; 728: #endif 729: for (; ngx >= 0; ngx--) { 730: if (toread[ngx] == TR_BOGUS) 731: relocate_newsgroup(ngx,nextrcline-1); 732: } 733: #ifdef DELBOGUS 734: reask_bogus: 735: in_char("Delete bogus newsgroups? [ny] "); 736: putchar('\n') FLUSH; 737: setdef(buf,"n"); 738: #ifdef VERIFY 739: printcmd(); 740: #endif 741: if (*buf == 'h') { 742: #ifdef VERBOSE 743: IF(verbose) 744: fputs("\ 745: Type y to delete bogus newsgroups.\n\ 746: Type n or SP to leave them at the end in case they return.\n\ 747: ",stdout) FLUSH; 748: ELSE 749: #endif 750: #ifdef TERSE 751: fputs("y to delete, n to keep\n",stdout) FLUSH; 752: #endif 753: goto reask_bogus; 754: } 755: else if (*buf == 'n' || *buf == 'q') 756: ; 757: else if (*buf == 'y') { 758: while (toread[nextrcline-1] == TR_BOGUS && nextrcline > 0) 759: --nextrcline; /* real tough, huh? */ 760: } 761: else { 762: fputs(hforhelp,stdout) FLUSH; 763: settle_down(); 764: goto reask_bogus; 765: } 766: #endif 767: } 768: #else 769: #ifdef VERBOSE 770: IF(verbose) 771: fputs("You should edit bogus newsgroups out of your .newsrc.\n", 772: stdout) FLUSH; 773: ELSE 774: #endif 775: #ifdef TERSE 776: fputs("Edit boguses from .newsrc.\n",stdout) FLUSH; 777: #endif 778: #endif 779: paranoid = FALSE; 780: } 781: 782: #ifdef HASHNG 783: /* make an entry in the hash table for the current newsgroup */ 784: 785: void 786: sethash(thisng) 787: NG_NUM thisng; 788: { 789: register int hashix = hash(rcline[thisng]); 790: register int incr = 1; 791: #ifdef DEBUGGING 792: static int hashhits = 0, hashtries = 0; 793: #endif 794: 795: #ifdef DEBUGGING 796: hashtries++; 797: #endif 798: while (hashtbl[hashix] >= 0) { 799: #ifdef DEBUGGING 800: hashhits++; 801: if (debug & DEB_HASH) { 802: printf(" Hash hits: %d / %d\n",hashhits, hashtries) FLUSH; 803: } 804: hashtries++; 805: #endif 806: hashix = (hashix + incr) % HASHSIZ; 807: incr += 2; /* offsets from original are in n*2 */ 808: } 809: hashtbl[hashix] = thisng; 810: } 811: 812: short prime[] = {1,2,-3,-5,7,11,-13,-17,19,23,-29,-31,37,41,-43,-47,53,57,-59, 813: -61,67,71,-73,-79,83,89,-97,-101,1,1,1,1,1,1,1,1,1,1,1,1}; 814: 815: int 816: hash(ngnam) 817: register char *ngnam; 818: { 819: register int i = 0; 820: register int ch; 821: register int sum = 0; 822: #ifdef DEBUGGING 823: char *ngn = ngnam; 824: #endif 825: 826: while (ch = *ngnam++) { 827: sum += (ch + i) * prime[i]; /* gives ~ 10% hits at 25% full */ 828: i++; 829: } 830: #ifdef DEBUGGING 831: if (debug & DEB_HASH) 832: printf("hash(%s) => %d => %d\n",ngn, sum, (sum<0?-sum:sum)%HASHSIZ) 833: FLUSH; 834: #endif 835: if (sum < 0) 836: sum = -sum; 837: return sum % HASHSIZ; 838: } 839: 840: #endif 841: 842: void 843: newsrc_check() 844: { 845: rcfp = fopen(rcname,"r"); /* open it */ 846: if (rcfp == Nullfp) { /* not there? */ 847: #ifdef VERBOSE 848: IF(verbose) 849: fputs("\ 850: Trying to set up a .newsrc file--running newsetup...\n\n\ 851: ",stdout) FLUSH; 852: ELSE 853: #endif 854: #ifdef TERSE 855: fputs("Setting up .newsrc...\n",stdout) FLUSH; 856: #endif 857: if (doshell(sh,filexp(NEWSETUP)) || 858: (rcfp = fopen(rcname,"r")) == Nullfp) { 859: #ifdef VERBOSE 860: IF(verbose) 861: fputs("\ 862: Can't create a .newsrc--you must do it yourself.\n\ 863: ",stdout) FLUSH; 864: ELSE 865: #endif 866: #ifdef TERSE 867: fputs("(Fatal)\n",stdout) FLUSH; 868: #endif 869: finalize(1); 870: } 871: } 872: else { 873: UNLINK(rcbname); /* unlink backup file name */ 874: link(rcname,rcbname); /* and backup current name */ 875: } 876: } 877: 878: /* write out the (presumably) revised .newsrc */ 879: 880: void 881: write_rc() 882: { 883: register NG_NUM tmpng; 884: register char *delim; 885: 886: rcfp = fopen(rctname, "w"); /* open .newsrc */ 887: if (rcfp == Nullfp) { 888: printf("Can't recreate .newsrc\n") FLUSH; 889: finalize(1); 890: } 891: 892: /* write out each line*/ 893: 894: for (tmpng = 0; tmpng < nextrcline; tmpng++) { 895: if (rcnums[tmpng]) { 896: delim = rcline[tmpng] + rcnums[tmpng] - 1; 897: *delim = rcchar[tmpng]; 898: } 899: else 900: delim = Nullch; 901: #ifdef DEBUGGING 902: if (debug & DEB_NEWSRC_LINE) 903: printf("%s\n",rcline[tmpng]) FLUSH; 904: #endif 905: fprintf(rcfp,"%s\n",rcline[tmpng]); 906: if (delim) 907: *delim = '\0'; /* might still need this line */ 908: } 909: 910: fclose(rcfp); /* close .newsrc */ 911: UNLINK(rcname); 912: link(rctname,rcname); 913: UNLINK(rctname); 914: 915: if (writesoft) { 916: tmpfp = fopen(filexp(softname), "w"); /* open .rnsoft */ 917: if (tmpfp == Nullfp) { 918: printf(cantcreate,filexp(softname)) FLUSH; 919: return; 920: } 921: for (tmpng = 0; tmpng < nextrcline; tmpng++) { 922: fprintf(tmpfp,"%ld\n",(long)softptr[tmpng]); 923: } 924: fclose(tmpfp); 925: } 926: } 927: 928: void 929: get_old_rc() 930: { 931: UNLINK(rctname); 932: link(rcname,rctname); 933: UNLINK(rcname); 934: link(rcbname,rcname); 935: UNLINK(rcbname); 936: }