home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* 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 <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <fcntl.h>
- #include <io.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- /*--------------------------------------------------------------------*/
- /* 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
-