/*
* VSEV.C
*
* Written by Paul Edwards and released to the public domain.
*
* Version7 nodelist processor.
*
* The version 7 nodelist is normally comprised as follows:
*
* 1. NODEX.DAT - the complete nodelist data file.
* 2. NODEX.NDX - an index into nodex.dat. The index entries are all
* address-based. After using the index, you will obtain an offset,
* which can be used to access nodex.dat.
* 3. SYSOP.NDX - another index into nodex.dat, this time by sysop name.
* The name used for the index is "surname, firstname". Although the
* names are stored in mixed case, they are ordered case-insensitive.
*/
/*
* This module has only one external function - vsevGetInfo. It
* requires a pointer to a VSEV structure, which should be empty. The
* second parameter is the name of the V7 data file. The third
* parameter is the offset. You are expected to have used one of the
* indexes to have retrieved the proper offset before retrieving the
* data.
*
* The function returns 0 on success, non-zero on failure. If the call
* was successful, then via the passed VSEV data structure, you will now
* have access to the following information:
*
*
* zone, net, node, point, hub, cost, fee, flags, modem, phone, password,
* board, sysop, misc, baud.
*
* Note that on return from this function, the board name, sysop name
* and misc info will be both unpacked and converted into mixed case.
* Internally, the data in the v7 nodelist data file is packed by
* converting everything to uppercase and then compressing it by
* compressing 3 bytes into 2. Presumably someone thought that the
* space advantages of making an abortion like this was worth it, and
* not just a gigantic wank.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "vsev.h"
static void vsevActual(VSEV * vsev);
static void vsevActual2(VSEV * vsev);
static void processPack(VSEV * vsev);
static void unpack(unsigned char *one, unsigned char *two, int len);
static void mixstr(unsigned char *str);
int vsevGetInfo(VSEV * vsev, char *dataFile, long offset)
{
vsev->error = 0;
vsev->fp = fopen(dataFile, "rb");
if (vsev->fp == NULL)
{
vsev->error = 1;
}
else
{
if (fseek(vsev->fp, offset, SEEK_SET) != 0)
{
vsev->error = 1;
}
else
{
vsevActual(vsev);
}
}
fclose(vsev->fp);
if (vsev->error)
{
return 1;
}
else
{
return 0;
}
}
static void vsevActual(VSEV * vsev)
{
fread(&vsev->zone, sizeof vsev->zone, 1, vsev->fp);
fread(&vsev->net, sizeof vsev->net, 1, vsev->fp);
fread(&vsev->node, sizeof vsev->node, 1, vsev->fp);
fread(&vsev->hub, sizeof vsev->hub, 1, vsev->fp);
fread(&vsev->cost, sizeof vsev->cost, 1, vsev->fp);
fread(&vsev->fee, sizeof vsev->fee, 1, vsev->fp);
fread(&vsev->flags, sizeof vsev->flags, 1, vsev->fp);
fread(&vsev->modem, sizeof vsev->modem, 1, vsev->fp);
fread(&vsev->phoneLen, sizeof vsev->phoneLen, 1, vsev->fp);
fread(&vsev->passwordLen, sizeof vsev->passwordLen, 1, vsev->fp);
fread(&vsev->boardLen, sizeof vsev->boardLen, 1, vsev->fp);
fread(&vsev->sysopLen, sizeof vsev->sysopLen, 1, vsev->fp);
fread(&vsev->miscLen, sizeof vsev->miscLen, 1, vsev->fp);
fread(&vsev->packLen, sizeof vsev->packLen, 1, vsev->fp);
fread(&vsev->baud, sizeof vsev->baud, 1, vsev->fp);
if (feof(vsev->fp) || ferror(vsev->fp))
{
vsev->error = 1;
}
else
{
vsevActual2(vsev);
}
}
static void vsevActual2(VSEV * vsev)
{
if ((vsev->flags & 0x1000U) != 0)
{
vsev->point = vsev->hub;
vsev->hub = vsev->node;
}
else
{
vsev->point = 0;
}
fread(vsev->phone, vsev->phoneLen, 1, vsev->fp);
fread(vsev->password, vsev->passwordLen, 1, vsev->fp);
fread(vsev->packData, sizeof vsev->packData, 1, vsev->fp);
if (feof(vsev->fp) || ferror(vsev->fp))
{
vsev->error = 1;
}
else
{
processPack(vsev);
}
}
static void processPack(VSEV * vsev)
{
int x, offset = 0;
vsev->packData[vsev->packLen] = '\0'; /* just in case */
unpack(vsev->unpackData, vsev->packData, vsev->packLen);
x = vsev->boardLen;
if (x > 100)
{
x = 100;
}
memcpy(vsev->board, vsev->unpackData + offset, x);
vsev->board[x] = '\0';
offset += vsev->boardLen;
mixstr(vsev->board);
x = vsev->sysopLen;
if (x > 100)
{
x = 100;
}
memcpy(vsev->sysop, vsev->unpackData + offset, x);
vsev->sysop[x] = '\0';
offset += vsev->sysopLen;
mixstr(vsev->sysop);
x = vsev->miscLen;
if (x > 100)
{
x = 100;
}
memcpy(vsev->misc, vsev->unpackData + offset, x);
vsev->misc[x] = '\0';
mixstr(vsev->misc);
}
static void unpack(unsigned char *one, unsigned char *two, int len)
{
int x, y;
char *code = " EANROSTILCHBDMUGPKYWFVJXZQ-'0123456789";
unsigned int i;
for (x = 0, y = 0; x < len; x += 2, y += 3)
{
i = two[x] | (two[x + 1] << 8);
one[y + 2] = code[(size_t) (i % 40)];
i /= 40;
one[y + 1] = code[(size_t) (i % 40)];
i /= 40;
one[y] = code[(size_t) (i % 40)];
}
one[y] = '\0';
}
static void mixstr(unsigned char *str)
{
int upper = 1;
while (*str != '\0')
{
if (upper)
{
*str = (unsigned char)toupper(*str);
}
else
{
*str = (unsigned char)tolower(*str);
}
if (isalpha(*str))
{
upper = 0;
}
else
{
upper = 1;
}
str++;
}
}
syntax highlighted by Code2HTML, v. 0.9.1