⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rt-mt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $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 + -