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