BSD 4_3 development
[unix-history] / usr / contrib / rn / rcln.c
CommitLineData
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
23void
24rcln_init()
25{
26 ;
27}
28
29#ifdef CATCHUP
30void
31catch_up(ngx)
32NG_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
54int
55addartnum(artnum,ngnam)
56ART_NUM artnum;
57char *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
183void
184subartnum(artnum,ngnam)
185register ART_NUM artnum;
186char *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
297void
298prange(where,min,max)
299char *where;
300ART_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
311void
312set_toread(ngnum)
313register 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
385void
386checkexpired(ngnum,ngsize)
387register NG_NUM ngnum;
388ART_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
440ret:; /* 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