📄 makehistory.c
字号:
/* $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 + -