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

📄 makehistory.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  $Revision: 1.14 $****  Rebuild the history database.*/#include "configdata.h"#include <stdio.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#if	defined(DO_NEED_TIME)#include <time.h>#endif	/* defined(DO_NEED_TIME) */#include <sys/time.h>#include <errno.h>#include "paths.h"#include "libinn.h"#include "clibrary.h"#include "inndcomm.h"#include "dbz.h"#include "qio.h"#include "macros.h"#include "mydir.h"typedef struct _BUFFER {    char	*Data;    int		Size;    int		Used;} BUFFER;STATIC char		ACTIVE[] = _PATH_ACTIVE;STATIC char		SPOOL[] = _PATH_SPOOL;STATIC char		*HISTORYDIR;STATIC char		HISTORY[] = _PATH_HISTORY;STATIC char		MESSAGEID[] = "Message-ID:";STATIC char		EXPIRES[] = "Expires:";STATIC char		DATE[] = "Date:";STATIC BOOL		INNDrunning;STATIC char		*TextFile;STATIC char		Reason[] = "makehistory is running";STATIC TIMEINFO		Now;extern long		dbztagmask();/***  Change to a directory or exit out.*/STATIC voidxchdir(where)    char	*where;{    if (chdir(where) < 0) {	(void)fprintf(stderr, "Can't change to \"%s\", %s\n",		where, strerror(errno));	exit(1);    }}/***  Remove the DBZ files for the specified base text file.*/STATIC voidRemoveDBZFiles(p)    char	*p;{    static char	NOCANDO[] = "Can't remove \"%s\", %s\n";    char	buff[SMBUF];    (void)sprintf(buff, "%s.dir", p);    if (unlink(buff) && errno != ENOENT)	(void)fprintf(stderr, NOCANDO, buff, strerror(errno));    (void)sprintf(buff, "%s.pag", p);    if (unlink(buff) && errno != ENOENT)	(void)fprintf(stderr, NOCANDO, buff, strerror(errno));}/***  Rebuild the DBZ file from the text file.*/STATIC voidRebuild(size, IgnoreOld, Overwrite)    long		size;    BOOL		IgnoreOld;    BOOL		Overwrite;{    register QIOSTATE	*qp;    register char	*p;    register char	*save;    register long	count;    long		where;    datum		key;    datum		value;    char		temp[SMBUF];    xchdir(HISTORYDIR);    /* Open the text file. */    qp = QIOopen(TextFile, QIO_BUFFER);    if (qp == NULL) {	(void)fprintf(stderr, "Can't open \"%s\", %s\n",		TextFile, strerror(errno));	exit(1);    }    /* If using the standard history file, force DBZ to use history.n. */    if (EQ(TextFile, HISTORY) && !Overwrite) {	(void)sprintf(temp, "%s.n", HISTORY);	if (link(HISTORY, temp) < 0) {	    (void)fprintf(stderr, "Can't make temporary link to \"%s\", %s\n",		    temp, strerror(errno));	    exit(1);	}	RemoveDBZFiles(temp);	p = temp;    }    else {	temp[0] = '\0';	RemoveDBZFiles(TextFile);	p = TextFile;    }    /* Open the new database, using the old file if desired and possible. */    (void)dbzincore(1);    if (IgnoreOld) {	if (dbzfresh(p, dbzsize(size), HIS_FIELDSEP, 'C', dbztagmask(size)) < 0) {	    (void)fprintf(stderr, "Can't do dbzfresh, %s\n",		    strerror(errno));	    if (temp[0])		(void)unlink(temp);	    exit(1);	}    }    else {	if (dbzagain(p, HISTORY) < 0) {	    (void)fprintf(stderr, "Can't do dbzagain, %s\n", strerror(errno));	    if (temp[0])		(void)unlink(temp);	    exit(1);	}    }    /* Set up the value pointer. */    value.dptr = (char *)&where;    value.dsize = sizeof where;    /* Loop through all lines in the text file. */    count = 0;    for (where = QIOtell(qp); (p = QIOread(qp)) != NULL; where = QIOtell(qp)) {	count++;	if ((save = strchr(p, HIS_FIELDSEP)) == NULL) {	    (void)fprintf(stderr, "Bad line #%ld \"%.30s...\"\n", count, p);	    if (temp[0])		(void)unlink(temp);	    exit(1);	}	*save = '\0';	key.dptr = p;	key.dsize = save - p + 1;	if (dbzstore(key, value) < 0) {	    (void)fprintf(stderr, "Can't store \"%s\", %s\n",		    p, strerror(errno));	    if (temp[0])		(void)unlink(temp);	    exit(1);	}    }    if (QIOerror(qp)) {	(void)fprintf(stderr, "Can't read \"%s\" near line %ld, %s\n",		TextFile, count, strerror(errno));	if (temp[0])	    (void)unlink(temp);	exit(1);    }    if (QIOtoolong(qp)) {	(void)fprintf(stderr, "Line %ld is too long\n", count);	if (temp[0])	    (void)unlink(temp);	exit(1);    }    /* Close files. */    QIOclose(qp);    if (dbmclose() < 0) {	(void)fprintf(stderr, "Can't close history, %s\n", strerror(errno));	if (temp[0])	    (void)unlink(temp);	exit(1);    }    if (temp[0])	(void)unlink(temp);}/***  Remove a bad article.*/STATIC voidRemoveit(name)    char	*name;{    char	*p;    /* Already in the spool directory, so skip right past the name;     * the strchr can't return NULL. */    p = strchr(name, '/') + 1;    if (unlink(p) < 0 && errno != ENOENT)	(void)fprintf(stderr, "Can't unlink %s, %s\n",		name, strerror(errno));    else	(void)fprintf(stderr, "Removing %s\n", name);}/***  Check and parse a Message-ID header line.  Return an allocated copy**  or a static empty string on error.*/static char *GetMessageID(p)    register char	*p;{    static char		NIL[] = "";    char		*save;    while (ISWHITE(*p))	p++;    if (p[0] != '<' || p[strlen(p) - 1] != '>')	return NIL;    for (save = COPY(p), p = save; *p; p++)	if (*p == HIS_FIELDSEP)	    *p = HIS_BADCHAR;    return save;}/***  Check and parse an date header line.  Return the new value or**  zero on error.*/static longGetaDate(p)    register char	*p;{    time_t		t;    while (ISWHITE(*p))	p++;    if ((t = parsedate(p, &Now)) == -1)	return 0L;    return (long)t;}/***  Process a single article.*/STATIC voidDoArticle(qp, Sbp, name, out, RemoveBad, Update)    register QIOSTATE	*qp;    struct stat		*Sbp;    char		*name;    FILE		*out;    BOOL		RemoveBad;    BOOL		Update;{    static char		IGNORE[] = "Ignoring duplicate %s header in %s\n";    static char		BADHDR[] = "Bad %s header in %s\n";    register char	*p;    char		*MessageID;    time_t		Arrived;    time_t		Expires;    time_t		Posted;    int			i;    datum		key;    datum		value;    /* Read the file for Message-ID and Expires header. */    Arrived = Sbp->st_mtime;    Expires = 0;    MessageID = NULL;    Posted = 0;    while ((p = QIOread(qp)) != NULL && *p != '\0')	switch (*p) {	default:	    break;	case 'M': case 'm':	    if (caseEQn(p, MESSAGEID, STRLEN(MESSAGEID))) {		if (MessageID)		    (void)fprintf(stderr, IGNORE, MESSAGEID, name);		else {		    MessageID = GetMessageID(&p[STRLEN(MESSAGEID)]);		    if (*MessageID == '\0')			(void)fprintf(stderr, BADHDR, MESSAGEID, name);		}	    }	    break;	case 'E': case 'e':	    if (caseEQn(p, EXPIRES, STRLEN(EXPIRES))) {		if (Expires > 0)		    (void)fprintf(stderr, IGNORE, EXPIRES, name);		else {		    Expires = GetaDate(&p[STRLEN(EXPIRES)]);		    if (Expires == 0)			(void)fprintf(stderr, BADHDR, EXPIRES, name);		}	    }	    break;	case 'D': case 'd':	    if (caseEQn(p, DATE, STRLEN(DATE))) {		if (Posted > 0)		    (void)fprintf(stderr, IGNORE, DATE, name);		else {		    Posted = GetaDate(&p[STRLEN(DATE)]);		    if (Posted == 0)			(void)fprintf(stderr, BADHDR, DATE, name);		}	    }	    break;	}    /* Check for errors, close the input. */    if (p == NULL) {	if (QIOerror(qp)) {	    (void)fprintf(stderr, "Can't read %s, %s\n",		    name, strerror(errno));	    return;	}	if (QIOtoolong(qp)) {	    (void)fprintf(stderr, "Line too long in %s\n", name);	    return;	}    }    /* Make sure we have everything we need. */    if (MessageID == NULL || *MessageID == '\0') {	if (MessageID == NULL)	    (void)fprintf(stderr, "No %s in %s\n", MESSAGEID, name);	if (RemoveBad)	    Removeit(name);	return;    }    if (Update) {	/* Server already know about this one? */	key.dptr = MessageID;	key.dsize = strlen(MessageID) + 1;	value = dbzfetch(key);	if (value.dptr != NULL)	    return;    }    /* Output the line. */    if (Posted == 0)	Posted = Arrived;    if (Expires > 0)	i = fprintf(out, "%s%c%ld%c%ld%c%ld%c%s\n",		MessageID, HIS_FIELDSEP,		(long)Arrived, HIS_SUBFIELDSEP, (long)Expires,		    HIS_SUBFIELDSEP, (long)Posted, HIS_FIELDSEP,		name);    else	i = fprintf(out, "%s%c%ld%c%s%c%ld%c%s\n",		MessageID, HIS_FIELDSEP,		(long)Arrived, HIS_SUBFIELDSEP, HIS_NOEXP,		    HIS_SUBFIELDSEP, (long)Posted, HIS_FIELDSEP,		name);    if (i == EOF || ferror(out)) {	(void)fprintf(stderr, "Can't write history line, %s\n",		strerror(errno));	exit(1);    }    DISPOSE(MessageID);}/***  Process one newsgroup directory.*/STATIC voidDoNewsgroup(group, out, RemoveBad, Update)    char		*group;    FILE		*out;    BOOL		RemoveBad;    BOOL		Update;{    register DIR	*dp;    register DIRENTRY	*ep;    register QIOSTATE	*qp;    register char	*p;    register char	*q;    struct stat		Sb;    char		buff[SPOOLNAMEBUFF];#if	defined(DO_HAVE_SYMLINK)    char		linkbuff[SPOOLNAMEBUFF];    int			oerrno;#endif	/* defined(DO_HAVE_SYMLINK) */    (void)strcpy(buff, group);    for (p = group; *p; p++)	if (*p == '.')	    *p = '/';    xchdir(SPOOL);    if (chdir(group) < 0)	return;    if ((dp = opendir(".")) == NULL) {	(void)fprintf(stderr, "Can't opendir %s, %s\n", group, strerror(errno));	return;    }    q = &buff[strlen(buff)];    *q++ = '/';    /* Read all entries in the directory. */    while ((ep = readdir(dp)) != NULL) {	p = ep->d_name;	if (!CTYPE(isdigit, *p) || strspn(p, "0123456789") != strlen(p))	    continue;	(void)strcpy(q, p);	/* Is this a regular file? */	if (stat(p, &Sb) < 0) {	    (void)fprintf(stderr, "Can't stat %s, %s\n",		    buff, strerror(errno));#if	defined(DO_HAVE_SYMLINK)	    /* Symlink to nowhere? */	    oerrno = errno;	    (void)memset((POINTER)linkbuff, '\0', sizeof linkbuff);	    if (lstat(p, &Sb) >= 0	     && readlink(p, linkbuff, sizeof linkbuff - 1) >= 0) {

⌨️ 快捷键说明

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