Annotation of sbbs/sbbs3/zmodem.c, revision 1.1.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.