From a1e5aba0dde8a12140927a7b5c36d2846c587739 Mon Sep 17 00:00:00 2001 From: "Alexander S. Aganichev" Date: Sat, 27 Oct 2001 06:57:20 +0000 Subject: [PATCH] Redone synchronet support --- docs/notework.txt | 3 + golded3/Makefile | 4 +- goldlib/gmb3/Makefile | 3 +- goldlib/gmb3/gmb3.all | 1 - goldlib/gmb3/gmosmb.h | 380 +-------- goldlib/gmb3/gmosmb1.cpp | 303 ++++---- goldlib/gmb3/gmosmb2.cpp | 25 +- goldlib/gmb3/gmosmb3.cpp | 1042 ------------------------- goldlib/smblib/Makefile | 9 + goldlib/smblib/crc32.h | 9 + goldlib/smblib/lzh.cpp | 808 +++++++++++++++++++ goldlib/smblib/lzh.h | 81 ++ goldlib/smblib/smbdefs.h | 548 +++++++++++++ goldlib/smblib/smblib.all | 3 + goldlib/smblib/smblib.cpp | 1555 +++++++++++++++++++++++++++++++++++++ goldlib/smblib/smblib.h | 218 ++++++ goldlib/smblib/smbtxt.cpp | 121 +++ 17 files changed, 3536 insertions(+), 1577 deletions(-) delete mode 100644 goldlib/gmb3/gmosmb3.cpp create mode 100644 goldlib/smblib/Makefile create mode 100644 goldlib/smblib/crc32.h create mode 100644 goldlib/smblib/lzh.cpp create mode 100644 goldlib/smblib/lzh.h create mode 100644 goldlib/smblib/smbdefs.h create mode 100644 goldlib/smblib/smblib.all create mode 100644 goldlib/smblib/smblib.cpp create mode 100644 goldlib/smblib/smblib.h create mode 100644 goldlib/smblib/smbtxt.cpp diff --git a/docs/notework.txt b/docs/notework.txt index 0194de0..74b5131 100644 --- a/docs/notework.txt +++ b/docs/notework.txt @@ -12,6 +12,9 @@ ______________________________________________________________________ Notes for GoldED+ 1.1.5, /snapshot/ ______________________________________________________________________ +! Completely redone Synchronet support. Should be more stable and + adequate. + + Added support for SpaceToss areafile. WARNING: there's no known way to obtain primary AKA for echo areas from tosser config ver 1.10 so you'll need to define them manually. Main AKA will be used by diff --git a/golded3/Makefile b/golded3/Makefile index c59acf3..951774b 100644 --- a/golded3/Makefile +++ b/golded3/Makefile @@ -3,8 +3,8 @@ TOP=.. SHORTTARGET=ged TARGET=golded3 -GLIBS=gmb3 gall gcfg uulib -INCS=-I. -I$(TOP)/goldlib/gall -I$(TOP)/goldlib/gcfg -I$(TOP)/goldlib/gmb3 -I$(TOP)/goldlib/uulib +GLIBS=gmb3 gall gcfg uulib smblib +INCS=-I. -I$(TOP)/goldlib/gall -I$(TOP)/goldlib/gcfg -I$(TOP)/goldlib/gmb3 -I$(TOP)/goldlib/uulib -I$(TOP)/goldlib/smblib ifeq ($(findstring EMX, $(PATH)), EMX) STDLIBS=-los2me -lstdcpp diff --git a/goldlib/gmb3/Makefile b/goldlib/gmb3/Makefile index 4e243e4..8581b14 100644 --- a/goldlib/gmb3/Makefile +++ b/goldlib/gmb3/Makefile @@ -2,7 +2,8 @@ TOP=../.. TARGET=gmb3 -INCS=-I$(TOP)/goldlib/gall -I$(TOP)/goldlib/gcfg -I$(TOP)/goldlib/gmb3 +INCS=-I$(TOP)/goldlib/gall -I$(TOP)/goldlib/gcfg -I$(TOP)/goldlib/gmb3 -I$(TOP)/goldlib/smblib +CFLAGS=-DGOLDEDPLUS include $(TOP)/GNUmakef.inc ifeq ($(PLATFORM),emx) diff --git a/goldlib/gmb3/gmb3.all b/goldlib/gmb3/gmb3.all index 5cde257..d2e32f5 100644 --- a/goldlib/gmb3/gmb3.all +++ b/goldlib/gmb3/gmb3.all @@ -46,7 +46,6 @@ gmopcbd4 cpp all nov bco bcx wcn wco wcx lnx emx djg rsx cyg gmopcbd5 cpp all nov bco bcx wcn wco wcx lnx emx djg rsx cyg gmosmb1 cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg gmosmb2 cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg -gmosmb3 cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg gmosqsh1 cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg gmosqsh2 cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg gmosqsh3 cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg diff --git a/goldlib/gmb3/gmosmb.h b/goldlib/gmb3/gmosmb.h index 9da0820..cc7aa98 100644 --- a/goldlib/gmb3/gmosmb.h +++ b/goldlib/gmb3/gmosmb.h @@ -31,396 +31,22 @@ // ------------------------------------------------------------------ +#include #include -// ------------------------------------------------------------------ -// SMB library version used as reference (1.21a) - -const int SMB_VERSION = 0x0121; // SMB format version (High byte major, low byte minor) - - -// ------------------------------------------------------------------ - -const int SDT_BLOCK_LEN = 256; // Size of data blocks -const int SHD_BLOCK_LEN = 256; // Size of header blocks - -const int SMB_SELFPACK = 0; // Self-packing storage allocation -const int SMB_FASTALLOC = 1; // Fast allocation -const int SMB_HYPERALLOC = 2; // No allocation - -const int SMB_EMAIL = 1; // User numbers stored in Indexes - -// Time zone macros for when_t.zone -const int DAYLIGHT = 0x8000; // Daylight savings is active -const int US_ZONE = 0x4000; // U.S. time zone -const int WESTERN_ZONE = 0x2000; // Non-standard zone west of UT -const int EASTERN_ZONE = 0x1000; // Non-standard zone east of UT - -// Valid hfield_t.types -const int SENDER = 0x00; -const int SENDERAGENT = 0x01; -const int SENDERNETTYPE = 0x02; -const int SENDERNETADDR = 0x03; -const int SENDEREXT = 0x04; -const int SENDERPOS = 0x05; -const int SENDERORG = 0x06; - -const int AUTHOR = 0x10; -const int AUTHORAGENT = 0x11; -const int AUTHORNETTYPE = 0x12; -const int AUTHORNETADDR = 0x13; -const int AUTHOREXT = 0x14; -const int AUTHORPOS = 0x15; -const int AUTHORORG = 0x16; - -const int REPLYTO = 0x20; -const int REPLYTOAGENT = 0x21; -const int REPLYTONETTYPE = 0x22; -const int REPLYTONETADDR = 0x23; -const int REPLYTOEXT = 0x24; -const int REPLYTOPOS = 0x25; -const int REPLYTOORG = 0x26; - -const int RECIPIENT = 0x30; -const int RECIPIENTAGENT = 0x31; -const int RECIPIENTNETTYPE = 0x32; -const int RECIPIENTNETADDR = 0x33; -const int RECIPIENTEXT = 0x34; -const int RECIPIENTPOS = 0x35; -const int RECIPIENTORG = 0x36; - -const int FORWARDTO = 0x40; -const int FORWARDTOAGENT = 0x41; -const int FORWARDTONETTYPE = 0x42; -const int FORWARDTONETADDR = 0x43; -const int FORWARDTOEXT = 0x44; -const int FORWARDTOPOS = 0x45; -const int FORWARDTOORG = 0x46; - -const int FORWARDED = 0x48; - -const int RECEIVEDBY = 0x50; -const int RECEIVEDBYAGENT = 0x51; -const int RECEIVEDBYNETTYPE = 0x52; -const int RECEIVEDBYNETADDR = 0x53; -const int RECEIVEDBYEXT = 0x54; -const int RECEIVEDBYPOS = 0x55; -const int RECEIVEDBYORG = 0x56; - -const int RECEIVED = 0x58; - -const int SUBJECT = 0x60; -const int SUMMARY = 0x61; -const int SMBCOMMENT = 0x62; -const int CARBONCOPY = 0x63; -const int GROUP = 0x64; -const int EXPIRATION = 0x65; -const int PRIORITY = 0x66; - -const int FILEATTACH = 0x70; -const int DESTFILE = 0x71; -const int FILEATTACHLIST = 0x72; -const int DESTFILELIST = 0x73; -const int FILEREQUEST = 0x74; -const int FILEPASSWORD = 0x75; -const int FILEREQUESTLIST = 0x76; -const int FILEPASSWORDLIST = 0x77; - -const int IMAGEATTACH = 0x80; -const int ANIMATTACH = 0x81; -const int FONTATTACH = 0x82; -const int SOUNDATTACH = 0x83; -const int PRESENTATTACH = 0x84; -const int VIDEOATTACH = 0x85; -const int APPDATAATTACH = 0x86; - -const int IMAGETRIGGER = 0x90; -const int ANIMTRIGGER = 0x91; -const int FONTTRIGGER = 0x92; -const int SOUNDTRIGGER = 0x93; -const int PRESENTTRIGGER = 0x94; -const int VIDEOTRIGGER = 0x95; -const int APPDATATRIGGER = 0x96; - -const int FIDOCTRL = 0xa0; -const int FIDOAREA = 0xa1; -const int FIDOSEENBY = 0xa2; -const int FIDOPATH = 0xa3; -const int FIDOMSGID = 0xa4; -const int FIDOREPLYID = 0xa5; -const int FIDOPID = 0xa6; -const int FIDOFLAGS = 0xa7; - -const int RFC822HEADER = 0xb0; -const int RFC822MSGID = 0xb1; -const int RFC822REPLYID = 0xb2; - -const int UNKNOWN = 0xf1; -const int UNKNOWNASCII = 0xf2; -const int UNUSED = 0xff; - -// Valid dfield_t.types -const int TEXT_BODY = 0x00; -const int TEXT_SOUL = 0x01; -const int TEXT_TAIL = 0x02; -const int TEXT_WING = 0x03; -const int IMAGEEMBED = 0x20; -const int ANIMEMBED = 0x21; -const int FONTEMBED = 0x22; -const int SOUNDEMBED = 0x23; -const int PRESENTEMBED = 0x24; -const int VIDEOEMBED = 0x25; -const int APPDATAEMBED = 0x26; -//const int UNUSED = 0xff; - -// Message attributes -const int MSG_PRIVATE = (1<<0); -const int MSG_READ = (1<<1); -const int MSG_PERMANENT = (1<<2); -const int MSG_LOCKED = (1<<3); -const int MSG_DELETE = (1<<4); -const int MSG_ANONYMOUS = (1<<5); -const int MSG_KILLREAD = (1<<6); -const int MSG_MODERATED = (1<<7); -const int MSG_VALIDATED = (1<<8); - -// Auxillary header attributes -const int MSG_FILEREQUEST = (1<<0); // File request -const int MSG_FILEATTACH = (1<<1); // File(s) attached to Msg -const int MSG_TRUNCFILE = (1<<2); // Truncate file(s) when sent -const int MSG_KILLFILE = (1<<3); // Delete file(s) when sent -const int MSG_RECEIPTREQ = (1<<4); // Return receipt requested -const int MSG_CONFIRMREQ = (1<<5); // Confirmation receipt requested -const int MSG_NODISP = (1<<6); // Msg may not be displayed to user - -// Message network attributes -const int MSG_LOCAL = (1<<0); // Msg created locally -const int MSG_INTRANSIT = (1<<1); // Msg is in-transit -const int MSG_SENT = (1<<2); // Sent to remote -const int MSG_KILLSENT = (1<<3); // Kill when sent -const int MSG_ARCHIVESENT = (1<<4); // Archive when sent -const int MSG_HOLD = (1<<5); // Hold for pick-up -const int MSG_CRASH = (1<<6); // Crash -const int MSG_IMMEDIATE = (1<<7); // Send Msg now, ignore restrictions -const int MSG_DIRECT = (1<<8); // Send directly to destination -const int MSG_GATE = (1<<9); // Send via gateway -const int MSG_ORPHAN = (1<<10); // Unknown destination -const int MSG_FPU = (1<<11); // Force pickup -const int MSG_TYPELOCAL = (1<<12); // Msg is for local use only -const int MSG_TYPEECHO = (1<<13); // Msg is for conference distribution -const int MSG_TYPENET = (1<<14); // Msg is direct network mail - -enum { - NET_NONE, - NET_UNKNOWN, - NET_FIDO, - NET_POSTLINK, - NET_QWK, - NET_INTERNET, - NET_WWIV, - NET_MHS, - // Add new ones here - NET_TYPES -}; - -enum { - AGENT_PERSON, - AGENT_PROCESS, - // Add new ones here - AGENT_TYPES -}; - -enum { - XLAT_NONE, // No translation/End of translation list - XLAT_ENCRYPT, // Encrypted data - XLAT_ESCAPED, // 7-bit ASCII escaping for ctrl and 8-bit data - XLAT_HUFFMAN, // Static and adaptive Huffman coding compression - XLAT_LZW, // Limpel/Ziv/Welch compression - XLAT_MLZ78, // Modified LZ78 compression - XLAT_RLE, // Run length encoding compression - XLAT_IMPLODE, // Implode compression (PkZIP) - XLAT_SHRINK, // Shrink compression (PkZIP) - XLAT_LZH, // LHarc (LHA) Dynamic Huffman coding - // Add new ones here - XLAT_TYPES -}; - - -// ------------------------------------------------------------------ - -#if defined(GOLD_CANPACK) -#pragma pack(1) -#endif - - -// ------------------------------------------------------------------ - -typedef struct { - time_t time; // Local time (unix format) - sword zone; // Time zone -} when_t; - -typedef struct { - word to; // 16-bit CRC of recipient name (lower case) - word from; // 16-bit CRC of sender name (lower case) - word subj; // 16-bit CRC of subject (lower case, w/o RE:) - word attr; // attributes (read, permanent, etc.) - dword offset; // offset into header file - dword number; // number of message (1 based) - time_t time; // time/date message was imported/posted -} idxrec_t; - -typedef struct { - uchar id[4]; // text or binary unique hdr ID - word version; // version number (initially 100h for 1.00) - word length; // length including this struct -} smbhdr_t; - -typedef struct { - dword last_msg; // last message number - dword total_msgs; // total messages - dword header_offset; // byte offset to first header record - dword max_crcs; // Maximum number of CRCs to keep in history - dword max_msgs; // Maximum number of message to keep in sub - word max_age; // Maximum age of message to keep in sub (in days) - word attr; // Attributes for this message base (SMB_HYPER, etc) -} smbstatus_t; - -typedef struct { - uchar id[4]; // SHD<^Z> - word type; // Message type (normally 0) - word version; // Version of type (initially 100h for 1.00) - word length; // Total length of fixed record + all fields - word attr; // Attributes (bit field) (duped in SID) - dword auxattr; // Auxillary attributes (bit field) - dword netattr; // Network attributes - when_t when_written; // Time message was written (unix format) - when_t when_imported; // Time message was imported - dword number; // Message number - dword thread_orig; // Original message number in thread - dword thread_next; // Next message in thread - dword thread_first; // First reply to this message - uchar reserved[16]; // Reserved for future use - dword offset; // Offset for buffer into data file (0 or mod 256) - word total_dfields; // Total number of data fields -} msghdr_t; - -typedef struct { - word type; // Type of data field - dword offset; // Offset into buffer - dword length; // Length of data field -} dfield_t; - -typedef struct { - word type; - word length; // Length of buffer -} hfield_t; - -typedef struct { - word zone, net, node, point; -} fidoaddr_t; - -typedef struct { - word type; - void *addr; -} net_t; - -// ------------------------------------------------------------------ - -#if defined(GOLD_CANPACK) -#pragma pack() -#endif - - -// ------------------------------------------------------------------ - -typedef struct { - idxrec_t idx; // Index - msghdr_t hdr; // Header record (fixed portion) - uchar *to, // To name - *to_ext, // To extension - *from, // From name - *from_ext, // From extension - *replyto, // Reply-to name - *replyto_ext, // Reply-to extension */ - *subj; // Subject - word to_agent, // Type of agent message is to - from_agent, // Type of agent message is from - replyto_agent; // Type of agent replies should be sent to - net_t to_net, // Destination network type and address - from_net, // Origin network address - replyto_net; // Network type and address for replies - word total_hfields; // Total number of header fields - hfield_t *hfield; // Header fields (fixed length portion) - void **hfield_dat; // Header fields (variable length portion) - dfield_t *dfield; // Data fields (fixed length portion) - dword offset; // Offset (number of records) into index - uchar forwarded; // Forwarded from agent to another -} smbmsg_t; - - -// ------------------------------------------------------------------ - -struct SMBData { - char shd_buf[SHD_BLOCK_LEN]; - FILE *sdt_fp, *shd_fp, *sid_fp, *sda_fp, *sha_fp; -}; - - // ------------------------------------------------------------------ class SMBArea : public gmo_area { protected: - SMBData* data; + smb_t *data; void data_open(); void data_close(); void raw_scan(bool keep_index=false, bool scanpm=false); - - FILE* smb_openexlusively(const char *file, int retry_time); - int smb_openexlusively2(const char *file, int retry_time); - - int smb_open(int retry_time); - void smb_close(void); - int smb_open_da(int retry_time); - int smb_open_ha(int retry_time); - int smb_create(dword max_crcs, dword max_msgs, word max_age, word attr, int retry_time); - int smb_trunchdr(int retry_time); - int smb_locksmbhdr(int retry_time); - int smb_getstatus(smbstatus_t *status); - int smb_putstatus(smbstatus_t status); - int smb_unlocksmbhdr(void); - int smb_getmsgidx(smbmsg_t *msg); - int smb_getlastidx(idxrec_t *idx); - uint smb_getmsghdrlen(smbmsg_t msg); - dword smb_getmsgdatlen(smbmsg_t msg); - int smb_lockmsghdr(smbmsg_t msg, int retry_time); - int smb_getmsghdr(smbmsg_t *msg); - int smb_unlockmsghdr(smbmsg_t msg); - int smb_addcrc(dword max_crcs, dword crc, int retry_time); - int smb_hfield(smbmsg_t *msg, word type, word length, void *data); - int smb_dfield(smbmsg_t *msg, word type, dword length); - int smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage, int retry_time); - int smb_putmsg(smbmsg_t msg); - int smb_putmsgidx(smbmsg_t msg); - int smb_putmsghdr(smbmsg_t msg); - void smb_freemsgmem(smbmsg_t msg); - dword smb_hdrblocks(dword length); - dword smb_datblocks(dword length); - long smb_allochdr(dword length); - long smb_fallochdr(dword length); - long smb_hallochdr(dword header_offset); - long smb_allocdat(dword length, word headers); - long smb_fallocdat(dword length, word headers); - long smb_hallocdat(void); - int smb_incdat(dword offset, dword length, word headers); - int smb_freemsg(smbmsg_t msg, smbstatus_t status); - int smb_freemsgdat(dword offset, dword length, word headers); - int smb_freemsghdr(dword offset, dword length); int load_hdr(gmsg* __msg, smbmsg_t *msg); public: @@ -464,7 +90,7 @@ public: // ------------------------------------------------------------------ -extern SMBData* smbdata; +extern smb_t *smbdata; extern int smbdatano; diff --git a/goldlib/gmb3/gmosmb1.cpp b/goldlib/gmb3/gmosmb1.cpp index 8c1a55b..8522792 100644 --- a/goldlib/gmb3/gmosmb1.cpp +++ b/goldlib/gmb3/gmosmb1.cpp @@ -30,13 +30,12 @@ #include #include #include -#include #include // ------------------------------------------------------------------ -SMBData* smbdata = NULL; +smb_t* smbdata = NULL; int smbdatano = 0; @@ -52,71 +51,7 @@ void SMBExit() { void SMBInit() { - smbdata = (SMBData*)throw_calloc(3, sizeof(SMBData)); -} - - -// ------------------------------------------------------------------ - -FILE* SMBArea::smb_openexlusively(const char *__file, int retry_time) { - - FILE *_f; - long _tries = 0; - - do { - - _f = fsopen(__file, "rb+", SH_DENYRW); - if(_f == NULL) { - - if((errno != EACCES) or (PopupLocked(++_tries, false, __file) == false)) { - - // User requested to exit - WideLog->ErrOpen(); - WideLog->printf("! Synchronet message base could not be opened (exclusively)."); - WideLog->printf(": %s", __file); - WideLog->ErrOSInfo(); - OpenErrorExit(); - } - } - } while(_f == NULL); - - // Remove the popup window - if(_tries) - PopupLocked(0, 0, NULL); - - return _f; -} - - -// ------------------------------------------------------------------ - -int SMBArea::smb_openexlusively2(const char *__file, int retry_time) { - - int _fh; - long _tries = 0; - - do { - - _fh = ::sopen(__file, O_RDWR|O_CREAT|O_BINARY, SH_DENYRW, S_STDRW); - if(_fh == -1) { - - if((errno != EACCES) or (PopupLocked(++_tries, false, __file) == false)) { - - // User requested to exit - WideLog->ErrOpen(); - WideLog->printf("! Synchronet message base could not be opened (exclusively)."); - WideLog->printf(": %s", __file); - WideLog->ErrOSInfo(); - OpenErrorExit(); - } - } - } while(_fh == -1); - - // Remove the popup window - if(_tries) - PopupLocked(0, 0, NULL); - - return _fh; + smbdata = (smb_t *)throw_calloc(3, sizeof(smb_t)); } @@ -125,7 +60,10 @@ int SMBArea::smb_openexlusively2(const char *__file, int retry_time) { void SMBArea::data_open() { data = smbdata + (smbdatano++); + strxcpy(data->file, path(), sizeof(data->file) - 3); data->sdt_fp = data->shd_fp = data->sid_fp = data->sda_fp = data->sha_fp = NULL; + data->retry_time = 1; + data->last_error[0] = NUL; } @@ -156,9 +94,45 @@ void SMBArea::open() { } if(isopen == 1) { data_open(); - smb_open(10); - if(not fsize(data->shd_fp)) - smb_create(2000, 2000, 0, 0, 10); + + int _tries = 0; + + for(;;) { + if(smb_open(data) != 0) { + + if((errno != EACCES) or (PopupLocked(++_tries, false, data->file) == false)) { + + // User requested to exit + WideLog->ErrOpen(); + WideLog->printf("! Synchronet message base could not be opened (%s).", data->last_error); + WideLog->printf(": %s", path()); + WideLog->ErrOSInfo(); + OpenErrorExit(); + } + } + else + break; + }; + + // Remove the popup window + if(_tries) + PopupLocked(0, 0, NULL); + + if(not fsize(data->shd_fp)) { + data->status.max_crcs = 0; + data->status.max_age = 0; + data->status.max_msgs = 1000; + data->status.attr = 0; + if(smb_create(data) != 0) { + smb_close(data); + + WideLog->ErrOpen(); + WideLog->printf("! Synchronet message base could not be created (%s).", data->last_error); + WideLog->printf(": %s", path()); + WideLog->ErrOSInfo(); + OpenErrorExit(); + } + } scan(); } @@ -174,7 +148,7 @@ void SMBArea::close() if(isopen) { if(isopen == 1) { - smb_close(); + smb_close(data); data_close(); } isopen--; @@ -196,7 +170,7 @@ void SMBArea::close() void SMBArea::suspend() { - smb_close(); + smb_close(data); } @@ -204,9 +178,44 @@ void SMBArea::suspend() void SMBArea::resume() { - smb_open(10); - if(not fsize(data->shd_fp)) - smb_create(2000, 2000, 0, 0, 10); + int _tries = 0; + + for(;;) { + if(smb_open(data) != 0) { + + if((errno != EACCES) or (PopupLocked(++_tries, false, data->file) == false)) { + + // User requested to exit + WideLog->ErrOpen(); + WideLog->printf("! Synchronet message base could not be opened (%s).", data->last_error); + WideLog->printf(": %s", path()); + WideLog->ErrOSInfo(); + OpenErrorExit(); + } + } + else + break; + }; + + // Remove the popup window + if(_tries) + PopupLocked(0, 0, NULL); + + if(not fsize(data->shd_fp)) { + data->status.max_crcs = 0; + data->status.max_age = 0; + data->status.max_msgs = 1000; + data->status.attr = 0; + if(smb_create(data) != 0) { + smb_close(data); + + WideLog->ErrOpen(); + WideLog->printf("! Synchronet message base could not be created (%s).", data->last_error); + WideLog->printf(": %s", path()); + WideLog->ErrOSInfo(); + OpenErrorExit(); + } + } } @@ -238,12 +247,12 @@ int SMBArea::load_hdr(gmsg* __msg, smbmsg_t *smsg) return false; } fseek(data->sid_fp, (reln - 1L) * sizeof(idxrec_t), SEEK_SET); - if(not fread(&smsgp->idx, 1, sizeof(idxrec_t), data->sid_fp) or (smb_lockmsghdr(*smsgp, 10) != 0)) { + if(not fread(&smsgp->idx, 1, sizeof(idxrec_t), data->sid_fp) or (smb_lockmsghdr(data, smsgp) != 0)) { GFTRK(NULL); return false; } - int rv = smb_getmsghdr(smsgp); - smb_unlockmsghdr(*smsgp); + int rv = smb_getmsghdr(data, smsgp); + smb_unlockmsghdr(data, smsgp); if(rv != 0) { GFTRK(NULL); return false; @@ -315,7 +324,7 @@ int SMBArea::load_hdr(gmsg* __msg, smbmsg_t *smsg) __msg->received = 0; if(not smsg) - smb_freemsgmem(*smsgp); + smb_freemsgmem(smsgp); GFTRK(NULL); return true; } @@ -327,7 +336,7 @@ int SMBArea::load_msg(gmsg* msg) { smbmsg_t smsg; ushort xlat; - char *inbuf; + uchar *inbuf; long outlen; char buf[512]; int i; @@ -425,11 +434,11 @@ common: l += 2; } if(lzh) { - inbuf = (char *)throw_xmalloc(smsg.dfield[i].length); + inbuf = (uchar *)throw_xmalloc(smsg.dfield[i].length); fread(inbuf, smsg.dfield[i].length - l, 1, data->sdt_fp); outlen = *(long *)inbuf; msg->txt = (char *)throw_realloc(msg->txt, txt_len+outlen); - glzh_decode(inbuf, smsg.dfield[i].length - l, msg->txt+txt_len-1); + lzh_decode(inbuf, smsg.dfield[i].length - l, (uchar *)(msg->txt+txt_len-1)); throw_xfree(inbuf); } else { outlen = smsg.dfield[i].length - l; @@ -464,7 +473,7 @@ add2: } - smb_freemsgmem(smsg); + smb_freemsgmem(&smsg); GFTRK(NULL); return true; @@ -482,12 +491,11 @@ void SMBArea::save_hdr(int mode, gmsg* msg) char *fbuf, *sbody, *stail; char buf[256]; smbmsg_t smsg; - smbstatus_t status; fidoaddr_t destaddr, origaddr; GFTRK("SMBSaveHdr"); - smb_getstatus(&status); + smb_getstatus(data); memset(&smsg, 0, sizeof(smbmsg_t)); if(not (mode & GMSG_NEW)) { ulong reln = Msgn->ToReln(msg->msgno); @@ -496,12 +504,12 @@ void SMBArea::save_hdr(int mode, gmsg* msg) return; } fseek(data->sid_fp, (reln - 1L) * sizeof(idxrec_t), SEEK_SET); - if(not fread(&smsg.idx, 1, sizeof(idxrec_t), data->sid_fp) or (smb_lockmsghdr(smsg, 10) != 0)) { + if(not fread(&smsg.idx, 1, sizeof(idxrec_t), data->sid_fp) or (smb_lockmsghdr(data, &smsg) != 0)) { GFTRK(NULL); return; } - int rv = smb_getmsghdr(&smsg); - smb_unlockmsghdr(smsg); + int rv = smb_getmsghdr(data, &smsg); + smb_unlockmsghdr(data, &smsg); if(rv != 0) { GFTRK(NULL); return; @@ -512,7 +520,7 @@ void SMBArea::save_hdr(int mode, gmsg* msg) } else { memcpy(smsg.hdr.id, "SHD\x1a", 4); - smsg.hdr.version = SMB_VERSION; + smsg.hdr.version = smb_ver(); struct tm *tp = gmtime(&msg->written); tp->tm_isdst = -1; smsg.hdr.when_written.time = mktime(tp); @@ -548,23 +556,28 @@ void SMBArea::save_hdr(int mode, gmsg* msg) if((mode & GMSG_UPDATE) and not (mode & GMSG_TXT)) { if(mode & GMSG_NEW) - smb_addmsghdr(&smsg, &status, 1, 10); + smb_addmsghdr(data, &smsg, data->status.attr & SMB_HYPERALLOC); else - smb_putmsghdr(smsg); - smb_freemsgmem(smsg); + smb_putmsghdr(data, &smsg); + smb_freemsgmem(&smsg); GFTRK(NULL); return; } if(not (mode & GMSG_NEW)) { - if(smb_open_da(10) == 0) { - if(smb_open_ha(10) == 0) { - smb_freemsg(smsg, status); - fclose(data->sha_fp); + if(not (data->status.attr & SMB_HYPERALLOC)) { + if(smb_open_da(data) == 0) { + if(smb_open_ha(data) == 0) { + smb_freemsg(data, &smsg); + smb_close_ha(data); + } + smb_close_da(data); } - fclose(data->sda_fp); } - smb_freemsgmem(smsg); + else { + smb_freemsg(data, &smsg); + } + smb_freemsgmem(&smsg); smsg.dfield = NULL; smsg.hdr.total_dfields = 0; smsg.total_hfields = 0; @@ -703,44 +716,53 @@ void SMBArea::save_hdr(int mode, gmsg* msg) bodylen-=2; // remove last CRLF if present crc = ~memCrc32(sbody, bodylen, false, CRC32_MASK_CCITT); - rv = smb_addcrc(status.max_crcs, crc, 10); + rv = smb_addcrc(data, crc); while(taillen and (iscntrl(stail[taillen-1]) or isspace(stail[taillen-1]))) taillen--; - if(smb_open_da(10) == 0) { - l = bodylen+2; - if(taillen) - l += (taillen+2); - smsg.hdr.offset = smb_fallocdat(l, 1); - fclose(data->sda_fp); - if(not (smsg.hdr.offset and smsg.hdr.offset<1L)) { - fseek(data->sdt_fp, smsg.hdr.offset, SEEK_SET); - ushort xlat = XLAT_NONE; - fwrite(&xlat, 2, 1, data->sdt_fp); - l = ftell(data->sdt_fp); - fwrite(sbody, SDT_BLOCK_LEN, smb_datblocks(bodylen), data->sdt_fp); - if(taillen) { - fseek(data->sdt_fp, l+bodylen, SEEK_SET); - fwrite(&xlat, 2, 1, data->sdt_fp); - fwrite(stail, SDT_BLOCK_LEN, smb_datblocks(taillen), data->sdt_fp); - } - fflush(data->sdt_fp); - smb_dfield(&smsg, TEXT_BODY, bodylen+2); - if(taillen) - smb_dfield(&smsg, TEXT_TAIL, taillen+2); + l = bodylen+2; + if(taillen) + l += (taillen+2); - if(mode & GMSG_NEW) { - smb_addmsghdr(&smsg, &status, 1, 10); - Msgn->Append(smsg.hdr.number); - } - else - smb_putmsghdr(smsg); + if(not (data->status.attr & SMB_HYPERALLOC)) { + if(smb_open_da(data) == 0) { + smsg.hdr.offset = smb_allocdat(data, l, 1); + smb_close_da(data); } + else + smsg.hdr.offset = -1L; + } + else { + smsg.hdr.offset = smb_hallocdat(data); + } + + if(smsg.hdr.offset >= 0) { + fseek(data->sdt_fp, smsg.hdr.offset, SEEK_SET); + ushort xlat = XLAT_NONE; + fwrite(&xlat, 2, 1, data->sdt_fp); + l = ftell(data->sdt_fp); + fwrite(sbody, SDT_BLOCK_LEN, smb_datblocks(bodylen), data->sdt_fp); + if(taillen) { + fseek(data->sdt_fp, l+bodylen, SEEK_SET); + fwrite(&xlat, 2, 1, data->sdt_fp); + fwrite(stail, SDT_BLOCK_LEN, smb_datblocks(taillen), data->sdt_fp); + } + fflush(data->sdt_fp); + smb_dfield(&smsg, TEXT_BODY, bodylen+2); + if(taillen) + smb_dfield(&smsg, TEXT_TAIL, taillen+2); + + if(mode & GMSG_NEW) { + smb_addmsghdr(data, &smsg, data->status.attr & SMB_HYPERALLOC); + Msgn->Append(smsg.hdr.number); + } + else + smb_putmsghdr(data, &smsg); } throw_xfree(sbody); throw_xfree(stail); - smb_freemsgmem(smsg); + smb_freemsgmem(&smsg); GFTRK(NULL); } @@ -771,20 +793,20 @@ void SMBArea::del_msg(gmsg* msg) return; } fseek(data->sid_fp, (reln - 1L) * sizeof(idxrec_t), SEEK_SET); - if(not fread(&smsg.idx, 1, sizeof(idxrec_t), data->sid_fp) or (smb_lockmsghdr(smsg, 10) != 0)) { + if(not fread(&smsg.idx, 1, sizeof(idxrec_t), data->sid_fp) or (smb_lockmsghdr(data, &smsg) != 0)) { GFTRK(NULL); return; } - if(smb_getmsghdr(&smsg) == 0) { + if(smb_getmsghdr(data, &smsg) == 0) { smsg.hdr.attr |= MSG_DELETE; - int rv = smb_putmsghdr(smsg); - smb_unlockmsghdr(smsg); + int rv = smb_putmsghdr(data, &smsg); + smb_unlockmsghdr(data, &smsg); if(rv == 0) msg->attr.del1(); } else - smb_unlockmsghdr(smsg); - smb_freemsgmem(smsg); + smb_unlockmsghdr(data, &smsg); + smb_freemsgmem(&smsg); GFTRK(NULL); } @@ -794,10 +816,9 @@ void SMBArea::del_msg(gmsg* msg) void SMBArea::new_msgno(gmsg* msg) { - smbstatus_t status; - int res = smb_getstatus(&status); - smb_unlocksmbhdr(); - msg->msgno = (res == 0) ? status.last_msg+1 : 0; + int res = smb_getstatus(data); + smb_unlocksmbhdr(data); + msg->msgno = (res == 0) ? data->status.last_msg+1 : 0; } @@ -971,7 +992,7 @@ Line* SMBArea::make_dump_msg(Line*& lin, gmsg* msg, char* lng_head) line = AddLine(line, buf); ushort xlat; - char *inbuf; + uchar *inbuf; long outlen; bool lzh; bool tail = true; @@ -1004,11 +1025,11 @@ common: l += 2; } if(lzh) { - inbuf = (char *)throw_xmalloc(smsg.dfield[i].length); + inbuf = (uchar *)throw_xmalloc(smsg.dfield[i].length); fread(inbuf, smsg.dfield[i].length - l, 1, data->sdt_fp); outlen = *(long *)inbuf; msg->txt = (char *)throw_realloc(msg->txt, txt_len+outlen); - glzh_decode(inbuf, smsg.dfield[i].length - l, msg->txt+txt_len-1); + lzh_decode(inbuf, smsg.dfield[i].length - l, (uchar *)(msg->txt+txt_len-1)); throw_xfree(inbuf); } else { outlen = smsg.dfield[i].length - l; @@ -1020,7 +1041,7 @@ common: break; } - smb_freemsgmem(smsg); + smb_freemsgmem(&smsg); GFTRK(NULL); diff --git a/goldlib/gmb3/gmosmb2.cpp b/goldlib/gmb3/gmosmb2.cpp index 10de2fd..6aaa257 100644 --- a/goldlib/gmb3/gmosmb2.cpp +++ b/goldlib/gmb3/gmosmb2.cpp @@ -35,22 +35,21 @@ void SMBArea::raw_scan(bool keep_index, bool scanpm) { GFTRK("SMBArea::raw_scan"); - SMBData* _was_data = data; + smb_t *_was_data = data; if(_was_data == NULL) data_open(); ulong firstmsgno = 0; ulong lastmsgno = 0; Msgn->Reset(); PMrk->Reset(); - if(isopen or smb_open(10) == 0) { - if(smb_locksmbhdr(10) == 0) { - smbstatus_t status; - int res = smb_getstatus(&status); - smb_unlocksmbhdr(); + if(isopen or smb_open(data) == 0) { + if(smb_locksmbhdr(data) == 0) { + int res = smb_getstatus(data); + smb_unlocksmbhdr(data); ulong total_msgs = 0; if(res == 0) { - total_msgs = status.total_msgs; - lastmsgno = status.last_msg; + total_msgs = data->status.total_msgs; + lastmsgno = data->status.last_msg; if(keep_index or scanpm) { smbmsg_t msg; int umax = (WidePersonalmail & PM_ALLNAMES) ? WideUsernames : 1; @@ -59,9 +58,9 @@ void SMBArea::raw_scan(bool keep_index, bool scanpm) while(l <= total_msgs) { if(not fread(&msg.idx, 1, sizeof(idxrec_t), data->sid_fp)) break; - if(smb_lockmsghdr(msg, 10) == 0) { - int rc = smb_getmsghdr(&msg); - smb_unlockmsghdr(msg); + if(smb_lockmsghdr(data, &msg) == 0) { + int rc = smb_getmsghdr(data, &msg); + smb_unlockmsghdr(data, &msg); if(rc == 0) { if(firstmsgno == 0) firstmsgno = msg.hdr.number; @@ -81,7 +80,7 @@ void SMBArea::raw_scan(bool keep_index, bool scanpm) gotpm = false; } } - smb_freemsgmem(msg); + smb_freemsgmem(&msg); } } l++; @@ -90,7 +89,7 @@ void SMBArea::raw_scan(bool keep_index, bool scanpm) } } if(not isopen) - smb_close(); + smb_close(data); Msgn->SetCount(total_msgs); } } diff --git a/goldlib/gmb3/gmosmb3.cpp b/goldlib/gmb3/gmosmb3.cpp deleted file mode 100644 index 890edac..0000000 --- a/goldlib/gmb3/gmosmb3.cpp +++ /dev/null @@ -1,1042 +0,0 @@ -// This may look like C code, but it is really -*- C++ -*- - -// ------------------------------------------------------------------ -// The Goldware Library -// Copyright (C) 2000 Alexander S. Aganichev -// ------------------------------------------------------------------ -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// ------------------------------------------------------------------ -// $Id$ -// ------------------------------------------------------------------ -// Based on freeware sources from Digital Dynamics -// ------------------------------------------------------------------ -// Synchronet message base -// ------------------------------------------------------------------ - -#include -#include -#include - - -// ------------------------------------------------------------------ -// Open a message base -// If retry_time is 0, fast open method (no compatibility/validity check) -// Opens files for READing messages or updating message indices only - -int SMBArea::smb_open(int retry_time) -{ - int file; - smbhdr_t hdr; - - data->shd_fp = data->sdt_fp = data->sid_fp = NULL; - if ((data->shd_fp = fsopen(AddPath(path(), ".shd"), "rb+", WideSharemode)) == NULL) - return (2); - file = fileno(data->shd_fp); - if (retry_time && filelength(file) >= sizeof(smbhdr_t)) { - setvbuf(data->shd_fp, data->shd_buf, _IONBF, SHD_BLOCK_LEN); - if (smb_locksmbhdr(retry_time)) { - smb_close(); - return (-1); - } - memset(&hdr, 0, sizeof(smbhdr_t)); - fread(&hdr, sizeof(smbhdr_t), 1, data->shd_fp); - if (memcmp(hdr.id, "SMB\x1a", 4)) { - smb_close(); - return (-2); - } - if (hdr.version < 0x110) { // Compatibility check - smb_close(); - return (-3); - } - smb_unlocksmbhdr(); - rewind(data->shd_fp); - } - if ((data->sdt_fp = fsopen(AddPath(path(), ".sdt"), "rb+", WideSharemode)) == NULL) { - smb_close(); - return (1); - } - if ((data->sid_fp = fsopen(AddPath(path(), ".sid"), "rb+", WideSharemode)) == NULL) { - smb_close(); - return (3); - } - return (0); -} - - -// ------------------------------------------------------------------ -// Closes the currently open message base - -void SMBArea::smb_close(void) -{ - if (data->shd_fp != NULL) { - // In case it's been locked - smb_unlocksmbhdr(); - fclose(data->shd_fp); - } - if (data->sid_fp != NULL) - fclose(data->sid_fp); - if (data->sdt_fp != NULL) - fclose(data->sdt_fp); - data->sid_fp = data->shd_fp = data->sdt_fp = NULL; -} - - -// ------------------------------------------------------------------ -// Opens the data block allocation table message base 'smb_file' -// Retrys for retry_time number of seconds -// Return 0 on success, non-zero otherwise - -int SMBArea::smb_open_da(int retry_time) -{ - data->sda_fp = smb_openexlusively(AddPath(path(), ".sda"), retry_time); - return data->sda_fp == NULL ? 1 : 0; -} - - -// ------------------------------------------------------------------ -// Opens the header block allocation table for message base 'smb_file' -// Retrys for retry_time number of seconds -// Return 0 on success, non-zero otherwise - -int SMBArea::smb_open_ha(int retry_time) -{ - data->sha_fp = smb_openexlusively(AddPath(path(), ".sha"), retry_time); - return data->sha_fp == NULL ? 1 : 0; -} - - -// ------------------------------------------------------------------ -// Truncates header file -// Retrys for retry_time number of seconds -// Return 0 on success, non-zero otherwise - -int SMBArea::smb_trunchdr(int retry_time) -{ - long start; - - start = time(NULL); - rewind(data->shd_fp); - while (1) { - if (not chsize(fileno(data->shd_fp), 0L)) - break; - if (errno != EACCES) - return (-1); - if (time(NULL) - start >= retry_time) // Time-out - return (-2); - } - return (0); -} - - -// ------------------------------------------------------------------ -// Message Base Header Functions - -// ------------------------------------------------------------------ -// Attempts for retry_time number of seconds to lock the message base hdr - -int SMBArea::smb_locksmbhdr(int retry_time) -{ - dword start; - - if(WideCanLock) { - start = time(NULL); - while (1) { - if (not ::lock(fileno(data->shd_fp), 0L, sizeof(smbhdr_t) + sizeof(smbstatus_t))) - return (0); - if (time(NULL) - start >= retry_time) - break; // Incase we've already locked it - ::unlock(fileno(data->shd_fp), 0L, sizeof(smbhdr_t) + sizeof(smbstatus_t)); - } - return (-1); - } - return (0); -} - - -// ------------------------------------------------------------------ -// Read the SMB header from the header file and place into "status" - -int SMBArea::smb_getstatus(smbstatus_t *status) -{ - int i; - - clearerr(data->shd_fp); - fseek(data->shd_fp, sizeof(smbhdr_t), SEEK_SET); - i = fread(status, 1, sizeof(smbstatus_t), data->shd_fp); - if (i == sizeof(smbstatus_t)) - return (0); - return (1); -} - - -// ------------------------------------------------------------------ -// Writes message base header - -int SMBArea::smb_putstatus(smbstatus_t status) -{ - int i; - - clearerr(data->shd_fp); - fseek(data->shd_fp, sizeof(smbhdr_t), SEEK_SET); - i = fwrite(&status, 1, sizeof(smbstatus_t), data->shd_fp); - fflush(data->shd_fp); - if (i == sizeof(smbstatus_t)) - return (0); - return (1); -} - - -// ------------------------------------------------------------------ -// Unlocks previously locks message base header - -int SMBArea::smb_unlocksmbhdr() -{ - if(not WideCanLock) return 0; - return (::unlock(fileno(data->shd_fp), 0L, sizeof(smbhdr_t) + sizeof(smbstatus_t))); -} - - -// ------------------------------------------------------------------ -// Individual Message Functions - -// ------------------------------------------------------------------ -// Attempts for retry_time number of seconds to lock the header for 'msg' - -int SMBArea::smb_lockmsghdr(smbmsg_t msg, int retry_time) -{ - dword start; - - if(WideCanLock) { - start = time(NULL); - while (1) { - if (not ::lock(fileno(data->shd_fp), msg.idx.offset, sizeof(msghdr_t))) - return (0); - if (time(NULL) - start >= retry_time) - break; - ::unlock(fileno(data->shd_fp), msg.idx.offset, sizeof(msghdr_t)); - } - return (-1); - } - return 0; -} - - -// ------------------------------------------------------------------ -// Fills msg->idx with message index based on msg->hdr.number -// OR if msg->hdr.number is 0, based on msg->offset (record offset). -// if msg.hdr.number does not equal 0, then msg->offset is filled too. -// Either msg->hdr.number or msg->offset must be initialized before -// calling this function -// Returns 1 if message number wasn't found, 0 if it was - -int SMBArea::smb_getmsgidx(smbmsg_t *msg) -{ - idxrec_t idx; - dword l, length, total, bot, top; - - clearerr(data->sid_fp); - if (not msg->hdr.number) { - fseek(data->sid_fp, msg->offset * sizeof(idxrec_t), SEEK_SET); - if (not fread(&msg->idx, sizeof(idxrec_t), 1, data->sid_fp)) - return (1); - return (0); - } - length = filelength(fileno(data->sid_fp)); - if (not length) - return (1); - total = length / sizeof(idxrec_t); - if (not total) - return (1); - - bot = 0; - top = total; - l = total / 2; // Start at middle index - while (1) { - fseek(data->sid_fp, l * sizeof(idxrec_t), SEEK_SET); - if (not fread(&idx, sizeof(idxrec_t), 1, data->sid_fp)) - return (1); - if (bot == top - 1 and idx.number != msg->hdr.number) - return (1); - if (idx.number > msg->hdr.number) { - top = l; - l = bot + ((top - bot) / 2); - continue; - } - if (idx.number < msg->hdr.number) { - bot = l; - l = top - ((top - bot) / 2); - continue; - } - break; - } - msg->idx = idx; - msg->offset = l; - return (0); -} - - -// ------------------------------------------------------------------ -// Reads the last index record in the open message base - -int SMBArea::smb_getlastidx(idxrec_t *idx) -{ - long length; - - clearerr(data->sid_fp); - length = filelength(fileno(data->sid_fp)); - if (length < sizeof(idxrec_t)) - return (-1); - fseek(data->sid_fp, length - sizeof(idxrec_t), SEEK_SET); - if (not fread(idx, sizeof(idxrec_t), 1, data->sid_fp)) - return (-2); - return (0); -} - - -// ------------------------------------------------------------------ -// Figures out the total length of the header record for 'msg' -// Returns length - -uint SMBArea::smb_getmsghdrlen(smbmsg_t msg) -{ - int i; - - // fixed portion - msg.hdr.length = sizeof(msghdr_t); - // data fields - msg.hdr.length += msg.hdr.total_dfields * sizeof(dfield_t); - // header fields - for (i = 0; i < msg.total_hfields; i++) { - msg.hdr.length += sizeof(hfield_t); - msg.hdr.length += msg.hfield[i].length; - } - return (msg.hdr.length); -} - - -// ------------------------------------------------------------------ -// Figures out the total length of the data buffer for 'msg' -// Returns length - -dword SMBArea::smb_getmsgdatlen(smbmsg_t msg) -{ - int i; - dword length = 0L; - - for (i = 0; i < msg.hdr.total_dfields; i++) - length += msg.dfield[i].length; - return (length); -} - - -// ------------------------------------------------------------------ -// Read header information into 'msg' structure -// msg->idx.offset must be set before calling this function -// Must call smb_freemsgmem() to free memory allocated for var len strs -// Returns 0 on success, non-zero if error - -int SMBArea::smb_getmsghdr(smbmsg_t *msg) -{ - word i; - dword l, offset; - idxrec_t idx; - - rewind(data->shd_fp); - fseek(data->shd_fp, msg->idx.offset, SEEK_SET); - idx = msg->idx; - offset = msg->offset; - memset(msg, 0, sizeof(smbmsg_t)); - msg->idx = idx; - msg->offset = offset; - if (not fread(&msg->hdr, sizeof(msghdr_t), 1, data->shd_fp)) - return (-1); - if (memcmp(msg->hdr.id, "SHD\x1a", 4)) - return (-2); - if (msg->hdr.version < 0x110) - return (-9); - l = sizeof(msghdr_t); - msg->dfield = (dfield_t *)throw_xmalloc(msg->hdr.total_dfields*sizeof(dfield_t)); - i = 0; - while (i < msg->hdr.total_dfields and l < msg->hdr.length) { - if (not fread(&msg->dfield[i], sizeof(dfield_t), 1, data->shd_fp)) { - smb_freemsgmem(*msg); - return (-4); - } - i++; - l += sizeof(dfield_t); - } - if (i < msg->hdr.total_dfields) { - smb_freemsgmem(*msg); - return (-8); - } - while (l < msg->hdr.length) { - i = msg->total_hfields++; - msg->hfield_dat = (void **)throw_xrealloc(msg->hfield_dat, msg->total_hfields*sizeof(void *)); - msg->hfield = (hfield_t *)throw_xrealloc(msg->hfield, msg->total_hfields*sizeof(hfield_t)); - if (not fread(&msg->hfield[i], sizeof(hfield_t), 1, data->shd_fp)) { - smb_freemsgmem(*msg); - return (-5); - } - l += sizeof(hfield_t); - msg->hfield_dat[i] = (char *)throw_xmalloc(msg->hfield[i].length + 1); - memset(msg->hfield_dat[i], 0, msg->hfield[i].length + 1); // init to NULL - if (msg->hfield[i].length and not fread(msg->hfield_dat[i], msg->hfield[i].length, 1, data->shd_fp)) { - smb_freemsgmem(*msg); - return (-6); - } - switch (msg->hfield[i].type) { // convenience variables - case SENDER: - if (not msg->from) { - msg->from = (uchar *)msg->hfield_dat[i]; - break; - } - case FORWARDED: // fall through - msg->forwarded = 1; - break; - case SENDERAGENT: - if (not msg->forwarded) - msg->from_agent = *(word *)msg->hfield_dat[i]; - break; - case SENDEREXT: - if (not msg->forwarded) - msg->from_ext = (uchar *)msg->hfield_dat[i]; - break; - case SENDERNETTYPE: - if (not msg->forwarded) - msg->from_net.type = *(word *)msg->hfield_dat[i]; - break; - case SENDERNETADDR: - if (not msg->forwarded) - msg->from_net.addr = (char *)msg->hfield_dat[i]; - break; - case REPLYTO: - msg->replyto = (uchar *)msg->hfield_dat[i]; - break; - case REPLYTOEXT: - msg->replyto_ext = (uchar *)msg->hfield_dat[i]; - break; - case REPLYTOAGENT: - msg->replyto_agent = *(word *)msg->hfield_dat[i]; - break; - case REPLYTONETTYPE: - msg->replyto_net.type = *(word *)msg->hfield_dat[i]; - break; - case REPLYTONETADDR: - msg->replyto_net.addr = (char *)msg->hfield_dat[i]; - break; - case RECIPIENT: - msg->to = (uchar *)msg->hfield_dat[i]; - break; - case RECIPIENTEXT: - msg->to_ext = (uchar *)msg->hfield_dat[i]; - break; - case RECIPIENTAGENT: - msg->to_agent = *(word *)msg->hfield_dat[i]; - break; - case RECIPIENTNETTYPE: - msg->to_net.type = *(word *)msg->hfield_dat[i]; - break; - case RECIPIENTNETADDR: - msg->to_net.addr = (char *)msg->hfield_dat[i]; - break; - case SUBJECT: - msg->subj = (uchar *)msg->hfield_dat[i]; - break; - } - l += msg->hfield[i].length; - } - - if (not msg->from or not msg->to or not msg->subj) { - smb_freemsgmem(*msg); - return (-7); - } - return (0); -} - - -// ------------------------------------------------------------------ -// Frees memory allocated for 'msg' - -void SMBArea::smb_freemsgmem(smbmsg_t msg) -{ - word i; - - throw_xfree(msg.dfield); - for (i = 0; i < msg.total_hfields; i++) - throw_xfree(msg.hfield_dat[i]); - throw_xfree(msg.hfield); - throw_xfree(msg.hfield_dat); -} - - -// ------------------------------------------------------------------ -// Unlocks header for 'msg' - -int SMBArea::smb_unlockmsghdr(smbmsg_t msg) -{ - if(not WideCanLock) return 0; - return (::unlock(fileno(data->shd_fp), msg.idx.offset, sizeof(msghdr_t))); -} - - -// ------------------------------------------------------------------ -// Adds a header field to the 'msg' structure (in memory only) - -int SMBArea::smb_hfield(smbmsg_t * msg, word type, word length, void *data) -{ - int i; - - i = msg->total_hfields; - msg->hfield = (hfield_t *)throw_xrealloc(msg->hfield, (i+1)*sizeof(hfield_t)); - msg->hfield_dat = (void **)throw_xrealloc(msg->hfield_dat, (i+1)*sizeof(void *)); - msg->total_hfields++; - msg->hfield[i].type = type; - msg->hfield[i].length = length; - if (length) { - msg->hfield_dat[i] = (void *)throw_xmalloc(length); - memcpy(msg->hfield_dat[i], data, length); - } else - msg->hfield_dat[i] = NULL; - return (0); -} - - -// ------------------------------------------------------------------ -// Adds a data field to the 'msg' structure (in memory only) -// Automatically figures out the offset into the data buffer from existing -// dfield lengths - -int SMBArea::smb_dfield(smbmsg_t * msg, word type, dword length) -{ - int i, j; - - i = msg->hdr.total_dfields; - msg->dfield = (dfield_t *)throw_xrealloc(msg->dfield, (i+1)*sizeof(dfield_t)); - msg->hdr.total_dfields++; - msg->dfield[i].type = type; - msg->dfield[i].length = length; - for (j = msg->dfield[i].offset = 0; j < i; j++) - msg->dfield[i].offset += msg->dfield[j].length; - return (0); -} - - -// ------------------------------------------------------------------ -// Checks CRC history file for duplicate crc. If found, returns 1. -// If no dupe, adds to CRC history and returns 0, or negative if error. - -int SMBArea::smb_addcrc(dword max_crcs, dword crc, int retry_time) -{ - int file; - long length; - dword l, *buf; - - if (not max_crcs) - return (0); - file = smb_openexlusively2(AddPath(path(), ".sch"), retry_time); - length = filelength(file); - if (length < 0L) { - ::close(file); - return (-4); - } - buf = (dword *)throw_xmalloc(max_crcs * sizeof(dword)); - if (length >= max_crcs * 4) { // Reached or exceeds max crcs - read(file, buf, max_crcs * 4); - for (l = 0; l < max_crcs; l++) - if (crc == buf[l]) - break; - if (l < max_crcs) { // Dupe CRC found - ::close(file); - throw_xfree(buf); - return (1); - } - chsize(file, 0L); // truncate it - lseek(file, 0L, SEEK_SET); - write(file, buf + 4, (max_crcs - 1) * 4); - } else if (length / 4) { // Less than max crcs - read(file, buf, length); - for (l = 0; l < length / 4; l++) - if (crc == buf[l]) - break; - if (l < length / 4) { // Dupe CRC found - ::close(file); - throw_xfree(buf); - return (1); - } - } - lseek(file, 0L, SEEK_END); - write(file, &crc, 4); // Write to the end - throw_xfree(buf); - ::close(file); - return (0); -} - - -// ------------------------------------------------------------------ -// Creates a new message header record in the header file. -// If storage is SMB_SELFPACK, self-packing conservative allocation is used -// If storage is SMB_FASTALLOC, fast allocation is used -// If storage is SMB_HYPERALLOC, no allocation tables are used (fastest) - -int SMBArea::smb_addmsghdr(smbmsg_t * msg, smbstatus_t * status, int storage, int retry_time) -{ - int i; - long l; - - if (smb_locksmbhdr(retry_time)) - return (1); - if (smb_getstatus(status)) - return (2); - - if (storage != SMB_HYPERALLOC and (i = smb_open_ha(retry_time)) != 0) - return (i); - - msg->hdr.length = smb_getmsghdrlen(*msg); - if (storage == SMB_HYPERALLOC) - l = smb_hallochdr(status->header_offset); - else if (storage == SMB_FASTALLOC) - l = smb_fallochdr(msg->hdr.length); - else - l = smb_allochdr(msg->hdr.length); - if (l == -1L) { - smb_unlocksmbhdr(); - fclose(data->sha_fp); - return (-1); - } - status->last_msg++; - msg->idx.number = msg->hdr.number = status->last_msg; - msg->idx.offset = status->header_offset + l; - msg->idx.time = msg->hdr.when_imported.time; - msg->idx.attr = msg->hdr.attr; - msg->offset = status->total_msgs; - status->total_msgs++; - smb_putstatus(*status); - - if (storage != SMB_HYPERALLOC) - fclose(data->sha_fp); - i = smb_putmsg(*msg); - smb_unlocksmbhdr(); - return (i); -} - - -// ------------------------------------------------------------------ -// Writes both header and index information for msg 'msg' - -int SMBArea::smb_putmsg(smbmsg_t msg) -{ - int i; - - i = smb_putmsghdr(msg); - if (i) - return (i); - return (smb_putmsgidx(msg)); -} - - -// ------------------------------------------------------------------ -// Writes index information for 'msg' -// msg.idx and msg.offset must be set prior to calling to this function -// Returns 0 if everything ok - -int SMBArea::smb_putmsgidx(smbmsg_t msg) -{ - clearerr(data->sid_fp); - fseek(data->sid_fp, msg.offset * sizeof(idxrec_t), SEEK_SET); - if (not fwrite(&msg.idx, sizeof(idxrec_t), 1, data->sid_fp)) - return (1); - fflush(data->sid_fp); - return (0); -} - - -// ------------------------------------------------------------------ -// Writes header information for 'msg' -// msg.hdr.length -// msg.idx.offset -// and msg.offset must be set prior to calling to this function -// Returns 0 if everything ok - -int SMBArea::smb_putmsghdr(smbmsg_t msg) -{ - word i; - dword l; - - clearerr(data->shd_fp); - if (fseek(data->shd_fp, msg.idx.offset, SEEK_SET)) - return (-1); - - // Write the fixed portion of the header record - if (not fwrite(&msg.hdr, sizeof(msghdr_t), 1, data->shd_fp)) - return (-2); - - // Write the data fields (each is fixed length) - for (i = 0; i < msg.hdr.total_dfields; i++) - if (not fwrite(&msg.dfield[i], sizeof(dfield_t), 1, data->shd_fp)) - return (-3); - - // Write the variable length header fields - for (i = 0; i < msg.total_hfields; i++) { - if (not fwrite(&msg.hfield[i], sizeof(hfield_t), 1, data->shd_fp)) - return (-4); - if (msg.hfield[i].length and not fwrite(msg.hfield_dat[i], msg.hfield[i].length, 1, data->shd_fp)) - return (-5); - } - - l = smb_getmsghdrlen(msg); - while (l % SHD_BLOCK_LEN) { - if (fputc(0, data->shd_fp) == EOF) // pad block with NULL - return (-6); - l++; - } - fflush(data->shd_fp); - return (0); -} - - -// ------------------------------------------------------------------ -// Creates a sub-board's initial header file -// Truncates and deletes other associated SMB files - -int SMBArea::smb_create(dword max_crcs, dword max_msgs, word max_age, word attr, int retry_time) -{ - smbhdr_t hdr; - smbstatus_t status; - - if (filelength(fileno(data->shd_fp)) >= sizeof(smbhdr_t) + sizeof(smbstatus_t) - and smb_locksmbhdr(retry_time)) // header exists, so lock it - return (1); - memset(&hdr, 0, sizeof(smbhdr_t)); - memset(&status, 0, sizeof(smbstatus_t)); - memcpy(hdr.id, "SMB\x1a", 4); - hdr.version = SMB_VERSION; - hdr.length = sizeof(smbhdr_t) + sizeof(smbstatus_t); - status.last_msg = status.total_msgs = 0; - status.header_offset = sizeof(smbhdr_t) + sizeof(smbstatus_t); - status.max_crcs = max_crcs; - status.max_msgs = max_msgs; - status.max_age = max_age; - status.attr = attr; - rewind(data->shd_fp); - fwrite(&hdr, 1, sizeof(smbhdr_t), data->shd_fp); - fwrite(&status, 1, sizeof(smbstatus_t), data->shd_fp); - rewind(data->shd_fp); - chsize(fileno(data->shd_fp), sizeof(smbhdr_t) + sizeof(smbstatus_t)); - fflush(data->shd_fp); - - rewind(data->sdt_fp); - chsize(fileno(data->sdt_fp), 0L); - rewind(data->sid_fp); - chsize(fileno(data->sid_fp), 0L); - - remove(AddPath(path(), ".sda")); // if it exists, delete it - remove(AddPath(path(), ".sha")); // if it exists, delete it - remove(AddPath(path(), ".sch")); - smb_unlocksmbhdr(); - return (0); -} - - -// ------------------------------------------------------------------ -// Returns number of data blocks required to store "length" amount of data - -dword SMBArea::smb_datblocks(dword length) -{ - dword blocks; - - blocks = length / SDT_BLOCK_LEN; - if (length % SDT_BLOCK_LEN) - blocks++; - return (blocks); -} - - -// ------------------------------------------------------------------ -// Returns number of header blocks required to store "length" size header - -dword SMBArea::smb_hdrblocks(dword length) -{ - dword blocks; - - blocks = length / SHD_BLOCK_LEN; - if (length % SHD_BLOCK_LEN) - blocks++; - return (blocks); -} - - -// ------------------------------------------------------------------ -// Finds unused space in data file based on block allocation table and -// marks space as used in allocation table. -// File must be opened read/write DENY ALL -// Returns offset to beginning of data (in bytes, not blocks) -// Assumes smb_open_da() has been called -// fclose(data->sda_fp) should be called after -// Returns negative on error - -long SMBArea::smb_allocdat(dword length, word headers) -{ - word i, j; - dword l, blocks, offset = 0L; - - blocks = smb_datblocks(length); - j = 0; // j is consecutive unused block counter - fflush(data->sda_fp); - rewind(data->sda_fp); - while (not feof(data->sda_fp)) { - if (not fread(&i, 2, 1, data->sda_fp)) - break; - offset += SDT_BLOCK_LEN; - if (not i) - j++; - else - j = 0; - if (j == blocks) { - offset -= (blocks * SDT_BLOCK_LEN); - break; - } - } - clearerr(data->sda_fp); - fseek(data->sda_fp, (offset / SDT_BLOCK_LEN) * 2L, SEEK_SET); - for (l = 0; l < blocks; l++) - if (not fwrite(&headers, 2, 1, data->sda_fp)) - return (-1); - fflush(data->sda_fp); - return (offset); -} - - -// ------------------------------------------------------------------ -// Allocates space for data, but doesn't search for unused blocks -// Returns negative on error - -long SMBArea::smb_fallocdat(dword length, word headers) -{ - dword l, blocks, offset; - - fflush(data->sda_fp); - clearerr(data->sda_fp); - blocks = smb_datblocks(length); - fseek(data->sda_fp, 0L, SEEK_END); - offset = (ftell(data->sda_fp) / 2L) * SDT_BLOCK_LEN; - for (l = 0; l < blocks; l++) - if (not fwrite(&headers, 2, 1, data->sda_fp)) - break; - fflush(data->sda_fp); - if (l < blocks) - return (-1L); - return (offset); -} - - -// ------------------------------------------------------------------ -// De-allocates space for data -// Returns non-zero on error - -int SMBArea::smb_freemsgdat(dword offset, dword length, word headers) -{ - word i; - dword l, blocks; - - blocks = smb_datblocks(length); - - clearerr(data->sda_fp); - for (l = 0; l < blocks; l++) { - if (fseek(data->sda_fp, ((offset / SDT_BLOCK_LEN) + l) * 2L, SEEK_SET)) - return (1); - if (not fread(&i, 2, 1, data->sda_fp)) - return (2); - if (headers > i) - i = 0; // don't want to go negative - else - i -= headers; - if (fseek(data->sda_fp, -2L, SEEK_CUR)) - return (3); - if (not fwrite(&i, 2, 1, data->sda_fp)) - return (4); - } - fflush(data->sda_fp); - return (0); -} - - -// ------------------------------------------------------------------ -// Adds to data allocation records for blocks starting at 'offset' -// Returns non-zero on error - -int SMBArea::smb_incdat(dword offset, dword length, word headers) -{ - word i; - dword l, blocks; - - clearerr(data->sda_fp); - blocks = smb_datblocks(length); - for (l = 0; l < blocks; l++) { - fseek(data->sda_fp, ((offset / SDT_BLOCK_LEN) + l) * 2L, SEEK_SET); - if (not fread(&i, 2, 1, data->sda_fp)) - return (1); - i += headers; - fseek(data->sda_fp, -2L, SEEK_CUR); - if (not fwrite(&i, 2, 1, data->sda_fp)) - return (2); - } - fflush(data->sda_fp); - return (0); -} - - -// ------------------------------------------------------------------ -// De-allocates blocks for header record -// Returns non-zero on error - -int SMBArea::smb_freemsghdr(dword offset, dword length) -{ - uchar c = 0; - dword l, blocks; - - clearerr(data->sha_fp); - blocks = smb_hdrblocks(length); - fseek(data->sha_fp, offset / SHD_BLOCK_LEN, SEEK_SET); - for (l = 0; l < blocks; l++) - if (not fwrite(&c, 1, 1, data->sha_fp)) - return (1); - fflush(data->sha_fp); - return (0); -} - - -// ------------------------------------------------------------------ -// Frees all allocated header and data blocks for 'msg' - -int SMBArea::smb_freemsg(smbmsg_t msg, smbstatus_t status) -{ - int i; - word x; - - if (status.attr & SMB_HYPERALLOC) - return (0); // Nothing to do - - for (x = 0; x < msg.hdr.total_dfields; x++) { - if ((i = smb_freemsgdat(msg.hdr.offset + msg.dfield[x].offset, msg.dfield[x].length, 1)) != 0) - return (i); - } - return (smb_freemsghdr(msg.idx.offset - status.header_offset, msg.hdr.length)); -} - - -// ------------------------------------------------------------------ -// Finds unused space in header file based on block allocation table and -// marks space as used in allocation table. -// File must be opened read/write DENY ALL -// Returns offset to beginning of header (in bytes, not blocks) -// Assumes smb_open_ha() has been called -// fclose(data->sha_fp) should be called after -// Returns -1L on error - -long SMBArea::smb_allochdr(dword length) -{ - uchar c; - word i; - dword l, blocks, offset = 0; - - blocks = smb_hdrblocks(length); - i = 0; // i is consecutive unused block counter - fflush(data->sha_fp); - rewind(data->sha_fp); - while (not feof(data->sha_fp)) { - if (not fread(&c, 1, 1, data->sha_fp)) - break; - offset += SHD_BLOCK_LEN; - if (not c) - i++; - else - i = 0; - if (i == blocks) { - offset -= (blocks * SHD_BLOCK_LEN); - break; - } - } - clearerr(data->sha_fp); - fseek(data->sha_fp, offset / SHD_BLOCK_LEN, SEEK_SET); - c = 1; - for (l = 0; l < blocks; l++) - if (not fwrite(&c, 1, 1, data->sha_fp)) - return (-1L); - fflush(data->sha_fp); - return (offset); -} - - -// ------------------------------------------------------------------ -// Allocates space for index, but doesn't search for unused blocks -// Returns -1L on error - -long SMBArea::smb_fallochdr(dword length) -{ - uchar c = 1; - dword l, blocks, offset; - - blocks = smb_hdrblocks(length); - fflush(data->sha_fp); - clearerr(data->sha_fp); - fseek(data->sha_fp, 0L, SEEK_END); - offset = ftell(data->sha_fp) * SHD_BLOCK_LEN; - for (l = 0; l < blocks; l++) - if (not fwrite(&c, 1, 1, data->sha_fp)) - return (-1L); - fflush(data->sha_fp); - return (offset); -} - - -// ------------------------------------------------------------------ -// Allocate header blocks using Hyper Allocation -// this function should be most likely not be called from anywhere but -// smb_addmsghdr() - -long SMBArea::smb_hallochdr(dword header_offset) -{ - long l; - - fflush(data->shd_fp); - fseek(data->shd_fp, 0L, SEEK_END); - l = ftell(data->shd_fp); - if (l < header_offset) // Header file truncated?!? - return (header_offset); - while ((l - header_offset) % SHD_BLOCK_LEN) // Make sure even block boundry - l++; - return (l - header_offset); -} - - -// ------------------------------------------------------------------ -// Allocate data blocks using Hyper Allocation -// smb_locksmbhdr() should be called before this function and not -// unlocked until all data fields for this message have been written -// to the SDT file - -long SMBArea::smb_hallocdat() -{ - long l; - - fflush(data->sdt_fp); - fseek(data->sdt_fp, 0L, SEEK_END); - l = ftell(data->sdt_fp); - if (l <= 0) - return (l); - while (l % SDT_BLOCK_LEN) // Make sure even block boundry - l++; - return (l); -} diff --git a/goldlib/smblib/Makefile b/goldlib/smblib/Makefile new file mode 100644 index 0000000..8731166 --- /dev/null +++ b/goldlib/smblib/Makefile @@ -0,0 +1,9 @@ +# -*- makefile -*- + +TOP=../.. +TARGET=smblib +INCS=-I$(TOP)/goldlib/smblib -I$(TOP)/goldlib/gall +CFLAGS=-DGOLDEDPLUS + +include $(TOP)/GNUmakef.inc +include $(TOP)/GNUmakef.lib diff --git a/goldlib/smblib/crc32.h b/goldlib/smblib/crc32.h new file mode 100644 index 0000000..6e4ad7b --- /dev/null +++ b/goldlib/smblib/crc32.h @@ -0,0 +1,9 @@ +/* crc32.h */ + +/* wrapper for gall library */ + +#include + +#define ucrc32(ch,crc) updCrc32(ch,crc) + + diff --git a/goldlib/smblib/lzh.cpp b/goldlib/smblib/lzh.cpp new file mode 100644 index 0000000..707db9b --- /dev/null +++ b/goldlib/smblib/lzh.cpp @@ -0,0 +1,808 @@ +/* lzh.c */ + +/* Synchronet LZH compression library */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Rob Swindell's conversion of 1988 LZH (LHarc) encoding functions * + * Based on Japanese version 29-NOV-1988 * + * LZSS coded by Haruhiko Okumura * + * Adaptive Huffman Coding coded by Haruyasu Yoshizaki * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "lzh.h" + +/****************************************************************************/ +/* Memory allocation macros for various compilers and environments */ +/* MALLOC is used for allocations of 64k or less */ +/* FREE is used to free buffers allocated with MALLOC */ +/* LMALLOC is used for allocations of possibly larger than 64k */ +/* LFREE is used to free buffers allocated with LMALLOC */ +/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer */ +/****************************************************************************/ +#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__) + #if defined(__TURBOC__) + #define REALLOC(x,y) farrealloc(x,y) + #define LMALLOC(x) farmalloc(x) + #define MALLOC(x) farmalloc(x) + #define LFREE(x) farfree(x) + #define FREE(x) farfree(x) + #elif defined(__WATCOMC__) + #define REALLOC realloc + #define LMALLOC(x) halloc(x,1) /* far heap, but slow */ + #define MALLOC malloc /* far heap, but 64k max */ + #define LFREE hfree + #define FREE free + #else /* Other 16-bit Compiler */ + #define REALLOC realloc + #define LMALLOC malloc + #define MALLOC malloc + #define LFREE free + #define FREE free + #endif +#else /* 32-bit Compiler or Small Memory Model */ + #define REALLOC realloc + #define LMALLOC malloc + #define MALLOC malloc + #define LFREE free + #define FREE free +#endif + + + +/* LZSS Parameters */ + +#define LZH_N 4096 /* Size of string buffer */ +#define LZH_F 60 /* Size of look-ahead buffer */ +#define LZH_THRESHOLD 2 +#define LZH_NIL LZH_N /* End of tree's node */ + +#ifdef LZH_DYNAMIC_BUF + +unsigned char *lzh_text_buf; +short int lzh_match_position, lzh_match_length, + *lzh_lson, *lzh_rson, *lzh_dad; + +#else + +unsigned char lzh_text_buf[LZH_N + LZH_F - 1]; +short int lzh_match_position, lzh_match_length, + lzh_lson[LZH_N + 1], lzh_rson[LZH_N + 257], lzh_dad[LZH_N + 1]; + +#endif + + +void lzh_init_tree(void) /* Initializing tree */ +{ + short int i; + + for (i = LZH_N + 1; i <= LZH_N + 256; i++) + lzh_rson[i] = LZH_NIL; /* root */ + for (i = 0; i < LZH_N; i++) + lzh_dad[i] = LZH_NIL; /* node */ +} + +/******************************/ +/* Inserting node to the tree */ +/* Only used during encoding */ +/******************************/ +void lzh_insert_node(short int r) +{ + short int i, p, cmp; + unsigned char *key; + unsigned c; + + cmp = 1; + key = lzh_text_buf+r; + p = LZH_N + 1 + key[0]; + lzh_rson[r] = lzh_lson[r] = LZH_NIL; + lzh_match_length = 0; + for ( ; ; ) { + if (cmp >= 0) { + if (lzh_rson[p] != LZH_NIL) + p = lzh_rson[p]; + else { + lzh_rson[p] = r; + lzh_dad[r] = p; + return; + } + } else { + if (lzh_lson[p] != LZH_NIL) + p = lzh_lson[p]; + else { + lzh_lson[p] = r; + lzh_dad[r] = p; + return; + } + } + for (i = 1; i < LZH_F; i++) + if ((cmp = key[i] - lzh_text_buf[p + i]) != 0) + break; + if (i > LZH_THRESHOLD) { + if (i > lzh_match_length) { + lzh_match_position = ((r - p) & (LZH_N - 1)) - 1; + if ((lzh_match_length = i) >= LZH_F) + break; + } + if (i == lzh_match_length) { + if ((c = ((r - p) & (LZH_N - 1)) - 1) + < (unsigned)lzh_match_position) { + lzh_match_position = c; + } + } + } + } + lzh_dad[r] = lzh_dad[p]; + lzh_lson[r] = lzh_lson[p]; + lzh_rson[r] = lzh_rson[p]; + lzh_dad[lzh_lson[p]] = r; + lzh_dad[lzh_rson[p]] = r; + if (lzh_rson[lzh_dad[p]] == p) + lzh_rson[lzh_dad[p]] = r; + else + lzh_lson[lzh_dad[p]] = r; + lzh_dad[p] = LZH_NIL; /* remove p */ +} + +void lzh_delete_node(short int p) /* Deleting node from the tree */ +{ + short int q; + + if (lzh_dad[p] == LZH_NIL) + return; /* unregistered */ + if (lzh_rson[p] == LZH_NIL) + q = lzh_lson[p]; + else + if (lzh_lson[p] == LZH_NIL) + q = lzh_rson[p]; + else { + q = lzh_lson[p]; + if (lzh_rson[q] != LZH_NIL) { + do { + q = lzh_rson[q]; + } while (lzh_rson[q] != LZH_NIL); + lzh_rson[lzh_dad[q]] = lzh_lson[q]; + lzh_dad[lzh_lson[q]] = lzh_dad[q]; + lzh_lson[q] = lzh_lson[p]; + lzh_dad[lzh_lson[p]] = q; + } + lzh_rson[q] = lzh_rson[p]; + lzh_dad[lzh_rson[p]] = q; + } + lzh_dad[q] = lzh_dad[p]; + if (lzh_rson[lzh_dad[p]] == p) + lzh_rson[lzh_dad[p]] = q; + else + lzh_lson[lzh_dad[p]] = q; + lzh_dad[p] = LZH_NIL; +} + +/* Huffman coding parameters */ + +#define LZH_N_CHAR (256 - LZH_THRESHOLD + LZH_F) + /* character code (= 0..LZH_N_CHAR-1) */ +#define LZH_T (LZH_N_CHAR * 2 - 1) /* Size of table */ +#define LZH_R (LZH_T - 1) /* root position */ +#define MAX_FREQ 0x8000 + /* update when cumulative frequency */ + /* reaches to this value */ + +/* + * Tables for encoding/decoding upper 6 bits of + * sliding dictionary pointer + */ +/* encoder table */ +uchar lzh_p_len[64] = { + 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 +}; + +uchar lzh_p_code[64] = { + 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68, + 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C, + 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, + 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, + 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE, + 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF +}; + +/* decoder table */ +uchar lzh_d_code[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, + 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, + 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, + 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, + 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, + 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, + 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, + 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, +}; + +uchar lzh_d_len[256] = { + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, +}; + +#ifdef LZH_DYNAMIC_BUF + +unsigned short *lzh_freq=NULL; /* cumulative freq table */ + +/* + * pointing parent nodes. + * area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves + */ +short int *lzh_prnt=NULL; + +/* pointing children nodes (son[], son[] + 1)*/ +short int *lzh_son=NULL; + +#else /* STATIC */ + +unsigned short lzh_freq[LZH_T + 1]; /* cumulative freq table */ +short int lzh_prnt[LZH_T + LZH_N_CHAR]; +short int lzh_son[LZH_T + 1]; /* bug fixed by Digital Dynamics */ + +#endif + + +unsigned short lzh_getbuf = 0; /* Was just "unsigned" fixed 04/12/95 */ +uchar lzh_getlen = 0; + +int lzh_getbit(uchar *inbuf, long *incnt, long inlen) /* get one bit */ +{ + short int i; + + while (lzh_getlen <= 8) { + if((*incnt)>=inlen) + i=0; + else + i=inbuf[(*incnt)++]; + lzh_getbuf |= i << (8 - lzh_getlen); + lzh_getlen += 8; + } + i = lzh_getbuf; + lzh_getbuf <<= 1; + lzh_getlen--; + return (i < 0); +} + +short int lzh_getbyte(uchar *inbuf, long *incnt, long inlen) /* get a byte */ +{ + unsigned short i; + + while (lzh_getlen <= 8) { + if((*incnt)>=inlen) + i=0; + else + i=inbuf[(*incnt)++]; + lzh_getbuf |= i << (8 - lzh_getlen); + lzh_getlen += 8; + } + i = lzh_getbuf; + lzh_getbuf <<= 8; + lzh_getlen -= 8; + return i >> 8; +} + +unsigned lzh_putbuf = 0; +uchar lzh_putlen = 0; + +/* output c bits */ +void lzh_putcode(short int l, unsigned short c, uchar *outbuf, long *outlen) +{ + lzh_putbuf |= c >> lzh_putlen; + if ((lzh_putlen += l) >= 8) { + outbuf[(*outlen)++]=(lzh_putbuf >> 8); + if ((lzh_putlen -= 8) >= 8) { + outbuf[(*outlen)++]=lzh_putbuf; + lzh_putlen -= 8; + lzh_putbuf = c << (l - lzh_putlen); + } else { + lzh_putbuf <<= 8; + } + } +} + + +/* initialize freq tree */ + +void lzh_start_huff(void) +{ + short int i, j; + +lzh_getbuf = 0; /* Added by Digital Dynamics for repeating operations */ +lzh_getlen = 0; +lzh_putbuf = 0; +lzh_putlen = 0; + + for (i = 0; i < LZH_N_CHAR; i++) { + lzh_freq[i] = 1; + lzh_son[i] = i + LZH_T; + lzh_prnt[i + LZH_T] = i; + } + i = 0; j = LZH_N_CHAR; + while (j <= LZH_R) { + lzh_freq[j] = lzh_freq[i] + lzh_freq[i + 1]; + lzh_son[j] = i; + lzh_prnt[i] = lzh_prnt[i + 1] = j; + i += 2; j++; + } + lzh_freq[LZH_T] = 0xffff; + lzh_prnt[LZH_R] = 0; +} + + +/* reconstruct freq tree */ + +void lzh_reconst(void) +{ + short int i, j, k; + unsigned short f, l; + + /* halven cumulative freq for leaf nodes */ + j = 0; + for (i = 0; i < LZH_T; i++) { + if (lzh_son[i] >= LZH_T) { + lzh_freq[j] = (lzh_freq[i] + 1) / 2; + lzh_son[j] = lzh_son[i]; + j++; + } + } + /* make a tree : first, connect children nodes */ + for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) { + k = i + 1; + f = lzh_freq[j] = lzh_freq[i] + lzh_freq[k]; + for (k = j - 1; f < lzh_freq[k]; k--); + k++; + l = (j - k) * 2; + + /* movmem() is Turbo-C dependent + rewritten to memmove() by Kenji */ + + /* movmem(&lzh_freq[k], &lzh_freq[k + 1], l); */ + (void)memmove(lzh_freq+k+1,lzh_freq+k, l); + lzh_freq[k] = f; + /* movmem(&lzh_son[k], &lzh_son[k + 1], l); */ + (void)memmove(lzh_son+k+1,lzh_son+k, l); + lzh_son[k] = i; + } + /* connect parent nodes */ + for (i = 0; i < LZH_T; i++) { + if ((k = lzh_son[i]) >= LZH_T) { + lzh_prnt[k] = i; + } else { + lzh_prnt[k] = lzh_prnt[k + 1] = i; + } + } +} + +/* update freq tree */ + +void lzh_update(short int c) +{ + short int i, j, k, l; + + if (lzh_freq[LZH_R] == MAX_FREQ) { + lzh_reconst(); + } + c = lzh_prnt[c + LZH_T]; + do { + k = ++lzh_freq[c]; + + /* swap nodes to keep the tree freq-ordered */ + if (k > lzh_freq[l = c + 1]) { + while (k > lzh_freq[++l]); + l--; + lzh_freq[c] = lzh_freq[l]; + lzh_freq[l] = k; + + i = lzh_son[c]; + lzh_prnt[i] = l; + if (i < LZH_T) lzh_prnt[i + 1] = l; + + j = lzh_son[l]; + lzh_son[l] = i; + + lzh_prnt[j] = c; + if (j < LZH_T) lzh_prnt[j + 1] = c; + lzh_son[c] = j; + + c = l; + } + } while ((c = lzh_prnt[c]) != 0); /* do it until reaching the root */ +} + +unsigned short lzh_code, lzh_len; + +void lzh_encode_char(unsigned short c, uchar *outbuf, long *outlen) +{ + unsigned short i; + short int j, k; + + i = 0; + j = 0; + k = lzh_prnt[c + LZH_T]; + + /* search connections from leaf node to the root */ + do { + i >>= 1; + + /* + if node's address is odd, output 1 + else output 0 + */ + if (k & 1) i += 0x8000; + + j++; + } while ((k = lzh_prnt[k]) != LZH_R); + lzh_putcode(j, i, outbuf, outlen); + lzh_code = i; + lzh_len = j; + lzh_update(c); +} + +void lzh_encode_position(unsigned short c, uchar *outbuf, long *outlen) +{ + unsigned short i; + + /* output upper 6 bits with encoding */ + i = c >> 6; + lzh_putcode(lzh_p_len[i], (unsigned short)(lzh_p_code[i] << 8), outbuf, outlen); + + /* output lower 6 bits directly */ + lzh_putcode(6, (unsigned short)((c & 0x3f) << 10), outbuf, outlen); +} + +void lzh_encode_end(uchar *outbuf, long *outlen) +{ + if (lzh_putlen) { + outbuf[(*outlen)++]=(lzh_putbuf >> 8); + } +} + +short int lzh_decode_char(uchar *inbuf, long *incnt, long inlen) +{ + unsigned short c; + + c = lzh_son[LZH_R]; + + /* + * start searching tree from the root to leaves. + * choose node #(lzh_son[]) if input bit == 0 + * else choose #(lzh_son[]+1) (input bit == 1) + */ + while (c < LZH_T) { + c += lzh_getbit(inbuf,incnt,inlen); + c = lzh_son[c]; + } + c -= LZH_T; + lzh_update(c); + return c; +} + +short int lzh_decode_position(uchar *inbuf, long *incnt, long inlen) +{ + unsigned short i, j, c; + + /* decode upper 6 bits from given table */ + i = lzh_getbyte(inbuf,incnt,inlen); + c = (unsigned)lzh_d_code[i] << 6; + j = lzh_d_len[i]; + + /* input lower 6 bits directly */ + j -= 2; + while (j--) { + i = (i << 1) + lzh_getbit(inbuf,incnt,inlen); + } + return c | i & 0x3f; +} + +/* Compression */ + +/* Encoding/Compressing */ +/* Returns length of outbuf */ +long LZHCALL lzh_encode(uchar *inbuf, long inlen, uchar *outbuf) +{ + short int i, c, len, r, s, last_match_length; + long incnt,outlen; /* textsize=0; */ + +#ifdef LZH_DYNAMIC_BUF + + if((lzh_text_buf=(uchar *)MALLOC(LZH_N + LZH_F - 1))==NULL) + return(-1); + if((lzh_freq=(unsigned short*)MALLOC((LZH_T + 1)*sizeof(unsigned short)))==NULL) { + FREE(lzh_text_buf); + return(-1); } + if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_freq); + return(-1); } + if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + return(-1); } + if((lzh_lson=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); + return(-1); } + if((lzh_rson=(short *)MALLOC((LZH_N + 257)*sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); + FREE(lzh_lson); + return(-1); } + if((lzh_dad=(short *)MALLOC((LZH_N + 1)*sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); + FREE(lzh_lson); + FREE(lzh_rson); + return(-1); } +#endif + + incnt=0; + memcpy(outbuf,&inlen,sizeof(inlen)); + outlen=sizeof(inlen); + if(!inlen) { +#ifdef LZH_DYNAMIC_BUF + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); + FREE(lzh_lson); + FREE(lzh_rson); + FREE(lzh_dad); +#endif + return(outlen); } + lzh_start_huff(); + lzh_init_tree(); + s = 0; + r = LZH_N - LZH_F; + for (i = s; i < r; i++) + lzh_text_buf[i] = ' '; + for (len = 0; len < LZH_F && incnt len) + lzh_match_length = len; + if (lzh_match_length <= LZH_THRESHOLD) { + lzh_match_length = 1; + lzh_encode_char(lzh_text_buf[r],outbuf,&outlen); + } else { + lzh_encode_char((unsigned short)(255 - LZH_THRESHOLD + lzh_match_length) + ,outbuf,&outlen); + lzh_encode_position(lzh_match_position + ,outbuf,&outlen); + } + last_match_length = lzh_match_length; + for (i = 0; i < last_match_length && incnt printcount) { + printf("%12ld\r", textsize); + printcount += 1024; + } +***/ + while (i++ < last_match_length) { + lzh_delete_node(s); + s = (s + 1) & (LZH_N - 1); + r = (r + 1) & (LZH_N - 1); + if (--len) lzh_insert_node(r); + } + } while (len > 0); + lzh_encode_end(outbuf,&outlen); +/* + printf("input: %ld (%ld) bytes\n", inlen,textsize); + printf("output: %ld bytes\n", outlen); + printf("output/input: %.3f\n", (double)outlen / inlen); +*/ + +#ifdef LZH_DYNAMIC_BUF + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); + FREE(lzh_lson); + FREE(lzh_rson); + FREE(lzh_dad); +#endif + + return(outlen); +} + +/* Decoding/Uncompressing */ +/* Returns length of outbuf */ +long LZHCALL lzh_decode(uchar *inbuf, long inlen, uchar *outbuf) +{ + short int i, j, k, r, c; + unsigned long int count; + long incnt,textsize; + +#ifdef LZH_DYNAMIC_BUF + + if((lzh_text_buf=(uchar *)MALLOC((LZH_N + LZH_F - 1)*2))==NULL) + return(-1); + if((lzh_freq=(unsigned short *)MALLOC((LZH_T + 1)*sizeof(unsigned short))) + ==NULL) { + FREE(lzh_text_buf); + return(-1); } + if((lzh_prnt=(short *)MALLOC((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_freq); + return(-1); } + if((lzh_son=(short *)MALLOC((LZH_T + 1) * sizeof(short)))==NULL) { + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + return(-1); } + +#endif + + incnt=0; + memcpy(&textsize,inbuf,sizeof(textsize)); + incnt+=sizeof(textsize); + if (textsize == 0) { +#ifdef LZH_DYNAMIC_BUF + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); +#endif + return(textsize); } + lzh_start_huff(); + for (i = 0; i < LZH_N - LZH_F; i++) + *(lzh_text_buf+i) = ' '; + r = LZH_N - LZH_F; + for (count = 0; count < (unsigned long)textsize; ) { + c = lzh_decode_char(inbuf,&incnt,inlen); + if (c < 256) { + outbuf[count]=(uchar)c; +#if 0 + if(r>(LZH_N + LZH_F - 1) || r<0) { + printf("Overflow! (%d)\n",r); + getch(); + exit(-1); } +#endif + *(lzh_text_buf+r) = (uchar)c; + r++; + r &= (LZH_N - 1); + count++; + } else { + i = (r - lzh_decode_position(inbuf,&incnt,inlen) - 1) + & (LZH_N - 1); + j = c - 255 + LZH_THRESHOLD; + for (k = 0; k < j && count<(unsigned long)textsize; k++) { + c = lzh_text_buf[(i + k) & (LZH_N - 1)]; + outbuf[count]=(uchar)c; +#if 0 + if(r>(LZH_N + LZH_F - 1) || r<0) { + printf("Overflow! (%d)\n",r); + exit(-1); } +#endif + *(lzh_text_buf+r) = (uchar)c; + r++; + r &= (LZH_N - 1); + count++; + } + } + } +/*** + printf("%12ld\n", count); +***/ + +#ifdef LZH_DYNAMIC_BUF + FREE(lzh_text_buf); + FREE(lzh_prnt); + FREE(lzh_freq); + FREE(lzh_son); +#endif + +return(count); +} + + diff --git a/goldlib/smblib/lzh.h b/goldlib/smblib/lzh.h new file mode 100644 index 0000000..cb919b1 --- /dev/null +++ b/goldlib/smblib/lzh.h @@ -0,0 +1,81 @@ +/* lzh.h */ + +/* Synchronet LZH compression library */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Rob Swindell's conversion of 1988 LZH (LHarc) encoding functions * + * Based on Japanese version 29-NOV-1988 * + * LZSS coded by Haruhiko Okumura * + * Adaptive Huffman Coding coded by Haruyasu Yoshizaki * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifdef LZHEXPORT + #undef LZHEXPORT +#endif + +#ifdef _WIN32 + #ifndef __FLAT__ + #define __FLAT__ + #endif + #ifdef __BORLANDC__ + #define LZHCALL __stdcall + #else + #define LZHCALL + #endif + #ifdef LZHDLL /* LZH functions in DLL */ + #ifdef LZH_EXPORTS + #define LZHEXPORT __declspec( dllexport ) + #else + #define LZHEXPORT __declspec( dllimport ) + #endif + #else /* self-contained executable */ + #define LZHEXPORT + #endif +#else /* !_WIN32 */ + #define LZHCALL + #define LZHEXPORT +#endif + +#ifndef GOLDEDPLUS +#ifndef uchar +#define uchar unsigned char +#endif +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif +LZHEXPORT long LZHCALL lzh_encode(uchar *inbuf, long inlen, uchar *outbuf); +LZHEXPORT long LZHCALL lzh_decode(uchar *inbuf, long inlen, uchar *outbuf); +#ifdef __cplusplus +} +#endif + +#ifdef __WATCOMC__ /* Use MSC standard (prepended underscore) */ +#pragma aux lzh_encode "_*" +#pragma aux lzh_decode "_*" +#endif diff --git a/goldlib/smblib/smbdefs.h b/goldlib/smblib/smbdefs.h new file mode 100644 index 0000000..50a58b5 --- /dev/null +++ b/goldlib/smblib/smbdefs.h @@ -0,0 +1,548 @@ +/* smbdefs.h */ + +/* Synchronet message base constant and structure definitions */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef _SMBDEFS_H +#define _SMBDEFS_H + +#ifdef GOLDEDPLUS +#include +#endif +#include + +/**********/ +/* Macros */ +/**********/ + + +#undef TAB +#define TAB '\t' /* Horizontal tabulation ^I */ +#undef LF +#define LF '\n' /* Line feed ^J */ +#undef CR +#define CR '\r' /* Carriage return ^M */ +#undef SP +#define SP ' ' /* Space */ +#undef FF +#define FF 0x0c /* Form feed ^L */ +#undef ESC +#define ESC 0x1b /* Escape ^[ */ + +#ifndef GOLDEDPLUS +#ifndef uchar + #define uchar unsigned char +#endif +#ifdef __GLIBC__ + #include +#else + #ifndef ushort + #define ushort unsigned short + #define ulong unsigned long + #define uint unsigned int + #endif +#endif +#endif + +/****************************************************************************/ +/* Memory allocation macros for various compilers and environments */ +/* MALLOC is used for allocations of 64k or less */ +/* FREE is used to free buffers allocated with MALLOC */ +/* LMALLOC is used for allocations of possibly larger than 64k */ +/* LFREE is used to free buffers allocated with LMALLOC */ +/* REALLOC is used to re-size a previously MALLOCed or LMALLOCed buffer */ +/****************************************************************************/ +#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__) +# define HUGE16 huge +# define FAR16 far +# if defined(__TURBOC__) +# define REALLOC(x,y) farrealloc(x,y) +# define LMALLOC(x) farmalloc(x) +# define MALLOC(x) farmalloc(x) +# define LFREE(x) farfree(x) +# define FREE(x) farfree(x) +# elif defined(__WATCOMC__) +# define REALLOC realloc +# define LMALLOC(x) halloc(x,1) /* far heap, but slow */ +# define MALLOC malloc /* far heap, but 64k max */ +# define LFREE hfree +# define FREE free +# else /* Other 16-bit Compiler */ +# define REALLOC realloc +# define LMALLOC malloc +# define MALLOC malloc +# define LFREE free +# define FREE free +# endif +#else /* 32-bit Compiler or Small Memory Model */ +# define HUGE16 +# define FAR16 +# define REALLOC realloc +# define LMALLOC malloc +# define MALLOC malloc +# define LFREE free +# define FREE free +#endif + + +#define SDT_BLOCK_LEN 256 /* Size of data blocks */ +#define SHD_BLOCK_LEN 256 /* Size of header blocks */ + +#define SMB_SELFPACK 0 /* Self-packing storage allocation */ +#define SMB_FASTALLOC 1 /* Fast allocation */ +#define SMB_HYPERALLOC 2 /* No allocation */ + +#define SMB_EMAIL 1 /* User numbers stored in Indexes */ + + /* Time zone macros for when_t.zone */ +#define DAYLIGHT 0x8000 /* Daylight savings is active */ +#define US_ZONE 0x4000 /* U.S. time zone */ +#define WESTERN_ZONE 0x2000 /* Non-standard zone west of UT */ +#define EASTERN_ZONE 0x1000 /* Non-standard zone east of UT */ + + /* US Time Zones (standard) */ +#define AST 0x40F0 // Atlantic (-04:00) +#define EST 0x412C // Eastern (-05:00) +#define CST 0x4168 // Central (-06:00) +#define MST 0x41A4 // Mountain (-07:00) +#define PST 0x41E0 // Pacific (-08:00) +#define YST 0x421C // Yukon (-09:00) +#define HST 0x4258 // Hawaii/Alaska (-10:00) +#define BST 0x4294 // Bering (-11:00) + + /* US Time Zones (daylight) */ +#define ADT 0xC0F0 // Atlantic (-03:00) +#define EDT 0xC12C // Eastern (-04:00) +#define CDT 0xC168 // Central (-05:00) +#define MDT 0xC1A4 // Mountain (-06:00) +#define PDT 0xC1E0 // Pacific (-07:00) +#define YDT 0xC21C // Yukon (-08:00) +#define HDT 0xC258 // Hawaii/Alaska (-09:00) +#define BDT 0xC294 // Bering (-10:00) + + /* Non-standard Time Zones */ +#define MID 0x2294 // Midway (-11:00) +#define VAN 0x21E0 // Vancouver (-08:00) +#define EDM 0x21A4 // Edmonton (-07:00) +#define WIN 0x2168 // Winnipeg (-06:00) +#define BOG 0x212C // Bogota (-05:00) +#define CAR 0x20F0 // Caracas (-04:00) +#define RIO 0x20B4 // Rio de Janeiro (-03:00) +#define FER 0x2078 // Fernando de Noronha (-02:00) +#define AZO 0x203C // Azores (-01:00) +#define LON 0x1000 // London (+00:00) +#define BER 0x103C // Berlin (+01:00) +#define ATH 0x1078 // Athens (+02:00) +#define MOS 0x10B4 // Moscow (+03:00) +#define DUB 0x10F0 // Dubai (+04:00) +#define KAB 0x110E // Kabul (+04:30) +#define KAR 0x112C // Karachi (+05:00) +#define BOM 0x114A // Bombay (+05:30) +#define KAT 0x1159 // Kathmandu (+05:45) +#define DHA 0x1168 // Dhaka (+06:00) +#define BAN 0x11A4 // Bangkok (+07:00) +#define HON 0x11E0 // Hong Kong (+08:00) +#define TOK 0x121C // Tokyo (+09:00) +#define SYD 0x1258 // Sydney (+10:00) +#define NOU 0x1294 // Noumea (+11:00) +#define WEL 0x12D0 // Wellington (+12:00) + + /* Valid hfield_t.types */ +#define SENDER 0x00 +#define SENDERAGENT 0x01 +#define SENDERNETTYPE 0x02 +#define SENDERNETADDR 0x03 +#define SENDEREXT 0x04 +#define SENDERPOS 0x05 +#define SENDERORG 0x06 + +#define AUTHOR 0x10 +#define AUTHORAGENT 0x11 +#define AUTHORNETTYPE 0x12 +#define AUTHORNETADDR 0x13 +#define AUTHOREXT 0x14 +#define AUTHORPOS 0x15 +#define AUTHORORG 0x16 + +#define REPLYTO 0x20 +#define REPLYTOAGENT 0x21 +#define REPLYTONETTYPE 0x22 +#define REPLYTONETADDR 0x23 +#define REPLYTOEXT 0x24 +#define REPLYTOPOS 0x25 +#define REPLYTOORG 0x26 + +#define RECIPIENT 0x30 +#define RECIPIENTAGENT 0x31 +#define RECIPIENTNETTYPE 0x32 +#define RECIPIENTNETADDR 0x33 +#define RECIPIENTEXT 0x34 +#define RECIPIENTPOS 0x35 +#define RECIPIENTORG 0x36 + +#define FORWARDTO 0x40 +#define FORWARDTOAGENT 0x41 +#define FORWARDTONETTYPE 0x42 +#define FORWARDTONETADDR 0x43 +#define FORWARDTOEXT 0x44 +#define FORWARDTOPOS 0x45 +#define FORWARDTOORG 0x46 + +#define FORWARDED 0x48 + +#define RECEIVEDBY 0x50 +#define RECEIVEDBYAGENT 0x51 +#define RECEIVEDBYNETTYPE 0x52 +#define RECEIVEDBYNETADDR 0x53 +#define RECEIVEDBYEXT 0x54 +#define RECEIVEDBYPOS 0x55 +#define RECEIVEDBYORG 0x56 + +#define RECEIVED 0x58 + +#define SUBJECT 0x60 +#define SUMMARY 0x61 +#define SMB_COMMENT 0x62 +#define CARBONCOPY 0x63 +#define SMB_GROUP 0x64 +#define EXPIRATION 0x65 +#define PRIORITY 0x66 + +#define FILEATTACH 0x70 +#define DESTFILE 0x71 +#define FILEATTACHLIST 0x72 +#define DESTFILELIST 0x73 +#define FILEREQUEST 0x74 +#define FILEPASSWORD 0x75 +#define FILEREQUESTLIST 0x76 +#define FILEPASSWORDLIST 0x77 + +#define IMAGEATTACH 0x80 +#define ANIMATTACH 0x81 +#define FONTATTACH 0x82 +#define SOUNDATTACH 0x83 +#define PRESENTATTACH 0x84 +#define VIDEOATTACH 0x85 +#define APPDATAATTACH 0x86 + +#define IMAGETRIGGER 0x90 +#define ANIMTRIGGER 0x91 +#define FONTTRIGGER 0x92 +#define SOUNDTRIGGER 0x93 +#define PRESENTTRIGGER 0x94 +#define VIDEOTRIGGER 0x95 +#define APPDATATRIGGER 0x96 + +#define FIDOCTRL 0xa0 +#define FIDOAREA 0xa1 +#define FIDOSEENBY 0xa2 +#define FIDOPATH 0xa3 +#define FIDOMSGID 0xa4 +#define FIDOREPLYID 0xa5 +#define FIDOPID 0xa6 +#define FIDOFLAGS 0xa7 + +#define RFC822HEADER 0xb0 +#define RFC822MSGID 0xb1 +#define RFC822REPLYID 0xb2 + +#define UNKNOWN 0xf1 +#define UNKNOWNASCII 0xf2 +#define UNUSED 0xff + + /* Valid dfield_t.types */ +#define TEXT_BODY 0x00 +#define TEXT_SOUL 0x01 +#define TEXT_TAIL 0x02 +#define TEXT_WING 0x03 +#define IMAGEEMBED 0x20 +#define ANIMEMBED 0x21 +#define FONTEMBED 0x22 +#define SOUNDEMBED 0x23 +#define PRESENTEMBED 0x24 +#define VIDEOEMBED 0x25 +#define APPDATAEMBED 0x26 +#define UNUSED 0xff + + + /* Message attributes */ +#define MSG_PRIVATE (1<<0) +#define MSG_READ (1<<1) +#define MSG_PERMANENT (1<<2) +#define MSG_LOCKED (1<<3) +#define MSG_DELETE (1<<4) +#define MSG_ANONYMOUS (1<<5) +#define MSG_KILLREAD (1<<6) +#define MSG_MODERATED (1<<7) +#define MSG_VALIDATED (1<<8) +#define MSG_REPLIED (1<<9) // User replied to this message + + /* Auxillary header attributes */ +#define MSG_FILEREQUEST (1<<0) // File request +#define MSG_FILEATTACH (1<<1) // File(s) attached to Msg +#define MSG_TRUNCFILE (1<<2) // Truncate file(s) when sent +#define MSG_KILLFILE (1<<3) // Delete file(s) when sent +#define MSG_RECEIPTREQ (1<<4) // Return receipt requested +#define MSG_CONFIRMREQ (1<<5) // Confirmation receipt requested +#define MSG_NODISP (1<<6) // Msg may not be displayed to user + + /* Message network attributes */ +#define MSG_LOCAL (1<<0) // Msg created locally +#define MSG_INTRANSIT (1<<1) // Msg is in-transit +#define MSG_SENT (1<<2) // Sent to remote +#define MSG_KILLSENT (1<<3) // Kill when sent +#define MSG_ARCHIVESENT (1<<4) // Archive when sent +#define MSG_HOLD (1<<5) // Hold for pick-up +#define MSG_CRASH (1<<6) // Crash +#define MSG_IMMEDIATE (1<<7) // Send Msg now, ignore restrictions +#define MSG_DIRECT (1<<8) // Send directly to destination +#define MSG_GATE (1<<9) // Send via gateway +#define MSG_ORPHAN (1<<10) // Unknown destination +#define MSG_FPU (1<<11) // Force pickup +#define MSG_TYPELOCAL (1<<12) // Msg is for local use only +#define MSG_TYPEECHO (1<<13) // Msg is for conference distribution +#define MSG_TYPENET (1<<14) // Msg is direct network mail + + +enum { + NET_NONE + ,NET_UNKNOWN + ,NET_FIDO + ,NET_POSTLINK + ,NET_QWK + ,NET_INTERNET + ,NET_WWIV + ,NET_MHS + +/* Add new ones here */ + + ,NET_TYPES + }; + +enum { + AGENT_PERSON + ,AGENT_PROCESS + +/* Add new ones here */ + + ,AGENT_TYPES + }; + +enum { + XLAT_NONE // No translation/End of translation list + ,XLAT_ENCRYPT // Encrypted data + ,XLAT_ESCAPED // 7-bit ASCII escaping for ctrl and 8-bit data + ,XLAT_HUFFMAN // Static and adaptive Huffman coding compression + ,XLAT_LZW // Limpel/Ziv/Welch compression + ,XLAT_MLZ78 // Modified LZ78 compression + ,XLAT_RLE // Run length encoding compression + ,XLAT_IMPLODE // Implode compression (PkZIP) + ,XLAT_SHRINK // Shrink compression (PkZIP) + ,XLAT_LZH // LHarc (LHA) Dynamic Huffman coding + +/* Add new ones here */ + + ,XLAT_TYPES + }; + + +/************/ +/* Typedefs */ +/************/ + +#ifndef GOLDEDPLUS +#ifdef __GNUC__ + #define _PACK __attribute__ ((packed)) +#else + #define _PACK +#endif + +#ifdef _WIN32 +#pragma pack(push) /* Disk image structures must be packed */ +#pragma pack(1) +#endif +#else +#define _PACK +#if defined(GOLD_CANPACK) +#pragma pack(1) +#endif +#endif + +typedef struct _PACK { // Time with time-zone + + ulong time; // Local time (unix format) + short zone; // Time zone + + } when_t; + +typedef struct _PACK { // Index record + + ushort to; // 16-bit CRC of recipient name (lower case) + ushort from; // 16-bit CRC of sender name (lower case) + ushort subj; // 16-bit CRC of subject (lower case, w/o RE:) + ushort attr; // attributes (read, permanent, etc.) + ulong offset; // offset into header file + ulong number; // number of message (1 based) + ulong time; // time/date message was imported/posted + + } idxrec_t; + +typedef struct _PACK { // Message base header (fixed portion) + + uchar id[4]; // text or binary unique hdr ID + ushort version; // version number (initially 100h for 1.00) + ushort length; // length including this struct + + } smbhdr_t; + +typedef struct _PACK { // Message base status header + + ulong last_msg; // last message number + ulong total_msgs; // total messages + ulong header_offset; // byte offset to first header record + ulong max_crcs; // Maximum number of CRCs to keep in history + ulong max_msgs; // Maximum number of message to keep in sub + ushort max_age; // Maximum age of message to keep in sub (in days) + ushort attr; // Attributes for this message base (SMB_HYPER,etc) + + } smbstatus_t; + +typedef struct _PACK { // Message header + + uchar id[4]; // SHD<^Z> + ushort type; // Message type (normally 0) + ushort version; // Version of type (initially 100h for 1.00) + ushort length; // Total length of fixed record + all fields + ushort attr; // Attributes (bit field) (duped in SID) + ulong auxattr; // Auxillary attributes (bit field) + ulong netattr; // Network attributes + when_t when_written; // Time message was written (unix format) + when_t when_imported; // Time message was imported + ulong number; // Message number + ulong thread_orig; // Original message number in thread + ulong thread_next; // Next message in thread + ulong thread_first; // First reply to this message + ushort delivery_attempts; // Delivery attempt counter + uchar reserved[14]; // Reserved for future use + ulong offset; // Offset for buffer into data file (0 or mod 256) + ushort total_dfields; // Total number of data fields + + } msghdr_t; + +typedef struct _PACK { // Data field + + ushort type; // Type of data field + ulong offset; // Offset into buffer + ulong length; // Length of data field + + } dfield_t; + +typedef struct _PACK { // Header field + + ushort type; + ushort length; // Length of buffer + + } hfield_t; + +typedef struct _PACK { // FidoNet address (zone:net/node.point) + + ushort zone; + ushort net; + ushort node; + ushort point; + + } fidoaddr_t; + +typedef struct _PACK { // Network (type and address) + + ushort type; + void *addr; + + } net_t; + +#ifndef GOLDEDPLUS +#ifdef _WIN32 +#pragma pack(pop) /* original packing */ +#endif +#else +#undef _PACK +#if defined(GOLD_CANPACK) +#pragma pack() +#endif +#endif + +typedef struct { // Message + + idxrec_t idx; // Index + msghdr_t hdr; // Header record (fixed portion) + char *to, // To name + *to_ext, // To extension + *from, // From name + *from_ext, // From extension + *replyto, // Reply-to name + *replyto_ext, // Reply-to extension */ + *subj; // Subject + ushort to_agent, // Type of agent message is to + from_agent, // Type of agent message is from + replyto_agent; // Type of agent replies should be sent to + net_t to_net, // Destination network type and address + from_net, // Origin network address + replyto_net; // Network type and address for replies + ushort total_hfields; // Total number of header fields + hfield_t *hfield; // Header fields (fixed length portion) + void **hfield_dat; // Header fields (variable length portion) + dfield_t *dfield; // Data fields (fixed length portion) + ulong offset; // Offset (number of records) into index + uchar forwarded; // Forwarded from agent to another + when_t expiration; // Message will exipre on this day (if >0) + + } smbmsg_t; + +typedef struct { // Message base + + char file[128]; // Path and base filename (no extension) + FILE *sdt_fp; // File pointer for data (.sdt) file + FILE *shd_fp; // File pointer for header (.shd) file + FILE *sid_fp; // File pointer for index (.sid) file + FILE *sda_fp; // File pointer for data allocation (.sda) file + FILE *sha_fp; // File pointer for header allocation (.sha) file + ulong retry_time; // Maximum number of seconds to retry opens/locks + smbstatus_t status; // Status header record + char shd_buf[SHD_BLOCK_LEN]; // File I/O buffer for header file + char last_error[128]; // Last error message + + } smb_t; + +#endif /* Don't add anything after this #endif statement */ diff --git a/goldlib/smblib/smblib.all b/goldlib/smblib/smblib.all new file mode 100644 index 0000000..79105fb --- /dev/null +++ b/goldlib/smblib/smblib.all @@ -0,0 +1,3 @@ +lzh cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg +smblib cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg +smbtxt cpp all ovl bcd bco bcx wcn wco wcx lnx emx djg rsx cyg diff --git a/goldlib/smblib/smblib.cpp b/goldlib/smblib/smblib.cpp new file mode 100644 index 0000000..3ce828d --- /dev/null +++ b/goldlib/smblib/smblib.cpp @@ -0,0 +1,1555 @@ +/* smblib.c */ + +/* Synchronet message base (SMB) library routines */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#if defined __WATCOMC__ || defined __TURBOC__ + #include +#else + #include +#endif + +#ifdef __WATCOMC__ + #include +#elif defined __TURBOC__ + #include +#endif + +/* ANSI C Library headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SMB-specific headers */ +#include "smblib.h" +#ifndef GOLDEDPLUS +#include "smbwrap.h" +#else +#include + +#define sopen(fn,access,share) (sopen)((fn),(access),(share),S_IREAD|S_IWRITE) +#endif + +/* Use smb_ver() and smb_lib_ver() to obtain these values */ +#define SMBLIB_VERSION "2.13" /* SMB library version */ +#define SMB_VERSION 0x0121 /* SMB format version */ + /* High byte major, low byte minor */ + +int SMBCALL smb_ver(void) +{ + return(SMB_VERSION); +} + +char* SMBCALL smb_lib_ver(void) +{ + return(SMBLIB_VERSION); +} + +/****************************************************************************/ +/* Open a message base of name 'smb->file' */ +/* Opens files for READing messages or updating message indices only */ +/****************************************************************************/ +int SMBCALL smb_open(smb_t* smb) +{ + int file; + char str[128]; + smbhdr_t hdr; + + if(!smb->retry_time) + smb->retry_time=10; + smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL; + sprintf(str,"%s.shd",smb->file); + if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1 + || (smb->shd_fp=fdopen(file,"r+b"))==NULL) { + sprintf(smb->last_error,"%d opening %s",errno,str); + if(file!=-1) + close(file); + return(2); + } + + if(filelength(file)>=sizeof(smbhdr_t)) { + setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN); + if(smb_locksmbhdr(smb)!=0) { + smb_close(smb); + /* smb_lockmsghdr set last_error */ + return(-1); + } + memset(&hdr,0,sizeof(smbhdr_t)); + if(fread(&hdr,sizeof(smbhdr_t),1,smb->shd_fp)!=1) { + sprintf(smb->last_error,"reading header"); + smb_close(smb); + return(-10); + } + if(memcmp(hdr.id,"SMB\x1a",4)) { + sprintf(smb->last_error,"corrupt header id: %.4s",hdr.id); + smb_close(smb); + return(-2); + } + if(hdr.version<0x110) { /* Compatibility check */ + sprintf(smb->last_error,"insufficient header version: %X",hdr.version); + smb_close(smb); + return(-3); + } + if(fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp) + !=sizeof(smbstatus_t)) { + sprintf(smb->last_error,"failed to read status"); + smb_close(smb); + return(-4); + } + smb_unlocksmbhdr(smb); + rewind(smb->shd_fp); + } + + setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN); + + sprintf(str,"%s.sdt",smb->file); + if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1 + || (smb->sdt_fp=fdopen(file,"r+b"))==NULL) { + sprintf(smb->last_error,"%d opening %s",errno,str); + if(file!=-1) + close(file); + smb_close(smb); + return(1); + } + setvbuf(smb->sdt_fp,NULL,_IOFBF,2*1024); + + sprintf(str,"%s.sid",smb->file); + if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1 + || (smb->sid_fp=fdopen(file,"r+b"))==NULL) { + sprintf(smb->last_error,"%d opening %s",errno,str); + if(file!=-1) + close(file); + smb_close(smb); + return(3); + } + setvbuf(smb->sid_fp,NULL,_IOFBF,2*1024); + + return(0); +} + +/****************************************************************************/ +/* Closes the currently open message base */ +/****************************************************************************/ +void SMBCALL smb_close(smb_t* smb) +{ + if(smb->shd_fp!=NULL) { + smb_unlocksmbhdr(smb); /* In case it's been locked */ + fclose(smb->shd_fp); + } + if(smb->sid_fp!=NULL) + fclose(smb->sid_fp); + if(smb->sdt_fp!=NULL) + fclose(smb->sdt_fp); + smb->sid_fp=smb->shd_fp=smb->sdt_fp=NULL; +} + +/****************************************************************************/ +/* Opens the data block allocation table message base 'smb->file' */ +/* Retrys for retry_time number of seconds */ +/* Return 0 on success, non-zero otherwise */ +/****************************************************************************/ +int SMBCALL smb_open_da(smb_t* smb) +{ + int file; + char str[128]; + ulong start=0; + + sprintf(str,"%s.sda",smb->file); + while(1) { + if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1) + break; + if(errno!=EACCES) { + sprintf(smb->last_error,"%d opening %s",errno,str); + return(-1); + } + if(!start) + start=time(NULL); + else + if(time(NULL)-start>=smb->retry_time) { + sprintf(smb->last_error,"timeout opening %s",str); + return(-2); + } + } + if((smb->sda_fp=fdopen(file,"r+b"))==NULL) { + sprintf(smb->last_error,"%d fdopening %s",errno,str); + close(file); + return(-3); + } + setvbuf(smb->sda_fp,NULL,_IOFBF,2*1024); + return(0); +} + +void SMBCALL smb_close_da(smb_t* smb) +{ + if(smb->sda_fp!=NULL) + fclose(smb->sda_fp); + smb->sda_fp=NULL; +} + +/****************************************************************************/ +/* Opens the header block allocation table for message base 'smb.file' */ +/* Retrys for smb.retry_time number of seconds */ +/* Return 0 on success, non-zero otherwise */ +/****************************************************************************/ +int SMBCALL smb_open_ha(smb_t* smb) +{ + int file; + char str[128]; + ulong start=0; + + sprintf(str,"%s.sha",smb->file); + while(1) { + if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1) + break; + if(errno!=EACCES) { + sprintf(smb->last_error,"%d opening %s",errno,str); + return(-1); + } + if(!start) + start=time(NULL); + else + if(time(NULL)-start>=smb->retry_time) { + sprintf(smb->last_error,"timeout opening %s",str); + return(-2); + } + } + if((smb->sha_fp=fdopen(file,"r+b"))==NULL) { + sprintf(smb->last_error,"%d opening %s",errno,str); + close(file); + return(-3); + } + setvbuf(smb->sha_fp,NULL,_IOFBF,2*1024); + return(0); +} + +void SMBCALL smb_close_ha(smb_t* smb) +{ + if(smb->sha_fp!=NULL) + fclose(smb->sha_fp); + smb->sha_fp=NULL; +} + +/****************************************************************************/ +/* If the parameter 'push' is non-zero, this function stores the currently */ +/* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN */ +/* message bases may be stored (defined in SMBDEFS.H). */ +/* The parameter 'op' is the operation to perform on the stack. Either */ +/* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG */ +/* If the operation is SMB_STACK_POP, this function restores a message base */ +/* previously saved with a SMB_STACK_PUSH call to this same function. */ +/* If the operation is SMB_STACK_XCHNG, then the current message base is */ +/* exchanged with the message base on the top of the stack (most recently */ +/* pushed. */ +/* If the current message base is not open, the SMB_STACK_PUSH and */ +/* SMB_STACK_XCHNG operations do nothing */ +/* Returns 0 on success, non-zero if stack full. */ +/* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0. */ +/****************************************************************************/ +int SMBCALL smb_stack(smb_t* smb, int op) +{ + static char stack_file[SMB_STACK_LEN][128]; + static FILE* stack_sdt[SMB_STACK_LEN], + *stack_shd[SMB_STACK_LEN], + *stack_sid[SMB_STACK_LEN], + *stack_sda[SMB_STACK_LEN], + *stack_sha[SMB_STACK_LEN]; + static int stack_idx = 0; + char tmp_file[128]; + FILE *tmp; + + switch(op) { + case SMB_STACK_PUSH: + if(stack_idx>=SMB_STACK_LEN) { + sprintf(smb->last_error,"SMB stack overflow"); + return(1); + } + if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL) + return(0); /* Msg base not open */ + memcpy(stack_file[stack_idx],smb->file,128); + stack_sdt[stack_idx]=smb->sdt_fp; + stack_shd[stack_idx]=smb->shd_fp; + stack_sid[stack_idx]=smb->sid_fp; + stack_sda[stack_idx]=smb->sda_fp; + stack_sha[stack_idx]=smb->sha_fp; + stack_idx++; + return(0); + case SMB_STACK_POP: + if(!stack_idx) /* Nothing on the stack, so do nothing */ + return(0); + stack_idx--; + memcpy(smb->file,stack_file[stack_idx],128); + smb->sdt_fp=stack_sdt[stack_idx]; + smb->shd_fp=stack_shd[stack_idx]; + smb->sid_fp=stack_sid[stack_idx]; + smb->sda_fp=stack_sda[stack_idx]; + smb->sha_fp=stack_sha[stack_idx]; + return(0); + case SMB_STACK_XCHNG: + if(!stack_idx) /* Nothing on the stack, so do nothing */ + return(0); + if(!smb->shd_fp) + return(0); + stack_idx--; + + memcpy(tmp_file,stack_file[stack_idx],128); + memcpy(stack_file[stack_idx],smb->file,128); + memcpy(smb->file,tmp_file,128); + + tmp=stack_sdt[stack_idx]; + stack_sdt[stack_idx]=smb->sdt_fp; + smb->sdt_fp=tmp; + + tmp=stack_shd[stack_idx]; + stack_shd[stack_idx]=smb->shd_fp; + smb->shd_fp=tmp; + + tmp=stack_sid[stack_idx]; + stack_sid[stack_idx]=smb->sid_fp; + smb->sid_fp=tmp; + + tmp=stack_sda[stack_idx]; + stack_sda[stack_idx]=smb->sda_fp; + smb->sda_fp=tmp; + + tmp=stack_sha[stack_idx]; + stack_sha[stack_idx]=smb->sha_fp; + smb->sha_fp=tmp; + + stack_idx++; + return(0); + } + return(0); +} + +/****************************************************************************/ +/* Truncates header file */ +/* Retrys for smb.retry_time number of seconds */ +/* Return 0 on success, non-zero otherwise */ +/****************************************************************************/ +int SMBCALL smb_trunchdr(smb_t* smb) +{ + ulong start=0; + + rewind(smb->shd_fp); + while(1) { + if(!chsize(fileno(smb->shd_fp),0L)) + break; + if(errno!=EACCES) { + sprintf(smb->last_error,"%d changing header file size",errno); + return(-1); + } + if(!start) + start=time(NULL); + else + if(time(NULL)-start>=smb->retry_time) { /* Time-out */ + sprintf(smb->last_error,"timeout changing header file size"); + return(-2); + } + } + return(0); +} + +/*********************************/ +/* Message Base Header Functions */ +/*********************************/ + +/****************************************************************************/ +/* Attempts for smb.retry_time number of seconds to lock the msg base hdr */ +/****************************************************************************/ +int SMBCALL smb_locksmbhdr(smb_t* smb) +{ + ulong start=0; + + while(1) { + if(!lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))) + return(0); + if(!start) + start=time(NULL); + else + if(time(NULL)-start>=smb->retry_time) + break; + /* In case we've already locked it */ + unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); + } + sprintf(smb->last_error,"timeout locking header"); + return(-1); +} + +/****************************************************************************/ +/* Read the SMB header from the header file and place into smb.status */ +/****************************************************************************/ +int SMBCALL smb_getstatus(smb_t* smb) +{ + int i; + + setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN); + clearerr(smb->shd_fp); + fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET); + i=fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp); + setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN); + if(i==sizeof(smbstatus_t)) + return(0); + sprintf(smb->last_error,"read %d instead of %d",i,sizeof(smbstatus_t)); + return(1); +} + +/****************************************************************************/ +/* Writes message base header */ +/****************************************************************************/ +int SMBCALL smb_putstatus(smb_t* smb) +{ + int i; + + clearerr(smb->shd_fp); + fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET); + i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp); + fflush(smb->shd_fp); + if(i==sizeof(smbstatus_t)) + return(0); + sprintf(smb->last_error,"wrote %d instead of %d",i,sizeof(smbstatus_t)); + return(1); +} + +/****************************************************************************/ +/* Unlocks previously locks message base header */ +/****************************************************************************/ +int SMBCALL smb_unlocksmbhdr(smb_t* smb) +{ + return(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))); +} + +/********************************/ +/* Individual Message Functions */ +/********************************/ + +/****************************************************************************/ +/* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg' */ +/****************************************************************************/ +int SMBCALL smb_lockmsghdr(smb_t* smb, smbmsg_t* msg) +{ + ulong start=0; + + while(1) { + if(!lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t))) + return(0); + if(!start) + start=time(NULL); + else + if(time(NULL)-start>=smb->retry_time) + break; + /* In case we've already locked it */ + unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)); + } + sprintf(smb->last_error,"timeout locking header"); + return(-1); +} + +/****************************************************************************/ +/* Fills msg->idx with message index based on msg->hdr.number */ +/* OR if msg->hdr.number is 0, based on msg->offset (record offset). */ +/* if msg.hdr.number does not equal 0, then msg->offset is filled too. */ +/* Either msg->hdr.number or msg->offset must be initialized before */ +/* calling this function */ +/* Returns 1 if message number wasn't found, 0 if it was */ +/****************************************************************************/ +int SMBCALL smb_getmsgidx(smb_t* smb, smbmsg_t* msg) +{ + idxrec_t idx; + ulong l,length,total,bot,top; + + clearerr(smb->sid_fp); + if(!msg->hdr.number) { + fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET); + if(!fread(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) { + sprintf(smb->last_error,"reading index"); + return(1); + } + return(0); + } + + length=filelength(fileno(smb->sid_fp)); + if(!length) { + sprintf(smb->last_error,"invalid index file length: %ld",length); + return(1); + } + total=length/sizeof(idxrec_t); + if(!total) { + sprintf(smb->last_error,"invalid index file length: %ld",length); + return(1); + } + + bot=0; + top=total; + l=total/2; /* Start at middle index */ + while(1) { + fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET); + if(!fread(&idx,sizeof(idxrec_t),1,smb->sid_fp)) { + sprintf(smb->last_error,"reading index"); + return(1); + } + if(bot==top-1 && idx.number!=msg->hdr.number) { + sprintf(smb->last_error,"msg %ld not found",msg->hdr.number); + return(1); + } + if(idx.number>msg->hdr.number) { + top=l; + l=bot+((top-bot)/2); + continue; + } + if(idx.numberhdr.number) { + bot=l; + l=top-((top-bot)/2); + continue; + } + break; + } + msg->idx=idx; + msg->offset=l; + return(0); +} + +/****************************************************************************/ +/* Reads the last index record in the open message base */ +/****************************************************************************/ +int SMBCALL smb_getlastidx(smb_t* smb, idxrec_t *idx) +{ + long length; + + clearerr(smb->sid_fp); + length=filelength(fileno(smb->sid_fp)); + if(lengthlast_error,"invalid index file length: %ld",length); + return(-1); + } + fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET); + if(!fread(idx,sizeof(idxrec_t),1,smb->sid_fp)) { + sprintf(smb->last_error,"reading index"); + return(-2); + } + return(0); +} + +/****************************************************************************/ +/* Figures out the total length of the header record for 'msg' */ +/* Returns length */ +/****************************************************************************/ +uint SMBCALL smb_getmsghdrlen(smbmsg_t* msg) +{ + int i; + + /* fixed portion */ + msg->hdr.length=sizeof(msghdr_t); + /* data fields */ + msg->hdr.length+=msg->hdr.total_dfields*sizeof(dfield_t); + /* header fields */ + for(i=0;itotal_hfields;i++) { + msg->hdr.length+=sizeof(hfield_t); + msg->hdr.length+=msg->hfield[i].length; + } + return(msg->hdr.length); +} + +/****************************************************************************/ +/* Figures out the total length of the data buffer for 'msg' */ +/* Returns length */ +/****************************************************************************/ +ulong SMBCALL smb_getmsgdatlen(smbmsg_t* msg) +{ + int i; + ulong length=0L; + + for(i=0;ihdr.total_dfields;i++) + length+=msg->dfield[i].length; + return(length); +} + +/****************************************************************************/ +/* Read header information into 'msg' structure */ +/* msg->idx.offset must be set before calling this function */ +/* Must call smb_freemsgmem() to free memory allocated for var len strs */ +/* Returns 0 on success, non-zero if error */ +/****************************************************************************/ +int SMBCALL smb_getmsghdr(smb_t* smb, smbmsg_t* msg) +{ + hfield_t *vp; + void **vpp; + ushort i; + ulong l,offset; + idxrec_t idx; + + rewind(smb->shd_fp); + fseek(smb->shd_fp,msg->idx.offset,SEEK_SET); + idx=msg->idx; + offset=msg->offset; + memset(msg,0,sizeof(smbmsg_t)); + msg->idx=idx; + msg->offset=offset; + if(!fread(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) { + sprintf(smb->last_error,"reading msg header"); + return(-1); + } + if(memcmp(msg->hdr.id,"SHD\x1a",4)) { + sprintf(smb->last_error,"corrupt header id: %.4s",msg->hdr.id); + return(-2); + } + if(msg->hdr.version<0x110) { + sprintf(smb->last_error,"insufficient header version: %X",msg->hdr.version); + return(-9); + } + l=sizeof(msghdr_t); + if(msg->hdr.total_dfields && (msg->dfield + =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) { + smb_freemsgmem(msg); + sprintf(smb->last_error,"malloc failure of %d bytes for %d data fields" + ,sizeof(dfield_t)*msg->hdr.total_dfields, msg->hdr.total_dfields); + return(-3); + } + i=0; + while(ihdr.total_dfields && lhdr.length) { + if(!fread(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) { + smb_freemsgmem(msg); + sprintf(smb->last_error,"reading data field %d",i); + return(-4); + } + i++; + l+=sizeof(dfield_t); + } + if(ihdr.total_dfields) { + smb_freemsgmem(msg); + sprintf(smb->last_error,"insufficient data fields read (%d instead of %d)" + ,i,msg->hdr.total_dfields); + return(-8); + } + while(lhdr.length) { + i=msg->total_hfields; + if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) { + smb_freemsgmem(msg); + sprintf(smb->last_error + ,"realloc failure of %d bytes for header field data" + ,sizeof(void*)*(i+1)); + return(-3); + } + msg->hfield_dat=vpp; + if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) { + smb_freemsgmem(msg); + sprintf(smb->last_error + ,"realloc failure of %d bytes for header fields" + ,sizeof(hfield_t)*(i+1)); + return(-3); + } + msg->hfield=vp; + msg->total_hfields++; + if(!fread(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) { + smb_freemsgmem(msg); + sprintf(smb->last_error,"reading header field"); + return(-5); + } + l+=sizeof(hfield_t); + if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length+1)) + ==NULL) { /* Allocate 1 extra for NULL terminator */ + sprintf(smb->last_error + ,"malloc failure of %d bytes for header field %d" + ,msg->hfield[i].length+1, i); + smb_freemsgmem(msg); /* or 0 length field */ + return(-3); + } + memset(msg->hfield_dat[i],0,msg->hfield[i].length+1); /* init to NULL */ + if(msg->hfield[i].length + && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) { + smb_freemsgmem(msg); + sprintf(smb->last_error,"reading header field data"); + return(-6); + } + switch(msg->hfield[i].type) { /* convenience variables */ + case SENDER: + if(!msg->from) { + msg->from=(char *)msg->hfield_dat[i]; + break; + } + case FORWARDED: /* fall through */ + msg->forwarded=1; + break; + case SENDERAGENT: + if(!msg->forwarded) + msg->from_agent=*(ushort *)msg->hfield_dat[i]; + break; + case SENDEREXT: + if(!msg->forwarded) + msg->from_ext=(char *)msg->hfield_dat[i]; + break; + case SENDERNETTYPE: + if(!msg->forwarded) + msg->from_net.type=*(ushort *)msg->hfield_dat[i]; + break; + case SENDERNETADDR: + if(!msg->forwarded) + msg->from_net.addr=msg->hfield_dat[i]; + break; + case REPLYTO: + msg->replyto=(char *)msg->hfield_dat[i]; + break; + case REPLYTOEXT: + msg->replyto_ext=(char *)msg->hfield_dat[i]; + break; + case REPLYTOAGENT: + msg->replyto_agent=*(ushort *)msg->hfield_dat[i]; + break; + case REPLYTONETTYPE: + msg->replyto_net.type=*(ushort *)msg->hfield_dat[i]; + break; + case REPLYTONETADDR: + msg->replyto_net.addr=msg->hfield_dat[i]; + break; + case RECIPIENT: + msg->to=(char *)msg->hfield_dat[i]; + break; + case RECIPIENTEXT: + msg->to_ext=(char *)msg->hfield_dat[i]; + break; + case RECIPIENTAGENT: + msg->to_agent=*(ushort *)msg->hfield_dat[i]; + break; + case RECIPIENTNETTYPE: + msg->to_net.type=*(ushort *)msg->hfield_dat[i]; + break; + case RECIPIENTNETADDR: + msg->to_net.addr=msg->hfield_dat[i]; + break; + case SUBJECT: + msg->subj=(char *)msg->hfield_dat[i]; + break; + } + l+=msg->hfield[i].length; + } + + if(!msg->from || !msg->to || !msg->subj) { + sprintf(smb->last_error,"missing required header field (from/to/subj)"); + smb_freemsgmem(msg); + return(-7); + } + return(0); +} + +/****************************************************************************/ +/* Frees memory allocated for 'msg' */ +/****************************************************************************/ +void SMBCALL smb_freemsgmem(smbmsg_t* msg) +{ + ushort i; + + if(msg->dfield) { + FREE(msg->dfield); + msg->dfield=NULL; + } + for(i=0;itotal_hfields;i++) + if(msg->hfield_dat[i]) { + FREE(msg->hfield_dat[i]); + msg->hfield_dat[i]=NULL; + } + msg->total_hfields=0; + if(msg->hfield) { + FREE(msg->hfield); + msg->hfield=NULL; + } + if(msg->hfield_dat) { + FREE(msg->hfield_dat); + msg->hfield_dat=NULL; + } +} + +/****************************************************************************/ +/* Copies memory allocated for 'srcmsg' to 'msg' */ +/****************************************************************************/ +int SMBCALL smb_copymsgmem(smbmsg_t* msg, smbmsg_t* srcmsg) +{ + int i; + + memcpy(msg,srcmsg,sizeof(smbmsg_t)); + + /* data field types/lengths */ + if((msg->dfield=(dfield_t *)MALLOC(msg->hdr.total_dfields*sizeof(dfield_t)))==NULL) + return(1); + memcpy(msg->dfield,srcmsg->dfield,msg->hdr.total_dfields*sizeof(dfield_t)); + + /* header field types/lengths */ + if((msg->hfield=(hfield_t *)MALLOC(msg->total_hfields*sizeof(hfield_t)))==NULL) + return(2); + memcpy(msg->hfield,srcmsg->hfield,msg->total_hfields*sizeof(hfield_t)); + + /* header field data */ + if((msg->hfield_dat=(void* *)MALLOC(msg->total_hfields*sizeof(void*)))==NULL) + return(3); + + for(i=0;itotal_hfields;i++) { + if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length))==NULL) + return(4); + memcpy(msg->hfield_dat[i],srcmsg->hfield_dat[i],msg->hfield[i].length); + } + + return(0); +} + +/****************************************************************************/ +/* Unlocks header for 'msg' */ +/****************************************************************************/ +int SMBCALL smb_unlockmsghdr(smb_t* smb, smbmsg_t* msg) +{ + return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t))); +} + + +/****************************************************************************/ +/* Adds a header field to the 'msg' structure (in memory only) */ +/****************************************************************************/ +int SMBCALL smb_hfield(smbmsg_t* msg, ushort type, ushort length, void* data) +{ + hfield_t *vp; + void **vpp; + int i; + + i=msg->total_hfields; + if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) + return(1); + + msg->hfield=vp; + if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) + return(2); + + msg->hfield_dat=vpp; + msg->total_hfields++; + msg->hfield[i].type=type; + msg->hfield[i].length=length; + if(length) { + if((msg->hfield_dat[i]=(void* )MALLOC(length))==NULL) + return(4); + memcpy(msg->hfield_dat[i],data,length); + } + else + msg->hfield_dat[i]=NULL; + return(0); +} + +/****************************************************************************/ +/* Adds a data field to the 'msg' structure (in memory only) */ +/* Automatically figures out the offset into the data buffer from existing */ +/* dfield lengths */ +/****************************************************************************/ +int SMBCALL smb_dfield(smbmsg_t* msg, ushort type, ulong length) +{ + dfield_t *vp; + int i,j; + + i=msg->hdr.total_dfields; + if((vp=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL) + return(1); + + msg->dfield=vp; + msg->hdr.total_dfields++; + msg->dfield[i].type=type; + msg->dfield[i].length=length; + for(j=msg->dfield[i].offset=0;jdfield[i].offset+=msg->dfield[j].length; + return(0); +} + +/****************************************************************************/ +/* Checks CRC history file for duplicate crc. If found, returns 1. */ +/* If no dupe, adds to CRC history and returns 0, or negative if error. */ +/****************************************************************************/ +int SMBCALL smb_addcrc(smb_t* smb, ulong crc) +{ + char str[128]; + int file; + long length; + ulong l,*buf; + ulong start=0; + + if(!smb->status.max_crcs) + return(0); + + sprintf(str,"%s.sch",smb->file); + while(1) { + if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1) + break; + if(errno!=EACCES) { + sprintf(smb->last_error,"%d opening %s", errno, str); + return(-1); + } + if(!start) + start=time(NULL); + else + if(time(NULL)-start>=smb->retry_time) { + sprintf(smb->last_error,"timeout opening %s", str); + return(-2); + } + } + + length=filelength(file); + if(length<0L) { + close(file); + sprintf(smb->last_error,"invalid file length: %ld", length); + return(-4); + } + if((buf=(ulong*)MALLOC(smb->status.max_crcs*4))==NULL) { + close(file); + sprintf(smb->last_error + ,"malloc failure of %ld bytes" + ,smb->status.max_crcs*4); + return(-3); + } + if((ulong)length>=smb->status.max_crcs*4L) { /* Reached or exceeds max crcs */ + read(file,buf,smb->status.max_crcs*4); + for(l=0;lstatus.max_crcs;l++) + if(crc==buf[l]) + break; + if(lstatus.max_crcs) { /* Dupe CRC found */ + close(file); + FREE(buf); + return(1); + } + chsize(file,0L); /* truncate it */ + lseek(file,0L,SEEK_SET); + write(file,buf+4,(smb->status.max_crcs-1)*4); + } + + else if(length/4) { /* Less than max crcs */ + read(file,buf,length); + for(l=0;l<(ulong)(length/4);l++) + if(crc==buf[l]) + break; + if(l<(ulong)(length/4L)) { /* Dupe CRC found */ + close(file); + FREE(buf); + return(1); + } + } + + lseek(file,0L,SEEK_END); + write(file,&crc,4); /* Write to the end */ + FREE(buf); + close(file); + return(0); +} + +/****************************************************************************/ +/* Creates a new message header record in the header file. */ +/* If storage is SMB_SELFPACK, self-packing conservative allocation is used */ +/* If storage is SMB_FASTALLOC, fast allocation is used */ +/* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest) */ +/****************************************************************************/ +int SMBCALL smb_addmsghdr(smb_t* smb, smbmsg_t* msg, int storage) +{ + int i; + long l; + + if(smb_locksmbhdr(smb)) + return(1); + if(smb_getstatus(smb)) + return(2); + + if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=0) + return(i); + + msg->hdr.length=smb_getmsghdrlen(msg); + if(storage==SMB_HYPERALLOC) + l=smb_hallochdr(smb); + else if(storage==SMB_FASTALLOC) + l=smb_fallochdr(smb,msg->hdr.length); + else + l=smb_allochdr(smb,msg->hdr.length); + if(l==-1L) { + smb_unlocksmbhdr(smb); + smb_close_ha(smb); + return(-1); + } + + smb->status.last_msg++; + msg->idx.number=msg->hdr.number=smb->status.last_msg; + msg->idx.offset=smb->status.header_offset+l; + msg->idx.time=msg->hdr.when_imported.time; + msg->idx.attr=msg->hdr.attr; + msg->offset=smb->status.total_msgs; + smb->status.total_msgs++; + smb_putstatus(smb); + + if(storage!=SMB_HYPERALLOC) + smb_close_ha(smb); + i=smb_putmsg(smb,msg); + smb_unlocksmbhdr(smb); + return(i); +} + +/****************************************************************************/ +/* Writes both header and index information for msg 'msg' */ +/****************************************************************************/ +int SMBCALL smb_putmsg(smb_t* smb, smbmsg_t* msg) +{ + int i; + + i=smb_putmsghdr(smb,msg); + if(i) + return(i); + return(smb_putmsgidx(smb,msg)); +} + +/****************************************************************************/ +/* Writes index information for 'msg' */ +/* msg->idx */ +/* and msg->offset must be set prior to calling to this function */ +/* Returns 0 if everything ok */ +/****************************************************************************/ +int SMBCALL smb_putmsgidx(smb_t* smb, smbmsg_t* msg) +{ + + clearerr(smb->sid_fp); + fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET); + if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) { + sprintf(smb->last_error,"writing index"); + return(1); + } + fflush(smb->sid_fp); + return(0); +} + +/****************************************************************************/ +/* Writes header information for 'msg' */ +/* msg->hdr.length */ +/* msg->idx.offset */ +/* and msg->offset must be set prior to calling to this function */ +/* Returns 0 if everything ok */ +/****************************************************************************/ +int SMBCALL smb_putmsghdr(smb_t* smb, smbmsg_t* msg) +{ + ushort i; + ulong l; + + clearerr(smb->shd_fp); + if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) { + sprintf(smb->last_error,"seeking to %ld in index",msg->idx.offset); + return(-1); + } + + /************************************************/ + /* Write the fixed portion of the header record */ + /************************************************/ + if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) { + sprintf(smb->last_error,"writing fixed portion of header record"); + return(-2); + } + + /************************************************/ + /* Write the data fields (each is fixed length) */ + /************************************************/ + for(i=0;ihdr.total_dfields;i++) + if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) { + sprintf(smb->last_error,"writing data field"); + return(-3); + } + + /*******************************************/ + /* Write the variable length header fields */ + /*******************************************/ + for(i=0;itotal_hfields;i++) { + if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) { + sprintf(smb->last_error,"writing header field"); + return(-4); + } + if(msg->hfield[i].length /* more then 0 bytes long */ + && !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) { + sprintf(smb->last_error,"writing header field data"); + return(-5); + } + } + + l=smb_getmsghdrlen(msg); + while(l%SHD_BLOCK_LEN) { + if(fputc(0,smb->shd_fp)==EOF) { + sprintf(smb->last_error,"padding header block"); + return(-6); /* pad block with NULL */ + } + l++; + } + fflush(smb->shd_fp); + return(0); +} + +/****************************************************************************/ +/* Creates a sub-board's initial header file */ +/* Truncates and deletes other associated SMB files */ +/****************************************************************************/ +int SMBCALL smb_create(smb_t* smb) +{ + char str[128]; + smbhdr_t hdr; + + if(filelength(fileno(smb->shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t) + && smb_locksmbhdr(smb)) /* header exists, so lock it */ + return(1); + memset(&hdr,0,sizeof(smbhdr_t)); + memcpy(hdr.id,"SMB\x1a",4); /* <^Z> */ + hdr.version=SMB_VERSION; + hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t); + smb->status.last_msg=smb->status.total_msgs=0; + smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t); + rewind(smb->shd_fp); + fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp); + fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp); + rewind(smb->shd_fp); + chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t)); + fflush(smb->shd_fp); + + rewind(smb->sdt_fp); + chsize(fileno(smb->sdt_fp),0L); + rewind(smb->sid_fp); + chsize(fileno(smb->sid_fp),0L); + + sprintf(str,"%s.sda",smb->file); + remove(str); /* if it exists, delete it */ + sprintf(str,"%s.sha",smb->file); + remove(str); /* if it exists, delete it */ + sprintf(str,"%s.sch",smb->file); + remove(str); + smb_unlocksmbhdr(smb); + return(0); +} + +/****************************************************************************/ +/* Returns number of data blocks required to store "length" amount of data */ +/****************************************************************************/ +ulong SMBCALL smb_datblocks(ulong length) +{ + ulong blocks; + + blocks=length/SDT_BLOCK_LEN; + if(length%SDT_BLOCK_LEN) + blocks++; + return(blocks); +} + +/****************************************************************************/ +/* Returns number of header blocks required to store "length" size header */ +/****************************************************************************/ +ulong SMBCALL smb_hdrblocks(ulong length) +{ + ulong blocks; + + blocks=length/SHD_BLOCK_LEN; + if(length%SHD_BLOCK_LEN) + blocks++; + return(blocks); +} + +/****************************************************************************/ +/* Finds unused space in data file based on block allocation table and */ +/* marks space as used in allocation table. */ +/* File must be opened read/write DENY ALL */ +/* Returns offset to beginning of data (in bytes, not blocks) */ +/* Assumes smb_open_da() has been called */ +/* smb_close_da() should be called after */ +/* Returns negative on error */ +/****************************************************************************/ +long SMBCALL smb_allocdat(smb_t* smb, ulong length, ushort headers) +{ + ushort i,j; + ulong l,blocks,offset=0L; + + blocks=smb_datblocks(length); + j=0; /* j is consecutive unused block counter */ + fflush(smb->sda_fp); + rewind(smb->sda_fp); + while(!feof(smb->sda_fp)) { + if(!fread(&i,2,1,smb->sda_fp)) + break; + offset+=SDT_BLOCK_LEN; + if(!i) j++; + else j=0; + if(j==blocks) { + offset-=(blocks*SDT_BLOCK_LEN); + break; + } + } + clearerr(smb->sda_fp); + fseek(smb->sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET); + for(l=0;lsda_fp)) { + sprintf(smb->last_error,"writing allocation bytes"); + return(-1); + } + fflush(smb->sda_fp); + return(offset); +} + +/****************************************************************************/ +/* Allocates space for data, but doesn't search for unused blocks */ +/* Returns negative on error */ +/****************************************************************************/ +long SMBCALL smb_fallocdat(smb_t* smb, ulong length, ushort headers) +{ + ulong l,blocks,offset; + + fflush(smb->sda_fp); + clearerr(smb->sda_fp); + blocks=smb_datblocks(length); + fseek(smb->sda_fp,0L,SEEK_END); + offset=(ftell(smb->sda_fp)/2L)*SDT_BLOCK_LEN; + for(l=0;lsda_fp)) + break; + fflush(smb->sda_fp); + if(llast_error,"writing allocation bytes"); + return(-1L); + } + return(offset); +} + +/****************************************************************************/ +/* De-allocates space for data */ +/* Returns non-zero on error */ +/****************************************************************************/ +int SMBCALL smb_freemsgdat(smb_t* smb, ulong offset, ulong length + , ushort headers) +{ + int da_opened=0; + ushort i; + ulong l,blocks; + + blocks=smb_datblocks(length); + + if(smb->sda_fp==NULL) { + if((i=smb_open_da(smb))!=0) + return(i); + da_opened=1; + } + + clearerr(smb->sda_fp); + for(l=0;lsda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET)) { + sprintf(smb->last_error + ,"seeking to %ld of allocation file" + ,((offset/SDT_BLOCK_LEN)+l)*2L); + return(1); + } + if(!fread(&i,2,1,smb->sda_fp)) { + sprintf(smb->last_error,"reading allocation bytes"); + return(2); + } + if(headers>i) + i=0; /* don't want to go negative */ + else + i-=headers; + if(fseek(smb->sda_fp,-2L,SEEK_CUR)) { + sprintf(smb->last_error,"seeking backwards 2 bytes in allocation file"); + return(3); + } + if(!fwrite(&i,2,1,smb->sda_fp)) { + sprintf(smb->last_error,"writing allocation bytes"); + return(4); + } + } + fflush(smb->sda_fp); + if(da_opened) + smb_close_da(smb); + return(0); +} + +/****************************************************************************/ +/* Adds to data allocation records for blocks starting at 'offset' */ +/* Returns non-zero on error */ +/****************************************************************************/ +int SMBCALL smb_incdat(smb_t* smb, ulong offset, ulong length, ushort headers) +{ + ushort i; + ulong l,blocks; + + clearerr(smb->sda_fp); + blocks=smb_datblocks(length); + for(l=0;lsda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET); + if(!fread(&i,2,1,smb->sda_fp)) { + sprintf(smb->last_error,"reading allocation record"); + return(1); + } + i+=headers; + fseek(smb->sda_fp,-2L,SEEK_CUR); + if(!fwrite(&i,2,1,smb->sda_fp)) { + sprintf(smb->last_error,"writing allocation record"); + return(2); + } + } + fflush(smb->sda_fp); + return(0); +} + +/****************************************************************************/ +/* De-allocates blocks for header record */ +/* Returns non-zero on error */ +/****************************************************************************/ +int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length) +{ + uchar c=0; + ulong l,blocks; + + clearerr(smb->sha_fp); + blocks=smb_hdrblocks(length); + fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET); + for(l=0;lsha_fp)) { + sprintf(smb->last_error,"writing allocation record"); + return(1); + } + fflush(smb->sha_fp); + return(0); +} + +/****************************************************************************/ +/* Frees all allocated header and data blocks for 'msg' */ +/****************************************************************************/ +int SMBCALL smb_freemsg(smb_t* smb, smbmsg_t* msg) +{ + int i; + ushort x; + + if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */ + return(0); + + for(x=0;xhdr.total_dfields;x++) { + if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset + ,msg->dfield[x].length,1))!=0) + return(i); + } + return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset + ,msg->hdr.length)); +} + +/****************************************************************************/ +/* Finds unused space in header file based on block allocation table and */ +/* marks space as used in allocation table. */ +/* File must be opened read/write DENY ALL */ +/* Returns offset to beginning of header (in bytes, not blocks) */ +/* Assumes smb_open_ha() has been called */ +/* smb_close_ha() should be called after */ +/* Returns -1L on error */ +/****************************************************************************/ +long SMBCALL smb_allochdr(smb_t* smb, ulong length) +{ + uchar c; + ushort i; + ulong l,blocks,offset=0; + + blocks=smb_hdrblocks(length); + i=0; /* i is consecutive unused block counter */ + fflush(smb->sha_fp); + rewind(smb->sha_fp); + while(!feof(smb->sha_fp)) { + if(!fread(&c,1,1,smb->sha_fp)) + break; + offset+=SHD_BLOCK_LEN; + if(!c) i++; + else i=0; + if(i==blocks) { + offset-=(blocks*SHD_BLOCK_LEN); + break; + } + } + clearerr(smb->sha_fp); + fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET); + c=1; + for(l=0;lsha_fp)) { + sprintf(smb->last_error,"writing allocation record"); + return(-1L); + } + fflush(smb->sha_fp); + return(offset); +} + +/****************************************************************************/ +/* Allocates space for index, but doesn't search for unused blocks */ +/* Returns -1L on error */ +/****************************************************************************/ +long SMBCALL smb_fallochdr(smb_t* smb, ulong length) +{ + uchar c=1; + ulong l,blocks,offset; + + blocks=smb_hdrblocks(length); + fflush(smb->sha_fp); + clearerr(smb->sha_fp); + fseek(smb->sha_fp,0L,SEEK_END); + offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN; + for(l=0;lsha_fp)) { + sprintf(smb->last_error,"writing allocation record"); + return(-1L); + } + fflush(smb->sha_fp); + return(offset); +} + +/************************************************************************/ +/* Allocate header blocks using Hyper Allocation */ +/* this function should be most likely not be called from anywhere but */ +/* smb_addmsghdr() */ +/************************************************************************/ +long SMBCALL smb_hallochdr(smb_t* smb) +{ + ulong l; + + fflush(smb->shd_fp); + fseek(smb->shd_fp,0L,SEEK_END); + l=ftell(smb->shd_fp); + if(lstatus.header_offset) /* Header file truncated?!? */ + return(smb->status.header_offset); + while((l-smb->status.header_offset)%SHD_BLOCK_LEN) /* Even block boundry */ + l++; + return(l-smb->status.header_offset); +} + +/************************************************************************/ +/* Allocate data blocks using Hyper Allocation */ +/* smb_locksmbhdr() should be called before this function and not */ +/* unlocked until all data fields for this message have been written */ +/* to the SDT file */ +/************************************************************************/ +long SMBCALL smb_hallocdat(smb_t* smb) +{ + long l; + + fflush(smb->sdt_fp); + fseek(smb->sdt_fp,0L,SEEK_END); + l=ftell(smb->sdt_fp); + if(l<=0) + return(l); + while(l%SDT_BLOCK_LEN) /* Make sure even block boundry */ + l++; + return(l); +} + + +int SMBCALL smb_feof(FILE* fp) +{ + return(feof(fp)); +} + +int SMBCALL smb_ferror(FILE* fp) +{ + return(ferror(fp)); +} + +int SMBCALL smb_fflush(FILE* fp) +{ + return(fflush(fp)); +} + +int SMBCALL smb_fgetc(FILE* fp) +{ + return(fgetc(fp)); +} + +int SMBCALL smb_fputc(int ch, FILE* fp) +{ + return(fputc(ch,fp)); +} + +int SMBCALL smb_fseek(FILE* fp, long offset, int whence) +{ + return(fseek(fp,offset,whence)); +} + +long SMBCALL smb_ftell(FILE* fp) +{ + return(ftell(fp)); +} + +long SMBCALL smb_fgetlength(FILE* fp) +{ + return(filelength(fileno(fp))); +} + +int SMBCALL smb_fsetlength(FILE* fp, long length) +{ + return(chsize(fileno(fp),length)); +} + +void SMBCALL smb_rewind(FILE* fp) +{ + rewind(fp); +} + +void SMBCALL smb_clearerr(FILE* fp) +{ + clearerr(fp); +} + +long SMBCALL smb_fread(void HUGE16* buf, long bytes, FILE* fp) +{ +#ifdef __FLAT__ + return(fread(buf,1,bytes,fp)); +#else + long count; + + for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff) + if(fread((char*)buf,1,0x7fff,fp)!=0x7fff) + return(bytes-count); + if(fread((char*)buf,1,(size_t)count,fp)!=(size_t)count) + return(bytes-count); + return(bytes); +#endif +} + +long SMBCALL smb_fwrite(void HUGE16* buf, long bytes, FILE* fp) +{ +#ifdef __FLAT__ + return(fwrite(buf,1,bytes,fp)); +#else + long count; + + for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff) + if(fwrite((char*)buf,1,0x7fff,fp)!=0x7fff) + return(bytes-count); + if(fwrite((char*)buf,1,(size_t)count,fp)!=(size_t)count) + return(bytes-count); + return(bytes); +#endif +} + +/* End of SMBLIB.C */ diff --git a/goldlib/smblib/smblib.h b/goldlib/smblib/smblib.h new file mode 100644 index 0000000..6142c93 --- /dev/null +++ b/goldlib/smblib/smblib.h @@ -0,0 +1,218 @@ +/* smblib.h */ + +/* Synchronet message base (SMB) library function prototypes */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU General Public License for more details: gpl.txt or * + * http://www.fsf.org/copyleft/gpl.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +#ifndef _SMBLIB_H +#define _SMBLIB_H + +#include + +#ifdef SMBEXPORT + #undef SMBEXPORT +#endif + +#ifdef _WIN32 + #ifndef __FLAT__ + #define __FLAT__ + #endif + #ifdef __BORLANDC__ + #define SMBCALL __stdcall + #else + #define SMBCALL + #endif + #ifdef SMBDLL /* SMBLIB contained in DLL */ + #ifdef SMB_EXPORTS + #define SMBEXPORT __declspec( dllexport ) + #else + #define SMBEXPORT __declspec( dllimport ) + #endif + #else /* self-contained executable */ + #define SMBEXPORT + #endif +#elif defined __unix__ + #define SMBCALL + #define SMBEXPORT +#elif defined __FLAT__ + #define SMBCALL + #define SMBEXPORT _export +#else + #define SMBCALL + #define SMBEXPORT +#endif + +#include + +#define SMB_STACK_LEN 4 /* Max msg bases in smb_stack() */ +#define SMB_STACK_POP 0 /* Pop a msg base off of smb_stack() */ +#define SMB_STACK_PUSH 1 /* Push a msg base onto smb_stack() */ +#define SMB_STACK_XCHNG 2 /* Exchange msg base w/last pushed */ + +#define GETMSGTXT_TAILS 1 /* Get message tail(s) too */ + +#ifdef __cplusplus +extern "C" { +#endif + +SMBEXPORT int SMBCALL smb_ver(void); +SMBEXPORT char * SMBCALL smb_lib_ver(void); +SMBEXPORT int SMBCALL smb_open(smb_t* smb); +SMBEXPORT void SMBCALL smb_close(smb_t* smb); +SMBEXPORT int SMBCALL smb_open_da(smb_t* smb); +SMBEXPORT void SMBCALL smb_close_da(smb_t* smb); +SMBEXPORT int SMBCALL smb_open_ha(smb_t* smb); +SMBEXPORT void SMBCALL smb_close_ha(smb_t* smb); +SMBEXPORT int SMBCALL smb_create(smb_t* smb); +SMBEXPORT int SMBCALL smb_stack(smb_t* smb, int op); +SMBEXPORT int SMBCALL smb_trunchdr(smb_t* smb); +SMBEXPORT int SMBCALL smb_locksmbhdr(smb_t* smb); +SMBEXPORT int SMBCALL smb_getstatus(smb_t* smb); +SMBEXPORT int SMBCALL smb_putstatus(smb_t* smb); +SMBEXPORT int SMBCALL smb_unlocksmbhdr(smb_t* smb); +SMBEXPORT int SMBCALL smb_getmsgidx(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_getlastidx(smb_t* smb, idxrec_t *idx); +SMBEXPORT uint SMBCALL smb_getmsghdrlen(smbmsg_t* msg); +SMBEXPORT ulong SMBCALL smb_getmsgdatlen(smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_lockmsghdr(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_getmsghdr(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_unlockmsghdr(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_addcrc(smb_t* smb, ulong crc); +SMBEXPORT int SMBCALL smb_hfield(smbmsg_t* msg, ushort type, ushort length, void* data); +SMBEXPORT int SMBCALL smb_dfield(smbmsg_t* msg, ushort type, ulong length); +SMBEXPORT int SMBCALL smb_addmsghdr(smb_t* smb, smbmsg_t* msg,int storage); +SMBEXPORT int SMBCALL smb_putmsg(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_putmsgidx(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_putmsghdr(smb_t* smb, smbmsg_t* msg); +SMBEXPORT void SMBCALL smb_freemsgmem(smbmsg_t* msg); +SMBEXPORT ulong SMBCALL smb_hdrblocks(ulong length); +SMBEXPORT ulong SMBCALL smb_datblocks(ulong length); +SMBEXPORT long SMBCALL smb_allochdr(smb_t* smb, ulong length); +SMBEXPORT long SMBCALL smb_fallochdr(smb_t* smb, ulong length); +SMBEXPORT long SMBCALL smb_hallochdr(smb_t* smb); +SMBEXPORT long SMBCALL smb_allocdat(smb_t* smb, ulong length, ushort headers); +SMBEXPORT long SMBCALL smb_fallocdat(smb_t* smb, ulong length, ushort headers); +SMBEXPORT long SMBCALL smb_hallocdat(smb_t* smb); +SMBEXPORT int SMBCALL smb_incdat(smb_t* smb, ulong offset, ulong length, ushort headers); +SMBEXPORT int SMBCALL smb_freemsg(smb_t* smb, smbmsg_t* msg); +SMBEXPORT int SMBCALL smb_freemsgdat(smb_t* smb, ulong offset, ulong length, ushort headers); +SMBEXPORT int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length); +SMBEXPORT void SMBCALL smb_freemsgtxt(char HUGE16* buf); +SMBEXPORT int SMBCALL smb_copymsgmem(smbmsg_t* destmsg, smbmsg_t* srcmsg); +SMBEXPORT char HUGE16* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode); + +/* FILE pointer I/O functions */ + +SMBEXPORT int SMBCALL smb_feof(FILE* fp); +SMBEXPORT int SMBCALL smb_ferror(FILE* fp); +SMBEXPORT int SMBCALL smb_fflush(FILE* fp); +SMBEXPORT int SMBCALL smb_fgetc(FILE* fp); +SMBEXPORT int SMBCALL smb_fputc(int ch, FILE* fp); +SMBEXPORT int SMBCALL smb_fseek(FILE* fp, long offset, int whence); +SMBEXPORT long SMBCALL smb_ftell(FILE* fp); +SMBEXPORT long SMBCALL smb_fread(void HUGE16* buf, long bytes, FILE* fp); +SMBEXPORT long SMBCALL smb_fwrite(void HUGE16* buf, long bytes, FILE* fp); +SMBEXPORT long SMBCALL smb_fgetlength(FILE* fp); +SMBEXPORT int SMBCALL smb_fsetlength(FILE* fp, long length); +SMBEXPORT void SMBCALL smb_rewind(FILE* fp); +SMBEXPORT void SMBCALL smb_clearerr(FILE* fp); + +#ifdef __cplusplus +} +#endif + +#ifdef __WATCOMC__ /* Use MSC standard (prepended underscore) */ +#pragma aux smb_ver "_*" +#pragma aux smb_lib_ver "_*" +#pragma aux smb_open "_*" +#pragma aux smb_close "_*" +#pragma aux smb_open_da "_*" +#pragma aux smb_close_da "_*" +#pragma aux smb_open_ha "_*" +#pragma aux smb_close_ha "_*" +#pragma aux smb_create "_*" +#pragma aux smb_stack "_*" +#pragma aux smb_trunchdr "_*" +#pragma aux smb_locksmbhdr "_*" +#pragma aux smb_getstatus "_*" +#pragma aux smb_putstatus "_*" +#pragma aux smb_unlocksmbhdr "_*" +#pragma aux smb_getmsgidx "_*" +#pragma aux smb_getlastidx "_*" +#pragma aux smb_getmsghdrlen "_*" +#pragma aux smb_getmsgdatlen "_*" +#pragma aux smb_lockmsghdr "_*" +#pragma aux smb_getmsghdr "_*" +#pragma aux smb_unlockmsghdr "_*" +#pragma aux smb_addcrc "_*" +#pragma aux smb_hfield "_*" +#pragma aux smb_dfield "_*" +#pragma aux smb_addmsghdr "_*" +#pragma aux smb_putmsg "_*" +#pragma aux smb_putmsgidx "_*" +#pragma aux smb_putmsghdr "_*" +#pragma aux smb_freemsgmem "_*" +#pragma aux smb_hdrblocks "_*" +#pragma aux smb_datblocks "_*" +#pragma aux smb_allochdr "_*" +#pragma aux smb_fallochdr "_*" +#pragma aux smb_hallochdr "_*" +#pragma aux smb_allocdat "_*" +#pragma aux smb_fallocdat "_*" +#pragma aux smb_hallocdat "_*" +#pragma aux smb_incdat "_*" +#pragma aux smb_freemsg "_*" +#pragma aux smb_freemsgdat "_*" +#pragma aux smb_freemsghdr "_*" +#pragma aux smb_getmsgtxt "_*" +#pragma aux smb_freemsgtxt "_*" +#pragma aux smb_feof "_*" +#pragma aux smb_ferror "_*" +#pragma aux smb_fflush "_*" +#pragma aux smb_fgetc "_*" +#pragma aux smb_fputc "_*" +#pragma aux smb_fseek "_*" +#pragma aux smb_ftell "_*" +#pragma aux smb_fread "_*" +#pragma aux smb_fwrite "_*" +#pragma aux smb_fgetlength "_*" +#pragma aux smb_fsetlength "_*" +#pragma aux smb_rewind "_*" +#pragma aux smb_clearerr "_*" +#pragma aux lzh_encode "_*" +#pragma aux lzh_decode "_*" +#endif /* Watcom */ + + +#endif /* Don't add anything after this #endif statement */ diff --git a/goldlib/smblib/smbtxt.cpp b/goldlib/smblib/smbtxt.cpp new file mode 100644 index 0000000..5a033a2 --- /dev/null +++ b/goldlib/smblib/smbtxt.cpp @@ -0,0 +1,121 @@ +/* smbtxt.c */ + +/* Synchronet message base (SMB) message text library routines */ + +/* $Id$ */ + +/**************************************************************************** + * @format.tab-size 4 (Plain Text/Source Code File Header) * + * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * + * * + * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * See the GNU Lesser General Public License for more details: lgpl.txt or * + * http://www.fsf.org/copyleft/lesser.html * + * * + * Anonymous FTP access to the most recent released source is available at * + * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * + * * + * Anonymous CVS access to the development source and modification history * + * is available at cvs.synchro.net:/cvsroot/sbbs, example: * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login * + * (just hit return, no password is necessary) * + * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src * + * * + * For Synchronet coding style and modification guidelines, see * + * http://www.synchro.net/source.html * + * * + * You are encouraged to submit any modifications (preferably in Unix diff * + * format) via e-mail to mods@synchro.net * + * * + * Note: If this box doesn't appear square, then you need to fix your tabs. * + ****************************************************************************/ + +/* ANSI */ +#include + +/* SMB-specific */ +#include "smblib.h" + +char HUGE16* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode) +{ + char HUGE16* buf=NULL,HUGE16* lzhbuf,HUGE16* p; + ushort xlat; + int i,lzh; + long l=0,lzhlen,length; + + for(i=0;ihdr.total_dfields;i++) { + if(!(msg->dfield[i].type==TEXT_BODY + || (mode&GETMSGTXT_TAILS && msg->dfield[i].type==TEXT_TAIL)) + || msg->dfield[i].length<=2L) + continue; + fseek(smb->sdt_fp,msg->hdr.offset+msg->dfield[i].offset + ,SEEK_SET); + fread(&xlat,2,1,smb->sdt_fp); + lzh=0; + if(xlat==XLAT_LZH) { + lzh=1; + fread(&xlat,2,1,smb->sdt_fp); + } + if(xlat!=XLAT_NONE) /* no other translations currently supported */ + continue; + + length=msg->dfield[i].length-2L; + if(lzh) { + length-=2; + if(length<1) + continue; + if((lzhbuf=(char HUGE16 *)LMALLOC(length))==NULL) { + sprintf(smb->last_error + ,"malloc failure of %ld bytes for LZH buffer" + ,length); + return(buf); + } + smb_fread(lzhbuf,length,smb->sdt_fp); + lzhlen=*(long*)lzhbuf; + if((p=(char HUGE16 *)REALLOC(buf,l+lzhlen+3L))==NULL) { + sprintf(smb->last_error + ,"realloc failure of %ld bytes for text buffer" + ,l+lzhlen+3L); + FREE(lzhbuf); + return(buf); + } + buf=p; + lzh_decode((uchar*)lzhbuf,length,(uchar*)buf+l); + FREE(lzhbuf); + l+=lzhlen; + } + else { + if((p=(char HUGE16 *)REALLOC(buf,l+length+3L))==NULL) { + sprintf(smb->last_error + ,"realloc failure of %ld bytes for text buffer" + ,l+length+3L); + return(buf); + } + buf=p; + p=buf+l; + l+=fread(p,1,length,smb->sdt_fp); + } + if(!l) + continue; + l--; + while(l && buf[l]==0) l--; + l++; + *(buf+l)=CR; + l++; + *(buf+l)=LF; + l++; + *(buf+l)=0; + } + return(buf); +} + +void SMBCALL smb_freemsgtxt(char HUGE16* buf) +{ + if(buf!=NULL) + FREE(buf); +}