/* 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
syntax highlighted by Code2HTML, v. 0.9.1