Annotation of sbbs/sbbs3/zmodem.c, revision 1.1

1.1     ! root        1: /* zmodem.c */
        !             2: 
        !             3: /* Synchronet ZMODEM Functions */
        !             4: 
        !             5: /* $Id: zmodem.c,v 1.4 2003/09/18 03:43:44 rswindell Exp $ */
        !             6: 
        !             7: /******************************************************************************/
        !             8: /* Project : Unite!       File : zmodem general        Version : 1.02         */
        !             9: /*                                                                            */
        !            10: /* (C) Mattheij Computer Service 1994                                         */
        !            11: /*                                                                            */
        !            12: /* contact us through (in order of preference)                                */
        !            13: /*                                                                            */
        !            14: /*   email:          [email protected]                                      */
        !            15: /*   mail:           MCS                                                      */
        !            16: /*                   Prinses Beatrixlaan 535                                  */
        !            17: /*                   2284 AT  RIJSWIJK                                        */
        !            18: /*                   The Netherlands                                          */
        !            19: /*   voice phone:    31+070-3936926                                           */
        !            20: /******************************************************************************/
        !            21: 
        !            22: #if 0
        !            23: 
        !            24: /****************************************/
        !            25: /* Zmodem specific functions start here */
        !            26: /****************************************/
        !            27: 
        !            28: 
        !            29: /***********************/
        !            30: /* Output a hex header */
        !            31: /***********************/
        !            32: void putzhhdr(char type)
        !            33: {
        !            34:        uint i;
        !            35:        ushort crc=0;
        !            36: 
        !            37:        putcom(ZPAD);
        !            38:        putcom(ZPAD);
        !            39:        putcom(ZDLE);
        !            40:        if(zmode&VAR_HDRS) {
        !            41:                putcom(ZVHEX);
        !            42:                putzhex(4)        !            43:        }
        !            44:        else
        !            45:                putcom(ZHEX);
        !            46:        putzhex(type);
        !            47: //     crc=ucrc16(type,crc);
        !            48:        for(i=0;i<4;i++) {
        !            49:                putzhex(Txhdr[i]);
        !            50:                crc=ucrc16(Txhdr[i],crc); 
        !            51:        }
        !            52: //     crc=ucrc16(0,crc);
        !            53: //     crc=ucrc16(0,crc);
        !            54:        putzhex(crc>>8);
        !            55:        putzhex(crc&0xff);
        !            56:        putcom(CR);
        !            57:        putcom(LF);     /* Chuck's RZ.C sends LF|0x80 for some unknown reason */
        !            58:        if(type!=ZFIN && type!=ZACK)
        !            59:                putcom(XON);
        !            60: }
        !            61: 
        !            62: /****************************************************************************/
        !            63: /* Stores a long in the Zmodem transmit header (usually position offset)       */
        !            64: /****************************************************************************/
        !            65: void ltohdr(long l)
        !            66: {
        !            67: 
        !            68:        Txhdr[ZP0] = l;
        !            69:        Txhdr[ZP1] = l>>8;
        !            70:        Txhdr[ZP2] = l>>16;
        !            71:        Txhdr[ZP3] = l>>24;
        !            72: }
        !            73: 
        !            74: /*
        !            75:  * Read a byte, checking for ZMODEM escape encoding
        !            76:  *  including CAN*5 which represents a quick abort
        !            77:  */
        !            78: int getzcom()
        !            79: {
        !            80:        int i;
        !            81: 
        !            82:        while(1) {
        !            83:                /* Quick check for non control characters */
        !            84:                if((i=getcom(Rxtimeout))&0x60)
        !            85:                        return(i);
        !            86:                if(i==ZDLE)
        !            87:                        break;
        !            88:                if((i&0x7f)==XOFF || (i&0x7f)==XON)
        !            89:                        continue;
        !            90:                if(zmode&CTRL_ESC && !(i&0x60))
        !            91:                        continue;
        !            92:                return(i); 
        !            93:        }
        !            94: 
        !            95:        while(1) {      /* Escaped characters */
        !            96:                if((i=getcom(Rxtimeout))<0)
        !            97:                        return(i);
        !            98:                if(i==CAN && (i=getcom(Rxtimeout))<0)
        !            99:                        return(i);
        !           100:                if(i==CAN && (i=getcom(Rxtimeout))<0)
        !           101:                        return(i);
        !           102:                if(i==CAN && (i=getcom(Rxtimeout))<0)
        !           103:                        return(i);
        !           104:                switch (i) {
        !           105:                        case CAN:
        !           106:                                return(GOTCAN);
        !           107:                        case ZCRCE:
        !           108:                        case ZCRCG:
        !           109:                        case ZCRCQ:
        !           110:                        case ZCRCW:
        !           111:                                return(i|GOTOR);
        !           112:                        case ZRUB0:
        !           113:                                return(0x7f);
        !           114:                        case ZRUB1:
        !           115:                                return(0xff);
        !           116:                        case XON:
        !           117:                        case XON|0x80:
        !           118:                        case XOFF:
        !           119:                        case XOFF|0x80:
        !           120:                                continue;
        !           121:                        default:
        !           122:                                if (zmode&CTRL_ESC && !(i&0x60))
        !           123:                                        continue;
        !           124:                                if ((i&0x60)==0x40)
        !           125:                                        return(i^0x40);
        !           126:                                break; 
        !           127:                }
        !           128:                break; 
        !           129:        }
        !           130:        return(ERROR);
        !           131: }
        !           132: 
        !           133: 
        !           134: 
        !           135: /*
        !           136:  * Read a character from the modem line with timeout.
        !           137:  *  Eat parity, XON and XOFF characters.
        !           138:  */
        !           139: int getcom7()
        !           140: {
        !           141:        int i;
        !           142: 
        !           143:        while(1) {
        !           144:                i=getcom(10);
        !           145:                switch(i) {
        !           146:                        case XON:
        !           147:                        case XOFF:
        !           148:                                continue;
        !           149:                        case CR:
        !           150:                        case LF:
        !           151:                        case NOINP:
        !           152:                        case ZDLE:
        !           153:                                return(i);
        !           154:                        default:
        !           155:                                if(!(i&0x60) && zmode&CTRL_ESC)
        !           156:                                        continue;
        !           157:                                return(i); 
        !           158:                } 
        !           159:        }
        !           160: }
        !           161: 
        !           162: #endif
        !           163: 
        !           164: /*
        !           165:  * zmodem primitives and other code common to zmtx and zmrx
        !           166:  */
        !           167: 
        !           168: #include <stdio.h>
        !           169: #include <sys/stat.h>  /* struct stat */
        !           170: 
        !           171: #include "sexyz.h"
        !           172: #include "genwrap.h"
        !           173: #include "sockwrap.h"
        !           174: 
        !           175: #include "zmodem.h"
        !           176: #include "crc16.h"
        !           177: #include "crc32.h"
        !           178: 
        !           179: #define ENDOFFRAME 2
        !           180: #define FRAMEOK    1
        !           181: #define TIMEOUT   -1   /* rx routine did not receive a character within timeout */
        !           182: #define INVHDR    -2   /* invalid header received; but within timeout */
        !           183: #define INVDATA   -3   /* invalid data subpacket received */
        !           184: #define ZDLEESC 0x8000 /* one of ZCRCE; ZCRCG; ZCRCQ or ZCRCW was received; ZDLE escaped */
        !           185: 
        !           186: #define HDRLEN     5   /* size of a zmodem header */
        !           187: 
        !           188: 
        !           189: int opt_v = TRUE;              /* show progress output */
        !           190: int opt_d = TRUE;              /* show debug output */
        !           191: 
        !           192: /*
        !           193:  * read bytes as long as rdchk indicates that
        !           194:  * more data is available.
        !           195:  */
        !           196: 
        !           197: void
        !           198: zmodem_rx_purge(zmodem_t* zm)
        !           199: {
        !           200:        while(recv_byte(zm->sock,0,zm->mode)<=0xff);
        !           201: }
        !           202: 
        !           203: /* 
        !           204:  * transmit a character. 
        !           205:  * this is the raw modem interface
        !           206:  */
        !           207: 
        !           208: void
        !           209: zmodem_tx_raw(zmodem_t* zm, unsigned char ch)
        !           210: {
        !           211: 
        !           212: #if 0 /* def _DEBUG */
        !           213:        if (zm->raw_trace) {
        !           214:                fprintf(zm->statfp,"%02x ",ch);
        !           215:        }
        !           216: #endif
        !           217: 
        !           218:        if(send_byte(zm->sock,ch,10,zm->mode))
        !           219:                fprintf(zm->errfp,"!Send error: %u\n",ERROR_VALUE);
        !           220: 
        !           221:        zm->last_sent = ch;
        !           222: }
        !           223: 
        !           224: /*
        !           225:  * transmit a character ZDLE escaped
        !           226:  */
        !           227: 
        !           228: void
        !           229: zmodem_tx_esc(zmodem_t* zm, unsigned char c)
        !           230: {
        !           231:        zmodem_tx_raw(zm, ZDLE);
        !           232:        /*
        !           233:         * exclusive or; not an or so ZDLE becomes ZDLEE
        !           234:         */
        !           235:        zmodem_tx_raw(zm, (uchar)(c ^ 0x40));
        !           236: }
        !           237: 
        !           238: /*
        !           239:  * transmit a character; ZDLE escaping if appropriate
        !           240:  */
        !           241: 
        !           242: #if 0
        !           243: /****************************************************************************/
        !           244: /* Outputs single Zmodem character, escaping with ZDLE when appropriate     */
        !           245: /****************************************************************************/
        !           246: void putzcom(uchar ch)
        !           247: {
        !           248:     static lastsent;
        !           249: 
        !           250:        if(ch&0x60) /* not a control char */
        !           251:                putcom(lastsent=ch);
        !           252:        else
        !           253:                switch(ch) {
        !           254:                        case DLE:
        !           255:                        case DLE|0x80:          /* even if high-bit set */
        !           256:                        case XON:
        !           257:                        case XON|0x80:
        !           258:                        case XOFF:
        !           259:                        case XOFF|0x80:
        !           260:                        case ZDLE:
        !           261:                                putcom(ZDLE);
        !           262:                                ch^=0x40;
        !           263:                                putcom(lastsent=ch);
        !           264:                                break;
        !           265:                        case CR:
        !           266:                        case CR|0x80:
        !           267:                                if(!(zmode&CTRL_ESC) && (lastsent&0x7f)!='@')
        !           268:                                        putcom(lastsent=ch);
        !           269:                                else {
        !           270:                                        putcom(ZDLE);
        !           271:                                        ch^=0x40;
        !           272:                                        putcom(lastsent=ch); 
        !           273:                                }
        !           274:                                break;
        !           275:                        default:
        !           276:                                if(zmode&CTRL_ESC && !(ch&0x60)) {  /* it's a ctrl char */
        !           277:                                        putcom(ZDLE);
        !           278:                                        ch^=0x40; 
        !           279:                                }
        !           280:                                putcom(lastsent=ch);
        !           281:                                break; 
        !           282:                }
        !           283: }
        !           284: #endif
        !           285: 
        !           286: void
        !           287: zmodem_tx(zmodem_t* zm, unsigned char c)
        !           288: {
        !           289:        switch (c) {
        !           290:                case DLE:
        !           291:                case DLE|0x80:          /* even if high-bit set */
        !           292:                case XON:
        !           293:                case XON|0x80:
        !           294:                case XOFF:
        !           295:                case XOFF|0x80:
        !           296:                case ZDLE:
        !           297:                        zmodem_tx_esc(zm, c);
        !           298:                        return;
        !           299:                case CR:
        !           300:                case CR|0x80:
        !           301:                        if (zm->escape_all_control_characters && (zm->last_sent&0x7f) == '@') {
        !           302:                                zmodem_tx_esc(zm, c);
        !           303:                                return;
        !           304:                        }
        !           305:                        break;
        !           306:                default:
        !           307:                        if (zm->escape_all_control_characters && (c&0x60)==0) {
        !           308:                                zmodem_tx_esc(zm, c);
        !           309:                                return;
        !           310:                        }
        !           311:                        break;
        !           312:        }
        !           313:        /*
        !           314:         * anything that ends here is so normal we might as well transmit it.
        !           315:         */
        !           316:        zmodem_tx_raw(zm, c);
        !           317: }
        !           318: 
        !           319: /**********************************************/
        !           320: /* Output single byte as two hex ASCII digits */
        !           321: /**********************************************/
        !           322: void
        !           323: zmodem_tx_hex(zmodem_t* zm, char val)
        !           324: {
        !           325:        char* xdigit="0123456789abcdef";
        !           326: 
        !           327:        zmodem_tx_raw(zm, xdigit[val>>4]);
        !           328:        zmodem_tx_raw(zm, xdigit[val&0xf]);
        !           329: }
        !           330: 
        !           331: /* 
        !           332:  * transmit a hex header.
        !           333:  * these routines use tx_raw because we're sure that all the
        !           334:  * characters are not to be escaped.
        !           335:  */
        !           336: void
        !           337: zmodem_tx_hex_header(zmodem_t* zm, unsigned char * p)
        !           338: {
        !           339:        int i;
        !           340:        unsigned short int crc;
        !           341: 
        !           342: #if 0 /* def _DEBUG */
        !           343:        fprintf(zm->statfp,"tx_hheader : ");
        !           344: #endif
        !           345: 
        !           346:        zmodem_tx_raw(zm, ZPAD);
        !           347:        zmodem_tx_raw(zm, ZPAD);
        !           348:        zmodem_tx_raw(zm, ZDLE);
        !           349: 
        !           350:        if (zm->use_variable_headers) {
        !           351:                zmodem_tx_raw(zm, ZVHEX);
        !           352:                zmodem_tx_hex(zm, HDRLEN);
        !           353:        }
        !           354:        else {
        !           355:                zmodem_tx_raw(zm, ZHEX);
        !           356:        }
        !           357: 
        !           358:        /*
        !           359:         * initialise the crc
        !           360:         */
        !           361: 
        !           362:        crc = 0;
        !           363: 
        !           364:        /*
        !           365:         * transmit the header
        !           366:         */
        !           367: 
        !           368:        for (i=0;i<HDRLEN;i++) {
        !           369:                zmodem_tx_hex(zm, *p);
        !           370:                crc = ucrc16(*p, crc);
        !           371:                p++;
        !           372:        }
        !           373: 
        !           374:        /*
        !           375:         * update the crc as though it were zero
        !           376:         */
        !           377: 
        !           378: //     crc = ucrc16(0,crc);
        !           379: //     crc = ucrc16(0,crc);
        !           380: 
        !           381:        /* 
        !           382:         * transmit the crc
        !           383:         */
        !           384: 
        !           385:        zmodem_tx_hex(zm, (char)(crc>>8));
        !           386:        zmodem_tx_hex(zm, (char)(crc&0xff));
        !           387: 
        !           388:        /*
        !           389:         * end of line sequence
        !           390:         */
        !           391: 
        !           392:        zmodem_tx_raw(zm, '\r');
        !           393:        zmodem_tx_raw(zm, '\n');
        !           394: 
        !           395:        zmodem_tx_raw(zm, XON);
        !           396: 
        !           397: 
        !           398: #if 0 /* def _DEBUG */
        !           399:        fprintf(zm->statfp,"\n");
        !           400: #endif
        !           401: }
        !           402: 
        !           403: /*
        !           404:  * Send ZMODEM binary header hdr
        !           405:  */
        !           406: 
        !           407: void
        !           408: zmodem_tx_bin32_header(zmodem_t* zm, unsigned char * p)
        !           409: {
        !           410:        int i;
        !           411:        unsigned long crc;
        !           412: 
        !           413: #if 0 /* def _DEBUG */
        !           414:        fprintf(zm->statfp,"tx binary header 32 bits crc\n");
        !           415: //     zm->raw_trace = 1;
        !           416: #endif
        !           417: 
        !           418:        zmodem_tx_raw(zm, ZPAD);
        !           419:        zmodem_tx_raw(zm, ZPAD);
        !           420:        zmodem_tx_raw(zm, ZDLE);
        !           421: 
        !           422:        if (zm->use_variable_headers) {
        !           423:                zmodem_tx_raw(zm, ZVBIN32);
        !           424:                zmodem_tx(zm, HDRLEN);
        !           425:        }
        !           426:        else {
        !           427:                zmodem_tx_raw(zm, ZBIN32);
        !           428:        }
        !           429: 
        !           430:        crc = 0xffffffffL;
        !           431: 
        !           432:        for (i=0;i<HDRLEN;i++) {
        !           433:                crc = ucrc32(*p,crc);
        !           434:                zmodem_tx(zm, *p++);
        !           435:        }
        !           436: 
        !           437:        crc = ~crc;
        !           438: 
        !           439:        zmodem_tx(zm, (uchar)((crc      ) & 0xff));
        !           440:        zmodem_tx(zm, (uchar)((crc >>  8) & 0xff));
        !           441:        zmodem_tx(zm, (uchar)((crc >> 16) & 0xff));
        !           442:        zmodem_tx(zm, (uchar)((crc >> 24) & 0xff));
        !           443: }
        !           444: 
        !           445: void
        !           446: zmodem_tx_bin16_header(zmodem_t* zm, unsigned char * p)
        !           447: {
        !           448:        int i;
        !           449:        unsigned int crc;
        !           450: 
        !           451: #if 0 /* def _DEBUG */
        !           452:        fprintf(zm->statfp,"tx binary header 16 bits crc\n");
        !           453: #endif
        !           454: 
        !           455:        zmodem_tx_raw(zm, ZPAD);
        !           456:        zmodem_tx_raw(zm, ZPAD);
        !           457:        zmodem_tx_raw(zm, ZDLE);
        !           458: 
        !           459:        if (zm->use_variable_headers) {
        !           460:                zmodem_tx_raw(zm, ZVBIN);
        !           461:                zmodem_tx(zm, HDRLEN);
        !           462:        }
        !           463:        else {
        !           464:                zmodem_tx_raw(zm, ZBIN);
        !           465:        }
        !           466: 
        !           467:        crc = 0;
        !           468: 
        !           469:        for (i=0;i<HDRLEN;i++) {
        !           470:                crc = ucrc16(*p,crc);
        !           471:                zmodem_tx(zm, *p++);
        !           472:        }
        !           473: 
        !           474: //     crc = ucrc16(0,crc);
        !           475: //     crc = ucrc16(0,crc);
        !           476: 
        !           477:        zmodem_tx(zm, (uchar)(crc >> 8));
        !           478:        zmodem_tx(zm, (uchar)(crc&0xff));
        !           479: }
        !           480: 
        !           481: 
        !           482: /* 
        !           483:  * transmit a header using either hex 16 bit crc or binary 32 bit crc
        !           484:  * depending on the receivers capabilities
        !           485:  * we dont bother with variable length headers. I dont really see their
        !           486:  * advantage and they would clutter the code unneccesarily
        !           487:  */
        !           488: 
        !           489: void
        !           490: zmodem_tx_header(zmodem_t* zm, unsigned char * p)
        !           491: {
        !           492:        if (zm->can_fcs_32) {
        !           493:                if (!zm->want_fcs_16) {
        !           494:                        zmodem_tx_bin32_header(zm, p);
        !           495:                }
        !           496:                else {
        !           497:                        zmodem_tx_bin16_header(zm, p);
        !           498:                }
        !           499:        }
        !           500:        else {
        !           501:                zmodem_tx_hex_header(zm, p);
        !           502:        }
        !           503: }
        !           504: 
        !           505: /*
        !           506:  * data subpacket transmission
        !           507:  */
        !           508: 
        !           509: void
        !           510: zmodem_tx_32_data(zmodem_t* zm, uchar sub_frame_type, unsigned char * p, int l)
        !           511: {
        !           512:        unsigned long crc;
        !           513: 
        !           514: #if 0 /* def _DEBUG */
        !           515:        fprintf(zm->statfp,"tx_32_data\n");
        !           516: #endif
        !           517: 
        !           518:        crc = 0xffffffffl;
        !           519: 
        !           520:        while (l > 0) {
        !           521:                crc = ucrc32(*p,crc);
        !           522:                zmodem_tx(zm, *p++);
        !           523:                l--;
        !           524:        }
        !           525: 
        !           526:        crc = ucrc32(sub_frame_type, crc);
        !           527: 
        !           528:        zmodem_tx_raw(zm, ZDLE);
        !           529:        zmodem_tx_raw(zm, sub_frame_type);
        !           530: 
        !           531:        crc = ~crc;
        !           532: 
        !           533:        zmodem_tx(zm, (uchar) ((crc      ) & 0xff));
        !           534:        zmodem_tx(zm, (uchar) ((crc >> 8 ) & 0xff));
        !           535:        zmodem_tx(zm, (uchar) ((crc >> 16) & 0xff));
        !           536:        zmodem_tx(zm, (uchar) ((crc >> 24) & 0xff));
        !           537: }
        !           538: 
        !           539: void
        !           540: zmodem_tx_16_data(zmodem_t* zm, uchar sub_frame_type,unsigned char * p,int l)
        !           541: {
        !           542:        unsigned short crc;
        !           543: 
        !           544: #if 0 /* def _DEBUG */
        !           545:        fprintf(zm->statfp,"tx_16_data\n");
        !           546: #endif
        !           547: 
        !           548:        crc = 0;
        !           549: 
        !           550:        while (l > 0) {
        !           551:                crc = ucrc16(*p,crc);
        !           552:                zmodem_tx(zm, *p++);
        !           553:                l--;
        !           554:        }
        !           555: 
        !           556:        crc = ucrc16(sub_frame_type,crc);
        !           557: 
        !           558:        zmodem_tx_raw(zm, ZDLE); 
        !           559:        zmodem_tx_raw(zm, sub_frame_type);
        !           560:        
        !           561: //     crc = ucrc16(0,crc);
        !           562: //     crc = ucrc16(0,crc);
        !           563: 
        !           564:        zmodem_tx(zm, (uchar)(crc >> 8));
        !           565:        zmodem_tx(zm, (uchar)(crc&0xff));
        !           566: }
        !           567: 
        !           568: /*
        !           569:  * send a data subpacket using crc 16 or crc 32 as desired by the receiver
        !           570:  */
        !           571: 
        !           572: void
        !           573: zmodem_tx_data(zmodem_t* zm, uchar sub_frame_type,unsigned char * p, int l)
        !           574: {
        !           575:        if (!zm->want_fcs_16 && zm->can_fcs_32) {
        !           576:                zmodem_tx_32_data(zm, sub_frame_type,p,l);
        !           577:        }
        !           578:        else {  
        !           579:                zmodem_tx_16_data(zm, sub_frame_type,p,l);
        !           580:        }
        !           581: 
        !           582:        if (sub_frame_type == ZCRCW) {
        !           583:                zmodem_tx_raw(zm, XON);
        !           584:        }
        !           585: 
        !           586: }
        !           587: 
        !           588: void
        !           589: zmodem_tx_pos_header(zmodem_t* zm, int type,long pos) 
        !           590: {
        !           591:        char header[5];
        !           592: 
        !           593:        header[0]   = type;
        !           594:        header[ZP0] =  pos        & 0xff;
        !           595:        header[ZP1] = (pos >>  8) & 0xff;
        !           596:        header[ZP2] = (pos >> 16) & 0xff;
        !           597:        header[ZP3] = (pos >> 24) & 0xff;
        !           598: 
        !           599:        zmodem_tx_hex_header(zm, header);
        !           600: }
        !           601: 
        !           602: void
        !           603: zmodem_tx_znak(zmodem_t* zm)
        !           604: {
        !           605:        fprintf(zm->statfp,"tx_znak\n");
        !           606: 
        !           607:        zmodem_tx_pos_header(zm, ZNAK, zm->ack_file_pos);
        !           608: }
        !           609: 
        !           610: void
        !           611: zmodem_tx_zskip(zmodem_t* zm)
        !           612: {
        !           613:        zmodem_tx_pos_header(zm, ZSKIP, 0L);
        !           614: }
        !           615: 
        !           616: /*
        !           617:  * receive any style header within timeout milliseconds
        !           618:  */
        !           619: 
        !           620: int
        !           621: zmodem_rx_poll(zmodem_t* zm)
        !           622: {
        !           623:        int rd=0;
        !           624: 
        !           625:        socket_check(zm->sock,&rd,NULL,0);
        !           626: 
        !           627:        return(rd);
        !           628: }
        !           629: 
        !           630: /*
        !           631:  * rx_raw ; receive a single byte from the line.
        !           632:  * reads as many are available and then processes them one at a time
        !           633:  * check the data stream for 5 consecutive CAN characters;
        !           634:  * and if you see them abort. this saves a lot of clutter in
        !           635:  * the rest of the code; even though it is a very strange place
        !           636:  * for an exit. (but that was wat session abort was all about.)
        !           637:  */
        !           638: 
        !           639: int
        !           640: zmodem_rx_raw(zmodem_t* zm, int to)
        !           641: {
        !           642:        int c;
        !           643: 
        !           644:        if((c=recv_byte(zm->sock,to,zm->mode)) > 0xff)
        !           645:                return TIMEOUT;
        !           646: 
        !           647: //     fprintf(zm->statfp,"%02X  ",c);
        !           648: 
        !           649:        if (c == CAN) {
        !           650:                zm->n_cans++;
        !           651:                if (zm->n_cans == 5) {
        !           652:                        fprintf(zm->statfp,"\nCancelled Remotely\n");
        !           653:                        bail(CAN);
        !           654:                }
        !           655:        }
        !           656:        else {
        !           657:                zm->n_cans = 0;
        !           658:        }
        !           659: 
        !           660:        return c;
        !           661: }
        !           662: 
        !           663: /*
        !           664:  * rx; receive a single byte undoing any escaping at the
        !           665:  * sending site. this bit looks like a mess. sorry for that
        !           666:  * but there seems to be no other way without incurring a lot
        !           667:  * of overhead. at least like this the path for a normal character
        !           668:  * is relatively short.
        !           669:  */
        !           670: 
        !           671: 
        !           672: int
        !           673: zmodem_rx(zmodem_t* zm, int to)
        !           674: {
        !           675:        int c;
        !           676: 
        !           677:        /*
        !           678:         * outer loop for ever so for sure something valid
        !           679:         * will come in; a timeout will occur or a session abort
        !           680:         * will be received.
        !           681:         */
        !           682: 
        !           683:        while (TRUE) {
        !           684: 
        !           685:                /*
        !           686:                 * fake do loop so we may continue
        !           687:                 * in case a character should be dropped.
        !           688:                 */
        !           689: 
        !           690:                do {
        !           691:                        c = zmodem_rx_raw(zm, to);
        !           692:                        if (c == TIMEOUT) {
        !           693:                                return c;
        !           694:                        }
        !           695:        
        !           696:                        switch (c) {
        !           697:                                case ZDLE:
        !           698:                                        break;
        !           699:                                case XON:
        !           700:                                case XON|0x80:
        !           701:                                case XOFF:
        !           702:                                case XOFF|0x80:
        !           703:                                        continue;                       
        !           704:                                default:
        !           705:                                        /*
        !           706:                                         * if all control characters should be escaped and 
        !           707:                                         * this one wasnt then its spurious and should be dropped.
        !           708:                                         */
        !           709:                                        if (zm->escape_all_control_characters && (c & 0x60) == 0) {
        !           710:                                                continue;
        !           711:                                        }
        !           712:                                        /*
        !           713:                                         * normal character; return it.
        !           714:                                         */
        !           715:                                        return c;
        !           716:                        }
        !           717:                } while (FALSE);
        !           718:        
        !           719:                /*
        !           720:                 * ZDLE encoded sequence or session abort.
        !           721:                 * (or something illegal; then back to the top)
        !           722:                 */
        !           723: 
        !           724:                do {
        !           725:                        c = zmodem_rx_raw(zm, to);
        !           726: 
        !           727:                        if (c == XON || c == (XON|0x80) || c == XOFF || c == (XOFF|0x80) || c == ZDLE) {
        !           728:                                /*
        !           729:                                 * these can be dropped.
        !           730:                                 */
        !           731:                                continue;
        !           732:                        }
        !           733: 
        !           734:                        switch (c) {
        !           735:                                /*
        !           736:                                 * these four are really nasty.
        !           737:                                 * for convenience we just change them into 
        !           738:                                 * special characters by setting a bit outside the
        !           739:                                 * first 8. that way they can be recognized and still
        !           740:                                 * be processed as characters by the rest of the code.
        !           741:                                 */
        !           742:                                case ZCRCE:
        !           743:                                case ZCRCG:
        !           744:                                case ZCRCQ:
        !           745:                                case ZCRCW:
        !           746:                                        return (c | ZDLEESC);
        !           747:                                case ZRUB0:
        !           748:                                        return 0x7f;
        !           749:                                case ZRUB1:
        !           750:                                        return 0xff;
        !           751:                                default:
        !           752:                                        if (zm->escape_all_control_characters && (c & 0x60) == 0) {
        !           753:                                                /*
        !           754:                                                 * a not escaped control character; probably
        !           755:                                                 * something from a network. just drop it.
        !           756:                                                 */
        !           757:                                                continue;
        !           758:                                        }
        !           759:                                        /*
        !           760:                                         * legitimate escape sequence.
        !           761:                                         * rebuild the orignal and return it.
        !           762:                                         */
        !           763:                                        if ((c & 0x60) == 0x40) {
        !           764:                                                return c ^ 0x40;
        !           765:                                        }
        !           766:                                        break;
        !           767:                        }
        !           768:                } while (FALSE);
        !           769:        }
        !           770: 
        !           771:        /*
        !           772:         * not reached.
        !           773:         */
        !           774: 
        !           775:        return 0;
        !           776: }
        !           777: 
        !           778: /*
        !           779:  * receive a data subpacket as dictated by the last received header.
        !           780:  * return 2 with correct packet and end of frame
        !           781:  * return 1 with correct packet frame continues
        !           782:  * return 0 with incorrect frame.
        !           783:  * return TIMEOUT with a timeout
        !           784:  * if an acknowledgement is requested it is generated automatically
        !           785:  * here. 
        !           786:  */
        !           787: 
        !           788: /*
        !           789:  * data subpacket reception
        !           790:  */
        !           791: 
        !           792: int
        !           793: zmodem_rx_32_data(zmodem_t* zm, unsigned char * p,int * l)
        !           794: {
        !           795:        int c;
        !           796:        unsigned long rxd_crc;
        !           797:        unsigned long crc;
        !           798:        int sub_frame_type;
        !           799: 
        !           800: #if 0 /* def _DEBUG */
        !           801:        fprintf(zm->statfp,"rx_32_data\n");
        !           802: #endif
        !           803: 
        !           804:        crc = 0xffffffffl;
        !           805: 
        !           806:        do {
        !           807:                c = zmodem_rx(zm, 1);
        !           808: 
        !           809:                if (c == TIMEOUT) {
        !           810:                        return TIMEOUT;
        !           811:                }
        !           812:                if (c < 0x100) {
        !           813:                        crc = ucrc32(c,crc);
        !           814:                        *p++ = c;
        !           815:                        (*l)++;
        !           816:                        continue;
        !           817:                }
        !           818:        } while (c < 0x100);
        !           819: 
        !           820:        sub_frame_type = c & 0xff;
        !           821: 
        !           822:        crc = ucrc32(sub_frame_type, crc);
        !           823: 
        !           824:        crc = ~crc;
        !           825: 
        !           826:        rxd_crc  = zmodem_rx(zm, 1);
        !           827:        rxd_crc |= zmodem_rx(zm, 1) << 8;
        !           828:        rxd_crc |= zmodem_rx(zm, 1) << 16;
        !           829:        rxd_crc |= zmodem_rx(zm, 1) << 24;
        !           830: 
        !           831:        if (rxd_crc != crc) {
        !           832:                return FALSE;
        !           833:        }
        !           834: 
        !           835:        zm->ack_file_pos += *l;
        !           836: 
        !           837:        return sub_frame_type;
        !           838: }
        !           839: 
        !           840: int
        !           841: zmodem_rx_16_data(zmodem_t* zm, register unsigned char * p,int * l)
        !           842: {
        !           843:        register int c;
        !           844:        int sub_frame_type;
        !           845:        register unsigned short crc;
        !           846:        unsigned short rxd_crc;
        !           847: 
        !           848: #if 0 /* def _DEBUG */
        !           849:        fprintf(zm->statfp,"rx_16_data\n");
        !           850: #endif
        !           851: 
        !           852:        crc = 0;
        !           853: 
        !           854:        do {
        !           855:                c = zmodem_rx(zm, 5);
        !           856: 
        !           857:                if (c == TIMEOUT) {
        !           858:                        return TIMEOUT;
        !           859:                }
        !           860:                if (c < 0x100) {
        !           861:                        crc = ucrc16(c,crc);
        !           862:                        *p++ = c;
        !           863:                        (*l)++;
        !           864:                }
        !           865:        } while (c < 0x100);
        !           866: 
        !           867:        sub_frame_type = c & 0xff;
        !           868: 
        !           869:        crc = ucrc16(sub_frame_type,crc);
        !           870: 
        !           871: //     crc = ucrc16(0,crc);
        !           872: //     crc = ucrc16(0,crc);
        !           873: 
        !           874:        rxd_crc  = zmodem_rx(zm, 1) << 8;
        !           875:        rxd_crc |= zmodem_rx(zm, 1);
        !           876: 
        !           877:        if (rxd_crc != crc) {
        !           878:                return FALSE;
        !           879:        }
        !           880: 
        !           881:        zm->ack_file_pos += *l;
        !           882: 
        !           883:        return sub_frame_type;
        !           884: }
        !           885: 
        !           886: int
        !           887: zmodem_rx_data(zmodem_t* zm, unsigned char * p, int * l)
        !           888: {
        !           889:        unsigned char zack_header[] = { ZACK, 0, 0, 0, 0 };
        !           890:        int sub_frame_type;
        !           891:        long pos;
        !           892: 
        !           893:        /*
        !           894:         * fill in the file pointer in case acknowledgement is requested.       
        !           895:         * the ack file pointer will be updated in the subpacket read routine;
        !           896:         * so we need to get it now
        !           897:         */
        !           898: 
        !           899:        pos = zm->ack_file_pos;
        !           900: 
        !           901:        /*
        !           902:         * receive the right type of frame
        !           903:         */
        !           904: 
        !           905:        *l = 0;
        !           906: 
        !           907:        if (zm->receive_32_bit_data) {
        !           908:                sub_frame_type = zmodem_rx_32_data(zm, p,l);
        !           909:        }
        !           910:        else {  
        !           911:                sub_frame_type = zmodem_rx_16_data(zm, p,l);
        !           912:        }
        !           913: 
        !           914:        switch (sub_frame_type)  {
        !           915:                case TIMEOUT:
        !           916:                        return TIMEOUT;
        !           917:                /*
        !           918:                 * frame continues non-stop
        !           919:                 */
        !           920:                case ZCRCG:
        !           921:                        return FRAMEOK;
        !           922:                /*
        !           923:                 * frame ends
        !           924:                 */
        !           925:                case ZCRCE:
        !           926:                        return ENDOFFRAME;
        !           927:                /*
        !           928:                 * frame continues; ZACK expected
        !           929:                 */
        !           930:                case ZCRCQ:             
        !           931:                        zmodem_tx_pos_header(zm, ZACK, pos);
        !           932:                        return FRAMEOK;
        !           933:                /*
        !           934:                 * frame ends; ZACK expected
        !           935:                 */
        !           936:                case ZCRCW:
        !           937:                        zmodem_tx_pos_header(zm, ZACK, pos);
        !           938:                        return ENDOFFRAME;
        !           939:        }
        !           940: 
        !           941:        return FALSE;
        !           942: }
        !           943: 
        !           944: int
        !           945: zmodem_rx_nibble(zmodem_t* zm, int to) 
        !           946: {
        !           947:        int c;
        !           948: 
        !           949:        c = zmodem_rx(zm, to);
        !           950: 
        !           951:        if (c == TIMEOUT) {
        !           952:                return c;
        !           953:        }
        !           954: 
        !           955:        if (c > '9') {
        !           956:                if (c < 'a' || c > 'f') {
        !           957:                        /*
        !           958:                         * illegal hex; different than expected.
        !           959:                         * we might as well time out.
        !           960:                         */
        !           961:                        return TIMEOUT;
        !           962:                }
        !           963: 
        !           964:                c -= 'a' - 10;
        !           965:        }
        !           966:        else {
        !           967:                if (c < '0') {
        !           968:                        /*
        !           969:                         * illegal hex; different than expected.
        !           970:                         * we might as well time out.
        !           971:                         */
        !           972:                        return TIMEOUT;
        !           973:                }
        !           974:                c -= '0';
        !           975:        }
        !           976: 
        !           977:        return c;
        !           978: }
        !           979: 
        !           980: int
        !           981: zmodem_rx_hex(zmodem_t* zm, int to)
        !           982: {
        !           983:        int n1;
        !           984:        int n0;
        !           985: 
        !           986:        n1 = zmodem_rx_nibble(zm, to);
        !           987: 
        !           988:        if (n1 == TIMEOUT) {
        !           989:                return n1;
        !           990:        }
        !           991: 
        !           992:        n0 = zmodem_rx_nibble(zm, to);
        !           993: 
        !           994:        if (n0 == TIMEOUT) {
        !           995:                return n0;
        !           996:        }
        !           997: 
        !           998:        return (n1 << 4) | n0;
        !           999: }
        !          1000: 
        !          1001: /*
        !          1002:  * receive routines for each of the six different styles of header.
        !          1003:  * each of these leaves zm->rxd_header_len set to 0 if the end result is
        !          1004:  * not a valid header.
        !          1005:  */
        !          1006: 
        !          1007: void
        !          1008: zmodem_rx_bin16_header(zmodem_t* zm, int to)
        !          1009: {
        !          1010:        int c;
        !          1011:        int n;
        !          1012:        unsigned short int crc;
        !          1013:        unsigned short int rxd_crc;
        !          1014: 
        !          1015: #if 0 /* def _DEBUG */
        !          1016:        fprintf(zm->statfp,"rx binary header 16 bits crc\n");
        !          1017: #endif
        !          1018: 
        !          1019:        crc = 0;
        !          1020: 
        !          1021:        for (n=0;n<5;n++) {
        !          1022:                c = zmodem_rx(zm, to);
        !          1023:                if (c == TIMEOUT) {
        !          1024:                        fprintf(zm->errfp,"timeout\n");
        !          1025:                        return;
        !          1026:                }
        !          1027:                crc = ucrc16(c,crc);
        !          1028:                zm->rxd_header[n] = c;
        !          1029:        }
        !          1030: 
        !          1031: //     crc = ucrc16(0,crc);
        !          1032: //     crc = ucrc16(0,crc);
        !          1033: 
        !          1034:        rxd_crc  = zmodem_rx(zm, 1) << 8;
        !          1035:        rxd_crc |= zmodem_rx(zm, 1);
        !          1036: 
        !          1037:        if (rxd_crc != crc) {
        !          1038:                fprintf(zm->errfp,"bad crc %4.4x %4.4x\n",rxd_crc,crc);
        !          1039:                return;
        !          1040:        }
        !          1041: 
        !          1042:        zm->rxd_header_len = 5;
        !          1043: }
        !          1044: 
        !          1045: void
        !          1046: zmodem_rx_hex_header(zmodem_t* zm, int to)
        !          1047: {
        !          1048:        int c;
        !          1049:        int i;
        !          1050:        unsigned short int crc = 0;
        !          1051:        unsigned short int rxd_crc;
        !          1052: 
        !          1053: #if 0 /* def _DEBUG */
        !          1054:        fprintf(zm->statfp,"rx_hex_header : ");
        !          1055: #endif
        !          1056:        for (i=0;i<5;i++) {
        !          1057:                c = zmodem_rx_hex(zm, to);
        !          1058:                if (c == TIMEOUT) {
        !          1059:                        return;
        !          1060:                }
        !          1061:                crc = ucrc16(c,crc);
        !          1062: 
        !          1063:                zm->rxd_header[i] = c;
        !          1064:        }
        !          1065: 
        !          1066: //     crc = ucrc16(0,crc);
        !          1067: //     crc = ucrc16(0,crc);
        !          1068: 
        !          1069:        /*
        !          1070:         * receive the crc
        !          1071:         */
        !          1072: 
        !          1073:        c = zmodem_rx_hex(zm, to);
        !          1074: 
        !          1075:        if (c == TIMEOUT) {
        !          1076:                return;
        !          1077:        }
        !          1078: 
        !          1079:        rxd_crc = c << 8;
        !          1080: 
        !          1081:        c = zmodem_rx_hex(zm, to);
        !          1082: 
        !          1083:        if (c == TIMEOUT) {
        !          1084:                return;
        !          1085:        }
        !          1086: 
        !          1087:        rxd_crc |= c;
        !          1088: 
        !          1089:        if (rxd_crc == crc) {
        !          1090:                zm->rxd_header_len = 5;
        !          1091:        }
        !          1092:        else {
        !          1093:                fprintf(zm->errfp,"\n!BAD CRC-16: 0x%hX, expected: 0x%hX\n", rxd_crc, crc);
        !          1094:        }
        !          1095: 
        !          1096:        /*
        !          1097:         * drop the end of line sequence after a hex header
        !          1098:         */
        !          1099:        c = zmodem_rx(zm, to);
        !          1100:        if (c == CR) {
        !          1101:                /*
        !          1102:                 * both are expected with CR
        !          1103:                 */
        !          1104:                zmodem_rx(zm, to);      /* drop LF */
        !          1105:        }
        !          1106: }
        !          1107: 
        !          1108: void
        !          1109: zmodem_rx_bin32_header(zmodem_t* zm, int to)
        !          1110: {
        !          1111:        int c;
        !          1112:        int n;
        !          1113:        unsigned long crc;
        !          1114:        unsigned long rxd_crc;
        !          1115: 
        !          1116: #if 0 /* def _DEBUG */
        !          1117:        fprintf(zm->statfp,"rx binary header 32 bits crc\n");
        !          1118: #endif
        !          1119: 
        !          1120:        crc = 0xffffffffL;
        !          1121: 
        !          1122:        for (n=0;n<to;n++) {
        !          1123:                c = zmodem_rx(zm, 1);
        !          1124:                if (c == TIMEOUT) {
        !          1125:                        return;
        !          1126:                }
        !          1127:                crc = ucrc32(c,crc);
        !          1128:                zm->rxd_header[n] = c;
        !          1129:        }
        !          1130: 
        !          1131:        crc = ~crc;
        !          1132: 
        !          1133:        rxd_crc  = zmodem_rx(zm, 1);
        !          1134:        rxd_crc |= zmodem_rx(zm, 1) << 8;
        !          1135:        rxd_crc |= zmodem_rx(zm, 1) << 16;
        !          1136:        rxd_crc |= zmodem_rx(zm, 1) << 24;
        !          1137: 
        !          1138:        if (rxd_crc != crc) {
        !          1139:                return;
        !          1140:        }
        !          1141: 
        !          1142:        zm->rxd_header_len = 5;
        !          1143: }
        !          1144: 
        !          1145: /*
        !          1146:  * receive any style header
        !          1147:  * if the errors flag is set than whenever an invalid header packet is
        !          1148:  * received INVHDR will be returned. otherwise we wait for a good header
        !          1149:  * also; a flag (receive_32_bit_data) will be set to indicate whether data
        !          1150:  * packets following this header will have 16 or 32 bit data attached.
        !          1151:  * variable headers are not implemented.
        !          1152:  */
        !          1153: 
        !          1154: int
        !          1155: zmodem_rx_header_raw(zmodem_t* zm, int to,int errors)
        !          1156: {
        !          1157:        int c;
        !          1158: 
        !          1159: #if 0 /* def _DEBUG */
        !          1160:        fprintf(zm->statfp,"rx header : ");
        !          1161: #endif
        !          1162:        zm->rxd_header_len = 0;
        !          1163: 
        !          1164:        do {
        !          1165:                do {
        !          1166:                        c = zmodem_rx_raw(zm, to);
        !          1167:                        if (c == TIMEOUT) {
        !          1168:                                fprintf(zm->statfp,"\n%s %d\n",__FILE__,__LINE__);
        !          1169:                                return c;
        !          1170:                        }
        !          1171:                } while (c != ZPAD);
        !          1172: 
        !          1173:                c = zmodem_rx_raw(zm, to);
        !          1174:                if (c == TIMEOUT) {
        !          1175:                        fprintf(zm->statfp,"\n%s %d\n",__FILE__,__LINE__);
        !          1176:                        return c;
        !          1177:                }
        !          1178: 
        !          1179:                if (c == ZPAD) {
        !          1180:                        c = zmodem_rx_raw(zm, to);
        !          1181:                        if (c == TIMEOUT) {
        !          1182:                                fprintf(zm->statfp,"\n%s %d\n",__FILE__,__LINE__);
        !          1183:                                return c;
        !          1184:                        }
        !          1185:                }
        !          1186: 
        !          1187:                /*
        !          1188:                 * spurious ZPAD check
        !          1189:                 */
        !          1190: 
        !          1191:                if (c != ZDLE) {
        !          1192:                        fprintf(zm->errfp,"expected ZDLE; got %c\n",c);
        !          1193:                        continue;
        !          1194:                }
        !          1195: 
        !          1196:                /*
        !          1197:                 * now read the header style
        !          1198:                 */
        !          1199: 
        !          1200:                c = zmodem_rx(zm, to);
        !          1201: 
        !          1202:                if (c == TIMEOUT) {
        !          1203:                        fprintf(zm->errfp,"\n!TIMEOUT %s %d\n",__FILE__,__LINE__);
        !          1204:                        return c;
        !          1205:                }
        !          1206: 
        !          1207: #if 0 /* def _DEBUG */
        !          1208:                fprintf(zm->statfp,"\n");
        !          1209: #endif
        !          1210:                switch (c) {
        !          1211:                        case ZBIN:
        !          1212:                                zmodem_rx_bin16_header(zm, to);
        !          1213:                                zm->receive_32_bit_data = FALSE;
        !          1214:                                break;
        !          1215:                        case ZHEX:
        !          1216:                                zmodem_rx_hex_header(zm, to);
        !          1217:                                zm->receive_32_bit_data = FALSE;
        !          1218:                                break;
        !          1219:                        case ZBIN32:
        !          1220:                                zmodem_rx_bin32_header(zm, to);
        !          1221:                                zm->receive_32_bit_data = TRUE;
        !          1222:                                break;
        !          1223:                        default:
        !          1224:                                /*
        !          1225:                                 * unrecognized header style
        !          1226:                                 */
        !          1227:                                fprintf(zm->errfp,"unrecognized header style %c\n",c);
        !          1228:                                if (errors) {
        !          1229:                                        return INVHDR;
        !          1230:                                }
        !          1231: 
        !          1232:                                continue;
        !          1233:                }
        !          1234:                if (errors && zm->rxd_header_len == 0) {
        !          1235:                        return INVHDR;
        !          1236:                }
        !          1237: 
        !          1238:        } while (zm->rxd_header_len == 0);
        !          1239: 
        !          1240:        /*
        !          1241:         * this appears to have been a valid header.
        !          1242:         * return its type.
        !          1243:         */
        !          1244: 
        !          1245:        if (zm->rxd_header[0] == ZDATA) {
        !          1246:                zm->ack_file_pos = zm->rxd_header[ZP0] | (zm->rxd_header[ZP1] << 8) |
        !          1247:                        (zm->rxd_header[ZP2] << 16) | (zm->rxd_header[ZP3] << 24);
        !          1248:        }
        !          1249: 
        !          1250:        if (zm->rxd_header[0] == ZFILE) {
        !          1251:                zm->ack_file_pos = 0l;
        !          1252:        }
        !          1253: 
        !          1254: #if 0 /* def _DEBUG */
        !          1255:        fprintf(zm->statfp,"type %d\n",zm->rxd_header[0]);
        !          1256: #endif
        !          1257: 
        !          1258:        return zm->rxd_header[0];
        !          1259: }
        !          1260: 
        !          1261: int
        !          1262: zmodem_rx_header(zmodem_t* zm, int timeout)
        !          1263: {
        !          1264:        return zmodem_rx_header_raw(zm, timeout, FALSE);
        !          1265: }
        !          1266: 
        !          1267: int
        !          1268: zmodem_rx_header_and_check(zmodem_t* zm, int timeout)
        !          1269: {
        !          1270:        int type;
        !          1271:        while (TRUE) {
        !          1272:                type = zmodem_rx_header_raw(zm, timeout,TRUE);          
        !          1273: 
        !          1274:                if (type != INVHDR) {
        !          1275:                        break;
        !          1276:                }
        !          1277: 
        !          1278:                zmodem_tx_znak(zm);
        !          1279:        }
        !          1280: 
        !          1281:        return type;
        !          1282: }
        !          1283: 
        !          1284: void zmodem_parse_zrinit(zmodem_t* zm)
        !          1285: {
        !          1286:        zm->can_full_duplex                                     = (zm->rxd_header[ZF0] & ZF0_CANFDX)  != 0;
        !          1287:        zm->can_overlap_io                                      = (zm->rxd_header[ZF0] & ZF0_CANOVIO) != 0;
        !          1288:        zm->can_break                                           = (zm->rxd_header[ZF0] & ZF0_CANBRK)  != 0;
        !          1289:        zm->can_fcs_32                                          = (zm->rxd_header[ZF0] & ZF0_CANFC32) != 0;
        !          1290:        zm->escape_all_control_characters       = (zm->rxd_header[ZF0] & ZF0_ESCCTL)  != 0;
        !          1291:        zm->escape_8th_bit                                      = (zm->rxd_header[ZF0] & ZF0_ESC8)    != 0;
        !          1292: 
        !          1293:        zm->use_variable_headers                        = (zm->rxd_header[ZF1] & ZF1_CANVHDR) != 0;
        !          1294: }
        !          1295: 
        !          1296: int zmodem_get_zrinit(zmodem_t* zm)
        !          1297: {
        !          1298:        unsigned char zrqinit_header[] = { ZRQINIT, 0, 0, 0, 0 };
        !          1299: 
        !          1300:        zmodem_tx_raw(zm,'r');
        !          1301:        zmodem_tx_raw(zm,'z');
        !          1302:        zmodem_tx_raw(zm,'\r');
        !          1303:        zmodem_tx_hex_header(zm,zrqinit_header);
        !          1304:        
        !          1305:        return zmodem_rx_header(zm,7);
        !          1306: }
        !          1307: 
        !          1308: int zmodem_send_zfin(zmodem_t* zm)
        !          1309: {
        !          1310:        int type;
        !          1311:        unsigned char zfin_header[] = { ZFIN, 0, 0, 0, 0 };
        !          1312: 
        !          1313:        zmodem_tx_hex_header(zm,zfin_header);
        !          1314:        do {
        !          1315:                type = zmodem_rx_header(zm,10);
        !          1316:        } while (type != ZFIN && type != TIMEOUT);
        !          1317:        
        !          1318:        /*
        !          1319:         * these Os are formally required; but they don't do a thing
        !          1320:         * unfortunately many programs require them to exit 
        !          1321:         * (both programs already sent a ZFIN so why bother ?)
        !          1322:         */
        !          1323: 
        !          1324:        if (type != TIMEOUT) {
        !          1325:                zmodem_tx_raw(zm,'O');
        !          1326:                zmodem_tx_raw(zm,'O');
        !          1327:        }
        !          1328: 
        !          1329:        return 0;
        !          1330: }
        !          1331: 
        !          1332: /* 
        !          1333:  * show the progress of the transfer like this:
        !          1334:  * zmtx: sending file "garbage" 4096 bytes ( 20%)
        !          1335:  */
        !          1336: 
        !          1337: void
        !          1338: show_progress(zmodem_t* zm, ulong offset)
        !          1339: {
        !          1340:        time_t  t;
        !          1341:        long    l;
        !          1342:        uint    cps;
        !          1343: 
        !          1344:        t=time(NULL)-zm->transfer_start;
        !          1345:        if(!t) t=1;             /* t is time so far */
        !          1346: 
        !          1347:        cps=offset/t;   /* cps so far */
        !          1348:        if(!cps) cps=1;
        !          1349:        l=zm->current_file_size/cps;            /* total transfer est time */
        !          1350:        l-=t;                                                           /* now, it's est time left */
        !          1351: 
        !          1352:        fprintf(zm->statfp,"\rByte: %lu/%lu  "
        !          1353:                "Time: %lu:%02lu/%lu:%02lu  CPS: %u  %lu%% "
        !          1354:                ,offset
        !          1355:                ,zm->current_file_size
        !          1356:                ,t/60L
        !          1357:                ,t%60L
        !          1358:                ,l/60L
        !          1359:                ,l%60L
        !          1360:                ,cps
        !          1361:                ,(long)(((float)offset/(float)zm->current_file_size)*100.0)
        !          1362:                );
        !          1363: 
        !          1364: }
        !          1365: 
        !          1366: /*
        !          1367:  * send from the current position in the file
        !          1368:  * all the way to end of file or until something goes wrong.
        !          1369:  * (ZNAK or ZRPOS received)
        !          1370:  * the name is only used to show progress
        !          1371:  */
        !          1372: 
        !          1373: int
        !          1374: send_from(zmodem_t* zm, FILE * fp)
        !          1375: {
        !          1376:        int n;
        !          1377:        long pos;
        !          1378:        uchar type = ZCRCG;
        !          1379:        char zdata_frame[] = { ZDATA, 0, 0, 0, 0 };
        !          1380: 
        !          1381:        /*
        !          1382:         * put the file position in the ZDATA frame
        !          1383:         */
        !          1384: 
        !          1385:        pos = ftell(fp);
        !          1386:        zdata_frame[ZP0] =  pos        & 0xff;
        !          1387:        zdata_frame[ZP1] = (pos >> 8)  & 0xff;
        !          1388:        zdata_frame[ZP2] = (pos >> 16) & 0xff;
        !          1389:        zdata_frame[ZP3] = (pos >> 24) & 0xff;
        !          1390: 
        !          1391:        zmodem_tx_header(zm, zdata_frame);
        !          1392:        /*
        !          1393:         * send the data in the file
        !          1394:         */
        !          1395: 
        !          1396:        while (!feof(fp)) {
        !          1397: 
        !          1398:                show_progress(zm, ftell(fp));
        !          1399: 
        !          1400:                /*
        !          1401:                 * read a block from the file
        !          1402:                 */
        !          1403:                n = fread(zm->tx_data_subpacket,1,sizeof(zm->tx_data_subpacket),fp);
        !          1404: 
        !          1405:                if (n == 0) {
        !          1406:                        /*
        !          1407:                         * nothing to send ?
        !          1408:                         */
        !          1409:                        break;
        !          1410:                }
        !          1411: 
        !          1412:                /*
        !          1413:                 * at end of file wait for an ACK
        !          1414:                 */
        !          1415:                if (ftell(fp) == zm->current_file_size) {
        !          1416:                        type = ZCRCW;
        !          1417:                }
        !          1418: 
        !          1419:                zmodem_tx_data(zm, type, zm->tx_data_subpacket, n);
        !          1420: 
        !          1421:                if (type == ZCRCW) {
        !          1422:                        int type;
        !          1423:                        do {
        !          1424:                                type = zmodem_rx_header(zm, 10);
        !          1425:                                if (type == ZNAK || type == ZRPOS) {
        !          1426:                                        return type;
        !          1427:                                }
        !          1428:                        } while (type != ZACK);
        !          1429: 
        !          1430:                        if (ftell(fp) == zm->current_file_size) {
        !          1431:                                if (opt_d) {
        !          1432:                                        fprintf(zm->statfp,"end of file\n");
        !          1433:                                }
        !          1434:                                return ZACK;
        !          1435:                        }
        !          1436:                }
        !          1437: 
        !          1438:                /* 
        !          1439:                 * characters from the other side
        !          1440:                 * check out that header
        !          1441:                 */
        !          1442: 
        !          1443:                while (zmodem_rx_poll(zm)) {
        !          1444:                        int type;
        !          1445:                        int c;
        !          1446:                        c = zmodem_rx_raw(zm, 1);
        !          1447:                        if (c == ZPAD) {
        !          1448:                                type = zmodem_rx_header(zm, 1);
        !          1449:                                if (type != TIMEOUT && type != ACK) {
        !          1450:                                        return type;
        !          1451:                                }
        !          1452:                        }
        !          1453:                }
        !          1454: 
        !          1455:        }
        !          1456: 
        !          1457:        /*
        !          1458:         * end of file reached.
        !          1459:         * should receive something... so fake ZACK
        !          1460:         */
        !          1461: 
        !          1462:        return ZACK;
        !          1463: }
        !          1464: 
        !          1465: /*
        !          1466:  * send a file; returns true when session is aborted.
        !          1467:  * (using ZABORT frame)
        !          1468:  */
        !          1469: 
        !          1470: int
        !          1471: zmodem_send_file(zmodem_t* zm, char* name, FILE* fp)
        !          1472: {
        !          1473:        long pos;
        !          1474:        struct stat s;
        !          1475:        unsigned char * p;
        !          1476:        char zfile_frame[] = { ZFILE, 0, 0, 0, 0 };
        !          1477:        char zeof_frame[] = { ZEOF, 0, 0, 0, 0 };
        !          1478:        int type;
        !          1479: 
        !          1480:        fstat(fileno(fp),&s);
        !          1481:        zm->current_file_size = s.st_size;
        !          1482: 
        !          1483:        /*
        !          1484:         * the file exists. now build the ZFILE frame
        !          1485:         */
        !          1486: 
        !          1487:        /*
        !          1488:         * set conversion option
        !          1489:         * (not used; always binary)
        !          1490:         */
        !          1491: 
        !          1492:        zfile_frame[ZF0] = ZF0_ZCBIN;
        !          1493: 
        !          1494:        /*
        !          1495:         * management option
        !          1496:         */
        !          1497: 
        !          1498:        if (zm->management_protect) {
        !          1499:                zfile_frame[ZF1] = ZF1_ZMPROT;          
        !          1500:                if (opt_d) {
        !          1501:                        fprintf(zm->statfp,"zmtx: protecting destination\n");
        !          1502:                }
        !          1503:        }
        !          1504: 
        !          1505:        if (zm->management_clobber) {
        !          1506:                zfile_frame[ZF1] = ZF1_ZMCLOB;
        !          1507:                if (opt_d) {
        !          1508:                        fprintf(zm->statfp,"zmtx: overwriting destination\n");
        !          1509:                }
        !          1510:        }
        !          1511: 
        !          1512:        if (zm->management_newer) {
        !          1513:                zfile_frame[ZF1] = ZF1_ZMNEW;
        !          1514:                if (opt_d) {
        !          1515:                        fprintf(zm->statfp,"zmtx: overwriting destination if newer\n");
        !          1516:                }
        !          1517:        }
        !          1518: 
        !          1519:        /*
        !          1520:         * transport options
        !          1521:         * (just plain normal transfer)
        !          1522:         */
        !          1523: 
        !          1524:        zfile_frame[ZF2] = ZF2_ZTNOR;
        !          1525: 
        !          1526:        /*
        !          1527:         * extended options
        !          1528:         */
        !          1529: 
        !          1530:        zfile_frame[ZF3] = 0;
        !          1531: 
        !          1532:        /*
        !          1533:         * now build the data subpacket with the file name and lots of other
        !          1534:         * useful information.
        !          1535:         */
        !          1536: 
        !          1537:        /*
        !          1538:         * first enter the name and a 0
        !          1539:         */
        !          1540: 
        !          1541:        p = zm->tx_data_subpacket;
        !          1542: 
        !          1543:        strcpy(p,name);
        !          1544: 
        !          1545:        p += strlen(p) + 1;
        !          1546: 
        !          1547:        sprintf(p,"%lu %lo %lo %d %u %lu %d"
        !          1548:                ,s.st_size
        !          1549:                ,s.st_mtime
        !          1550:                ,0                                              /* file mode */
        !          1551:                ,0                                              /* serial number */
        !          1552:                ,zm->n_files_remaining
        !          1553:                ,zm->n_bytes_remaining
        !          1554:                ,0                                              /* file type */
        !          1555:                );
        !          1556: 
        !          1557:        p += strlen(p) + 1;
        !          1558: 
        !          1559:        do {
        !          1560:                /*
        !          1561:                 * send the header and the data
        !          1562:                 */
        !          1563: 
        !          1564:                zmodem_tx_header(zm,zfile_frame);
        !          1565:                zmodem_tx_data(zm,ZCRCW,zm->tx_data_subpacket,p - zm->tx_data_subpacket);
        !          1566:        
        !          1567:                /*
        !          1568:                 * wait for anything but an ZACK packet
        !          1569:                 */
        !          1570: 
        !          1571:                do {
        !          1572:                        type = zmodem_rx_header(zm,10);
        !          1573:                } while (type == ZACK);
        !          1574: 
        !          1575: #if 0
        !          1576:                fprintf(zm->statfp,"type : %d\n",type);
        !          1577: #endif
        !          1578: 
        !          1579:                if (type == ZSKIP) {
        !          1580:                        fclose(fp);
        !          1581:                        if (opt_v) {
        !          1582:                                fprintf(zm->statfp,"zmtx: skipped file \"%s\"                       \n",name);
        !          1583:                        }
        !          1584:                        return -1;
        !          1585:                }
        !          1586: 
        !          1587:        } while (type != ZRPOS);
        !          1588: 
        !          1589:        zm->transfer_start = time(NULL);
        !          1590: 
        !          1591:        do {
        !          1592:                /*
        !          1593:                 * fetch pos from the ZRPOS header
        !          1594:                 */
        !          1595: 
        !          1596:                if (type == ZRPOS) {
        !          1597:                        pos = zm->rxd_header[ZP0] | (zm->rxd_header[ZP1] << 8) | (zm->rxd_header[ZP2] << 16) | (zm->rxd_header[ZP3] << 24);
        !          1598:                }
        !          1599: 
        !          1600:                /*
        !          1601:                 * seek to the right place in the file
        !          1602:                 */
        !          1603:                fseek(fp,pos,SEEK_SET);
        !          1604: 
        !          1605:                /*
        !          1606:                 * and start sending
        !          1607:                 */
        !          1608: 
        !          1609:                type = send_from(zm,fp);
        !          1610: 
        !          1611:                if (type == ZFERR || type == ZABORT) {
        !          1612:                        fclose(fp);
        !          1613:                        return -1;
        !          1614:                }
        !          1615: 
        !          1616:        } while (type == ZRPOS || type == ZNAK);
        !          1617: 
        !          1618:        /*
        !          1619:         * file sent. send end of file frame
        !          1620:         * and wait for zrinit. if it doesnt come then try again
        !          1621:         */
        !          1622: 
        !          1623:        zeof_frame[ZP0] =  s.st_size        & 0xff;
        !          1624:        zeof_frame[ZP1] = (s.st_size >> 8)  & 0xff;
        !          1625:        zeof_frame[ZP2] = (s.st_size >> 16) & 0xff;
        !          1626:        zeof_frame[ZP3] = (s.st_size >> 24) & 0xff;
        !          1627: 
        !          1628:        do {
        !          1629:                zmodem_tx_hex_header(zm,zeof_frame);
        !          1630:                type = zmodem_rx_header(zm,10);
        !          1631:        } while (type != ZRINIT);
        !          1632: 
        !          1633:        /*
        !          1634:         * and close the input file
        !          1635:         */
        !          1636: 
        !          1637:        if (opt_v) {
        !          1638:                fprintf(zm->statfp,"zmtx: sent file \"%s\"                                    \n",name);
        !          1639:        }
        !          1640: 
        !          1641:        fclose(fp);
        !          1642: 
        !          1643:        return 0;
        !          1644: }
        !          1645: 
        !          1646: #if 0
        !          1647: 
        !          1648: zmodem_send_files(char** fname, int total_files)
        !          1649: {
        !          1650:        int i;
        !          1651:        int fnum;
        !          1652:        char * s;
        !          1653: 
        !          1654:        /*
        !          1655:         * clear the input queue from any possible garbage
        !          1656:         * this also clears a possible ZRINIT from an already started
        !          1657:         * zmodem receiver. this doesn't harm because we reinvite to
        !          1658:         * receive again below and it may be that the receiver whose
        !          1659:         * ZRINIT we are about to wipe has already died.
        !          1660:         */
        !          1661: 
        !          1662:        zmodem_rx_purge();
        !          1663: 
        !          1664:        /*
        !          1665:         * establish contact with the receiver
        !          1666:         */
        !          1667: 
        !          1668:        if (opt_v) {
        !          1669:                fprintf(zm->statfp,"zmtx: establishing contact with receiver\n");
        !          1670:        }
        !          1671: 
        !          1672:        i = 0;
        !          1673:        do {
        !          1674:                unsigned char zrqinit_header[] = { ZRQINIT, 0, 0, 0, 0 };
        !          1675:                i++;
        !          1676:                if (i > 10) {
        !          1677:                        fprintf(zm->statfp,"zmtx: can't establish contact with receiver\n");
        !          1678:                        bail(3);
        !          1679:                }
        !          1680: 
        !          1681:                zmodem_tx_raw('r');
        !          1682:                zmodem_tx_raw('z');
        !          1683:                zmodem_tx_raw('\r');
        !          1684:                zmodem_tx_hex_header(zrqinit_header);
        !          1685:        } while (zmodem_rx_header(7) != ZRINIT);
        !          1686: 
        !          1687:        if (opt_v) {
        !          1688:                fprintf(zm->statfp,"zmtx: contact established\n");
        !          1689:                fprintf(zm->statfp,"zmtx: starting file transfer\n");
        !          1690:        }
        !          1691: 
        !          1692:        /*
        !          1693:         * decode receiver capability flags
        !          1694:         * forget about encryption and compression.
        !          1695:         */
        !          1696: 
        !          1697:        zmodem_can_full_duplex                                  = (zm->rxd_header[ZF0] & ZF0_CANFDX)  != 0;
        !          1698:        zmodem_can_overlap_io                                   = (zm->rxd_header[ZF0] & ZF0_CANOVIO) != 0;
        !          1699:        zmodem_can_break                                                = (zm->rxd_header[ZF0] & ZF0_CANBRK)  != 0;
        !          1700:        zmodem_can_fcs_32                                               = (zm->rxd_header[ZF0] & ZF0_CANFC32) != 0;
        !          1701:        zmodem_escape_all_control_characters    = (zm->rxd_header[ZF0] & ZF0_ESCCTL)  != 0;
        !          1702:        zmodem_escape_8th_bit                                   = (zm->rxd_header[ZF0] & ZF0_ESC8)    != 0;
        !          1703: 
        !          1704:        zm->use_variable_headers                        = (zm->rxd_header[ZF1] & ZF1_CANVHDR) != 0;
        !          1705: 
        !          1706:        if (opt_d) {
        !          1707:                fprintf(zm->statfp,"receiver %s full duplex\n"          ,zmodem_can_full_duplex               ? "can"      : "can't");
        !          1708:                fprintf(zm->statfp,"receiver %s overlap io\n"           ,zmodem_can_overlap_io                ? "can"      : "can't");
        !          1709:                fprintf(zm->statfp,"receiver %s break\n"                ,zmodem_can_break                     ? "can"      : "can't");
        !          1710:                fprintf(zm->statfp,"receiver %s fcs 32\n"               ,zmodem_can_fcs_32                    ? "can"      : "can't");
        !          1711:                fprintf(zm->statfp,"receiver %s escaped control chars\n",zmodem_escape_all_control_characters ? "requests" : "doesn't request");
        !          1712:                fprintf(zm->statfp,"receiver %s escaped 8th bit\n"      ,zmodem_escape_8th_bit                ? "requests" : "doesn't request");
        !          1713:                fprintf(zm->statfp,"receiver %s use variable headers\n" ,zm->use_variable_headers          ? "can"      : "can't");
        !          1714:        }
        !          1715: 
        !          1716:        /* 
        !          1717:         * and send each file in turn
        !          1718:         */
        !          1719: 
        !          1720:        n_files_remaining = total_files;
        !          1721: 
        !          1722:        for(fnum=0;fnum<total_files;fnum++) {
        !          1723:                if(send_file(fname[fnum])) {
        !          1724:                        if (opt_v) {
        !          1725:                                fprintf(zm->statfp,"zmtx: remote aborted.\n");
        !          1726:                        }
        !          1727:                        break;
        !          1728:                }
        !          1729:                n_files_remaining--;
        !          1730:        }
        !          1731: 
        !          1732:        /*
        !          1733:         * close the session
        !          1734:         */
        !          1735: 
        !          1736:        if (opt_v) {
        !          1737:                fprintf(zm->statfp,"zmtx: closing the session\n");
        !          1738:        }
        !          1739: 
        !          1740:        {
        !          1741:                int type;
        !          1742:                unsigned char zfin_header[] = { ZFIN, 0, 0, 0, 0 };
        !          1743: 
        !          1744:                zmodem_tx_hex_header(zfin_header);
        !          1745:                do {
        !          1746:                        type = zmodem_rx_header(10);
        !          1747:                } while (type != ZFIN && type != TIMEOUT);
        !          1748:                
        !          1749:                /*
        !          1750:                 * these Os are formally required; but they don't do a thing
        !          1751:                 * unfortunately many programs require them to exit 
        !          1752:                 * (both programs already sent a ZFIN so why bother ?)
        !          1753:                 */
        !          1754: 
        !          1755:                if (type != TIMEOUT) {
        !          1756:                        zmodem_tx_raw('O');
        !          1757:                        zmodem_tx_raw('O');
        !          1758:                }
        !          1759:        }
        !          1760: 
        !          1761:        /*
        !          1762:         * c'est fini
        !          1763:         */
        !          1764: 
        !          1765:        if (opt_d) {
        !          1766:                fprintf(zm->statfp,"zmtx: cleanup and exit\n");
        !          1767:        }
        !          1768: 
        !          1769:        return 0;
        !          1770: }
        !          1771: 
        !          1772: #endif
        !          1773: 
        !          1774: const char* zmodem_source(void)
        !          1775: {
        !          1776:        return(__FILE__);
        !          1777: }
        !          1778: 
        !          1779: char* zmodem_ver(char *buf)
        !          1780: {
        !          1781:        sscanf("$Revision: 1.4 $", "%*s %s", buf);
        !          1782: 
        !          1783:        return(buf);
        !          1784: }
        !          1785: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.