📄 rt-mt.c
字号:
/* $Id: rt-mt.c,v 3.0 1992/12/14 00:14:13 davison Trn $*/#include "EXTERN.h"#include "common.h"#include "intrp.h"#include "trn.h"#include "cache.h"#include "bits.h"#include "ng.h"#include "ngdata.h"#include "rcln.h"#include "util.h"#include "hash.h"#include "nntp.h"#include "rthread.h"#include "rt-process.h"#ifdef USE_MT#include "INTERN.h"#include "rt-mt.h"extern HASHTABLE *msgid_hash;extern bool try_mt;#ifndef USE_XTHREADstatic FILE *fp;#endifstatic bool word_same, long_same;static BMAP my_bmap, mt_bmap;static char *strings = Nullch;static WORD *author_cnts = 0;static WORD *ids = 0;static ARTICLE **article_array = 0;static SUBJECT **subject_array = 0;static char **author_array = 0;static TOTAL total;static PACKED_ROOT p_root;static PACKED_ARTICLE p_article;/* Initialize our thread code by determining the byte-order of the thread** files and our own current byte-order. If they differ, set flags to let** the read code know what we'll need to translate.*/boolmt_init(){ int i;#ifdef USE_XTHREAD long size;#endif bool success = TRUE; /* I'm an optimist */ word_same = long_same = TRUE;#ifdef USE_XTHREAD sprintf(ser_line, "XTHREAD DBINIT"); nntp_command(ser_line); size = nntp_readcheck(); if (size < 0) return FALSE; size = nntp_read((char*)&mt_bmap, (long)sizeof (BMAP)); if (size >= sizeof (BMAP) - 1) {#else /* !USE_XTHREAD */ if ((fp = fopen(filexp(DBINIT), FOPEN_RB)) != Nullfp && fread((char*)&mt_bmap, 1, sizeof (BMAP), fp) >= sizeof (BMAP) - 1) {#endif if (mt_bmap.version != DB_VERSION) { printf("\nMthreads database is the wrong version -- ignoring it.\n") FLUSH; return FALSE; } mybytemap(&my_bmap); for (i = 0; i < sizeof (LONG); i++) { if (i < sizeof (WORD)) { if (my_bmap.w[i] != mt_bmap.w[i]) { word_same = FALSE; } } if (my_bmap.l[i] != mt_bmap.l[i]) { long_same = FALSE; } } } else success = FALSE;#ifdef USE_XTHREAD while (nntp_read(ser_line, (long)sizeof ser_line)) ; /* trash any extraneous bytes */#else if (fp != Nullfp) fclose(fp);#endif return success;}/* Open and process the data in the group's thread file. Returns TRUE unless** we discovered a bogus thread file, destroyed the cache, and re-built it.*/boolmt_data(){ bool success = TRUE;#ifdef USE_XTHREAD /* use remote thread file? */ long size; sprintf(ser_line, "XTHREAD THREAD"); nntp_command(ser_line); size = nntp_readcheck(); if (size < 0) return TRUE; printf("\nGetting thread file."), fflush(stdout); if (nntp_read((char*)&total, (long)sizeof (TOTAL)) < sizeof (TOTAL)) goto exit;#else /* !USE_XTHREAD */ if ((fp = fopen(mt_name(ngname), FOPEN_RB)) == Nullfp) return TRUE; printf("\nReading thread file."), fflush(stdout); if (fread((char*)&total, 1, sizeof (TOTAL), fp) < sizeof (TOTAL)) goto exit;#endif /* !USE_XTHREAD */ lp_bmap(&total.first, 4); wp_bmap(&total.root, 5); if (!total.root) { tweak_data(); goto exit; } if (total.last > lastart) grow_cache(total.last); if (read_authors() && read_subjects() && read_roots() && read_articles() && read_ids()) { tweak_data(); first_cached = absfirst; last_cached = (total.last < absfirst ? absfirst-1: total.last); cached_all_in_range = TRUE; goto exit; } /* Something failed. Safefree takes care of checking if some items ** were already freed. Any partially-allocated structures were freed ** before we got here. All other structures are cleaned up now. */ close_cache(); safefree(&strings); safefree((char**)&article_array); safefree((char**)&subject_array); safefree((char**)&author_array); safefree((char**)&ids); try_mt = FALSE; build_cache(); try_mt = TRUE; success = FALSE;exit:#ifdef USE_XTHREAD while (nntp_read(ser_line, (long)sizeof ser_line)) ; /* trash any extraneous bytes */#else fclose(fp);#endif return success;}#ifndef USE_XTHREAD/* Change a newsgroup name into the name of the thread data file. We** subsitute any '.'s in the group name into '/'s (unless LONG_THREAD_NAMES** is defined), prepend the path, and append the '/.thread' or '.th' on to** the end.*/static char *mt_name(group)char *group;{#ifdef LONG_THREAD_NAMES sprintf(buf, "%s/%s", threaddir, group);#else register char *cp; cp = strcpy(buf, threaddir) + strlen(threaddir); *cp++ = '/'; strcpy(cp, group); while ((cp = index(cp, '.'))) *cp = '/';#endif if (threaddir == spool) strcat(buf, "/.thread"); else strcat(buf, ".th"); return buf;}#endifstatic char *subject_strings, *string_end;/* The author information is an array of use-counts, followed by all the** null-terminated strings crammed together. The subject strings are read** in at the same time, since they are appended to the end of the author** strings.*/static intread_authors(){ register int count; register char *string_ptr, **author_ptr; if (!read_item((char**)&author_cnts, (MEM_SIZE)total.author*sizeof (WORD))) return 0; safefree((char**)&author_cnts); /* we don't need these */ if (!read_item(&strings, (MEM_SIZE)total.string1)) return 0; string_ptr = strings; string_end = string_ptr + total.string1; if (string_end[-1] != '\0') { /*error("first string table is invalid.\n");*/ return 0; } /* We'll use this array to point each article at its proper author ** (the packed values were saved as indexes). */ author_array = (char**)safemalloc(total.author * sizeof (char*)); author_ptr = author_array; for (count = total.author; count; count--) { if (string_ptr >= string_end) break; *author_ptr++ = string_ptr; string_ptr += strlen(string_ptr) + 1; } subject_strings = string_ptr; if (count) { /*error("author unpacking failed.\n");*/ return 0; } return 1;}/* The subject values consist of the crammed-together null-terminated strings** (already read in above) and the use-count array. They were saved in the** order that the roots require while being unpacked.*/static intread_subjects(){ register int count; register char *string_ptr; register SUBJECT **subj_ptr; WORD *subject_cnts; if (!read_item((char**)&subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD))) { /* (Error already logged.) */ return 0; } free((char*)subject_cnts); /* we don't need these */ /* Use this array when unpacking the article's subject offset. */ subject_array = (SUBJECT**)safemalloc(total.subject * sizeof (SUBJECT*)); subj_ptr = subject_array; string_ptr = subject_strings; /* string_end is already set */ for (count = total.subject; count; count--) { int len; ARTICLE arty; if (string_ptr >= string_end) break; len = strlen(string_ptr); arty.subj = 0; set_subj_line(&arty, string_ptr, len); if (len == 72) arty.subj->flags |= SF_SUBJTRUNCED; string_ptr += len + 1; *subj_ptr++ = arty.subj; } if (count || string_ptr != string_end) { /*error("subject data is invalid.\n");*/ return 0; } return 1;}/* Read in the packed root structures to set each subject's thread article** offset. This gets turned into a real pointer later.*/static intread_roots(){ register int count, i; register SUBJECT **subj_ptr; int ret; subj_ptr = subject_array; for (count = total.root; count--; ) {#ifdef USE_XTHREAD ret = nntp_read((char*)&p_root, (long)sizeof (PACKED_ROOT));#else ret = fread((char*)&p_root, 1, sizeof (PACKED_ROOT), fp);#endif if (ret != sizeof (PACKED_ROOT)) { /*error("failed root read -- %d bytes instead of %d.\n", ret, sizeof (PACKED_ROOT));*/ return 0; } wp_bmap(&p_root.articles, 3); /* converts subject_cnt too */ if (p_root.articles < 0 || p_root.articles >= total.article) { /*error("root has invalid values.\n");*/ return 0; } i = p_root.subject_cnt; if (i <= 0 || (subj_ptr - subject_array) + i > total.subject) { /*error("root has invalid values.\n");*/ return 0; } subj_ptr[i-1]->thread_link = subj_ptr[0]; while (i--) { union { ARTICLE *ap; int num; } uni; if (i) subj_ptr[0]->thread_link = subj_ptr[1]; subj_ptr[0]->flags &= ~SF_THREAD; uni.num = p_root.articles; (*subj_ptr++)->thread = uni.ap; } } return 1;}static bool invalid_data;/* A simple routine that checks the validity of the article's subject value.** A -1 means that it is NULL, otherwise it should be an offset into the** subject array we just unpacked.*/static SUBJECT *the_subject(num)WORD num;{ if (num == -1) return Nullsubj; if (num < 0 || num >= total.subject) { /*printf("Invalid subject in thread file: %d [%ld]\n", num, art_num);*/ invalid_data = TRUE; return Nullsubj; } return subject_array[num];}/* Ditto for author checking. */static char *the_author(num)WORD num;{ if (num == -1) return Nullch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -