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