Category : Linux Files
Archive   : UPC12BS2.ZIP
Filename : HISTORY.C

 
Output of file : HISTORY.C contained in archive : UPC12BS2.ZIP
/*--------------------------------------------------------------------*/
/* h i s t o r y . c */
/* */
/* News history file maintenance for UUPC/extended. */
/* */
/* Written by Mike Lipsie */
/* */
/* The history file */
/* */
/* This file describes and implements the history file. */
/* */
/* The history file is [newsdir]/history and is "added" to by */
/* rnews. It is "pruned" by expire and is used by rnews (to */
/* check that the article has not arrived before), expire (to */
/* find all copies of the article), and rn (to mark as read all */
/* copies of an article.) */
/* */
/* The history file is entirely ASCII. */
/* */
/* The first line is a code that identifies the version level */
/* (so that future versions can automatically upgrade.) For */
/* version one that code is "ZIP1". */
/* */
/* Every line (except the version line) is the record of a */
/* single incoming article. That line is exactly as described */
/* without added spaces or other punctuation. The first field */
/* is the Message-ID including (or added if they don't exist), */
/* the "<" and ">", a space, the date received (dd/mm/yyyy with */
/* days and months being zero filled if necessary), a space, */
/* and the "destination" information. */
/* */
/* The destination information is the Newsgroups: with a colon */
/* and the article number for each group added (article number */
/* zero is used for newsgroups not accepted.) */
/* */
/* For example, if article <123@pyramid> was received on 3 Jan */
/* 1992 and was posted to ba.food, ba.transportation, and */
/* soc.singles and ended up in article 4334, 1234, and 56789 */
/* (respectively), the record would be */
/* */
/* <123@pyramid> 03/01/1992 */
/* ba.food:4334,ba.transportation:1234,soc.singles:56789 */
/* */
/* To speed access into the history file there is a parallel */
/* file history.ndx which contains information where each day's */
/* worth of history records begins. The first line is a */
/* version number and must be the same as that of the history */
/* file. All the other records are the 10 character date code, */
/* a space, and a ten digit location code (right justified, */
/* zero or blank filled.) The location code is the byte */
/* displacement into the history file of the first record with */
/* that date code. */
/*--------------------------------------------------------------------*/


/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/

#include
#include
#include
#include
#include
#include
#include
#include

/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/

#include "lib.h"
#include "hlib.h"
#include "timestmp.h"
#include "active.h"
#include "history.h"

/* These variables are used to improve the performance of checking
* for previous existance of an article.
*
* The basic theory of how this feature works is that a file
* (history.dbm) is built with enough information (it is hoped)
* to eliminate 99% (well, most) of the non matching message IDs.
* A check is made when a match is made confiming that the match
* is real. Since most articles are not "re-sends" (all if you
* have only one feed) this won't impose a large overhead.
*
* The information that is used to eliminate unnecessary checks into
* the history file for duplicate messageIDs is the first ten
* characters of the message ID (not including the leading "<"),
* the number of characters in the full ID (including the "<" and ">"),
* a checksum of the full ID (also including the "<" and ">"), and
* the location in the history file of the full ID.
*
* Additionally, an array of MAXbuf (currently 8) buffers of history.dbm
* are maintained in memory to avoid disk I/O.
*
*/

int cur_buff = 0;
int cur_off = 0;
#define MAXbuf 8

char *hb[MAXbuf];
int hb_blk[MAXbuf];

extern FILE *hfile;

FILE *hdbm_file = NULL;

struct perf_elem {
char IDpart[10]; /* The first 10 characters (after the "<") of the message-ID */
char cksum; /* Checksum of the entire ID (including <>) */
char IDlen; /* Number of characters in the ID (including <>) */
long where; /* ftell() in file of actual record */
};


/*--------------------------------------------------------------------*/
/* h i s t o r y _ e x i s t s */
/* */
/* Determine if the history file exists and is a file (instead */
/* of a directory). */
/*--------------------------------------------------------------------*/

boolean history_exists( void )
{
char hfile_name[FILENAME_MAX];
struct stat buff;

mkfilename(hfile_name, E_newsdir, "history");

if ((stat(hfile_name, &buff) == 0) && buff.st_mode & S_IFREG)
return TRUE;
else
return FALSE;

} /* history_exists */


/*--------------------------------------------------------------------*/
/* o p e n _ h i s t o r y */
/* */
/* Open the history file and verify that it is of the correct */
/* version. If any error occurs, NULL is returned. */
/*--------------------------------------------------------------------*/

#ifdef __TURBOC__
#pragma argsused
#endif

FILE *open_history(char *history_date)
{

#ifdef NEXT_RELEASE_MAYBE
char hfile_name[FILENAME_MAX];
FILE *hfile;
FILE *index_file;
char buff[BUFSIZ];

mkfilename(hfile_name, newsdir, "history");
hfile = fopen(hfile_name, "a+b");
if (hfile == NULL) {
printmsg(0,"Unable to open history file");
return hfile;
}
fseek(hfile, 0L, SEEK_SET);
fgets(buff, sizeof(buff), hfile);
buff[strlen(buff)-1] = '\0';
if (buff[strlen(buff)-1] == '\r') buff[strlen(buff)-1] = '\0';
if ((strlen(buff)) != strlen(H_VERSION)) {
printmsg(0, "History version incorrect");
return NULL;
}
if (!equal(buff, H_VERSION)) {
printmsg(0, "History version incorrect");
return NULL;
}


fseek(hfile, 0L, SEEK_END); /* I know it is unnecessary */

/* Now the index file */
strcat(hfile_name, ".ndx");
index_file = fopen(hfile_name, "a+b");
if (index_file == NULL) {
printmsg(0,"Unable to open history file index");
}
fseek(index_file, 0L, SEEK_SET);
fgets(buff, sizeof(buff), index_file);
buff[strlen(buff)-1] = '\0';
if (buff[strlen(buff)-1] == '\r') buff[strlen(buff)-1] = '\0';
if ((strlen(buff)) != strlen(H_VERSION)) {
printmsg(0, "History index version incorrect");
}
if (!equal(buff, H_VERSION)) {
printmsg(0, "History index version incorrect");
}
fseek(index_file, -21L, SEEK_END);
fgets(buff, 25, index_file);
if (strncmp(history_date, buff, strlen(history_date)) != 0) {
fseek(index_file, 0L, SEEK_END);
sprintf(buff, "%s %9.9ld\n", history_date, ftell(hfile));
fwrite(buff, sizeof(char), strlen(buff), index_file);
}
fclose(index_file);
#else
hfile = NULL;
#endif

return NULL;

}



/*
Create a history file.
*/

FILE *create_history(char *history_date) {

char hfile_name[FILENAME_MAX];
FILE *hfile;
FILE *index_file;
char buff[BUFSIZ];

mkfilename(hfile_name, E_newsdir, "history");
hfile = fopen(hfile_name, "wb");
if (hfile == NULL) {
printmsg(0, "Unable to create history file");
return hfile;
}

strcpy(buff, H_VERSION);
strcat(buff, "\n");
fwrite(buff, sizeof(char), strlen(buff), hfile);

strcat(hfile_name, ".ndx");
index_file = fopen(hfile_name, "wb");
fwrite(buff, sizeof(char), strlen(buff), index_file);
sprintf(buff, "%s %9.9ld\n", history_date, ftell(hfile));
fwrite(buff, sizeof(char), strlen(buff), index_file);
fclose(index_file);

return hfile;
}



void init_history_dbm(void) {

#ifdef NEXT_RELEASE_MAYBE
int not_eof;
char *t;
long l;
int i;
int j;

int cur_block;

struct perf_elem *p;

char dbm_name[FILENAME_MAX];
char hbuf[BUFSIZ]; /* Buffer for each history file record */

mkfilename(dbm_name, tempdir, "history.dbm");
hdbm_file = fopen(dbm_name, "w+b");
if (hdbm_file == NULL) {
printmsg(0,"Unable to create history dbm file");
exit(5);
}

for (i = 0; i < MAXbuf; i++) {
hb[i] = malloc(BUFSIZ);
checkref(hb[i]);
hb_blk[i] = -1;
}

cur_block = 0;
cur_buff = 0;
cur_off = 0;

/* Now build the file */
fseek(hfile, (long)(strlen(H_VERSION)+1), SEEK_SET); /* Back to the beginning */
not_eof = TRUE;
while (not_eof) {
l = ftell(hfile);
t = fgets(hbuf, BUFSIZ, hfile);
if (t == NULL) {
not_eof = FALSE;
} else {
if (cur_off >= (BUFSIZ/sizeof(struct perf_elem))) {
fwrite(hb[cur_buff], sizeof(char), BUFSIZ, hdbm_file);
hb_blk[cur_buff] = cur_block++;
cur_off = 0;
if (++cur_buff >= MAXbuf) {
cur_buff = 0;
}
}
p = (struct perf_elem *)hb[cur_buff];
p += cur_off++;

t = strchr(hbuf, ' ');
if (t == NULL) t = hbuf;
*t = '\0';

p->where = l;
p->IDlen = strlen(t);
j = 0;
for (i = p->IDlen-1; i >= 0; i--) {
j = j + t[i];
}
p->cksum = (char)j;
strncpy(p->IDpart, &(t[1]), sizeof(p->IDpart));
}
} /* while not eof */

/* Dump out last (probably partial) block */
if (cur_off < (BUFSIZ/sizeof(struct perf_elem))) {
p = (struct perf_elem *)hb[cur_buff];
p += cur_off;
strnset((char *)p, '\0', (&hb[cur_buff][BUFSIZ] - &(char *)p));
}
fwrite(hb[cur_buff], sizeof(char), BUFSIZ, hdbm_file);
hb_blk[cur_buff] = cur_block;
#endif

return;
}

/*--------------------------------------------------------------------*/
/* i s _ i n _ h i s t o r y */
/* */
/* Check whether messageID is already in the history file. */
/*--------------------------------------------------------------------*/

boolean is_in_history(FILE *hfile, char *messageID)
{

#ifdef NEXT_RELEASE_MAYBE
int this_blk;

struct perf_elem *p;

if (hdbm_file == NULL) {
/* Initialize */
init_history_dbm();
}

/* First check the blocks in memory */
this_blk = 0;
cur_off = 0;

while (this_blk < MAXbuf) {
if (cur_off >= (BUFSIZ/sizeof(struct perf_elem))) {
cur_off = 0;
if (++this_blk >= MAXbuf) {
break;
}
if (hb_blk[this_blk] == -1) break;
}
p = (struct perf_elem *)hb[this_blk];
p += cur_off++;

if (check_out_this_one(messageID, p)) {
return TRUE;
}
}

/* Now check out the rest of the file */
#else

/*--------------------------------------------------------------------*/
/* Slow but true version extracted from rnews.c by ahd */
/*--------------------------------------------------------------------*/

boolean not_eof = TRUE;

fseek(hfile, (long)(strlen(H_VERSION)+1), SEEK_SET);
/* Back to the beginning */

/*--------------------------------------------------------------------*/
/* Scan the entire disk file from the beginning */
/*--------------------------------------------------------------------*/

while (not_eof)
{
char hist_record[BUFSIZ];
char *gc_ptr = fgets(hist_record, sizeof(hist_record), hfile);

if (gc_ptr == NULL)
not_eof = FALSE;
else {
gc_ptr = strchr(hist_record, ' ');
if (gc_ptr == NULL)
gc_ptr = hist_record;
*gc_ptr = '\0';
printmsg(9, "rnews:Comparing to history:%s", hist_record);
if (equal(hist_record, messageID))
return TRUE;
} /* else */
} /* while (not_eof) */

#endif

return FALSE;
} /* is_in_history */


#ifdef NEXT_RELEASE_MAYBE

int check_out_this_one(char *m_id, struct perf_elem *p)
{

printf("check_out_this_one called \n");
return TRUE;

}

#endif


  3 Responses to “Category : Linux Files
Archive   : UPC12BS2.ZIP
Filename : HISTORY.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/