Commit | Line | Data |
---|---|---|
aa875b17 C |
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 | } | |
448 |