/* * 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 #include #include #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++; } }