1: /* $Header: rcln.c,v 4.3.1.2 85/07/23 17:39:08 lwall Exp $ 2: * 3: * $Log: rcln.c,v $ 4: * Revision 4.3.1.2 85/07/23 17:39:08 lwall 5: * Oops, was freeing a static buf on -c in checkexpired. 6: * 7: * Revision 4.3.1.1 85/05/10 11:37:08 lwall 8: * Branch for patches. 9: * 10: * Revision 4.3 85/05/01 11:45:36 lwall 11: * Baseline for release with 4.3bsd. 12: * 13: */ 14: 15: #include "EXTERN.h" 16: #include "common.h" 17: #include "util.h" 18: #include "rcstuff.h" 19: #include "ngdata.h" 20: #include "INTERN.h" 21: #include "rcln.h" 22: 23: void 24: rcln_init() 25: { 26: ; 27: } 28: 29: #ifdef CATCHUP 30: void 31: catch_up(ngx) 32: NG_NUM ngx; 33: { 34: char tmpbuf[128]; 35: 36: #ifdef VERBOSE 37: IF(verbose) 38: printf("\nMarking %s as all read.\n",rcline[ngx]) FLUSH; 39: ELSE 40: #endif 41: #ifdef TERSE 42: fputs("\nMarked read\n",stdout) FLUSH; 43: #endif 44: sprintf(tmpbuf,"%s: 1-%ld", rcline[ngx],(long)getngsize(ngx)); 45: free(rcline[ngx]); 46: rcline[ngx] = savestr(tmpbuf); 47: *(rcline[ngx] + rcnums[ngx] - 1) = '\0'; 48: write_rc(); 49: } 50: #endif 51: 52: /* add an article number to a newsgroup, if it isn't already read */ 53: 54: int 55: addartnum(artnum,ngnam) 56: ART_NUM artnum; 57: char *ngnam; 58: { 59: register NG_NUM ngnum = find_ng(ngnam); 60: register char *s, *t, *maxt = Nullch; 61: ART_NUM min = 0, max = -1, lastnum = 0; 62: char *mbuf; 63: bool morenum; 64: 65: if (!artnum) 66: return 0; 67: if (ngnum == nextrcline || !rcnums[ngnum]) 68: /* not found in newsrc? */ 69: return 0; 70: #ifdef CACHEFIRST 71: if (!abs1st[ngnum]) 72: #else 73: if (!toread[ngnum]) 74: #endif 75: /* now is a good time to trim down */ 76: set_toread(ngnum); /* the list due to expires if we */ 77: /* have not yet. */ 78: #ifdef DEBUGGING 79: if (artnum > ngmax[ngnum] + 10 /* allow for incoming articles */ 80: ) { 81: printf("\nCorrupt Xref line!!! %ld --> %s(1..%ld)\n", 82: artnum,ngnam, 83: ngmax[ngnum]) FLUSH; 84: paranoid = TRUE; /* paranoia reigns supreme */ 85: return -1; /* hope this was the first newsgroup */ 86: } 87: #endif 88: 89: if (toread[ngnum] == TR_BOGUS) 90: return 0; 91: #ifdef DEBUGGING 92: if (debug & DEB_XREF_MARKER) { 93: printf("%ld->\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum], 94: rcline[ngnum] + rcnums[ngnum]) FLUSH; 95: } 96: #endif 97: s = rcline[ngnum] + rcnums[ngnum]; 98: while (*s == ' ') s++; /* skip spaces */ 99: t = s; 100: while (isdigit(*s) && artnum >= (min = atol(s))) { 101: /* while it might have been read */ 102: for (t = s; isdigit(*t); t++) ; /* skip number */ 103: if (*t == '-') { /* is it a range? */ 104: t++; /* skip to next number */ 105: if (artnum <= (max = atol(t))) 106: return 0; /* it is in range => already read */ 107: lastnum = max; /* remember it */ 108: maxt = t; /* remember position in case we */ 109: /* want to overwrite the max */ 110: while (isdigit(*t)) t++; /* skip second number */ 111: } 112: else { 113: if (artnum == min) /* explicitly a read article? */ 114: return 0; 115: lastnum = min; /* remember what the number was */ 116: maxt = Nullch; /* last one was not a range */ 117: } 118: while (*t && !isdigit(*t)) t++; /* skip comma and any spaces */ 119: s = t; 120: } 121: 122: /* we have not read it, so insert the article number before s */ 123: 124: morenum = isdigit(*s); /* will it need a comma after? */ 125: *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum]; 126: mbuf = safemalloc((MEM_SIZE)(strlen(s) + (s-rcline[ngnum]) + 8)); 127: strcpy(mbuf,rcline[ngnum]); /* make new rc line */ 128: if (maxt && lastnum && artnum == lastnum+1) 129: /* can we just extend last range? */ 130: t = mbuf + (maxt-rcline[ngnum]);/* then overwrite previous max */ 131: else { 132: t = mbuf + (t-rcline[ngnum]); /* point t into new line instead */ 133: if (lastnum) { /* have we parsed any line? */ 134: if (!morenum) /* are we adding to the tail? */ 135: *t++ = ','; /* supply comma before */ 136: if (!maxt && artnum == lastnum+1 && *(t-1) == ',') 137: /* adjacent singletons? */ 138: *(t-1) = '-'; /* turn them into a range */ 139: } 140: } 141: if (morenum) { /* is there more to life? */ 142: if (min == artnum+1) { /* can we consolidate further? */ 143: bool range_before = (*(t-1) == '-'); 144: bool range_after; 145: char *nextmax; 146: 147: for (nextmax = s; isdigit(*nextmax); nextmax++) ; 148: range_after = *nextmax++ == '-'; 149: 150: if (range_before) 151: *t = '\0'; /* artnum is redundant */ 152: else 153: sprintf(t,"%ld-",(long)artnum);/* artnum will be new min */ 154: 155: if (range_after) 156: s = nextmax; /* *s is redundant */ 157: /* else 158: s = s */ /* *s is new max */ 159: } 160: else 161: sprintf(t,"%ld,",(long)artnum); /* put the number and comma */ 162: } 163: else 164: sprintf(t,"%ld",(long)artnum); /* put the number there (wherever) */ 165: strcat(t,s); /* copy remainder of line */ 166: #ifdef DEBUGGING 167: if (debug & DEB_XREF_MARKER) { 168: printf("%s\n",mbuf) FLUSH; 169: } 170: #endif 171: free(rcline[ngnum]); 172: rcline[ngnum] = mbuf; /* pull the switcheroo */ 173: *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0'; 174: /* wipe out : or ! */ 175: if (toread[ngnum] > TR_NONE) /* lest we turn unsub into bogus */ 176: --toread[ngnum]; 177: return 0; 178: } 179: 180: #ifdef MCHASE 181: /* delete an article number from a newsgroup, if it is there */ 182: 183: void 184: subartnum(artnum,ngnam) 185: register ART_NUM artnum; 186: char *ngnam; 187: { 188: register NG_NUM ngnum = find_ng(ngnam); 189: register char *s, *t; 190: register ART_NUM min, max; 191: char *mbuf; 192: int curlen; 193: 194: if (!artnum) 195: return; 196: if (ngnum == nextrcline || !rcnums[ngnum]) 197: return; /* not found in newsrc? */ 198: #ifdef DEBUGGING 199: if (debug & DEB_XREF_MARKER) { 200: printf("%ld<-\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum], 201: rcline[ngnum] + rcnums[ngnum]) FLUSH; 202: } 203: #endif 204: s = rcline[ngnum] + rcnums[ngnum]; 205: while (*s == ' ') s++; /* skip spaces */ 206: 207: /* a little optimization, since it is almost always the last number */ 208: 209: for (t=s; *t; t++) ; /* find end of string */ 210: curlen = t-rcline[ngnum]; 211: for (t--; isdigit(*t); t--) ; /* find previous delim */ 212: if (*t == ',' && atol(t+1) == artnum) { 213: *t = '\0'; 214: if (toread[ngnum] >= TR_NONE) 215: ++toread[ngnum]; 216: #ifdef DEBUGGING 217: if (debug & DEB_XREF_MARKER) 218: printf("%s%c %s\n",rcline[ngnum],rcchar[ngnum],s) FLUSH; 219: #endif 220: return; 221: } 222: 223: /* not the last number, oh well, we may need the length anyway */ 224: 225: while (isdigit(*s) && artnum >= (min = atol(s))) { 226: /* while it might have been read */ 227: for (t = s; isdigit(*t); t++) ; /* skip number */ 228: if (*t == '-') { /* is it a range? */ 229: t++; /* skip to next number */ 230: max = atol(t); 231: while (isdigit(*t)) t++; /* skip second number */ 232: if (artnum <= max) { 233: /* it is in range => already read */ 234: if (artnum == min) { 235: min++; 236: artnum = 0; 237: } 238: else if (artnum == max) { 239: max--; 240: artnum = 0; 241: } 242: *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum]; 243: mbuf = safemalloc((MEM_SIZE)(curlen + (artnum?15:2))); 244: *s = '\0'; 245: strcpy(mbuf,rcline[ngnum]); /* make new rc line */ 246: s = mbuf + (s-rcline[ngnum]); 247: /* point s into mbuf now */ 248: if (artnum) { /* split into two ranges? */ 249: prange(s,min,artnum-1); 250: s += strlen(s); 251: *s++ = ','; 252: prange(s,artnum+1,max); 253: } 254: else /* only one range */ 255: prange(s,min,max); 256: s += strlen(s); 257: strcpy(s,t); /* copy remainder over */ 258: #ifdef DEBUGGING 259: if (debug & DEB_XREF_MARKER) { 260: printf("%s\n",mbuf) FLUSH; 261: } 262: #endif 263: free(rcline[ngnum]); 264: rcline[ngnum] = mbuf; /* pull the switcheroo */ 265: *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0'; 266: /* wipe out : or ! */ 267: if (toread[ngnum] >= TR_NONE) 268: ++toread[ngnum]; 269: return; 270: } 271: } 272: else { 273: if (artnum == min) { /* explicitly a read article? */ 274: if (*t == ',') /* pick a comma, any comma */ 275: t++; 276: else if (s[-1] == ',') 277: s--; 278: else if (s[-2] == ',') /* (in case of space) */ 279: s -= 2; 280: strcpy(s,t); /* no need to realloc */ 281: if (toread[ngnum] >= TR_NONE) 282: ++toread[ngnum]; 283: #ifdef DEBUGGING 284: if (debug & DEB_XREF_MARKER) { 285: printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum], 286: rcline[ngnum] + rcnums[ngnum]) FLUSH; 287: } 288: #endif 289: return; 290: } 291: } 292: while (*t && !isdigit(*t)) t++; /* skip comma and any spaces */ 293: s = t; 294: } 295: } 296: 297: void 298: prange(where,min,max) 299: char *where; 300: ART_NUM min,max; 301: { 302: if (min == max) 303: sprintf(where,"%ld",(long)min); 304: else 305: sprintf(where,"%ld-%ld",(long)min,(long)max); 306: } 307: #endif 308: 309: /* calculate the number of unread articles for a newsgroup */ 310: 311: void 312: set_toread(ngnum) 313: register NG_NUM ngnum; 314: { 315: register char *s, *c, *h; 316: char tmpbuf[64], *mybuf = tmpbuf; 317: char *nums; 318: int length; 319: #ifdef CACHEFIRST 320: bool virgin_ng = (!abs1st[ngnum]); 321: #endif 322: ART_NUM ngsize = getngsize(ngnum); 323: ART_NUM unread = ngsize; 324: ART_NUM newmax; 325: 326: #ifdef DEBUGGING 327: ngmax[ngnum] = ngsize; /* for checking out-of-range Xrefs */ 328: #endif 329: if (ngsize == TR_BOGUS) { 330: printf("Warning! Bogus newsgroup: %s\n",rcline[ngnum]) FLUSH; 331: paranoid = TRUE; 332: toread[ngnum] = TR_BOGUS; 333: return; 334: } 335: #ifdef CACHEFIRST 336: if (virgin_ng) 337: #else 338: if (!toread[ngnum]) 339: #endif 340: { 341: sprintf(tmpbuf," 1-%ld",(long)ngsize); 342: if (strNE(tmpbuf,rcline[ngnum]+rcnums[ngnum])) 343: checkexpired(ngnum,ngsize); /* this might realloc rcline */ 344: } 345: nums = rcline[ngnum]+rcnums[ngnum]; 346: length = strlen(nums); 347: if (length >= 60) 348: mybuf = safemalloc((MEM_SIZE)(length+5)); 349: strcpy(mybuf,nums); 350: mybuf[length++] = ','; 351: mybuf[length] = '\0'; 352: for (s = mybuf; isspace(*s); s++) 353: ; 354: for ( ; (c = index(s,',')) != Nullch ; s = ++c) { 355: /* for each range */ 356: *c = '\0'; /* keep index from running off */ 357: if ((h = index(s,'-')) != Nullch) /* find - in range, if any */ 358: unread -= (newmax = atol(h+1)) - atol(s) + 1; 359: else if (newmax = atol(s)) 360: unread--; /* recalculate length */ 361: if (newmax > ngsize) { /* paranoia check */ 362: unread = -1; 363: break; 364: } 365: } 366: if (unread >= 0) /* reasonable number? */ 367: toread[ngnum] = (ART_UNREAD)unread; 368: /* remember how many are left */ 369: else { /* SOMEONE RESET THE NEWSGROUP!!! */ 370: toread[ngnum] = (ART_UNREAD)ngsize; 371: /* assume nothing carried over */ 372: printf("Warning! Somebody reset %s--assuming nothing read.\n", 373: rcline[ngnum]) FLUSH; 374: *(rcline[ngnum] + rcnums[ngnum]) = '\0'; 375: paranoid = TRUE; /* enough to make a guy paranoid */ 376: } 377: if (mybuf != tmpbuf) 378: free(mybuf); 379: if (rcchar[ngnum] == NEGCHAR) 380: toread[ngnum] = TR_UNSUB; 381: } 382: 383: /* make sure expired articles are marked as read */ 384: 385: void 386: checkexpired(ngnum,ngsize) 387: register NG_NUM ngnum; 388: ART_NUM ngsize; 389: { 390: register ART_NUM a1st = getabsfirst(ngnum,ngsize); 391: register char *s, *t; 392: register ART_NUM num, lastnum = 0; 393: char *mbuf, *newnum; 394: 395: if (a1st<=1) 396: return; 397: #ifdef DEBUGGING 398: if (debug & DEB_XREF_MARKER) { 399: printf("1-%ld->\n%s%c%s\n",(long)(a1st-1),rcline[ngnum],rcchar[ngnum], 400: rcline[ngnum] + rcnums[ngnum]) FLUSH; 401: } 402: #endif 403: for (s = rcline[ngnum] + rcnums[ngnum]; isspace(*s); s++); 404: while (*s && (num = atol(s)) <= a1st) { 405: while (isdigit(*s)) s++; 406: while (*s && !isdigit(*s)) s++; 407: lastnum = num; 408: } 409: if (*s) { 410: if (s[-1] == '-') { /* landed in a range? */ 411: if (lastnum != 1) 412: sprintf(rcline[ngnum]+rcnums[ngnum]," 1-%s",s); 413: goto ret; 414: } 415: } 416: /* s now points to what should follow first range */ 417: if (s - rcline[ngnum] > rcnums[ngnum] + 10) 418: mbuf = rcline[ngnum]; 419: else { 420: mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + strlen(s) + 10)); 421: strcpy(mbuf,rcline[ngnum]); 422: } 423: newnum = t = mbuf+rcnums[ngnum]; 424: sprintf(t," 1-%ld",(long)(a1st - (lastnum != a1st))); 425: if (*s) { 426: t += strlen(t); 427: *t++ = ','; 428: strcpy(t,s); 429: } 430: if (mbuf == rcline[ngnum]) { 431: rcline[ngnum] = saferealloc(rcline[ngnum], 432: (MEM_SIZE)(rcnums[ngnum] + strlen(newnum) + 1)); 433: } 434: else { 435: if (!checkflag) 436: free(rcline[ngnum]); 437: rcline[ngnum] = mbuf; 438: } 439: 440: ret:; /* semicolon in case DEBUGGING undefined */ 441: #ifdef DEBUGGING 442: if (debug & DEB_XREF_MARKER) { 443: printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum], 444: rcline[ngnum] + rcnums[ngnum]) FLUSH; 445: } 446: #endif 447: }