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

📄 art.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  $Revision: 1.52 $****  Article-processing.*/#include "innd.h"#include "dbz.h"#include <sys/uio.h>typedef struct iovec	IOVEC;/***  A way to index into the header table.*/#define HDR(_x)		(ARTheaders[(_x)].Value)#if	defined(S_IXUSR)#define EXECUTE_BITS	(S_IXUSR | S_IXGRP | S_IXOTH)#else#define EXECUTE_BITS	0111#endif	/* defined(S_IXUSR) *//***  Mark that the site gets this article.*/#define SITEmark(sp_, ngp_) \    do { \	SITE	*funnel; \    \	sp_->Sendit = TRUE; \	if (sp_->ng == NULL) \	    sp_->ng = ngp_; \	if (sp_->Funnel != NOSITE) { \	    funnel = &Sites[sp_->Funnel]; \	    if (funnel->ng == NULL) \		funnel->ng = ngp_; \	} \    } while (JUSTONCE)/***  Header types.*/typedef enum _ARTHEADERTYPE {    HTreq,			/* Drop article if this is missing	*/    HTobs,			/* Delete this header if found		*/    HTstd			/* Standard optional header		*/} ARTHEADERTYPE;/***  Entry in the header table.*/typedef struct _ARTHEADER {    STRING		Name;    ARTHEADERTYPE	Type;    int			Size;			/* Length of Name	*/    char		*Value;    int			Length;			/* Length of Value	*/    int			Found;    BOOL		Allocated;} ARTHEADER;/***  For speed we build a binary tree of the headers, sorted by their**  name.  We also store the header's Name fields in the tree to avoid**  doing an extra indirection.*/typedef struct _TREE {    STRING		Name;    ARTHEADER		*Header;    struct _TREE	*Before;    struct _TREE	*After;} TREE;STATIC TREE		*ARTheadertree;/***  For doing the overview database, we keep a list of the headers and**  a flag saying if they're written in brief or full format.*/typedef struct _ARTOVERFIELD {    ARTHEADER		*Header;    BOOL		NeedHeader;} ARTOVERFIELD;STATIC ARTOVERFIELD		*ARTfields;/***  General newsgroup we care about, and what we put in the Path line.*/STATIC char		ARTctl[] = "control";STATIC char		ARTjnk[] = "junk";STATIC char		*ARTpathme;/***  Flag array, indexed by character.  Character classes for Message-ID's.*/STATIC char		ARTcclass[256];#define CC_MSGID_ATOM	01#define CC_MSGID_NORM	02#define CC_HOSTNAME	04#define ARTnormchar(c)	((ARTcclass[(c)] & CC_MSGID_NORM) != 0)#define ARTatomchar(c)	((ARTcclass[(c)] & CC_MSGID_ATOM) != 0)#define ARThostchar(c)	((ARTcclass[(c)] & CC_HOSTNAME) != 0)/***  The header table.  Not necessarily sorted, but the first character**  must be uppercase.*/STATIC ARTHEADER	ARTheaders[] = {    /*	Name			Type	... */    {	"Approved",		HTstd },#define _approved		 0    {	"Control",		HTstd },#define _control		 1    {	"Date",			HTreq },#define _date			 2    {	"Distribution",		HTstd },#define _distribution		 3    {	"Expires",		HTstd },#define _expires		 4    {	"From",			HTreq },#define _from			 5    {	"Lines",		HTstd },#define _lines			 6    {	"Message-ID",		HTreq },#define _message_id		 7    {	"Newsgroups",		HTreq },#define _newsgroups		 8    {	"Path",			HTreq },#define _path			 9    {	"Reply-To",		HTstd },#define _reply_to		10    {	"Sender",		HTstd },#define _sender			11    {	"Subject",		HTreq },#define _subject		12    {	"Supersedes",		HTstd },#define _supersedes		13    {	"Bytes",		HTstd },#define _bytes			14    {	"Also-Control",		HTstd },#define _alsocontrol		15    {	"References",		HTstd },#define _references		16    {	"Xref",			HTobs },#define _xref			17    {	"Date-Received",	HTobs },    {	"Posted",		HTobs },    {	"Posting-Version",	HTobs },    {	"Received",		HTobs },    {	"Relay-Version",	HTobs },};/****/BOOLARTreadschema(){    static char			SCHEMA[] = _PATH_SCHEMA;    register FILE		*F;    register int		i;    register char		*p;    register ARTOVERFIELD	*fp;    register ARTHEADER		*hp;    BOOL			ok;    char			buff[SMBUF];    if (ARTfields != NULL) {	DISPOSE(ARTfields);	ARTfields = NULL;    }    /* Open file, count lines. */    if ((F = fopen(SCHEMA, "r")) == NULL)	return FALSE;    for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++)	continue;    (void)fseek(F, (OFFSET_T)0, SEEK_SET);    ARTfields = NEW(ARTOVERFIELD, i + 1);    /* Parse each field. */    for (ok = TRUE, fp = ARTfields; fgets(buff, sizeof buff, F) != NULL; ) {	/* Ignore blank and comment lines. */	if ((p = strchr(buff, '\n')) != NULL)	    *p = '\0';	if ((p = strchr(buff, COMMENT_CHAR)) != NULL)	    *p = '\0';	if (buff[0] == '\0')	    continue;	if ((p = strchr(buff, ':')) != NULL) {	    *p++ = '\0';	    fp->NeedHeader = EQ(p, "full");	}	else	    fp->NeedHeader = FALSE;	for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++)	    if (EQ(buff, hp->Name)) {		fp->Header = hp;		break;	    }	if (hp == ENDOF(ARTheaders)) {	    syslog(L_ERROR, "%s bad_schema unknown header \"%s\"", buff);	    ok = FALSE;	    continue;	}	fp++;    }    fp->Header = NULL;    (void)fclose(F);    return ok;}/***  Build a balanced tree for the headers in subscript range [lo..hi).**  This only gets called once, and the tree only has about 20 entries,**  so we don't bother to unroll the recursion.*/static TREE *ARTbuildtree(Table, lo, hi)    ARTHEADER	**Table;    int		lo;    int		hi;{    int		mid;    TREE	*tp;    mid = lo + (hi - lo) / 2;    tp = NEW(TREE, 1);    tp->Header = Table[mid];    tp->Name = tp->Header->Name;    if (mid == lo)	tp->Before = NULL;    else	tp->Before = ARTbuildtree(Table, lo, mid);    if (mid == hi - 1)	tp->After = NULL;    else	tp->After = ARTbuildtree(Table, mid + 1, hi);    return tp;}/***  Sorting predicate for qsort call in ARTsetup.*/STATIC intARTcompare(p1, p2)    POINTER	p1;    POINTER	p2;{    ARTHEADER	**h1;    ARTHEADER	**h2;    h1 = CAST(ARTHEADER**, p1);    h2 = CAST(ARTHEADER**, p2);    return strcasecmp(h1[0]->Name, h2[0]->Name);}/***  Setup the article processing.*/voidARTsetup(){    register STRING	p;    register ARTHEADER	*hp;    ARTHEADER		**table;    register int	i;    /* Set up the character class tables.  These are written a     * little strangely to work around a GCC2.0 bug. */    (void)memset((POINTER)ARTcclass, 0, sizeof ARTcclass);    p = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";    while ((i = *p++) != 0) {        ARTcclass[i] = CC_HOSTNAME | CC_MSGID_ATOM | CC_MSGID_NORM;    }    p = "!#$%&'*+-/=?^_`{|}~";    while ((i = *p++) != 0) {	ARTcclass[i] = CC_MSGID_ATOM | CC_MSGID_NORM;    }    p = "\"(),.:;<@[\\]";    while ((i = *p++) != 0) {	ARTcclass[i] = CC_MSGID_NORM;    }    /* The RFC's don't require it, but we add underscore to the list of valid     * hostname characters. */    ARTcclass['.'] |= CC_HOSTNAME;    ARTcclass['-'] |= CC_HOSTNAME;    ARTcclass['_'] |= CC_HOSTNAME;    /* Allocate space in the header table. */    for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) {	hp->Size = strlen(hp->Name);	hp->Allocated = hp->Value == NULL && hp->Type != HTobs			&& hp != &ARTheaders[_bytes];	if (hp->Allocated)	    hp->Value = NEW(char, MAXHEADERSIZE + 1);    }    /* Build the header tree. */    table = NEW(ARTHEADER*, SIZEOF(ARTheaders));    for (i = 0; i < SIZEOF(ARTheaders); i++)	table[i] = &ARTheaders[i];    qsort((POINTER)table, SIZEOF(ARTheaders), sizeof *table, ARTcompare);    ARTheadertree = ARTbuildtree(table, 0, SIZEOF(ARTheaders));    DISPOSE(table);    /* Get our Path name, kill trailing !. */    ARTpathme = COPY(Path.Data);    ARTpathme[Path.Used - 1] = '\0';    /* Set up database; ignore errors. */    (void)ARTreadschema();}STATIC voidARTfreetree(tp)    TREE	*tp;{    TREE	*next;    for ( ; tp != NULL; tp = next) {	if (tp->Before)	    ARTfreetree(tp->Before);	next = tp->After;	DISPOSE(tp);    }}voidARTclose(){    register ARTHEADER	*hp;    /* Free space in the header table. */    for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++)	if (hp->Allocated)	    DISPOSE(hp->Value);    if (ARTfields != NULL) {	DISPOSE(ARTfields);	ARTfields = NULL;    }    ARTfreetree(ARTheadertree);}/***  Read in a file, return a pointer to static space that is reused.*/STATIC char *ARTreadfile(name)    char		*name;{    static BUFFER	File;    struct stat		Sb;    int			fd;    int			oerrno;    /* Open the file, get its size. */    if ((fd = open(name, O_RDONLY)) < 0)	return NULL;    if (fstat(fd, &Sb) < 0) {	oerrno = errno;	(void)close(fd);	errno = oerrno;	return NULL;    }    /* Make sure we have enough space. */    if (File.Size == 0) {	File.Size = Sb.st_size;	File.Data = NEW(char, File.Size + 1);    }    else if (File.Size <= Sb.st_size) {	File.Size = Sb.st_size + 16;	RENEW(File.Data, char, File.Size + 1);    }    /* Read in the file. */    if (xread(fd, File.Data, Sb.st_size) < 0) {	oerrno = errno;	(void)close(fd);	errno = oerrno;	return NULL;    }    /* Clean up and return the data. */    File.Data[Sb.st_size] = '\0';    (void)close(fd);    return File.Data;}/***  Open the article file and return a copy of it.  The files parameter is**  actually a whitespace-separated list of names.*/char *ARTreadarticle(files)    register char	*files;{    register char	*p;    register BOOL	more;    char		*art;    if (files == NULL)	return NULL;    /* Loop over all filenames until we can open one. */    for ( ; *files; files = p + 1) {	/* Snip off next name, turn dots to slashes. */	for (p = files; ISWHITE(*p); p++)	    continue;	for (files = p; *p && *p != ' '; p++)	    if (*p == '.')		*p = '/';	more = *p == ' ';	if (more)	    *p = '\0';	art = ARTreadfile(files);	if (more)	    *p = ' ';	if (art != NULL)	    return art;	if (!more)	    break;    }    return NULL;}/***  Open the article file and return a copy of the headers.*/char *ARTreadheader(files)    char		*files;{    register char	*p;    register char	*head;    if ((head = ARTreadarticle(files)) == NULL)	return NULL;    /* Find \n\n which means the end of the header. */    for (p = head; (p = strchr(p, '\n')) != NULL; p++)	if (p[1] == '\n') {	    p[1] = '\0';	    return head;	}    syslog(L_NOTICE, "%s bad_article %s is all headers", LogName, files);    DISPOSE(head);    return NULL;}/***  Parse a Path line, splitting it up into NULL-terminated array of strings.**  The argument is modified!*/STATIC char **ARTparsepath(p, countp)    register char	*p;    int			*countp;{    static char		*NULLPATH[1] = { NULL };    static int		oldlength;    static char		**hosts;    register int	i;    register char	**hp;    /* We can be called with a non-existant or empty path. */    if (p == NULL || *p == '\0') {	*countp = 0;	return NULLPATH;    }    /* Get an array of character pointers. */    i = strlen(p);    if (hosts == NULL) {	oldlength = i;	hosts = NEW(char*, oldlength + 1);    }    else if (oldlength <= i) {	oldlength = i;	RENEW(hosts, char*, oldlength + 1);    }    /* Loop over text. */    for (hp = hosts; *p; *p++ = '\0') {	/* Skip leading separators. */	for (; *p && !ARThostchar(*p); p++)	    continue;	if (*p == '\0')	    break;	/* Mark the start of the host, move to the end of it. */	for (*hp++ = p; *p && ARThostchar(*p); p++)	    continue;	if (*p == '\0')	    break;    }    *hp = NULL;    *countp = hp - hosts;    return hosts;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -