home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Unix System Administration Handbook 1997 October
/
usah_oct97.iso
/
news
/
nn.tar
/
nn-6.5.1
/
news.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-11
|
8KB
|
408 lines
/*
* (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
*
* Article header parsing.
*/
#include "config.h"
#include "news.h"
/* news.c */
static char **art_hdr_field __APROTO((register char *lp, int all));
export int retry_on_error = 0;
char *parse_header(f, hdr_field, modes, hdrbuf)
FILE *f;
char **(*hdr_field)();
int modes;
news_header_buffer hdrbuf;
{
register char *bp, *cp, **fptr;
int siz, all, date_only;
off_t pos;
pos = ftell(f);
/* read first NEWS_HEADER_BUFFER bytes (should be more than enough) */
all = modes & GET_ALL_FIELDS;
date_only = modes & GET_DATE_ONLY;
siz = fread(hdrbuf, sizeof(char), NEWS_HEADER_BUFFER, f);
if (siz <= 0) {
hdrbuf[0] = NUL;
return hdrbuf;
}
bp = hdrbuf;
bp[siz-1] = NUL;
/* decode subarticle header */
while (*bp) {
if (*bp == NL) { /* empty line following header */
++bp;
fseek(f, pos + (bp - hdrbuf), 0);
return bp;
}
if (bp[0] == SP && bp[1] == SP) { /* An ugly hack so that NN can read */
bp += 2; /* it's own FAQ... :-) (sorry Bill) */
continue;
}
if (date_only && *bp != 'D')
fptr = NULL;
else
if ((fptr = (*hdr_field)(bp, all))) {
while (*bp && *bp != ':' && isascii(*bp) && !isspace(*bp))
bp++;
if (*bp) bp++;
while (*bp && isascii(*bp) && isspace(*bp) && *bp != NL) bp++;
*fptr = bp;
}
#ifdef NO_HEADER_SEPARATION_HACK
else {
for (cp = bp; *cp && *cp != ':'; cp++) {
if (!isascii(*cp)) break;
if (*cp == '_' || *cp == '-') continue;
if (isalnum(*cp)) continue;
break;
}
if (*cp != ':') {
*bp = NL;
pos--;
continue;
}
}
#endif
while (*bp && *bp != NL) bp++;
/* Assume that continued lines are never empty! */
if (fptr && bp == *fptr) *fptr = NULL;
while (*bp) { /* look for continued lines */
cp = bp + 1;
if (! (*cp && isascii(*cp) && isspace(*cp) && *cp != NL)) {
/* next line is empty or not indented */
*bp++ = NUL;
break;
}
*bp = SP; /* substitute NL with SPACE */
bp = cp;
while (*bp && *bp != NL) bp++;
}
}
return bp;
}
static char **art_hdr_field(lp, all)
register char *lp;
int all;
{
#define check(name, lgt, field) \
if (isascii(lp[lgt]) && isspace(lp[lgt]) && strncmp(name, lp, lgt) == 0)\
return &news.field
switch (*lp++) {
case 'A':
case 'a':
if (!all) break;
check("pproved:", 8, ng_appr);
break;
case 'B':
case 'b':
check("ack-References:", 15, ng_bref);
break;
case 'C':
case 'c':
check("ontrol:", 7, ng_control);
check("omment-To:", 10, ng_comment);
break;
case 'D':
case 'd':
check("ate:", 4, ng_date);
if (!all) break;
check("ate-Received:", 13, ng_rdate);
check("istribution:", 12, ng_dist);
break;
case 'F':
case 'f':
check("rom:", 4, ng_from);
if (!all) break;
check("ollowup-To:", 11, ng_follow);
check("ollowup-to:", 11, ng_follow);
break;
case 'K':
case 'k':
if (!all) break;
check("eywords:", 8, ng_keyw);
break;
case 'L':
case 'l':
check("ines:", 5, ng_xlines);
break;
case 'M':
case 'm':
if (!all) break;
if (strncmp(lp, "essage-", 7)) break;
lp += 7;
check("ID:", 3, ng_ident);
check("Id:", 3, ng_ident);
check("id:", 3, ng_ident);
break;
case 'N':
case 'n':
check("ewsgroups:", 10, ng_groups);
break;
case 'O':
case 'o':
if (!all) break;
check("rganization:", 12, ng_org);
check("rganisation:", 12, ng_org);
check("riginator:", 10, ng_origr);
break;
case 'P':
case 'p':
if (!all) break;
check("ath:", 4, ng_path);
break;
case 'R':
case 'r':
check("eferences:", 10, ng_ref);
check("eply-To:", 8, ng_reply);
check("eply-to:", 8, ng_reply);
break;
case 'S':
case 's':
check("ubject:", 7, ng_subj);
check("ender:", 6, ng_sender);
if (!all) break;
check("ummary:", 7, ng_summ);
break;
case 'T':
case 't':
check("itle:", 5, ng_subj);
break;
case 'X':
case 'x':
check("ref:", 4, ng_xref);
break;
}
return NULL;
#undef check
}
int
is_header_line(line)
char *line;
{
return art_hdr_field(line, 0) != (char **)NULL;
}
FILE *open_news_article(art, modes, buffer1, buffer2)
article_header *art;
int modes;
news_header_buffer buffer1, buffer2;
{
char *digest_buffer;
int c, retry;
FILE *f;
struct stat statb;
#ifndef DONT_COUNT_LINES
off_t digest_artlen;
#endif /* DONT_COUNT_LINES */
#ifdef NNTP
int lazy;
off_t fpos;
FILE *nntp_get_article();
#endif /* NNTP */
#ifndef DONT_COUNT_LINES
digest_artlen = 0;
#endif /* DONT_COUNT_LINES */
if (art->flag & A_FOLDER) {
f = open_file(group_path_name, OPEN_READ);
if (f == NULL) return NULL;
fseek(f, art->hpos, 0);
#ifndef DONT_COUNT_LINES
digest_artlen = art->lpos - art->fpos;
#endif /* DONT_COUNT_LINES */
}
#ifdef NNTP
else if (use_nntp) {
lazy = (current_group->master_flag & M_ALWAYS_DIGEST) == 0
&& (modes & LAZY_BODY) ? 1 : 0;
f = nntp_get_article(art->a_number, lazy);
if (f == NULL) return NULL;
}
#endif /* NNTP */
else {
sprintf(group_file_name, "%d", art->a_number);
retry = retry_on_error;
while ((f = open_file(group_path_name, OPEN_READ)) == NULL)
if (--retry < 0) return NULL;
/* necessary because empty files wreak havoc */
if (fstat(fileno(f), &statb) < 0 ||
#ifdef NOV
(art->lpos = statb.st_size, statb.st_size <= (off_t)0)) {
#else
statb.st_size < art->lpos || statb.st_size <= (off_t)0) {
#endif /* NOV */
fclose(f);
return who_am_i == I_AM_MASTER ? (FILE *)1 : NULL;
}
}
digest_buffer = buffer1;
if (modes & FILL_NEWS_HEADER) {
news.ng_from = NULL;
news.ng_reply = NULL;
news.ng_name = NULL;
news.ng_subj = NULL;
news.ng_groups = NULL;
news.ng_ref = NULL;
news.ng_bref = NULL;
news.ng_sender = NULL;
news.ng_xlines = NULL;
news.ng_xref = NULL;
if (modes & GET_ALL_FIELDS) {
news.ng_path = NULL;
news.ng_reply = NULL;
news.ng_ident = NULL;
news.ng_follow = NULL;
news.ng_keyw = NULL;
news.ng_dist = NULL;
news.ng_org = NULL;
news.ng_appr = NULL;
news.ng_summ = NULL;
news.ng_control = NULL;
news.ng_date = NULL;
news.ng_rdate = NULL;
news.ng_comment = NULL;
news.ng_origr = NULL;
}
if (modes & GET_DATE_ONLY)
news.ng_date = NULL;
(void) parse_header(f, art_hdr_field, modes, buffer1);
if (news.ng_from == NULL) news.ng_from = news.ng_sender;
#ifdef NOV
/* fill in article positions.. new style.. */
if ((art->flag & (A_FOLDER | A_DIGEST)) == 0) {
setpos(art, f);
news.ng_fpos = art->fpos;
}
#else /* NOV */
if (modes & FILL_OFFSETS) /* used only by old DB code */
art->fpos = news.ng_fpos = ftell(f);
#endif /* NOV */
if (news.ng_xlines)
news.ng_lines = atoi(news.ng_xlines);
else {
#ifndef DONT_COUNT_LINES
#ifdef NNTP
if (use_nntp && lazy && !(art->flag & (A_DIGEST | A_FOLDER))) {
fpos = ftell(f);
fclose(f);
f = nntp_get_article(art->a_number, 2);
if (f == NULL) return NULL;
lazy = 0;
fseek(f, fpos, 0);
}
#endif /* NNTP */
news.ng_lines = 0;
while ((c = getc(f)) != EOF) {
if (c == '\n')
news.ng_lines++;
if (digest_artlen && --digest_artlen == 0)
break;
}
#else /* DONT_COUNT_LINES */
news.ng_lines = -1;
#endif /* DONT_COUNT_LINES */
}
if (modes & FILL_OFFSETS) {
fseek(f, (off_t)0, 2);
news.ng_lpos = ftell(f);
}
#ifdef NNTP
else if (use_nntp && (art->flag & (A_DIGEST | A_FOLDER)) == 0) {
fseek(f, (off_t)0, 2);
art->lpos = ftell(f);
}
#endif
news.ng_flag = 0;
if (news.ng_appr) news.ng_flag |= N_MODERATED;
if (modes & DIGEST_CHECK && is_digest(news.ng_subj))
news.ng_flag |= N_DIGEST;
#ifdef NNTP
if (use_nntp && lazy && news.ng_flag & N_DIGEST) {
fclose(f);
f = nntp_get_article(art->a_number, 2);
if (f == NULL) return NULL;
}
#endif
digest_buffer = buffer2;
}
#ifdef NNTP
else if (use_nntp && (art->flag & (A_DIGEST | A_FOLDER)) == 0) {
fseek(f, (off_t)0, 2);
art->lpos = ftell(f);
}
#endif
if (modes & FILL_DIGEST_HEADER) {
fseek(f, art->hpos, 0);
parse_digest_header(f, modes & GET_ALL_FIELDS, digest_buffer);
}
fseek(f, (modes & SKIP_HEADER) ? art->fpos : art->hpos, 0);
return f;
}