home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / rn_4_3_blars.lzh / rcstuff.c < prev    next >
Text File  |  1990-08-30  |  23KB  |  1,021 lines

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