TIP: Click on subject to list as thread! ANSI
echo: public_domain
to: All
from: Paul Edwards
date: 1995-03-13 23:42:50
subject: reczm.c

/*********************************************************************/
/*                                                                   */
/*  This Program Written by Paul Edwards, 3:711/934{at}fidonet.         */
/*  Released to the Public Domain                                    */
/*                                                                   */
/*********************************************************************/
/*********************************************************************/
/*                                                                   */
/*  reczm - zmodem receive                                           */
/*  this program is designed to receive a file using zmodem          */
/*                                                                   */
/*********************************************************************/

#include 
#include 

#include 
#include 
#include 
#include 

#include 


void extModemClearInbound(void);
void extModemResponseSent(void);
void extModemGetBlock(void *buf, size_t max, size_t *actual);
void extModemRegisterBad(void);
void extModemRegisterGood(void);
void extModemGetBlockImm(void *buf, size_t max, size_t *actual);
void extModemWriteBlock(void *buf, size_t max);
void extFileSetInfo(unsigned char *filename, 
                    unsigned char *fileinfo,
                    long *offset,
                    int *skip);
void extFileWriteData(void *buf, size_t bytes);
void extFileFinish(void);


#define ZPAD 0x2a
#define ZDLE 0x18
#define ZBIN 0x41
#define ZHEX 0x42
#define ZBIN32 0x43
#define ZRQINIT 0x00
#define ZRINIT 0x01
#define CANFDX 0x01
#define CANOVIO 0x02
#define ZFILE 0x04
#define ZCRCW 0x6b
#define ZRPOS 0x09
#define ZDATA 0x0a
#define ZCRCG 0x69
#define ZEOF 0x0b
#define ZFIN 0x08

static char hexdigit[] = "0123456789abcdef";

void receiveZmodem(void);
static void receiveFile(void);
static void receiveData(void);
static int posMatch(void);
static void getData(void);
static void getData16(void);
static void getData32(void);
static void getFileData(void);
static void getZMHeader(void);
static void getHexHeader(void);
static void getBinaryHeader(void);
static void getBin32Header(void);
static void getNextHexCh(void);
static void getNextDLECh(void);
static void getNextCh(void);
static void sendHeader(void);
static void sendHexHeader(void);
static void sendBinHeader(void);
static void sendBin32Header(void);
static void sendChar(void);
static void sendDLEChar(void);
static void sendHexChar(void);
static void sendZRINIT(void);
static void sendZRPOS(void);
static void sendZFIN(void);
static void getOO(void);

#define ZMODEM_INIT "ZMD001 Remote didn't accept my ZRINIT\n"
#define ZMODEM_POS "ZMD002 Remote failed to respond to my ZRPOS\n"
#define ZMODEM_ZDATA "ZMD003 Remote failed to sync to correct position\n"
#define ZMODEM_CRCXM "ZMD004 CRCXM error, ours = %x, theirs = %x\n"
#define ZMODEM_LONGSP "ZMD005 Error - subpacket too long\n"
#define ZMODEM_CRC32 "ZMD006 CRC32 error - ours = %lx, theirs = %lx\n"
#define ZMODEM_FILEDATA "ZMD007 File Data is out of spec\n"            
#define ZMODEM_BADHEX "ZMD008 Bad hex character %x received\n"
#define ZMODEM_TIMEOUT "ZMD009 Timeout\n"

#define MAXBUF 18000

static PDCOMM pdcomm;
static FILE *fq;

static unsigned char frameType;
static unsigned char headerType;
static unsigned char headerData[4];
static unsigned char recBuf[MAXBUF];
static unsigned char *bufPos;
static unsigned char *bufTop;
static int ch;
static int moreData;
static int gotSpecial;
static long goodOffset;
static unsigned char *fileName;
static unsigned char *fileInfo;
static int skip;
static int gotHeader;

int main(void)
{
    errorDefaults();
    errorInit();
    if (ALLOK)
    {
        pdcommInit(&pdcomm);
        pdcommOpen(&pdcomm, "COM2", 19200L);
        if (ALLOK)
        {
            receiveZmodem();
        }
        pdcommClose(&pdcomm);
        pdcommTerm(&pdcomm);
    }
    errorTerm();
    return (0);
}

void receiveZmodem(void)
{
    int fin, quit, tries;

    bufTop = recBuf + sizeof recBuf;    
    extModemClearInbound();   
    sendZRINIT();           
    fin = 0;
    while (ALLOK && !fin)
    {
        quit = 0;
        tries = 0;
        while (ALLOK && !quit)
        {
            getZMHeader();
            if (ALLOK)
            {
                if (headerType == ZFIN)
                {
                    sendZFIN();
                    extModemRegisterGood();
                    getOO();
                    quit = 1;
                    fin = 1;
                }
                else if (headerType == ZRQINIT)
                {    
                    if (tries < 10)
                    {
                        sendZRINIT();
                        tries++;
                    }
                    else
                    {
                        errorSet(ZMODEM_INIT);
                    }
                }
                else if (headerType == ZFILE)
                {
                    extModemRegisterGood();
                    getFileData();
                    if (ALLOK)
                    {
                        receiveFile();
                        quit = 1;
                    }
                }
            }
            else
            {
                if (errorCompare(ZMODEM_TIMEOUT))
                {
                    if (tries < 10)
                    {
                        errorClear();
                        sendZRINIT();
                        tries++;
                    }
                }
            }
        }
    }
    return;
}

static void receiveFile(void)
{
    int quit;
    int tries;
    
    skip = 0;
    goodOffset = 0;
    extFileSetInfo(fileName, fileInfo, &goodOffset, &skip);
    sendZRPOS();
    quit = 0;
    tries = 0;
    while (ALLOK && !quit)
    {
        getZMHeader();
        if (ALLOK)
        {
            if (headerType == ZFILE)
            {
                sendZRPOS();
                if (tries < 10)
                {
                    sendZRPOS();
                    tries++;
                }
                else
                {
                    errorSet(ZMODEM_POS);
                }
            }
            else if (headerType == ZDATA)
            {
                extModemRegisterGood();
                receiveData();
                quit = 1;
            }
        }
        else
        {
            if (errorCompare(ZMODEM_TIMEOUT) 
                || errorCompare(ZMODEM_CRCXM)
                || errorCompare(ZMODEM_CRC32))
            {
                if (tries < 10)
                {
                    errorFlush();
                    sendZRPOS();
                    tries++;
                }
            }
        }
    }
    return;
}
    
static void receiveData(void)
{
    int quit;
    int tries;
    
    quit = 0;
    tries = 0;
    moreData = 1;
    while (ALLOK && !quit)
    {
        if (moreData)
        {
            getData();
            if (ALLOK)
            {
                extFileWriteData(recBuf, (size_t)(bufPos - recBuf));
                tries = 0;
            }
        }
        else
        {
            getZMHeader();
            if (ALLOK)
            {
                if (headerType == ZDATA)
                {
                    if (!posMatch())
                    {
                        if (tries < 10)
                        {
                            sendZRPOS();
                            tries++;
                        }
                        else
                        {
                            errorSet(ZMODEM_ZDATA);
                        }
                    }
                    else
                    {
                        extModemRegisterGood();
                        moreData = 1;
                    }
                }
                else if (headerType == ZEOF)
                {
                    if (posMatch())
                    {
                        extModemRegisterGood();
                        extFileFinish();
                        quit = 1;
                    }
                }
            }
        }
        if (!ALLOK)
        {
            if (errorCompare(ZMODEM_TIMEOUT)
                || errorCompare(ZMODEM_LONGSP))
            {
                if (tries < 10)
                {
                    errorClear();
                    sendZRPOS();
                    tries++;
                }
            }
        }
    }
    return;
}

static int posMatch(void)
{
    long templ;
    int ret;
    
    templ = headerData[3];
    templ = (templ << 8) | headerData[2];
    templ = (templ << 8) | headerData[1];
    templ = (templ << 8) | headerData[0];
    if (templ == goodOffset)
    {
        ret = 1;
    }
    else
    {
        ret = 0;
    }
    return (ret);
}

static void getData(void)
{
    if (frameType == ZBIN32)
    {
        getData32();
    }
    else
    {
        getData16();
    }
    if (!ALLOK)
    {
        moreData = 0;
    }
    else
    {
        extModemRegisterGood();
    }
    return;
}

static void getData16(void)
{
    int quit;
    crcxm crc;
    unsigned int theirCRC;
    
    bufPos = recBuf;
    quit = 0;
    crcxm_init(crc);
    while (ALLOK && (bufPos < bufTop) && !quit)
    {
        getNextDLECh();
        if (ALLOK)
        {
            if (gotSpecial)
            {
                if (ch != ZCRCG)
                {
                    moreData = 0;
                }
                crcxm_update(crc, ch);
                getNextDLECh();
                if (ALLOK)
                {
                    theirCRC = ch;
                    getNextDLECh();
                }
                if (ALLOK)
                {
                    theirCRC = (theirCRC << 8) | ch;
                    if (crcxm_value(crc) != theirCRC)
                    {
                        errorSet(ZMODEM_CRCXM, 
                                 crcxm_value(crc), 
                                 theirCRC);
                    }
                    else
                    {
                        goodOffset += (bufPos - recBuf);
                        quit = 1;
                    }
                }
            }
            else
            {
                crcxm_update(crc, ch);
                *bufPos = (unsigned char)ch;
                bufPos++;
            }
        }
    }
    if (bufPos == bufTop)
    {
        errorSet(ZMODEM_LONGSP);
    }
    return;
}

static void getData32(void)
{
    int quit;
    crc32 crc;
    unsigned long theirCRC;
    
    bufPos = recBuf;
    quit = 0;
    crc32_init(crc);
    while (ALLOK && (bufPos < bufTop) && !quit)
    {
        getNextDLECh();
        if (ALLOK)
        {
            if (gotSpecial)
            {
                if (ch != ZCRCG)
                {
                    moreData = 0;
                }
                crc32_update(crc, ch);
                getNextDLECh();
                if (ALLOK)
                {
                    theirCRC = ch;
                    getNextDLECh();
                }
                if (ALLOK)
                {
                    theirCRC = (theirCRC << 8) | ch;
                    getNextDLECh();
                }
                if (ALLOK)
                {
                    theirCRC = (theirCRC << 8) | ch;
                    getNextDLECh();
                }
                if (ALLOK)
                {
                    theirCRC = (theirCRC << 8) | ch;
                    if (crc32_value(crc) != theirCRC)
                    {
                        errorSet(ZMODEM_CRC32,
                                 crc32_value(crc), 
                                 theirCRC);
                    }
                    else
                    {
                        quit = 1;
                    }
                }
            }
            else
            {
                crc32_update(crc, ch);
                *bufPos = (unsigned char)ch;
                bufPos++;
            }
        }
    }
    if (bufPos == bufTop)
    {
        errorSet(ZMODEM_LONGSP);
    }
    return;
}

static void getFileData(void)
{
    unsigned char *pos;
    int problem;
    
    getData();
    if (ALLOK)
    {
        problem = 1;
        fileName = recBuf;
        pos = memchr(recBuf, '\0', sizeof recBuf - 1);
        if (pos != NULL)
        {
            pos++;
            fileInfo = pos;
            pos = memchr(pos, '\0', sizeof recBuf - (pos - recBuf));
            if (pos != NULL)
            {
                if ((pos - recBuf) < 1024)
                {
                    problem = 0;
                }
            }        
        }
        if (problem)
        {
            errorSet(ZMODEM_FILEDATA);
        }
    }
    return;
}

static void getZMHeader(void)
{
    int count;
    
    gotHeader = 0;
    getNextCh();
    while (ALLOK && !gotHeader)
    {
        while (ALLOK && (ch != ZPAD))
        {
            extModemRegisterBad();
            getNextCh();
        }
        if (ALLOK)
        {
            count = 1;
            getNextCh();
            while (ALLOK && (ch == ZPAD))
            {
                count++;
                if (count > 2)
                {
                    extModemRegisterBad();
                }
                getNextCh(); 
            }
            if (ALLOK && (ch == ZDLE))
            {
                getNextCh();
                if (ALLOK)
                {
                    if (ch == ZBIN)
                    {
                        frameType = ZBIN;
                        getBinaryHeader();
                    }
                    else if (ch == ZBIN32)
                    {
                        frameType = ZBIN32;
                        getBin32Header();
                    }
                    else if ((ch == ZHEX) && (count >= 2))
                    {
                        frameType = ZHEX;
                        getHexHeader();
                    }
                }
            }
        }
    }
    return;
}

static void getHexHeader(void)
{
    crcxm crc;
    unsigned int theirCRC;
    
    getNextHexCh();
    while (ALLOK && !gotHeader)
    {
        crcxm_init(crc);
        headerType = (unsigned char)ch;
        crcxm_update(crc, ch);
        getNextHexCh();
        if (ALLOK)
        {
            headerData[0] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextHexCh();
        }
        if (ALLOK)
        {
            headerData[1] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextHexCh();
        }
        if (ALLOK)
        {
            headerData[2] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextHexCh();
        }
        if (ALLOK)
        {
            headerData[3] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextHexCh();
        }
        if (ALLOK)
        {
            theirCRC = ch;
            getNextHexCh();
        }
        if (ALLOK)
        {
            theirCRC = (theirCRC << 8) | ch;
            if (crcxm_value(crc) != theirCRC)
            {
                errorSet(ZMODEM_CRCXM, crcxm_value(crc), theirCRC);
            }
            else
            {
                gotHeader = 1;
            }
        }
    }
    return;
}

static void getBinaryHeader(void)
{
    crcxm crc;
    unsigned int theirCRC;

    getNextDLECh();
    while (ALLOK && !gotHeader)
    {
        crcxm_init(crc);
        headerType = (unsigned char)ch;
        crcxm_update(crc, ch);
        getNextDLECh();
        if (ALLOK)
        {
            headerData[0] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            headerData[1] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            headerData[2] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            headerData[3] = (unsigned char)ch;
            crcxm_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            theirCRC = ch;
            getNextDLECh();
        }
        if (ALLOK)
        {
            theirCRC = (theirCRC << 8) | ch;
            if (crcxm_value(crc) != theirCRC)
            {
                errorSet(ZMODEM_CRCXM, crcxm_value(crc), theirCRC);
            }
            else
            {
                gotHeader = 1;
            }
        }
    }
    return;
}

static void getBin32Header(void)
{
    crc32 crc;
    unsigned long theirCRC;
    
    getNextDLECh();
    while (ALLOK && !gotHeader)
    {
        crc32_init(crc);
        headerType = (unsigned char)ch;
        crc32_update(crc, ch);
        getNextDLECh();
        if (ALLOK)
        {
            headerData[0] = (unsigned char)ch;
            crc32_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            headerData[1] = (unsigned char)ch;
            crc32_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            headerData[2] = (unsigned char)ch;
            crc32_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            headerData[3] = (unsigned char)ch;
            crc32_update(crc, ch);
            getNextDLECh();
        }
        if (ALLOK)
        {
            theirCRC = ch;
            getNextDLECh();
        }
        if (ALLOK)
        {
            theirCRC = (theirCRC << 8) | ch;
            getNextDLECh();
        }
        if (ALLOK)
        {
            theirCRC = (theirCRC << 8) | ch;
            getNextDLECh();
        }
        if (ALLOK)
        {
            theirCRC = (theirCRC << 8) | ch;
            getNextDLECh();
        }
        if (ALLOK)
        {
            if (crc32_value(crc) != theirCRC)
            {
                errorSet(ZMODEM_CRC32, crc32_value(crc), theirCRC);
            }
            else
            {
                gotHeader = 1;
            }
        }
    }
    return;
}

static void getNextHexCh(void)
{
    int tempCh;
    
    getNextCh();
    if (ALLOK)
    { 
        if ((ch = 0x30))
        {
            tempCh = (ch - 0x30);
        }
        else if ((ch >= 0x61) && (ch <= 0x66))
        {
            tempCh = (ch - 0x61) + 0x0a;
        }
        else 
        {
            errorSet(ZMODEM_BADHEX, ch);
        }
        if (ALLOK)
        {
            getNextCh();
        }
        if (ALLOK)
        {
            tempCh = tempCh << 4;
            if ((ch = 0x30))
            {
                ch = (ch - 0x30);
            }
            else if ((ch >= 0x61) && (ch <= 0x66))
            {
                ch = (ch - 0x61) + 0x0a;
            }
            else
            {
                errorSet(ZMODEM_BADHEX, ch);
            }
        }
        if (ALLOK)
        {
            ch = ch | tempCh;
        }
    }
    return;
}

static void getNextDLECh(void)
{
    gotSpecial = 0;
    getNextCh();
    if (ALLOK)
    {
        if (ch == ZDLE)
        {
            getNextCh();
            if (ALLOK)
            {
                if (((ch & 0x40) != 0) && ((ch & 0x20) == 0))
                {
                    ch &= 0xbf;
                    gotSpecial = 0;
                }
                else
                {
                    gotSpecial = 1;
                }
            }
        }
    }
    return;
}

static void getNextCh(void)
{
    unsigned char buf[1];
    size_t actual;
    
    extModemGetBlock(buf, 1, &actual);
    if (ALLOK && (actual == 1))
    {
        ch = buf[0];
    }
    return;
}

static void sendHeader(void)
{
    if (frameType == ZHEX)
    {
        sendHexHeader();
    }
    else if (frameType == ZBIN)
    {
        sendBinHeader();
    }
    else if (frameType == ZBIN32)
    {
        sendBin32Header();
    }
    if (ALLOK)
    {
        extModemResponseSent();
    }
    return;
}

static void sendHexHeader(void)
{
    crcxm crc;

    crcxm_init(crc);    
    ch = ZPAD;
    sendChar();
    if (ALLOK)
    {
        sendChar();
    }
    if (ALLOK)
    {
        ch = ZDLE;
        sendChar();
    }
    if (ALLOK)
    {
        ch = frameType;
        sendChar();
    }
    if (ALLOK)
    {
        ch = headerType;
        crcxm_update(crc, ch);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = headerData[0];
        crcxm_update(crc, ch);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = headerData[1];
        crcxm_update(crc, ch);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = headerData[2];
        crcxm_update(crc, ch);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = headerData[3];
        crcxm_update(crc, ch);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = crcxm_highbyte(crc);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = crcxm_lowbyte(crc);
        sendHexChar();
    }
    if (ALLOK)
    {
        ch = 0x0d;
        sendChar();
    }
    if (ALLOK)
    {
        ch = 0x0a;
        sendChar();
    }
    if (ALLOK)
    {
        ch = 0x11;
        sendChar();
    }
    return;
}    

static void sendBinHeader(void)
{
    crcxm crc;

    crcxm_init(crc);    
    ch = ZPAD;
    sendChar();
    if (ALLOK)
    {
        ch = ZDLE;
        sendChar();
    }
    if (ALLOK)
    {
        ch = frameType;
        sendChar();
    }
    if (ALLOK)
    {
        ch = headerType;
        crcxm_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[0];
        crcxm_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[1];
        crcxm_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[2];
        crcxm_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[3];
        crcxm_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = crcxm_highbyte(crc);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = crcxm_lowbyte(crc);
        sendDLEChar();
    }
    return;
}    

static void sendBin32Header(void)
{
    crc32 crc;

    crc32_init(crc);    
    ch = ZPAD;
    sendChar();
    if (ALLOK)
    {
        ch = ZDLE;
        sendChar();
    }
    if (ALLOK)
    {
        ch = frameType;
        sendChar();
    }
    if (ALLOK)
    {
        ch = headerType;
        crc32_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[0];
        crc32_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[1];
        crc32_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[2];
        crc32_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = headerData[3];
        crc32_update(crc, ch);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = crc32_byte1(crc);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = crc32_byte2(crc);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = crc32_byte3(crc);
        sendDLEChar();
    }
    if (ALLOK)
    {
        ch = crc32_byte4(crc);
        sendDLEChar();
    }
    return;
}    

static void sendChar(void)
{
    unsigned char buf[1];
    
    buf[0] = (unsigned char)ch;
    extModemWriteBlock(buf, 1);
    return;
}

static void sendDLEChar(void)
{
    int tempCh;
    
    if ((ch == ZDLE) || (ch == 0x10) || (ch == 0x11) || (ch == 0x13)
        || (ch == 0x50) || (ch == 0x51) || (ch == 0x53))
    {
        tempCh = ch;
        ch = ZDLE;
        sendChar();
        if (ALLOK)
        {
            ch = tempCh;
            ch |= 0x40;
            sendChar();
        }
    }
    else
    {
        sendChar();
    }
    return;
}

static void sendHexChar(void)
{
    int tempCh;
    
    tempCh = ch;
    ch = hexdigit[(tempCh >> 4) & 0x0f];
    sendChar();
    if (ALLOK)
    {
        ch = hexdigit[tempCh & 0x0f];
        sendChar();
    }
    return;
}
                         
static void sendZRINIT(void)
{
    frameType = ZHEX;
    headerType = ZRINIT;
    headerData[0] = 0x00;
    headerData[1] = 0x00;
    headerData[2] = 0x00;
    headerData[3] = 0x03;
    sendHeader();
    return;
}

static void sendZRPOS(void)
{
    long templ;
    
    frameType = ZHEX;
    headerType = ZRPOS;
    templ = goodOffset;
    headerData[0] = (unsigned char)(templ & 0xff);
    templ = templ >> 8;
    headerData[1] = (unsigned char)(templ & 0xff);
    templ = templ >> 8;
    headerData[2] = (unsigned char)(templ & 0xff);
    templ = templ >> 8;
    headerData[3] = (unsigned char)(templ & 0xff);
    sendHeader();
    return;
}

static void sendZFIN(void)
{
    frameType = ZHEX;
    headerType = ZFIN;
    headerData[0] = 0x00;
    headerData[1] = 0x00;
    headerData[2] = 0x00;
    headerData[3] = 0x00;
    sendHeader();
    return;
}

static void getOO(void)
{
    getNextCh();
    if (ALLOK)
    {
        getNextCh();
    }
    if (!ALLOK && errorCompare(ZMODEM_TIMEOUT))
    {
        errorClear();
    }
    return;
}

void extModemClearInbound(void)
{
    return;
}

void extModemResponseSent(void)
{
    return;
}

void extModemGetBlock(void *buf, size_t max, size_t *actual)
{
    int x;
    
    x = pdcommRecBuf(&pdcomm, buf, max);
    if (x == 0)
    {
        DosSleep(1000);
        x = pdcommRecBuf(&pdcomm, buf, max);
    }
    if (x == 0)
    {
        errorSet(ZMODEM_TIMEOUT);
    }
    *actual = x;
    return;
}

void extModemRegisterBad(void)
{
    return;
}

void extModemRegisterGood(void)
{
    return;
}

void extModemGetBlockImm(void *buf, size_t max, size_t *actual)
{
    int x;
    
    x = pdcommRecBuf(&pdcomm, buf, max);
    *actual = x;
    return;
}

void extModemWriteBlock(void *buf, size_t max)
{
    pdcommTxBuf(&pdcomm, buf, max);
    return;
}
   
void extFileSetInfo(unsigned char *filename, 
                    unsigned char *fileinfo,
                    long *offset,
                    int *skip)
{
    (void)fileinfo;
    printf("opening file %s\n", filename);
    fq = fopen((char *)filename, "wb");
    if (fq == NULL)
    {
        printf("failed to open file %s\n", filename);
    }
    *offset = 0;
    *skip = 0;
    return;
}

void extFileWriteData(void *buf, size_t bytes)
{
    fwrite(buf, bytes, 1, fq);
    return;
}

void extFileFinish(void)
{
    printf("closing file\n");
    fclose(fq);
    return;
}
@EOT:

---
* Origin: This is just another kludge line like SEENBY (3:711/934.9)

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.