/* xover.c */ #include "common.h" #include "overview.h" #include "xover.h" #ifndef lint static char sccsid[] = "$Id: xover.c,v 1.2 1994/11/01 06:08:21 sob Exp sob $"; #endif #if defined(XOVER) || defined(XROVER) void numlist(argc, argv, obj) int argc; char *argv[]; struct xobj *obj; { register int low, high; int artnum, artptr; FILE *fp; if (!canread) { printf("%d You only have permission to transfer, sorry.\r\n", ERR_ACCESS); (void) fflush(stdout); return; } if (!ingroup) { printf("%d You are not currently in a newsgroup.\r\n", ERR_NCING); (void) fflush(stdout); return; } if (argc != 1 && argc != 2) { printf("%d Usage: %s [artrange]\r\n", ERR_CMDSYN, obj->cmd); (void) fflush(stdout); return; } if (argc == 1) { if (art_ptr < 0 || art_ptr >= num_arts) { printf("%d No article is currently selected.\r\n", ERR_NOCRNT); (void) fflush(stdout); return; } high = low = art_array[art_ptr]; artptr = art_ptr; } else { register char *cp = index(argv[1], '-'); if (cp == NULL) low = high = atoi(argv[1]); else { *cp++ = '\0'; low = atoi(argv[1]); high = atoi(cp); if (high < low) if (num_arts > 0) high = art_array[num_arts-1]; else high = low; } artptr = 0; } xfind(obj, low); fp = obj->fp; /* Return the desired data. This is written carefully to avoid * over-long lines. */ printf("%d %s data follows\r\n", OK_OVER, obj->name); for (;artptr < num_arts; artptr++) { if ((artnum = art_array[artptr]) < low) continue; if (artnum > high) break; if (obj->num > 0 && obj->num < artnum) xfind(obj, artnum); if (obj->num == artnum) { register int c; printf("%d", artnum); while ((c = getc(fp)) != EOF && c != '\n') putchar(c); if (fscanf(fp, "%d", &obj->num) != 1) obj->num = -1; printf("\r\n"); } else { printf("%d", artnum); (obj->fake)(artnum); } } printf(".\r\n"); (void) fflush(stdout); } #endif #ifdef XOVER FILE *over_open(); void over_fake(); struct xobj over = {0,-1,0,over_open,over_fake,"overview","XOVER"}; void doxover(argc, argv) int argc; char *argv[]; { numlist(argc, argv, &over); } int over_is_cheap(low, high) int low, high; { if (over.fp) return 1; if (over.open_tried) return 0; return high >= low; } FILE * over_open() { FILE *fp; #ifdef OVERVIEW_DIR char name_buff[MAXPATHLEN], *cp; sprintf(name_buff, "%s/", OVERVIEW_DIR); cp = name_buff + strlen(name_buff); strcpy(cp, group_name); while ((cp = index(cp, '.')) != (char *) NULL) *cp = '/'; sprintf(name_buff+strlen(name_buff), "/%s", OVER_NAME); fp = fopen(name_buff, "r"); #else fp = fopen(OVER_NAME, "r"); #endif return fp; } #define TOLOWER(c) (isupper(c) ? tolower(c) : (c)) int over_header(s) char *s; { int i; char ch; ch = (isascii(*s)? TOLOWER(*s) : *s); for (i = 1; i < OVER_FIELD_COUNT; i++) { if (ch == *over_field[i]) { if (strcasecmp(s, over_field[i]) == 0) return i; #ifdef OVER_UNIQUE_1ST_LTRS /* optimization assumes no 2 keywords w/same 1st ltr */ break; #endif } } return -1; } char * over_grab_header(hdr, output) int hdr; int output; { int c; int i = hdr; char *buf = NULL; #ifdef OVER_GROUP_FIELD if (i > OVER_GROUP_FIELD) i = OVER_GROUP_FIELD; #endif while (i--) { register int c; while ((c = getc(over.fp)) != '\t') if (c == EOF || c == '\n') goto no_contents; } c = getc(over.fp); #ifdef OVER_GROUP_FIELD if (hdr >= OVER_GROUP_FIELD) { for (i = 0; c != EOF && c != '\n'; i++) { if (c == ':' && !over_field[hdr][i]) { do { c = getc(over.fp); } while (c == ' '); break; } if (TOLOWER(c) != over_field[hdr][i]) { while (c != '\t') { if (c == EOF || c == '\n') goto no_contents; c = getc(over.fp); } i = -1; } c = getc(over.fp); } } #endif if (c == EOF || c == '\n' || c == '\t') { no_contents: if (output) printf("(none)\r\n"); } else if (output) { do { putchar(c); c = getc(over.fp); } while (c != EOF && c != '\n' && c != '\t'); printf("\r\n"); } else { #ifndef __FreeBSD__ char *malloc(), *realloc(); #endif register int size = 1024; buf = malloc(size); if (buf) { register int pos = 0; do { if (pos >= size-1) { size += 1024; buf = realloc(buf, size); if (!buf) break; } buf[pos++] = c; c = getc(over.fp); } while (c != EOF && c != '\n' && c != '\t'); if (buf) buf[pos] = '\0'; } } while (c != EOF && c != '\n') c = getc(over.fp); if (c == EOF || fscanf(over.fp, "%d", &over.num) != 1) over.num = -1; return buf; } void over_fake(artnum) int artnum; { char line[NNTP_STRLEN]; register FILE *fp; register char *cp, *cp2; register int hdr; char *array[OVER_FIELD_COUNT]; #ifndef __FreeBSD__ char *malloc(), *realloc(); #endif (void) sprintf(line, "%d", artnum); fp = fopen(line, "r"); if (fp == NULL) return; for (hdr = OVER_FIELD_COUNT-1; hdr > 0; hdr--) { array[hdr] = 0; } cp = line; while (fgets(line, sizeof line, fp) != NULL) { if (cp && *line == '\n') { break; } cp2 = cp; cp = index(line, '\n'); if (!cp2 || isspace(*line)) { if (hdr > 0 && array[hdr]) { register int len = strlen(array[hdr]); if (cp2) { for (cp2 = line+1; isspace(*cp2); cp2++) ; *--cp2 = ' '; } else cp2 = line; if (cp) *cp = '\0'; array[hdr] = realloc(array[hdr], strlen(cp2) + len + 1); if (array[hdr]) strcpy(array[hdr] + len, cp2); } } else if ((cp2 = index(line, ':')) != NULL) { *cp2 = '\0'; if ((hdr = over_header(line)) > 0) { if (array[hdr]) continue; /* a duplicate header?!? */ cp2 += 2; if (cp) *cp = '\0'; array[hdr] = malloc(strlen(cp2) + 1); if (array[hdr]) strcpy(array[hdr], cp2); } } else hdr = 0; } for (hdr = 1; hdr < OVER_FIELD_COUNT; hdr++) { putchar('\t'); if (array[hdr]) { #if defined(OVER_XREFS) && defined(OVER_XREF_PREFIX) if (hdr == 8) printf("xref: "); #endif printf("%s", array[hdr]); free(array[hdr]); } else if (hdr == 6) { /* Fudge the byte header */ struct stat s; fstat(fileno(fp), &s); printf("%u", s.st_size); } } printf("\r\n"); (void) fclose(fp); } #endif #ifdef XROVER FILE *rover_open(); void rover_fake(); struct xobj rover = {0,-1,0,rover_open,rover_fake,"reference","XROVER"}; void doxrover(argc, argv) int argc; char *argv[]; { numlist(argc, argv, &rover); } FILE * rover_open() { FILE *fp; #ifdef ROVER_DIR char name_buff[MAXPATHLEN], *cp; sprintf(name_buff, "%s/", ROVER_DIR); cp = name_buff + strlen(name_buff); strcpy(cp, group_name); while ((cp = index(cp, '.')) != (char *) NULL) *cp = '/'; sprintf(name_buff+strlen(name_buff), "/%s", ROVER_NAME); fp = fopen(name_buff, "r"); #else fp = fopen(ROVER_NAME, "r"); #endif return fp; } void rover_fake(artnum) int artnum; { char line[NNTP_STRLEN]; register FILE *fp; register char *cp, *cp2; char *references = NULL; #ifndef __FreeBSD__ char *malloc(), *realloc(); #endif #ifdef XOVER if (over_is_cheap(artnum, artnum)) { int hdr = over_header("references"); if (hdr >= 0 && xfind(&over, artnum)) { references = over_grab_header(hdr, 0); goto output_refs; } } #endif (void) sprintf(line, "%d", artnum); fp = fopen(line, "r"); if (fp == NULL) return; cp = line; while (fgets(line, sizeof line, fp) != NULL) { if (cp && *line == '\n') { break; } cp2 = cp; cp = index(line, '\n'); if (!cp2 || isspace(*line)) { if (references) { register int len = strlen(references); if (cp2) { for (cp2 = line+1; isspace(*cp2); cp2++) ; *--cp2 = ' '; } else cp2 = line; if (cp) *cp = '\0'; references = realloc(references, strlen(cp2) + len + 1); if (references) strcpy(references + len, cp2); } } else if (references) break; else if ((cp2 = index(line, ':')) != NULL) { *cp2 = '\0'; if (strcasecmp(line, "references") == 0) { cp2 += 2; if (cp) *cp = '\0'; references = malloc(strlen(cp2) + 1); if (references) strcpy(references, cp2); } } } (void) fclose(fp); #ifdef XOVER output_refs: #endif if (references) { cp2 = references + strlen(references) - 1; while ((cp = rindex(references, '<')) != NULL) { while (cp2 >= cp && ((unsigned char)*cp2 <= ' ' || *cp2 == ',')) cp2--; cp2[1] = '\0'; /* Quit parsing references if this one is garbage. */ if (!valid_message_id(cp, cp2)) break; /* Dump all domains that end in '.' */ if (cp2[-1] == '.') break; if (!gethistent(cp, 0) || group_artnum == 0) printf(" %s", cp); else { printf(" %d", group_artnum); break; } *cp = '\0'; cp2 = cp-1; } free(references); } printf("\r\n"); } /* Check if the string we've found looks like a valid message-id reference. */ int valid_message_id(start, end) register char *start, *end; { char *mid; if (start == end) return 0; if (*end != '>') { /* Compensate for space cadets who include the header in their ** subsitution of all '>'s into another citation character. */ if (*end == '<' || *end == '-' || *end == '!' || *end == '%' || *end == ')' || *end == '|' || *end == ':' || *end == '}' || *end == '*' || *end == '+' || *end == '#' || *end == ']' || *end == '@' || *end == '$') *end = '>'; } else if (end[-1] == '>') { *(end--) = '\0'; } /* Id must be "<...@...>" */ if (*start != '<' || *end != '>' || (mid = index(start, '@')) == NULL || mid == start+1 || mid+1 == end) return 0; return 1; } #endif #if defined(XOVER) || defined(XROVER) int xfind(obj, artnum) struct xobj *obj; int artnum; { FILE *fp = obj->fp; int file_num = obj->num; if (fp) { if (file_num < 0 || file_num > artnum) { fseek(fp, 0L, 0); file_num = 0; } } else { if (!obj->open_tried) obj->fp = fp = (obj->open)(); obj->open_tried = 1; if (!fp) { obj->num = -1; return 0; } file_num = 0; } if (!file_num) fscanf(fp, "%d", &file_num); while (1) { register int c; if (feof(fp)) { file_num = -1; break; } if (file_num >= artnum) { break; } while ((c = getc(fp)) != EOF && c != '\n') continue; fscanf(fp, "%d", &file_num); } obj->num = file_num; return file_num == artnum; } void xclose(obj) struct xobj *obj; { if (obj->fp) { fclose(obj->fp); obj->fp = NULL; obj->num = -1; } obj->open_tried = 0; } void close_xfiles() { #ifdef XOVER xclose(&over); #endif #ifdef XROVER xclose(&rover); #endif } #endif