/*
* DREADOVER group:article
*
* Read the overview record related to an article in a specific group.
* This command is typically used for debugging purposes only.
*
* (c)Copyright 1998, Matthew Dillon, All Rights Reserved. Refer to
* the COPYRIGHT file in the base directory of this distribution
* for specific rights granted.
*/
#include <dreaderd/defs.h>
char * allocTmpCopy(const char *buf, int bufLen);
void DReadOver(char *data);
void Usage(void);
void OverDump(void);
int ForceOpt = 0;
int ViewData = 0;
int VerboseMode = 0;
char *
allocTmpCopy(const char *buf, int bufLen)
{
static char *SaveAry[8];
static int SaveCnt;
char **pptr;
SaveCnt = (SaveCnt + 1) % arysize(SaveAry);
pptr = &SaveAry[SaveCnt];
if (*pptr)
free(*pptr);
*pptr = malloc(bufLen + 1);
memcpy(*pptr, buf, bufLen);
(*pptr)[bufLen] = 0;
return(*pptr);
}
int
main(int ac, char **av)
{
int i;
int Doneone = 0;
LoadDiabloConfig(ac, av);
if (ac < 2)
Usage();
for (i = 1; i < ac; ++i) {
char *ptr = av[i];
if (*ptr != '-' || strcmp(ptr, "-") == 0) {
if (*ptr != '-') {
DReadOver(ptr);
} else {
char buf[512];
while (fgets(buf, sizeof(buf), stdin) != NULL)
DReadOver(buf);
}
Doneone = 1;
continue;
}
ptr += 2;
switch(ptr[-1]) {
case 'a':
OverDump();
Doneone = 1;
break;
case 'C':
/* diablo.config path */
break;
case 'd':
VerboseMode = 1;
break;
case 'f':
ForceOpt = 1;
break;
case 'V':
PrintVersion();
break;
case 'v':
ViewData = 1;
break;
default:
Usage();
}
}
if (!Doneone)
Usage();
return(0);
}
void
Usage(void)
{
fprintf(stderr, "Prints out overview info from the overview cache\n");
fprintf(stderr, " Usage: dreadover [-f] [-v] [-a] [group:artno[-artnoend]]\n");
fprintf(stderr, " -f : Force retrieval if art no mismatch\n");
fprintf(stderr, " -v : Also view the overview data\n");
fprintf(stderr, " -a : List maxarts for all newsgroups\n");
fprintf(stderr, " group : The newsgroup group name\n");
fprintf(stderr, " artno : The starting article number\n");
fprintf(stderr, " artnoend : The ending article number\n");
exit(1);
}
void
DReadOver(char *data)
{
const char *gfname;
const char *slash;
char *ptr, *p;
int artNo = 0;
int artNoStart = 0;
int artNoEnd = 0;
int fd1;
int fd2;
OverHead oh;
struct stat st;
int maxarts;
char path[1024];
if ((ptr = strrchr(data, ':')) != NULL) {
*ptr++ = 0;
artNo = strtol(ptr, NULL, 10);
artNoStart = artNo;
artNoEnd = artNoStart;
if ((p = strrchr(ptr, '-')) != NULL)
artNoEnd = strtol(p + 1, NULL, 10);
}
/*
* Cycle through the overview entries
*/
for (artNo = artNoStart; artNo <= artNoEnd; artNo++) {
int pos;
OverArt oa;
/* Open the overview info file */
gfname = GFName(data, GRPFTYPE_OVER, 0, 1, 0, &DOpts.ReaderGroupHashMethod);
slash = strchr(gfname, '/');
snprintf(path, sizeof(path), "%s/%s", PatExpand(GroupHomePat), gfname);
printf("GROUPINFO:%s:%d\t%s", data, artNo, gfname);
if ((fd1 = open(path, O_RDONLY)) < 0) {
printf("\t(array open fail)\n");
return;
}
if (read(fd1, &oh, sizeof(oh)) != sizeof(oh)) {
printf("\t(read header fail)\n");
close(fd1);
return;
}
if (oh.oh_Version != OH_VERSION ||
oh.oh_ByteOrder != OH_BYTEORDER) {
printf("\t(wrong version or byte order)\n");
close(fd1);
return;
}
fstat(fd1, &st);
maxarts = (st.st_size - oh.oh_HeadSize) / sizeof(OverArt);
printf("\tmaxarts=%d", maxarts);
pos = oh.oh_HeadSize + ((artNo & 0x7FFFFFFF) % maxarts) *
sizeof(OverArt);
printf("\tpos=%d", pos);
lseek(fd1, pos, 0);
if (read(fd1, &oa, sizeof(oa)) != sizeof(oa)) {
printf("\t(unable to read OverArt)");
close(fd1);
return;
}
if (oa.oa_ArtNo <= 0) {
if (oa.oa_ArtNo == -1)
printf("\t(Article cancelled)(%d)\n", oa.oa_ArtNo);
else if (oa.oa_ArtNo == -2)
printf("\t(Article expired)(%d)\n", oa.oa_ArtNo);
else
printf("\t(Article not found)(%d)\n", oa.oa_ArtNo);
close(fd1);
continue;
}
if (oa.oa_ArtNo != artNo) {
printf("\tartNoMismatch(got=%d wanted=%d)\n", oa.oa_ArtNo, artNo);
if (!ForceOpt) {
close(fd1);
continue;
}
}
/*
* Open the overview data file
*/
gfname = GFName(data, GRPFTYPE_DATA, artNo & ~OD_HMASK, 1, 0,
&DOpts.ReaderGroupHashMethod);
snprintf(path, sizeof(path), "%s/%s",
PatExpand(GroupHomePat), gfname);
printf("\t%s", gfname);
if ((fd2 = open(path, O_RDONLY)) < 0) {
printf("\t(data open fail)\n");
close(fd1);
return;
}
printf("\tdataFilePos=%d\tsize=%d\treceived=%d\tbytes=%d\thash=%x.%x\n",
oa.oa_SeekPos, oa.oa_Bytes, oa.oa_TimeRcvd,
oa.oa_ArtSize, oa.oa_MsgHash.h1, oa.oa_MsgHash.h2);
if (ViewData) {
static char *buf = NULL;
int buflen = 0;
int n = oa.oa_Bytes + 1;
int r;
if (n > buflen)
buflen = n;
buf = (char *)realloc(buf, buflen);
lseek(fd2, oa.oa_SeekPos, 0);
while ((r = read(fd2, buf, n)) > 0) {
printf("%s", buf);
n -= r;
}
close(fd2);
}
close(fd1);
if (artNo <= artNoEnd)
printf("--------------------------------------------------------------------\n");
}
printf("\n");
}
/*
* Dump the contents of the overview info files for all newsgroups in
* active file.
*/
void
OverDump(void)
{
char path[PATH_MAX];
const char *gfname;
char *slash;
char *groupname;
int recLen;
int recOff;
int fd1;
OverHead oh;
struct stat st;
int maxarts;
KPDB *KDBActive = KPDBOpen(PatDbExpand(ReaderDActivePat), O_RDWR);
if (KDBActive == NULL) {
printf("Unable to open active file\n");
exit(1);
}
for (recOff = KPDBScanFirst(KDBActive, 0, &recLen);
recOff;
recOff = KPDBScanNext(KDBActive, recOff, 0, &recLen)
) {
int groupLen;
const char *rec;
const char *group;
int begno;
rec = KPDBReadRecordAt(KDBActive, recOff, 0, NULL);
group = KPDBGetField(rec, recLen, NULL, &groupLen, NULL);
if (!group)
continue;
groupname = allocTmpCopy(group, groupLen);
begno = strtol(KPDBGetField(rec, recLen, "NB", NULL, "0"), NULL, 10);
gfname = GFName(groupname, GRPFTYPE_OVER, 0, 1, 0,
&DOpts.ReaderGroupHashMethod);
slash = strchr(gfname, '/');
snprintf(path, sizeof(path), "%s/%s", PatExpand(GroupHomePat), gfname);
if ((fd1 = open(path, O_RDONLY)) < 0) {
if (VerboseMode)
printf("%s (array open fail)\n", groupname);
continue;;
}
if (read(fd1, &oh, sizeof(oh)) != sizeof(oh)) {
if (VerboseMode)
printf("%s (read header fail)\n", groupname);
close(fd1);
continue;;
}
if (oh.oh_Version != OH_VERSION ||
oh.oh_ByteOrder != OH_BYTEORDER) {
if (VerboseMode)
printf("%s (wrong version or byte order)\n", groupname);
close(fd1);
continue;;
}
fstat(fd1, &st);
maxarts = (st.st_size - oh.oh_HeadSize) / sizeof(OverArt);
printf("%s:%d\n", groupname, maxarts);
close(fd1);
}
}
syntax highlighted by Code2HTML, v. 0.9.1