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