1 /* xover.c */
2
3 #include "common.h"
4 #include "overview.h"
5 #include "xover.h"
6 #ifndef lint
7 static char sccsid[] = "$Id: xover.c,v 1.2 1994/11/01 06:08:21 sob Exp sob $";
8 #endif
9 #if defined(XOVER) || defined(XROVER)
10 void
numlist(argc,argv,obj)11 numlist(argc, argv, obj)
12 int argc;
13 char *argv[];
14 struct xobj *obj;
15 {
16 register int low, high;
17 int artnum, artptr;
18 FILE *fp;
19
20 if (!canread) {
21 printf("%d You only have permission to transfer, sorry.\r\n",
22 ERR_ACCESS);
23 (void) fflush(stdout);
24 return;
25 }
26
27 if (!ingroup) {
28 printf("%d You are not currently in a newsgroup.\r\n",
29 ERR_NCING);
30 (void) fflush(stdout);
31 return;
32 }
33 if (argc != 1 && argc != 2) {
34 printf("%d Usage: %s [artrange]\r\n", ERR_CMDSYN, obj->cmd);
35 (void) fflush(stdout);
36 return;
37 }
38
39 if (argc == 1) {
40 if (art_ptr < 0 || art_ptr >= num_arts) {
41 printf("%d No article is currently selected.\r\n",
42 ERR_NOCRNT);
43 (void) fflush(stdout);
44 return;
45 }
46 high = low = art_array[art_ptr];
47 artptr = art_ptr;
48 } else {
49 register char *cp = index(argv[1], '-');
50 if (cp == NULL)
51 low = high = atoi(argv[1]);
52 else {
53 *cp++ = '\0';
54 low = atoi(argv[1]);
55 high = atoi(cp);
56 if (high < low) {
57 if (num_arts > 0)
58 high = art_array[num_arts-1];
59 else
60 high = low;
61 }
62 }
63 artptr = 0;
64 }
65
66 xfind(obj, low);
67 fp = obj->fp;
68
69 /* Return the desired data. This is written carefully to avoid
70 * over-long lines. */
71 printf("%d %s data follows\r\n", OK_OVER, obj->name);
72
73 for (;artptr < num_arts; artptr++) {
74 if ((artnum = art_array[artptr]) < low)
75 continue;
76 if (artnum > high)
77 break;
78
79 if (obj->num > 0 && obj->num < artnum)
80 xfind(obj, artnum);
81 if (obj->num == artnum) {
82 register int c;
83 printf("%d", artnum);
84 while ((c = getc(fp)) != EOF && c != '\n')
85 putchar(c);
86 if (fscanf(fp, "%d", &obj->num) != 1)
87 obj->num = -1;
88 printf("\r\n");
89 } else {
90 printf("%d", artnum);
91 (obj->fake)(artnum);
92 }
93 }
94 printf(".\r\n");
95 (void) fflush(stdout);
96 }
97 #endif
98
99 #ifdef XOVER
100 FILE *over_open(void);
101 void over_fake(int artnum);
102 struct xobj over = {0,-1,0,over_open,over_fake,"overview","XOVER"};
103
104 void
doxover(argc,argv)105 doxover(argc, argv)
106 int argc;
107 char *argv[];
108 {
109 numlist(argc, argv, &over);
110 }
111
112 int
over_is_cheap(low,high)113 over_is_cheap(low, high)
114 int low, high;
115 {
116 if (over.fp)
117 return 1;
118 if (over.open_tried)
119 return 0;
120 return high >= low;
121 }
122
123 FILE *
over_open()124 over_open()
125 {
126 FILE *fp;
127 #ifdef OVERVIEW_DIR
128 char name_buff[MAXPATHLEN], *cp;
129 sprintf(name_buff, "%s/", OVERVIEW_DIR);
130 cp = name_buff + strlen(name_buff);
131 strcpy(cp, group_name);
132 while ((cp = index(cp, '.')) != (char *) NULL)
133 *cp = '/';
134 sprintf(name_buff+strlen(name_buff), "/%s", OVER_NAME);
135 fp = fopen(name_buff, "r");
136 #else
137 fp = fopen(OVER_NAME, "r");
138 #endif
139 return fp;
140 }
141
142 #define TOLOWER(c) (isupper(c) ? tolower(c) : (c))
143
144 int
over_header(s)145 over_header(s)
146 const char *s;
147 {
148 int i;
149 char ch;
150 ch = (isascii(*s)? TOLOWER(*s) : *s);
151
152 for (i = 1; i < OVER_FIELD_COUNT; i++) {
153 if (ch == *over_field[i]) {
154 if (strcasecmp(s, over_field[i]) == 0)
155 return i;
156 #ifdef OVER_UNIQUE_1ST_LTRS
157 /* optimization assumes no 2 keywords w/same 1st ltr */
158 break;
159 #endif
160 }
161 }
162 return -1;
163 }
164
165 char *
over_grab_header(hdr,output)166 over_grab_header(hdr, output)
167 int hdr;
168 int output;
169 {
170 int c;
171 int i = hdr;
172 char *buf = NULL;
173
174 #ifdef OVER_GROUP_FIELD
175 if (i > OVER_GROUP_FIELD)
176 i = OVER_GROUP_FIELD;
177 #endif
178 while (i--) {
179 while ((c = getc(over.fp)) != '\t')
180 if (c == EOF || c == '\n')
181 goto no_contents;
182 }
183 c = getc(over.fp);
184 #ifdef OVER_GROUP_FIELD
185 if (hdr >= OVER_GROUP_FIELD) {
186 for (i = 0; c != EOF && c != '\n'; i++) {
187 if (c == ':' && !over_field[hdr][i]) {
188 do {
189 c = getc(over.fp);
190 } while (c == ' ');
191 break;
192 }
193 if (TOLOWER(c) != over_field[hdr][i]) {
194 while (c != '\t') {
195 if (c == EOF || c == '\n')
196 goto no_contents;
197 c = getc(over.fp);
198 }
199 i = -1;
200 }
201 c = getc(over.fp);
202 }
203 }
204 #endif
205 if (c == EOF || c == '\n' || c == '\t') {
206 no_contents:
207 if (output)
208 printf("(none)\r\n");
209 } else if (output) {
210 do {
211 putchar(c);
212 c = getc(over.fp);
213 } while (c != EOF && c != '\n' && c != '\t');
214 printf("\r\n");
215 } else {
216 register int size = 1024;
217 buf = malloc(size);
218 if (buf) {
219 register int pos = 0;
220 do {
221 if (pos >= size-1) {
222 size += 1024;
223 buf = realloc(buf, size);
224 if (!buf)
225 break;
226 }
227 buf[pos++] = c;
228 c = getc(over.fp);
229 } while (c != EOF && c != '\n' && c != '\t');
230 if (buf)
231 buf[pos] = '\0';
232 }
233 }
234 while (c != EOF && c != '\n')
235 c = getc(over.fp);
236 if (c == EOF || fscanf(over.fp, "%d", &over.num) != 1)
237 over.num = -1;
238 return buf;
239 }
240
241 void
over_fake(artnum)242 over_fake(artnum)
243 int artnum;
244 {
245 char line[NNTP_STRLEN];
246 register FILE *fp;
247 register char *cp, *cp2;
248 register int hdr;
249 char *array[OVER_FIELD_COUNT];
250
251 (void) sprintf(line, "%d", artnum);
252 fp = fopen(line, "r");
253 if (fp == NULL)
254 return;
255
256 for (hdr = OVER_FIELD_COUNT-1; hdr > 0; hdr--) {
257 array[hdr] = 0;
258 }
259 cp = line;
260 while (fgets(line, sizeof line, fp) != NULL) {
261 if (cp && *line == '\n') {
262 break;
263 }
264 cp2 = cp;
265 cp = index(line, '\n');
266 if (!cp2 || isspace(*line)) {
267 if (hdr > 0 && array[hdr]) {
268 register int len = strlen(array[hdr]);
269 if (cp2) {
270 for (cp2 = line+1; isspace(*cp2); cp2++)
271 ;
272 *--cp2 = ' ';
273 }
274 else
275 cp2 = line;
276 if (cp)
277 *cp = '\0';
278 array[hdr] = realloc(array[hdr],
279 strlen(cp2) + len + 1);
280 if (array[hdr])
281 strcpy(array[hdr] + len, cp2);
282 }
283 } else if ((cp2 = index(line, ':')) != NULL) {
284 *cp2 = '\0';
285 if ((hdr = over_header(line)) > 0) {
286 if (array[hdr])
287 continue; /* a duplicate header?!? */
288 cp2 += 2;
289 if (cp)
290 *cp = '\0';
291 array[hdr] = malloc(strlen(cp2) + 1);
292 if (array[hdr])
293 strcpy(array[hdr], cp2);
294 }
295 } else
296 hdr = 0;
297 }
298
299 for (hdr = 1; hdr < OVER_FIELD_COUNT; hdr++) {
300 putchar('\t');
301 if (array[hdr]) {
302 #if defined(OVER_XREFS) && defined(OVER_XREF_PREFIX)
303 if (hdr == 8)
304 printf("xref: ");
305 #endif
306 printf("%s", array[hdr]);
307 free(array[hdr]);
308 } else if (hdr == 6) { /* Fudge the byte header */
309 struct stat s;
310 fstat(fileno(fp), &s);
311 printf("%ld", s.st_size);
312 }
313 }
314 printf("\r\n");
315
316 (void) fclose(fp);
317 }
318 #endif
319
320 #ifdef XROVER
321 FILE *rover_open();
322 void rover_fake();
323 struct xobj rover = {0,-1,0,rover_open,rover_fake,"reference","XROVER"};
324
325 void
doxrover(argc,argv)326 doxrover(argc, argv)
327 int argc;
328 char *argv[];
329 {
330 numlist(argc, argv, &rover);
331 }
332
333 FILE *
rover_open()334 rover_open()
335 {
336 FILE *fp;
337 #ifdef ROVER_DIR
338 char name_buff[MAXPATHLEN], *cp;
339 sprintf(name_buff, "%s/", ROVER_DIR);
340 cp = name_buff + strlen(name_buff);
341 strcpy(cp, group_name);
342 while ((cp = index(cp, '.')) != (char *) NULL)
343 *cp = '/';
344 sprintf(name_buff+strlen(name_buff), "/%s", ROVER_NAME);
345 fp = fopen(name_buff, "r");
346 #else
347 fp = fopen(ROVER_NAME, "r");
348 #endif
349 return fp;
350 }
351
352 void
rover_fake(artnum)353 rover_fake(artnum)
354 int artnum;
355 {
356 char line[NNTP_STRLEN];
357 register FILE *fp;
358 register char *cp, *cp2;
359 char *references = NULL;
360
361 #ifdef XOVER
362 if (over_is_cheap(artnum, artnum)) {
363 int hdr = over_header("references");
364 if (hdr >= 0 && xfind(&over, artnum)) {
365 references = over_grab_header(hdr, 0);
366 goto output_refs;
367 }
368 }
369 #endif
370 (void) sprintf(line, "%d", artnum);
371 fp = fopen(line, "r");
372 if (fp == NULL)
373 return;
374
375 cp = line;
376 while (fgets(line, sizeof line, fp) != NULL) {
377 if (cp && *line == '\n') {
378 break;
379 }
380 cp2 = cp;
381 cp = index(line, '\n');
382 if (!cp2 || isspace(*line)) {
383 if (references) {
384 register int len = strlen(references);
385 if (cp2) {
386 for (cp2 = line+1; isspace(*cp2); cp2++)
387 ;
388 *--cp2 = ' ';
389 }
390 else
391 cp2 = line;
392 if (cp)
393 *cp = '\0';
394 references = realloc(references,
395 strlen(cp2) + len + 1);
396 if (references)
397 strcpy(references + len, cp2);
398 }
399 } else if (references)
400 break;
401 else if ((cp2 = index(line, ':')) != NULL) {
402 *cp2 = '\0';
403 if (strcasecmp(line, "references") == 0) {
404 cp2 += 2;
405 if (cp)
406 *cp = '\0';
407 references = malloc(strlen(cp2) + 1);
408 if (references)
409 strcpy(references, cp2);
410 }
411 }
412 }
413
414 (void) fclose(fp);
415
416 #ifdef XOVER
417 output_refs:
418 #endif
419 if (references) {
420 cp2 = references + strlen(references) - 1;
421 while ((cp = rindex(references, '<')) != NULL) {
422 while (cp2 >= cp
423 && ((unsigned char)*cp2 <= ' ' || *cp2 == ','))
424 cp2--;
425 cp2[1] = '\0';
426 /* Quit parsing references if this one is garbage. */
427 if (!valid_message_id(cp, cp2))
428 break;
429 /* Dump all domains that end in '.' */
430 if (cp2[-1] == '.')
431 break;
432 if (!gethistent(cp, 0) || group_artnum == 0)
433 printf(" %s", cp);
434 else {
435 printf(" %ld", group_artnum);
436 break;
437 }
438 *cp = '\0';
439 cp2 = cp-1;
440 }
441 free(references);
442 }
443 printf("\r\n");
444 }
445
446 /* Check if the string we've found looks like a valid message-id reference.
447 */
448 int
valid_message_id(start,end)449 valid_message_id(start, end)
450 register char *start, *end;
451 {
452 char *mid;
453
454 if (start == end)
455 return 0;
456
457 if (*end != '>') {
458 /* Compensate for space cadets who include the header in their
459 ** subsitution of all '>'s into another citation character. */
460 if (*end == '<' || *end == '-' || *end == '!' || *end == '%'
461 || *end == ')' || *end == '|' || *end == ':' || *end == '}'
462 || *end == '*' || *end == '+' || *end == '#' || *end == ']'
463 || *end == '@' || *end == '$')
464 *end = '>';
465 } else if (end[-1] == '>') {
466 *(end--) = '\0';
467 }
468 /* Id must be "<...@...>" */
469 if (*start != '<' || *end != '>' || (mid = index(start, '@')) == NULL
470 || mid == start+1 || mid+1 == end)
471 return 0;
472 return 1;
473 }
474 #endif
475
476 #if defined(XOVER) || defined(XROVER)
477 int
xfind(obj,artnum)478 xfind(obj, artnum)
479 struct xobj *obj;
480 int artnum;
481 {
482 FILE *fp = obj->fp;
483 int file_num = obj->num;
484 if (fp) {
485 if (file_num < 0 || file_num > artnum) {
486 fseek(fp, 0L, 0);
487 file_num = 0;
488 }
489 } else {
490 if (!obj->open_tried)
491 obj->fp = fp = (obj->open)();
492 obj->open_tried = 1;
493 if (!fp) {
494 obj->num = -1;
495 return 0;
496 }
497 file_num = 0;
498 }
499 if (!file_num)
500 fscanf(fp, "%d", &file_num);
501 while (1) {
502 register int c;
503 if (feof(fp)) {
504 file_num = -1;
505 break;
506 }
507 if (file_num >= artnum) {
508 break;
509 }
510 while ((c = getc(fp)) != EOF && c != '\n')
511 continue;
512 fscanf(fp, "%d", &file_num);
513 }
514 obj->num = file_num;
515 return file_num == artnum;
516 }
517
518 void
xclose(obj)519 xclose(obj)
520 struct xobj *obj;
521 {
522 if (obj->fp) {
523 fclose(obj->fp);
524 obj->fp = NULL;
525 obj->num = -1;
526 }
527 obj->open_tried = 0;
528 }
529
530 void
close_xfiles()531 close_xfiles()
532 {
533 #ifdef XOVER
534 xclose(&over);
535 #endif
536 #ifdef XROVER
537 xclose(&rover);
538 #endif
539 }
540 #endif
541