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

1.1     ! root        1: /* zmodem.c */
        !             2: 
        !             3: /* Synchronet ZMODEM Functions */
        !             4: 
        !             5: /* $Id: zmodem.c,v 1.71 2006/09/07 00:43:59 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: /*
        !            23:  * zmodem primitives and other code common to zmtx and zmrx
        !            24:  */
        !            25: 
        !            26: #include <stdio.h>
        !            27: #include <string.h>
        !            28: #include <stdarg.h>    /* va_list */
        !            29: #include <sys/stat.h>  /* struct stat */
        !            30: 
        !            31: #include "genwrap.h"
        !            32: #include "dirwrap.h"   /* getfname() */
        !            33: #include "filewrap.h"  /* filelength() */
        !            34: 
        !            35: #include "zmodem.h"
        !            36: #include "crc16.h"
        !            37: #include "crc32.h"
        !            38: 
        !            39: #include "sexyz.h"
        !            40: #include "telnet.h"
        !            41: 
        !            42: #define ENDOFFRAME 2
        !            43: #define FRAMEOK    1
        !            44: #define TIMEOUT   -1   /* rx routine did not receive a character within timeout */
        !            45: #define INVHDR    -2   /* invalid header received; but within timeout */
        !            46: #define ZDLEESC 0x8000 /* one of ZCRCE; ZCRCG; ZCRCQ or ZCRCW was received; ZDLE escaped */
        !            47: 
        !            48: #define BADSUBPKT      0x80
        !            49: 
        !            50: #define HDRLEN     5   /* size of a zmodem header */
        !            51: 
        !            52: static int lprintf(zmodem_t* zm, int level, const char *fmt, ...)
        !            53: {
        !            54:        va_list argptr;
        !            55:        char    sbuf[1024];
        !            56: 
        !            57:        if(zm->lputs==NULL)
        !            58:                return(-1);
        !            59: 
        !            60:     va_start(argptr,fmt);
        !            61:     vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
        !            62:        sbuf[sizeof(sbuf)-1]=0;
        !            63:     va_end(argptr);
        !            64:     return(zm->lputs(zm->cbdata,level,sbuf));
        !            65: }
        !            66: 
        !            67: static BOOL is_connected(zmodem_t* zm)
        !            68: {
        !            69:        if(zm->is_connected!=NULL)
        !            70:                return(zm->is_connected(zm->cbdata));
        !            71:        return(TRUE);
        !            72: }
        !            73: 
        !            74: static BOOL is_cancelled(zmodem_t* zm)
        !            75: {
        !            76:        if(zm->is_cancelled!=NULL)
        !            77:                return(zm->cancelled=zm->is_cancelled(zm->cbdata));
        !            78:        return(zm->cancelled);
        !            79: }
        !            80: int zmodem_data_waiting(zmodem_t* zm, unsigned timeout)
        !            81: {
        !            82:        if(zm->data_waiting)
        !            83:                return(zm->data_waiting(zm->cbdata, timeout));
        !            84:        return(FALSE);
        !            85: }
        !            86: 
        !            87: static char *chr(int ch)
        !            88: {
        !            89:        static char str[25];
        !            90: 
        !            91:        switch(ch) {
        !            92:                case TIMEOUT:   return("TIMEOUT");
        !            93:                case ZRQINIT:   return("ZRQINIT");
        !            94:                case ZRINIT:    return("ZRINIT");
        !            95:                case ZSINIT:    return("ZSINIT");
        !            96:                case ZACK:              return("ZACK");
        !            97:                case ZFILE:             return("ZFILE");
        !            98:                case ZSKIP:             return("ZSKIP");
        !            99:                case ZCRC:              return("ZCRC");
        !           100:                case ZNAK:              return("ZNAK");
        !           101:                case ZABORT:    return("ZABORT");
        !           102:                case ZFIN:              return("ZFIN");
        !           103:                case ZRPOS:             return("ZRPOS");
        !           104:                case ZDATA:             return("ZDATA");
        !           105:                case ZEOF:              return("ZEOF");
        !           106:                case ZPAD:              return("ZPAD");
        !           107:                case ZCAN:              return("ZCAN");
        !           108:                case ZDLE:              return("ZDLE");
        !           109:                case ZDLEE:             return("ZDLEE");
        !           110:                case ZBIN:              return("ZBIN");
        !           111:                case ZHEX:              return("ZHEX");
        !           112:                case ZBIN32:    return("ZBIN32");
        !           113:                case ZRESC:             return("ZRESC");
        !           114:                case ZCRCE:             return("ZCRCE");
        !           115:                case ZCRCG:             return("ZCRCG");
        !           116:                case ZCRCQ:             return("ZCRCQ");
        !           117:                case ZCRCW:             return("ZCRCW");
        !           118: 
        !           119:        }
        !           120:        if(ch>=' ' && ch<='~')
        !           121:                sprintf(str,"'%c' (%02Xh)",(uchar)ch,(uchar)ch);
        !           122:        else
        !           123:                sprintf(str,"%u (%02Xh)",(uchar)ch,(uchar)ch);
        !           124:        return(str); 
        !           125: }
        !           126: 
        !           127: static char* frame_desc(int frame)
        !           128: {
        !           129:        static char str[25];
        !           130: 
        !           131:        if(frame==TIMEOUT)
        !           132:                return("TIMEOUT");
        !           133: 
        !           134:        if(frame==INVHDR)
        !           135:                return("Invalid Header");
        !           136: 
        !           137:        if(frame&BADSUBPKT)
        !           138:                strcpy(str,"BAD ");
        !           139:        else
        !           140:                str[0]=0;
        !           141: 
        !           142:        switch(frame&~BADSUBPKT) {
        !           143:                case ZRQINIT:           strcat(str,"ZRQINIT");          break;
        !           144:                case ZRINIT:            strcat(str,"ZRINIT");           break;
        !           145:                case ZSINIT:            strcat(str,"ZSINIT");           break;
        !           146:                case ZACK:                      strcat(str,"ZACK");                     break;
        !           147:                case ZFILE:                     strcat(str,"ZFILE");            break;
        !           148:                case ZSKIP:                     strcat(str,"ZSKIP");            break;
        !           149:                case ZNAK:                      strcat(str,"ZNAK");                     break;
        !           150:                case ZABORT:            strcat(str,"ZABORT");           break;
        !           151:                case ZFIN:                      strcat(str,"ZFIN");                     break;
        !           152:                case ZRPOS:                     strcat(str,"ZRPOS");            break;
        !           153:                case ZDATA:                     strcat(str,"ZDATA");            break;
        !           154:                case ZEOF:                      strcat(str,"ZEOF");                     break;
        !           155:                case ZFERR:                     strcat(str,"ZFERR");            break;
        !           156:                case ZCRC:                      strcat(str,"ZCRC");                     break;
        !           157:                case ZCHALLENGE:        strcat(str,"ZCHALLENGE");       break;
        !           158:                case ZCOMPL:            strcat(str,"ZCOMPL");           break;
        !           159:                case ZCAN:                      strcat(str,"ZCAN");                     break;
        !           160:                case ZFREECNT:          strcat(str,"ZFREECNT");         break;
        !           161:                case ZCOMMAND:          strcat(str,"ZCOMMAND");         break;  
        !           162:                case ZSTDERR:           strcat(str,"ZSTDERR");          break;          
        !           163:                default: 
        !           164:                        sprintf(str,"Unknown (%08X)", frame);
        !           165:                        break;
        !           166:        }
        !           167:        return(str); 
        !           168: }
        !           169: 
        !           170: 
        !           171: /*
        !           172:  * read bytes as long as rdchk indicates that
        !           173:  * more data is available.
        !           174:  */
        !           175: 
        !           176: void zmodem_recv_purge(zmodem_t* zm)
        !           177: {
        !           178:        while(zm->recv_byte(zm->cbdata,0)>=0);
        !           179: }
        !           180: 
        !           181: /* 
        !           182:  * transmit a character. 
        !           183:  * this is the raw modem interface
        !           184:  */
        !           185: 
        !           186: int zmodem_send_raw(zmodem_t* zm, unsigned char ch)
        !           187: {
        !           188:        int     result;
        !           189: 
        !           190:        if((result=zm->send_byte(zm->cbdata,ch,zm->send_timeout))!=0)
        !           191:                lprintf(zm,LOG_ERR,"send_raw SEND ERROR: %d",result);
        !           192: 
        !           193:        zm->last_sent = ch;
        !           194: 
        !           195:        return result;
        !           196: }
        !           197: 
        !           198: /*
        !           199:  * transmit a character ZDLE escaped
        !           200:  */
        !           201: 
        !           202: int zmodem_send_esc(zmodem_t* zm, unsigned char c)
        !           203: {
        !           204:        int     result;
        !           205: 
        !           206:        if((result=zmodem_send_raw(zm, ZDLE))!=0)
        !           207:                return(result);
        !           208:        /*
        !           209:         * exclusive or; not an or so ZDLE becomes ZDLEE
        !           210:         */
        !           211:        return zmodem_send_raw(zm, (uchar)(c ^ 0x40));
        !           212: }
        !           213: 
        !           214: /*
        !           215:  * transmit a character; ZDLE escaping if appropriate
        !           216:  */
        !           217: 
        !           218: int zmodem_tx(zmodem_t* zm, unsigned char c)
        !           219: {
        !           220:        int result;
        !           221: 
        !           222:        switch (c) {
        !           223:                case DLE:
        !           224:                case DLE|0x80:          /* even if high-bit set */
        !           225:                case XON:
        !           226:                case XON|0x80:
        !           227:                case XOFF:
        !           228:                case XOFF|0x80:
        !           229:                case ZDLE:
        !           230:                        return zmodem_send_esc(zm, c);
        !           231:                case CR:
        !           232:                case CR|0x80:
        !           233:                        if(zm->escape_ctrl_chars && (zm->last_sent&0x7f) == '@')
        !           234:                                return zmodem_send_esc(zm, c);
        !           235:                        break;
        !           236:                case TELNET_IAC:
        !           237:                        if(zm->escape_telnet_iac) {
        !           238:                                if((result=zmodem_send_raw(zm, ZDLE))!=0)
        !           239:                                        return(result);
        !           240:                                return zmodem_send_raw(zm, ZRUB1);
        !           241:                        }
        !           242:                        break;
        !           243:                default:
        !           244:                        if(zm->escape_ctrl_chars && (c&0x60)==0)
        !           245:                                return zmodem_send_esc(zm, c);
        !           246:                        break;
        !           247:        }
        !           248:        /*
        !           249:         * anything that ends here is so normal we might as well transmit it.
        !           250:         */
        !           251:        return zmodem_send_raw(zm, c);
        !           252: }
        !           253: 
        !           254: /**********************************************/
        !           255: /* Output single byte as two hex ASCII digits */
        !           256: /**********************************************/
        !           257: int zmodem_send_hex(zmodem_t* zm, uchar val)
        !           258: {
        !           259:        char* xdigit="0123456789abcdef";
        !           260:        int     result;
        !           261: 
        !           262:        lprintf(zm,LOG_DEBUG,"send_hex: %02X ",val);
        !           263: 
        !           264:        if((result=zmodem_send_raw(zm, xdigit[val>>4]))!=0)
        !           265:                return result;
        !           266:        return zmodem_send_raw(zm, xdigit[val&0xf]);
        !           267: }
        !           268: 
        !           269: int zmodem_send_padded_zdle(zmodem_t* zm)
        !           270: {
        !           271:        int result;
        !           272: 
        !           273:        if((result=zmodem_send_raw(zm, ZPAD))!=0)
        !           274:                return result;
        !           275:        if((result=zmodem_send_raw(zm, ZPAD))!=0)
        !           276:                return result;
        !           277:        return zmodem_send_raw(zm, ZDLE);
        !           278: }
        !           279: 
        !           280: /* 
        !           281:  * transmit a hex header.
        !           282:  * these routines use tx_raw because we're sure that all the
        !           283:  * characters are not to be escaped.
        !           284:  */
        !           285: int zmodem_send_hex_header(zmodem_t* zm, unsigned char * p)
        !           286: {
        !           287:        int i;
        !           288:        int result;
        !           289:        uchar type=*p;
        !           290:        unsigned short int crc;
        !           291: 
        !           292:        lprintf(zm,LOG_DEBUG,"send_hex_header: %s", chr(type));
        !           293: 
        !           294:        if((result=zmodem_send_padded_zdle(zm))!=0)
        !           295:                return result;
        !           296: 
        !           297:        if((result=zmodem_send_raw(zm, ZHEX))!=0)
        !           298:                return result;
        !           299: 
        !           300:        /*
        !           301:         * initialise the crc
        !           302:         */
        !           303: 
        !           304:        crc = 0;
        !           305: 
        !           306:        /*
        !           307:         * transmit the header
        !           308:         */
        !           309: 
        !           310:        for(i=0;i<HDRLEN;i++) {
        !           311:                if((result=zmodem_send_hex(zm, *p))!=0)
        !           312:                        return result;
        !           313:                crc = ucrc16(*p, crc);
        !           314:                p++;
        !           315:        }
        !           316: 
        !           317:        /*
        !           318:         * update the crc as though it were zero
        !           319:         */
        !           320: 
        !           321:        /* 
        !           322:         * transmit the crc
        !           323:         */
        !           324: 
        !           325:        if((result=zmodem_send_hex(zm, (uchar)(crc>>8)))!=0)
        !           326:                return result;
        !           327:        if((result=zmodem_send_hex(zm, (uchar)(crc&0xff)))!=0)
        !           328:                return result;
        !           329: 
        !           330:        /*
        !           331:         * end of line sequence
        !           332:         */
        !           333: 
        !           334:        if((result=zmodem_send_raw(zm, '\r'))!=0)
        !           335:                return result;
        !           336:        if((result=zmodem_send_raw(zm, '\n'))!=0)       /* FDSZ sends 0x8a instead of 0x0a */
        !           337:                return result;
        !           338: 
        !           339:        if(type!=ZACK && type!=ZFIN)
        !           340:                result=zmodem_send_raw(zm, XON);
        !           341: 
        !           342:        return(result);
        !           343: }
        !           344: 
        !           345: /*
        !           346:  * Send ZMODEM binary header hdr
        !           347:  */
        !           348: 
        !           349: int zmodem_send_bin32_header(zmodem_t* zm, unsigned char * p)
        !           350: {
        !           351:        int i;
        !           352:        int result;
        !           353:        unsigned long crc;
        !           354: 
        !           355:        lprintf(zm,LOG_DEBUG,"send_bin32_header: %s", chr(*p));
        !           356: 
        !           357:        if((result=zmodem_send_padded_zdle(zm))!=0)
        !           358:                return result;
        !           359: 
        !           360:        if((result=zmodem_send_raw(zm, ZBIN32))!=0)
        !           361:                return result;
        !           362: 
        !           363:        crc = 0xffffffffL;
        !           364: 
        !           365:        for(i=0;i<HDRLEN;i++) {
        !           366:                crc = ucrc32(*p,crc);
        !           367:                if((result=zmodem_tx(zm, *p++))!=0)
        !           368:                        return result;
        !           369:        }
        !           370: 
        !           371:        crc = ~crc;
        !           372: 
        !           373:        if((result=     zmodem_tx(zm, (uchar)((crc      ) & 0xff)))!=0)
        !           374:                return result;
        !           375:        if((result=     zmodem_tx(zm, (uchar)((crc >>  8) & 0xff)))!=0)
        !           376:                return result;
        !           377:        if((result=     zmodem_tx(zm, (uchar)((crc >> 16) & 0xff)))!=0)
        !           378:                return result;
        !           379:        return          zmodem_tx(zm, (uchar)((crc >> 24) & 0xff));
        !           380: }
        !           381: 
        !           382: int zmodem_send_bin16_header(zmodem_t* zm, unsigned char * p)
        !           383: {
        !           384:        int i;
        !           385:        int result;
        !           386:        unsigned int crc;
        !           387: 
        !           388:        lprintf(zm,LOG_DEBUG,"send_bin16_header: %s", chr(*p));
        !           389: 
        !           390:        if((result=zmodem_send_padded_zdle(zm))!=0)
        !           391:                return result;
        !           392: 
        !           393:        if((result=zmodem_send_raw(zm, ZBIN))!=0)
        !           394:                return result;
        !           395: 
        !           396:        crc = 0;
        !           397: 
        !           398:        for(i=0;i<HDRLEN;i++) {
        !           399:                crc = ucrc16(*p,crc);
        !           400:                if((result=zmodem_tx(zm, *p++))!=0)
        !           401:                        return result;
        !           402:        }
        !           403: 
        !           404:        if((result=     zmodem_tx(zm, (uchar)(crc >> 8)))!=0)
        !           405:                return result;
        !           406:        return          zmodem_tx(zm, (uchar)(crc&0xff));
        !           407: }
        !           408: 
        !           409: 
        !           410: /* 
        !           411:  * transmit a header using either hex 16 bit crc or binary 32 bit crc
        !           412:  * depending on the receivers capabilities
        !           413:  * we dont bother with variable length headers. I dont really see their
        !           414:  * advantage and they would clutter the code unneccesarily
        !           415:  */
        !           416: 
        !           417: int zmodem_send_bin_header(zmodem_t* zm, unsigned char * p)
        !           418: {
        !           419:        if(zm->can_fcs_32 && !zm->want_fcs_16)
        !           420:                return zmodem_send_bin32_header(zm, p);
        !           421:        return zmodem_send_bin16_header(zm, p);
        !           422: }
        !           423: 
        !           424: /*
        !           425:  * data subpacket transmission
        !           426:  */
        !           427: 
        !           428: int zmodem_send_data32(zmodem_t* zm, uchar subpkt_type, unsigned char * p, size_t l)
        !           429: {
        !           430:        int     result;
        !           431:        unsigned long crc;
        !           432: 
        !           433:        lprintf(zm,LOG_DEBUG,"send_data32: %s (%u bytes)", chr(subpkt_type), l);
        !           434: 
        !           435:        crc = 0xffffffffl;
        !           436: 
        !           437:        while(l > 0) {
        !           438:                crc = ucrc32(*p,crc);
        !           439:                if((result=zmodem_tx(zm, *p++))!=0)
        !           440:                        return result;
        !           441:                l--;
        !           442:        }
        !           443: 
        !           444:        crc = ucrc32(subpkt_type, crc);
        !           445: 
        !           446:        if((result=zmodem_send_raw(zm, ZDLE))!=0)
        !           447:                return result;
        !           448:        if((result=zmodem_send_raw(zm, subpkt_type))!=0)
        !           449:                return result;
        !           450: 
        !           451:        crc = ~crc;
        !           452: 
        !           453:        if((result=     zmodem_tx(zm, (uchar) ((crc      ) & 0xff)))!=0)
        !           454:                return result;
        !           455:        if((result=     zmodem_tx(zm, (uchar) ((crc >> 8 ) & 0xff)))!=0)
        !           456:                return result;
        !           457:        if((result=     zmodem_tx(zm, (uchar) ((crc >> 16) & 0xff)))!=0)
        !           458:                return result;
        !           459:        return          zmodem_tx(zm, (uchar) ((crc >> 24) & 0xff));
        !           460: }
        !           461: 
        !           462: int zmodem_send_data16(zmodem_t* zm, uchar subpkt_type,unsigned char * p, size_t l)
        !           463: {
        !           464:        int     result;
        !           465:        unsigned short crc;
        !           466: 
        !           467:        lprintf(zm,LOG_DEBUG,"send_data16: %s (%u bytes)", chr(subpkt_type), l);
        !           468: 
        !           469:        crc = 0;
        !           470: 
        !           471:        while(l > 0) {
        !           472:                crc = ucrc16(*p,crc);
        !           473:                if((result=zmodem_tx(zm, *p++))!=0)
        !           474:                        return result;
        !           475:                l--;
        !           476:        }
        !           477: 
        !           478:        crc = ucrc16(subpkt_type,crc);
        !           479: 
        !           480:        if((result=zmodem_send_raw(zm, ZDLE))!=0)
        !           481:                return result;
        !           482:        if((result=zmodem_send_raw(zm, subpkt_type))!=0)
        !           483:                return result;
        !           484:        
        !           485:        if((result=     zmodem_tx(zm, (uchar)(crc >> 8)))!=0)
        !           486:                return result;
        !           487:        return          zmodem_tx(zm, (uchar)(crc&0xff));
        !           488: }
        !           489: 
        !           490: /*
        !           491:  * send a data subpacket using crc 16 or crc 32 as desired by the receiver
        !           492:  */
        !           493: 
        !           494: int zmodem_send_data(zmodem_t* zm, uchar subpkt_type, unsigned char * p, size_t l)
        !           495: {
        !           496:        int result;
        !           497: 
        !           498:        if(!zm->want_fcs_16 && zm->can_fcs_32) {
        !           499:                if((result=zmodem_send_data32(zm, subpkt_type,p,l))!=0)
        !           500:                        return result;
        !           501:        }
        !           502:        else {  
        !           503:                if((result=zmodem_send_data16(zm, subpkt_type,p,l))!=0)
        !           504:                        return result;
        !           505:        }
        !           506: 
        !           507:        if(subpkt_type == ZCRCW)
        !           508:                result=zmodem_send_raw(zm, XON);
        !           509: 
        !           510:        return result;
        !           511: }
        !           512: 
        !           513: int zmodem_send_pos_header(zmodem_t* zm, int type, long pos, BOOL hex) 
        !           514: {
        !           515:        uchar header[5];
        !           516: 
        !           517:        header[0]   = type;
        !           518:        header[ZP0] = (uchar) (pos        & 0xff);
        !           519:        header[ZP1] = (uchar)((pos >>  8) & 0xff);
        !           520:        header[ZP2] = (uchar)((pos >> 16) & 0xff);
        !           521:        header[ZP3] = (uchar)((pos >> 24) & 0xff);
        !           522: 
        !           523:        if(hex)
        !           524:                return zmodem_send_hex_header(zm, header);
        !           525:        else
        !           526:                return zmodem_send_bin_header(zm, header);
        !           527: }
        !           528: 
        !           529: int zmodem_send_ack(zmodem_t* zm, long pos)
        !           530: {
        !           531:        return zmodem_send_pos_header(zm, ZACK, pos, /* Hex? */ TRUE);
        !           532: }
        !           533: 
        !           534: int zmodem_send_nak(zmodem_t* zm)
        !           535: {
        !           536:        return zmodem_send_pos_header(zm, ZNAK, 0, /* Hex? */ TRUE);
        !           537: }
        !           538: 
        !           539: int zmodem_send_zfin(zmodem_t* zm)
        !           540: {
        !           541:        unsigned char zfin_header[] = { ZFIN, 0, 0, 0, 0 };
        !           542: 
        !           543:        return zmodem_send_hex_header(zm,zfin_header);
        !           544: }
        !           545: 
        !           546: int zmodem_abort_receive(zmodem_t* zm)
        !           547: {
        !           548:        lprintf(zm,LOG_WARNING,"Aborting receive");
        !           549:        return zmodem_send_pos_header(zm, ZABORT, 0, /* Hex? */ TRUE);
        !           550: }
        !           551: 
        !           552: int zmodem_send_znak(zmodem_t* zm)
        !           553: {
        !           554:        return zmodem_send_pos_header(zm, ZNAK, zm->ack_file_pos, /* Hex? */ TRUE);
        !           555: }
        !           556: 
        !           557: int zmodem_send_zskip(zmodem_t* zm)
        !           558: {
        !           559:        return zmodem_send_pos_header(zm, ZSKIP, 0L, /* Hex? */ TRUE);
        !           560: }
        !           561: 
        !           562: int zmodem_send_zeof(zmodem_t* zm)
        !           563: {
        !           564:        return zmodem_send_pos_header(zm, ZEOF, zm->current_file_size, /* Hex? */ TRUE);
        !           565: }
        !           566: 
        !           567: 
        !           568: /*
        !           569:  * rx_raw ; receive a single byte from the line.
        !           570:  * reads as many are available and then processes them one at a time
        !           571:  * check the data stream for 5 consecutive CAN characters;
        !           572:  * and if you see them abort. this saves a lot of clutter in
        !           573:  * the rest of the code; even though it is a very strange place
        !           574:  * for an exit. (but that was wat session abort was all about.)
        !           575:  */
        !           576: 
        !           577: int zmodem_recv_raw(zmodem_t* zm)
        !           578: {
        !           579:        int c;
        !           580: 
        !           581:        if((c=zm->recv_byte(zm->cbdata,zm->recv_timeout)) < 0)
        !           582:                return(TIMEOUT);
        !           583: 
        !           584:        if(c == CAN) {
        !           585:                zm->n_cans++;
        !           586:                if(zm->n_cans == 5) {
        !           587:                        zm->cancelled=TRUE;
        !           588:                        lprintf(zm,LOG_WARNING,"recv_raw: Cancelled remotely");
        !           589: /*                     return(TIMEOUT);        removed June-12-2005 */
        !           590:                }
        !           591:        }
        !           592:        else {
        !           593:                zm->n_cans = 0;
        !           594:        }
        !           595: 
        !           596:        return c;
        !           597: }
        !           598: 
        !           599: /*
        !           600:  * rx; receive a single byte undoing any escaping at the
        !           601:  * sending site. this bit looks like a mess. sorry for that
        !           602:  * but there seems to be no other way without incurring a lot
        !           603:  * of overhead. at least like this the path for a normal character
        !           604:  * is relatively short.
        !           605:  */
        !           606: 
        !           607: int zmodem_rx(zmodem_t* zm)
        !           608: {
        !           609:        int c;
        !           610: 
        !           611:        /*
        !           612:         * outer loop for ever so for sure something valid
        !           613:         * will come in; a timeout will occur or a session abort
        !           614:         * will be received.
        !           615:         */
        !           616: 
        !           617:        while(is_connected(zm)) {
        !           618: 
        !           619:                while(TRUE) {
        !           620:                        if((c = zmodem_recv_raw(zm)) < 0)
        !           621:                                return(c);
        !           622:        
        !           623:                        switch (c) {
        !           624:                                case ZDLE:
        !           625:                                        break;
        !           626:                                case XON:
        !           627:                                case XON|0x80:
        !           628:                                case XOFF:
        !           629:                                case XOFF|0x80:
        !           630:                                        continue;                       
        !           631:                                default:
        !           632:                                        /*
        !           633:                                         * if all control characters should be escaped and 
        !           634:                                         * this one wasnt then its spurious and should be dropped.
        !           635:                                         */
        !           636:                                        if(zm->escape_ctrl_chars && (c & 0x60) == 0) {
        !           637:                                                continue;
        !           638:                                        }
        !           639:                                        /*
        !           640:                                         * normal character; return it.
        !           641:                                         */
        !           642:                                        return c;
        !           643:                        }
        !           644:                        break;
        !           645:                }
        !           646:        
        !           647:                /*
        !           648:                 * ZDLE encoded sequence or session abort.
        !           649:                 * (or something illegal; then back to the top)
        !           650:                 */
        !           651: 
        !           652:                while(TRUE) {
        !           653:                        if((c = zmodem_recv_raw(zm)) < 0)
        !           654:                                return(c);
        !           655: 
        !           656:                        if(c == XON || c == (XON|0x80) || c == XOFF || c == (XOFF|0x80) || c == ZDLE) {
        !           657:                                /*
        !           658:                                 * these can be dropped.
        !           659:                                 */
        !           660:                                continue;
        !           661:                        }
        !           662: 
        !           663:                        switch (c) {
        !           664:                                /*
        !           665:                                 * these four are really nasty.
        !           666:                                 * for convenience we just change them into 
        !           667:                                 * special characters by setting a bit outside the
        !           668:                                 * first 8. that way they can be recognized and still
        !           669:                                 * be processed as characters by the rest of the code.
        !           670:                                 */
        !           671:                                case ZCRCE:
        !           672:                                case ZCRCG:
        !           673:                                case ZCRCQ:
        !           674:                                case ZCRCW:
        !           675:                                        lprintf(zm,LOG_DEBUG,"rx: encoding data subpacket type: %s"
        !           676:                                                ,chr(c));
        !           677:                                        return (c | ZDLEESC);
        !           678:                                case ZRUB0:
        !           679:                                        return 0x7f;
        !           680:                                case ZRUB1:
        !           681:                                        return 0xff;
        !           682:                                default:
        !           683:                                        if(zm->escape_ctrl_chars && (c & 0x60) == 0) {
        !           684:                                                /*
        !           685:                                                 * a not escaped control character; probably
        !           686:                                                 * something from a network. just drop it.
        !           687:                                                 */
        !           688:                                                continue;
        !           689:                                        }
        !           690:                                        /*
        !           691:                                         * legitimate escape sequence.
        !           692:                                         * rebuild the orignal and return it.
        !           693:                                         */
        !           694:                                        if((c & 0x60) == 0x40) {
        !           695:                                                return c ^ 0x40;
        !           696:                                        }
        !           697:                                        lprintf(zm,LOG_WARNING,"rx: illegal sequence: ZDLE %s"
        !           698:                                                ,chr(c));
        !           699:                                        break;
        !           700:                        }
        !           701:                        break;
        !           702:                } 
        !           703:        }
        !           704: 
        !           705:        /*
        !           706:         * not reached.
        !           707:         */
        !           708: 
        !           709:        return 0;
        !           710: }
        !           711: 
        !           712: /*
        !           713:  * receive a data subpacket as dictated by the last received header.
        !           714:  * return 2 with correct packet and end of frame
        !           715:  * return 1 with correct packet frame continues
        !           716:  * return 0 with incorrect frame.
        !           717:  * return TIMEOUT with a timeout
        !           718:  * if an acknowledgement is requested it is generated automatically
        !           719:  * here. 
        !           720:  */
        !           721: 
        !           722: /*
        !           723:  * data subpacket reception
        !           724:  */
        !           725: 
        !           726: int zmodem_recv_data32(zmodem_t* zm, unsigned char * p, unsigned maxlen, unsigned* l)
        !           727: {
        !           728:        int c;
        !           729:        unsigned long rxd_crc;
        !           730:        unsigned long crc;
        !           731:        int subpkt_type;
        !           732: 
        !           733:        lprintf(zm,LOG_DEBUG,"recv_data32");
        !           734: 
        !           735:        crc = 0xffffffffl;
        !           736: 
        !           737:        do {
        !           738:                c = zmodem_rx(zm);
        !           739: 
        !           740:                if(c == TIMEOUT) {
        !           741:                        return TIMEOUT;
        !           742:                }
        !           743:                if(c < 0x100 && *l < maxlen) {
        !           744:                        crc = ucrc32(c,crc);
        !           745:                        *p++ = c;
        !           746:                        (*l)++;
        !           747:                        continue;
        !           748:                }
        !           749:        } while(c < 0x100);
        !           750: 
        !           751:        subpkt_type = c & 0xff;
        !           752: 
        !           753:        crc = ucrc32(subpkt_type, crc);
        !           754: 
        !           755:        crc = ~crc;
        !           756: 
        !           757:        rxd_crc  = zmodem_rx(zm);
        !           758:        rxd_crc |= zmodem_rx(zm) << 8;
        !           759:        rxd_crc |= zmodem_rx(zm) << 16;
        !           760:        rxd_crc |= zmodem_rx(zm) << 24;
        !           761: 
        !           762:        if(rxd_crc != crc) {
        !           763:                lprintf(zm,LOG_WARNING,"CRC32 ERROR (%08lX, expected: %08lX) Bytes=%u, subpacket-type=%s"
        !           764:                        ,rxd_crc, crc, *l, chr(subpkt_type));
        !           765:                return FALSE;
        !           766:        }
        !           767:        lprintf(zm,LOG_DEBUG,"GOOD CRC32: %08lX (Bytes=%u, subpacket-type=%s)"
        !           768:                ,crc, *l, chr(subpkt_type));
        !           769: 
        !           770:        zm->ack_file_pos += *l;
        !           771: 
        !           772:        return subpkt_type;
        !           773: }
        !           774: 
        !           775: int zmodem_recv_data16(zmodem_t* zm, register unsigned char* p, unsigned maxlen, unsigned* l)
        !           776: {
        !           777:        int c;
        !           778:        int subpkt_type;
        !           779:        unsigned short crc;
        !           780:        unsigned short rxd_crc;
        !           781: 
        !           782:        lprintf(zm,LOG_DEBUG,"recv_data16");
        !           783: 
        !           784:        crc = 0;
        !           785: 
        !           786:        do {
        !           787:                c = zmodem_rx(zm);
        !           788: 
        !           789:                if(c == TIMEOUT) {
        !           790:                        return TIMEOUT;
        !           791:                }
        !           792:                if(c < 0x100 && *l < maxlen) {
        !           793:                        crc = ucrc16(c,crc);
        !           794:                        *p++ = c;
        !           795:                        (*l)++;
        !           796:                }
        !           797:        } while(c < 0x100);
        !           798: 
        !           799:        subpkt_type = c & 0xff;
        !           800: 
        !           801:        crc = ucrc16(subpkt_type,crc);
        !           802: 
        !           803:        rxd_crc  = zmodem_rx(zm) << 8;
        !           804:        rxd_crc |= zmodem_rx(zm);
        !           805: 
        !           806:        if(rxd_crc != crc) {
        !           807:                lprintf(zm,LOG_WARNING,"CRC16 ERROR (%04hX, expected: %04hX) Bytes=%d"
        !           808:                        ,rxd_crc, crc, *l);
        !           809:                return FALSE;
        !           810:        }
        !           811:        lprintf(zm,LOG_DEBUG,"GOOD CRC16: %04hX (Bytes=%d)", crc, *l);
        !           812: 
        !           813:        zm->ack_file_pos += *l;
        !           814: 
        !           815:        return subpkt_type;
        !           816: }
        !           817: 
        !           818: int zmodem_recv_data(zmodem_t* zm, unsigned char* p, size_t maxlen, unsigned* l, BOOL ack)
        !           819: {
        !           820:        int subpkt_type;
        !           821:        unsigned n=0;
        !           822: 
        !           823:        if(l==NULL)
        !           824:                l=&n;
        !           825: 
        !           826:        lprintf(zm,LOG_DEBUG,"recv_data (%u-bit)", zm->receive_32bit_data ? 32:16);
        !           827: 
        !           828:        /*
        !           829:         * receive the right type of frame
        !           830:         */
        !           831: 
        !           832:        *l = 0;
        !           833: 
        !           834:        if(zm->receive_32bit_data) {
        !           835:                subpkt_type = zmodem_recv_data32(zm, p, maxlen, l);
        !           836:        }
        !           837:        else {  
        !           838:                subpkt_type = zmodem_recv_data16(zm, p, maxlen, l);
        !           839:        }
        !           840: 
        !           841:        if(subpkt_type==FALSE)
        !           842:                return(FALSE);
        !           843:        
        !           844:        if(subpkt_type==TIMEOUT)
        !           845:                return(TIMEOUT);
        !           846:        
        !           847:        lprintf(zm,LOG_DEBUG,"recv_data received subpacket-type: %s"
        !           848:                ,chr(subpkt_type));
        !           849: 
        !           850:        switch (subpkt_type)  {
        !           851:                /*
        !           852:                 * frame continues non-stop
        !           853:                 */
        !           854:                case ZCRCG:
        !           855:                        return FRAMEOK;
        !           856:                /*
        !           857:                 * frame ends
        !           858:                 */
        !           859:                case ZCRCE:
        !           860:                        return ENDOFFRAME;
        !           861:                /*
        !           862:                 * frame continues; ZACK expected
        !           863:                 */
        !           864:                case ZCRCQ:             
        !           865:                        if(ack)
        !           866:                                zmodem_send_ack(zm, zm->ack_file_pos);
        !           867:                        return FRAMEOK;
        !           868:                /*
        !           869:                 * frame ends; ZACK expected
        !           870:                 */
        !           871:                case ZCRCW:
        !           872:                        if(ack)
        !           873:                                zmodem_send_ack(zm, zm->ack_file_pos);
        !           874:                        return ENDOFFRAME;
        !           875:        }
        !           876: 
        !           877:        lprintf(zm,LOG_WARNING,"Invalid subpacket-type: %s",chr(subpkt_type));
        !           878: 
        !           879:        return FALSE;
        !           880: }
        !           881: 
        !           882: BOOL zmodem_recv_subpacket(zmodem_t* zm, BOOL ack)
        !           883: {
        !           884:        int type;
        !           885: 
        !           886:        type=zmodem_recv_data(zm,zm->rx_data_subpacket,sizeof(zm->rx_data_subpacket),NULL,ack);
        !           887:        if(type!=FRAMEOK && type!=ENDOFFRAME) {
        !           888:                zmodem_send_nak(zm);
        !           889:                return(FALSE);
        !           890:        }
        !           891: 
        !           892:        return(TRUE);
        !           893: }
        !           894: 
        !           895: int zmodem_recv_nibble(zmodem_t* zm) 
        !           896: {
        !           897:        int c;
        !           898: 
        !           899:        c = zmodem_rx(zm);
        !           900: 
        !           901:        if(c == TIMEOUT) {
        !           902:                return c;
        !           903:        }
        !           904: 
        !           905:        if(c > '9') {
        !           906:                if(c < 'a' || c > 'f') {
        !           907:                        /*
        !           908:                         * illegal hex; different than expected.
        !           909:                         * we might as well time out.
        !           910:                         */
        !           911:                        return TIMEOUT;
        !           912:                }
        !           913: 
        !           914:                c -= 'a' - 10;
        !           915:        }
        !           916:        else {
        !           917:                if(c < '0') {
        !           918:                        /*
        !           919:                         * illegal hex; different than expected.
        !           920:                         * we might as well time out.
        !           921:                         */
        !           922:                        return TIMEOUT;
        !           923:                }
        !           924:                c -= '0';
        !           925:        }
        !           926: 
        !           927:        return c;
        !           928: }
        !           929: 
        !           930: int zmodem_recv_hex(zmodem_t* zm)
        !           931: {
        !           932:        int n1;
        !           933:        int n0;
        !           934:        int ret;
        !           935: 
        !           936:        n1 = zmodem_recv_nibble(zm);
        !           937: 
        !           938:        if(n1 == TIMEOUT) {
        !           939:                return n1;
        !           940:        }
        !           941: 
        !           942:        n0 = zmodem_recv_nibble(zm);
        !           943: 
        !           944:        if(n0 == TIMEOUT) {
        !           945:                return n0;
        !           946:        }
        !           947: 
        !           948:        ret = (n1 << 4) | n0;
        !           949: 
        !           950:        lprintf(zm,LOG_DEBUG,"recv_hex returning: 0x%02X", ret);
        !           951: 
        !           952:        return ret;
        !           953: }
        !           954: 
        !           955: /*
        !           956:  * receive routines for each of the six different styles of header.
        !           957:  * each of these leaves zm->rxd_header_len set to 0 if the end result is
        !           958:  * not a valid header.
        !           959:  */
        !           960: 
        !           961: BOOL zmodem_recv_bin16_header(zmodem_t* zm)
        !           962: {
        !           963:        int c;
        !           964:        int n;
        !           965:        unsigned short int crc;
        !           966:        unsigned short int rxd_crc;
        !           967: 
        !           968:        lprintf(zm,LOG_DEBUG,"recv_bin16_header");
        !           969: 
        !           970:        crc = 0;
        !           971: 
        !           972:        for(n=0;n<HDRLEN;n++) {
        !           973:                c = zmodem_rx(zm);
        !           974:                if(c == TIMEOUT) {
        !           975:                        lprintf(zm,LOG_WARNING,"recv_bin16_header: timeout");
        !           976:                        return(FALSE);
        !           977:                }
        !           978:                crc = ucrc16(c,crc);
        !           979:                zm->rxd_header[n] = c;
        !           980:        }
        !           981: 
        !           982:        rxd_crc  = zmodem_rx(zm) << 8;
        !           983:        rxd_crc |= zmodem_rx(zm);
        !           984: 
        !           985:        if(rxd_crc != crc) {
        !           986:                lprintf(zm,LOG_WARNING,"CRC16 ERROR: 0x%hX, expected: 0x%hX", rxd_crc, crc);
        !           987:                return(FALSE);
        !           988:        }
        !           989:        lprintf(zm,LOG_DEBUG,"GOOD CRC16: %04hX", crc);
        !           990: 
        !           991:        zm->rxd_header_len = 5;
        !           992: 
        !           993:        return(TRUE);
        !           994: }
        !           995: 
        !           996: void zmodem_recv_hex_header(zmodem_t* zm)
        !           997: {
        !           998:        int c;
        !           999:        int i;
        !          1000:        unsigned short int crc = 0;
        !          1001:        unsigned short int rxd_crc;
        !          1002: 
        !          1003:        lprintf(zm,LOG_DEBUG,"recv_hex_header");
        !          1004: 
        !          1005:        for(i=0;i<HDRLEN;i++) {
        !          1006:                c = zmodem_recv_hex(zm);
        !          1007:                if(c == TIMEOUT) {
        !          1008:                        return;
        !          1009:                }
        !          1010:                crc = ucrc16(c,crc);
        !          1011: 
        !          1012:                zm->rxd_header[i] = c;
        !          1013:        }
        !          1014: 
        !          1015:        /*
        !          1016:         * receive the crc
        !          1017:         */
        !          1018: 
        !          1019:        c = zmodem_recv_hex(zm);
        !          1020: 
        !          1021:        if(c == TIMEOUT) {
        !          1022:                return;
        !          1023:        }
        !          1024: 
        !          1025:        rxd_crc = c << 8;
        !          1026: 
        !          1027:        c = zmodem_recv_hex(zm);
        !          1028: 
        !          1029:        if(c == TIMEOUT) {
        !          1030:                return;
        !          1031:        }
        !          1032: 
        !          1033:        rxd_crc |= c;
        !          1034: 
        !          1035:        if(rxd_crc == crc) {
        !          1036:                lprintf(zm,LOG_DEBUG,"GOOD CRC16: %04hX", crc);
        !          1037:                zm->rxd_header_len = 5;
        !          1038:        }
        !          1039:        else {
        !          1040:                lprintf(zm,LOG_WARNING,"CRC16 ERROR: 0x%hX, expected: 0x%hX", rxd_crc, crc);
        !          1041:        }
        !          1042: 
        !          1043:        /*
        !          1044:         * drop the end of line sequence after a hex header
        !          1045:         */
        !          1046:        c = zmodem_rx(zm);
        !          1047:        if(c == '\r') {
        !          1048:                /*
        !          1049:                 * both are expected with CR
        !          1050:                 */
        !          1051:                zmodem_rx(zm);  /* drop LF */
        !          1052:        }
        !          1053: }
        !          1054: 
        !          1055: BOOL zmodem_recv_bin32_header(zmodem_t* zm)
        !          1056: {
        !          1057:        int c;
        !          1058:        int n;
        !          1059:        unsigned long crc;
        !          1060:        unsigned long rxd_crc;
        !          1061: 
        !          1062:        lprintf(zm,LOG_DEBUG,"recv_bin32_header");
        !          1063: 
        !          1064:        crc = 0xffffffffL;
        !          1065: 
        !          1066:        for(n=0;n<HDRLEN;n++) {
        !          1067:                c = zmodem_rx(zm);
        !          1068:                if(c == TIMEOUT) {
        !          1069:                        return(TRUE);
        !          1070:                }
        !          1071:                crc = ucrc32(c,crc);
        !          1072:                zm->rxd_header[n] = c;
        !          1073:        }
        !          1074: 
        !          1075:        crc = ~crc;
        !          1076: 
        !          1077:        rxd_crc  = zmodem_rx(zm);
        !          1078:        rxd_crc |= zmodem_rx(zm) << 8;
        !          1079:        rxd_crc |= zmodem_rx(zm) << 16;
        !          1080:        rxd_crc |= zmodem_rx(zm) << 24;
        !          1081: 
        !          1082:        if(rxd_crc != crc) {
        !          1083:                lprintf(zm,LOG_WARNING,"CRC32 ERROR (%08lX, expected: %08lX)"
        !          1084:                        ,rxd_crc, crc);
        !          1085:                return(FALSE);
        !          1086:        }
        !          1087:        lprintf(zm,LOG_DEBUG,"GOOD CRC32: %08lX", crc);
        !          1088: 
        !          1089:        zm->rxd_header_len = 5;
        !          1090:        return(TRUE);
        !          1091: }
        !          1092: 
        !          1093: /*
        !          1094:  * receive any style header
        !          1095:  * if the errors flag is set than whenever an invalid header packet is
        !          1096:  * received INVHDR will be returned. otherwise we wait for a good header
        !          1097:  * also; a flag (receive_32bit_data) will be set to indicate whether data
        !          1098:  * packets following this header will have 16 or 32 bit data attached.
        !          1099:  * variable headers are not implemented.
        !          1100:  */
        !          1101: 
        !          1102: int zmodem_recv_header_raw(zmodem_t* zm, int errors)
        !          1103: {
        !          1104:        int c;
        !          1105:        int     frame_type;
        !          1106: 
        !          1107:        lprintf(zm,LOG_DEBUG,"recv_header_raw");
        !          1108: 
        !          1109:        zm->rxd_header_len = 0;
        !          1110: 
        !          1111:        do {
        !          1112:                do {
        !          1113:                        if((c = zmodem_recv_raw(zm)) < 0)
        !          1114:                                return(c);
        !          1115:                        if(is_cancelled(zm))
        !          1116:                                return(ZCAN);
        !          1117:                } while(c != ZPAD);
        !          1118: 
        !          1119:                if((c = zmodem_recv_raw(zm)) < 0)
        !          1120:                        return(c);
        !          1121: 
        !          1122:                if(c == ZPAD) {
        !          1123:                        if((c = zmodem_recv_raw(zm)) < 0)
        !          1124:                                return(c);
        !          1125:                }
        !          1126: 
        !          1127:                /*
        !          1128:                 * spurious ZPAD check
        !          1129:                 */
        !          1130: 
        !          1131:                if(c != ZDLE) {
        !          1132:                        lprintf(zm,LOG_WARNING,"recv_header_raw: Expected ZDLE, received: %s"
        !          1133:                                ,chr(c));
        !          1134:                        continue;
        !          1135:                }
        !          1136: 
        !          1137:                /*
        !          1138:                 * now read the header style
        !          1139:                 */
        !          1140: 
        !          1141:                c = zmodem_rx(zm);
        !          1142: 
        !          1143:                if(c == TIMEOUT) {
        !          1144:                        lprintf(zm,LOG_WARNING,"recv_header_raw: TIMEOUT");
        !          1145:                        return c;
        !          1146:                }
        !          1147: 
        !          1148:                switch (c) {
        !          1149:                        case ZBIN:
        !          1150:                                zmodem_recv_bin16_header(zm);
        !          1151:                                zm->receive_32bit_data = FALSE;
        !          1152:                                break;
        !          1153:                        case ZHEX:
        !          1154:                                zmodem_recv_hex_header(zm);
        !          1155:                                zm->receive_32bit_data = FALSE;
        !          1156:                                break;
        !          1157:                        case ZBIN32:
        !          1158:                                zmodem_recv_bin32_header(zm);
        !          1159:                                zm->receive_32bit_data = TRUE;
        !          1160:                                break;
        !          1161:                        default:
        !          1162:                                /*
        !          1163:                                 * unrecognized header style
        !          1164:                                 */
        !          1165:                                lprintf(zm,LOG_ERR,"recv_header_raw: UNRECOGNIZED header style: %s"
        !          1166:                                        ,chr(c));
        !          1167:                                if(errors) {
        !          1168:                                        return INVHDR;
        !          1169:                                }
        !          1170: 
        !          1171:                                continue;
        !          1172:                }
        !          1173:                if(errors && zm->rxd_header_len == 0) {
        !          1174:                        return INVHDR;
        !          1175:                }
        !          1176: 
        !          1177:        } while(zm->rxd_header_len == 0 && !is_cancelled(zm));
        !          1178: 
        !          1179:        if(is_cancelled(zm))
        !          1180:                return(ZCAN);
        !          1181: 
        !          1182:        /*
        !          1183:         * this appears to have been a valid header.
        !          1184:         * return its type.
        !          1185:         */
        !          1186: 
        !          1187:        frame_type = zm->rxd_header[0];
        !          1188: 
        !          1189:        zm->rxd_header_pos = zm->rxd_header[ZP0] | (zm->rxd_header[ZP1] << 8) |
        !          1190:                                (zm->rxd_header[ZP2] << 16) | (zm->rxd_header[ZP3] << 24);
        !          1191: 
        !          1192:        switch(frame_type) {
        !          1193:                case ZCRC:
        !          1194:                        zm->crc_request = zm->rxd_header_pos;
        !          1195:                        break;
        !          1196:                case ZDATA:
        !          1197:                        zm->ack_file_pos = zm->rxd_header_pos;
        !          1198:                        break;
        !          1199:                case ZFILE:
        !          1200:                        zm->ack_file_pos = 0l;
        !          1201:                        if(!zmodem_recv_subpacket(zm,/* ack? */FALSE))
        !          1202:                                frame_type |= BADSUBPKT;
        !          1203:                        break;
        !          1204:                case ZSINIT:
        !          1205:                case ZCOMMAND:
        !          1206:                        if(!zmodem_recv_subpacket(zm,/* ack? */TRUE))
        !          1207:                                frame_type |= BADSUBPKT;
        !          1208:                        break;
        !          1209:                case ZFREECNT:
        !          1210:                        zmodem_send_pos_header(zm, ZACK, getfreediskspace(".",1), /* Hex? */ TRUE);
        !          1211:                        break;
        !          1212:        }
        !          1213: 
        !          1214: #if 0 /*def _DEBUG */
        !          1215:        lprintf(zm,LOG_DEBUG,"recv_header_raw received header type: %s"
        !          1216:                ,frame_desc(frame_type));
        !          1217: #endif
        !          1218: 
        !          1219:        return frame_type;
        !          1220: }
        !          1221: 
        !          1222: int zmodem_recv_header(zmodem_t* zm)
        !          1223: {
        !          1224:        int ret;
        !          1225:        
        !          1226:        ret = zmodem_recv_header_raw(zm, FALSE);
        !          1227: 
        !          1228:        if(ret == TIMEOUT)
        !          1229:                lprintf(zm,LOG_WARNING,"recv_header TIMEOUT");
        !          1230:        else if(ret == INVHDR)
        !          1231:                lprintf(zm,LOG_WARNING,"recv_header detected an invalid header");
        !          1232:        else
        !          1233:                lprintf(zm,LOG_DEBUG,"recv_header returning: %s (pos=%ld)"
        !          1234:                        ,frame_desc(ret), zm->rxd_header_pos);
        !          1235: 
        !          1236:        if(ret==ZCAN)
        !          1237:                zm->cancelled=TRUE;
        !          1238: 
        !          1239:        return ret;
        !          1240: }
        !          1241: 
        !          1242: int zmodem_recv_header_and_check(zmodem_t* zm)
        !          1243: {
        !          1244:        int type;
        !          1245: 
        !          1246:        while(is_connected(zm)) {
        !          1247:                type = zmodem_recv_header_raw(zm,TRUE);         
        !          1248: 
        !          1249:                if(type != INVHDR && (type&BADSUBPKT) == 0) {
        !          1250:                        break;
        !          1251:                }
        !          1252: 
        !          1253:                zmodem_send_znak(zm);
        !          1254:        }
        !          1255: 
        !          1256:        return type;
        !          1257: }
        !          1258: 
        !          1259: BOOL zmodem_get_crc(zmodem_t* zm, long length, ulong* crc)
        !          1260: {
        !          1261:        zmodem_send_pos_header(zm,ZCRC,length,TRUE);
        !          1262:        if(!zmodem_data_waiting(zm,zm->crc_timeout*1000))
        !          1263:                return(FALSE);
        !          1264:        if(zmodem_recv_header(zm)!=ZCRC)
        !          1265:                return(FALSE);
        !          1266:        if(crc!=NULL)
        !          1267:                *crc = zm->crc_request;
        !          1268:        return(TRUE);
        !          1269: }
        !          1270: 
        !          1271: void zmodem_parse_zrinit(zmodem_t* zm)
        !          1272: {
        !          1273:        zm->can_full_duplex                                     = INT_TO_BOOL(zm->rxd_header[ZF0] & ZF0_CANFDX);
        !          1274:        zm->can_overlap_io                                      = INT_TO_BOOL(zm->rxd_header[ZF0] & ZF0_CANOVIO);
        !          1275:        zm->can_break                                           = INT_TO_BOOL(zm->rxd_header[ZF0] & ZF0_CANBRK);
        !          1276:        zm->can_fcs_32                                          = INT_TO_BOOL(zm->rxd_header[ZF0] & ZF0_CANFC32);
        !          1277:        zm->escape_ctrl_chars                           = INT_TO_BOOL(zm->rxd_header[ZF0] & ZF0_ESCCTL);
        !          1278:        zm->escape_8th_bit                                      = INT_TO_BOOL(zm->rxd_header[ZF0] & ZF0_ESC8);
        !          1279: 
        !          1280:        lprintf(zm,LOG_INFO,"Receiver requested mode (0x%02X):\r\n"
        !          1281:                "%s-duplex, %s overlap I/O, CRC-%u, Escape: %s"
        !          1282:                ,zm->rxd_header[ZF0]
        !          1283:                ,zm->can_full_duplex ? "Full" : "Half"
        !          1284:                ,zm->can_overlap_io ? "Can" : "Cannot"
        !          1285:                ,zm->can_fcs_32 ? 32 : 16
        !          1286:                ,zm->escape_ctrl_chars ? "ALL" : "Normal"
        !          1287:                );
        !          1288: 
        !          1289:        if((zm->recv_bufsize = (zm->rxd_header[ZP0] | zm->rxd_header[ZP1]<<8)) != 0)
        !          1290:                lprintf(zm,LOG_INFO,"Receiver specified buffer size of: %u", zm->recv_bufsize);
        !          1291: }
        !          1292: 
        !          1293: int zmodem_get_zrinit(zmodem_t* zm)
        !          1294: {
        !          1295:        unsigned char zrqinit_header[] = { ZRQINIT, /* ZF3: */0, 0, 0, /* ZF0: */0 };
        !          1296:        /* Note: sz/dsz/fdsz sends 0x80 in ZF3 because it supports var-length headers. */
        !          1297:        /* We do not, so we send 0x00, resulting in a CRC-16 value of 0x0000 as well. */
        !          1298: 
        !          1299:        zmodem_send_raw(zm,'r');
        !          1300:        zmodem_send_raw(zm,'z');
        !          1301:        zmodem_send_raw(zm,'\r');
        !          1302:        zmodem_send_hex_header(zm,zrqinit_header);
        !          1303:        
        !          1304:        if(!zmodem_data_waiting(zm,zm->init_timeout*1000))
        !          1305:                return(TIMEOUT);
        !          1306:        return zmodem_recv_header(zm);
        !          1307: }
        !          1308: 
        !          1309: int zmodem_send_zrinit(zmodem_t* zm)
        !          1310: {
        !          1311:        unsigned char zrinit_header[] = { ZRINIT, 0, 0, 0, 0 };
        !          1312:        
        !          1313:        zrinit_header[ZF0] = ZF0_CANFDX;
        !          1314: 
        !          1315:        if(!zm->no_streaming)
        !          1316:                zrinit_header[ZF0] |= ZF0_CANOVIO;
        !          1317: 
        !          1318:        if(zm->can_break)
        !          1319:                zrinit_header[ZF0] |= ZF0_CANBRK;
        !          1320: 
        !          1321:        if(!zm->want_fcs_16)
        !          1322:                zrinit_header[ZF0] |= ZF0_CANFC32;
        !          1323: 
        !          1324:        if(zm->escape_ctrl_chars)
        !          1325:                zrinit_header[ZF0] |= ZF0_ESCCTL;
        !          1326: 
        !          1327:        if(zm->escape_8th_bit)
        !          1328:                zrinit_header[ZF0] |= ZF0_ESC8;
        !          1329: 
        !          1330:        if(zm->no_streaming && zm->recv_bufsize==0)
        !          1331:                zm->recv_bufsize = sizeof(zm->rx_data_subpacket);
        !          1332: 
        !          1333:        zrinit_header[ZP0] = zm->recv_bufsize & 0xff;
        !          1334:        zrinit_header[ZP1] = zm->recv_bufsize >> 8;
        !          1335: 
        !          1336:        return zmodem_send_hex_header(zm, zrinit_header);
        !          1337: }
        !          1338: 
        !          1339: int zmodem_get_zfin(zmodem_t* zm)
        !          1340: {
        !          1341:        int type;
        !          1342: 
        !          1343:        zmodem_send_zfin(zm);
        !          1344:        do {
        !          1345:                type = zmodem_recv_header(zm);
        !          1346:        } while(type != ZFIN && type != TIMEOUT && is_connected(zm));
        !          1347:        
        !          1348:        /*
        !          1349:         * these Os are formally required; but they don't do a thing
        !          1350:         * unfortunately many programs require them to exit 
        !          1351:         * (both programs already sent a ZFIN so why bother ?)
        !          1352:         */
        !          1353: 
        !          1354:        if(type != TIMEOUT) {
        !          1355:                zmodem_send_raw(zm,'O');
        !          1356:                zmodem_send_raw(zm,'O');
        !          1357:        }
        !          1358: 
        !          1359:        return 0;
        !          1360: }
        !          1361: 
        !          1362: 
        !          1363: /*
        !          1364:  * send from the current position in the file
        !          1365:  * all the way to end of file or until something goes wrong.
        !          1366:  * (ZNAK or ZRPOS received)
        !          1367:  * the name is only used to show progress
        !          1368:  */
        !          1369: 
        !          1370: int zmodem_send_from(zmodem_t* zm, FILE* fp, ulong pos, ulong* sent)
        !          1371: {
        !          1372:        size_t n;
        !          1373:        uchar type;
        !          1374:        unsigned buf_sent=0;
        !          1375: 
        !          1376:        if(sent!=NULL)
        !          1377:                *sent=0;
        !          1378: 
        !          1379:        fseek(fp,pos,SEEK_SET);
        !          1380: 
        !          1381:        zmodem_send_pos_header(zm, ZDATA, pos, /* Hex? */ FALSE);
        !          1382: 
        !          1383:        /*
        !          1384:         * send the data in the file
        !          1385:         */
        !          1386: 
        !          1387:        while(is_connected(zm)) {
        !          1388: 
        !          1389:                /*
        !          1390:                 * read a block from the file
        !          1391:                 */
        !          1392: 
        !          1393:                n = fread(zm->tx_data_subpacket,sizeof(BYTE),zm->block_size,fp);
        !          1394: 
        !          1395:                if(zm->progress!=NULL)
        !          1396:                        zm->progress(zm->cbdata, ftell(fp));
        !          1397: 
        !          1398:                type = ZCRCG;
        !          1399: 
        !          1400:                /** ZMODEM.DOC:
        !          1401:                        ZCRCW data subpackets expect a response before the next frame is sent.
        !          1402:                        If the receiver does not indicate overlapped I/O capability with the
        !          1403:                        CANOVIO bit, or sets a buffer size, the sender uses the ZCRCW to allow
        !          1404:                        the receiver to write its buffer before sending more data.
        !          1405:                ***/
        !          1406:                if(!zm->can_overlap_io || zm->no_streaming
        !          1407:                        || (zm->recv_bufsize && buf_sent+n>=zm->recv_bufsize)) {
        !          1408:                        type=ZCRCW;
        !          1409:                        buf_sent=0;
        !          1410:                }
        !          1411: 
        !          1412:                if((ulong)ftell(fp) >= zm->current_file_size || n==0)   /* can't use feof() here! */
        !          1413:                        type = ZCRCE;
        !          1414: 
        !          1415:                if(zmodem_send_data(zm, type, zm->tx_data_subpacket, n)!=0)
        !          1416:                        return(TIMEOUT);
        !          1417: 
        !          1418:                if(type == ZCRCW || type == ZCRCE) {    
        !          1419:                        int ack;
        !          1420:                        lprintf(zm,LOG_DEBUG,"Sent end-of-frame (%s sub-packet)", chr(type));
        !          1421: 
        !          1422:                        if(type==ZCRCW) {       /* ZACK expected */
        !          1423: 
        !          1424:                                lprintf(zm,LOG_DEBUG,"Waiting for ZACK");
        !          1425:                                while(is_connected(zm)) {
        !          1426:                                        if((ack = zmodem_recv_header(zm)) != ZACK)
        !          1427:                                                return(ack);
        !          1428: 
        !          1429:                                        if(is_cancelled(zm))
        !          1430:                                                return(ZCAN);
        !          1431: 
        !          1432:                                        if(zm->rxd_header_pos == (ulong)ftell(fp))
        !          1433:                                                break;
        !          1434:                                        lprintf(zm,LOG_WARNING,"ZACK for incorrect offset (%lu vs %lu)"
        !          1435:                                                ,zm->rxd_header_pos, ftell(fp));
        !          1436:                                } 
        !          1437: 
        !          1438:                        }
        !          1439:                }
        !          1440: 
        !          1441:                if(sent!=NULL)
        !          1442:                        *sent+=n;
        !          1443: 
        !          1444:                buf_sent+=n;
        !          1445: 
        !          1446:                if((ulong)ftell(fp) >= zm->current_file_size) {
        !          1447:                        lprintf(zm,LOG_DEBUG,"send_from: end of file (%ld)", zm->current_file_size );
        !          1448:                        return ZACK;
        !          1449:                }
        !          1450:                if(n==0) {
        !          1451:                        lprintf(zm,LOG_ERR,"send_from: read error %d at offset %lu"
        !          1452:                                ,ferror(fp), ftell(fp) );
        !          1453:                        return ZACK;
        !          1454:                }
        !          1455: 
        !          1456:                /* 
        !          1457:                 * characters from the other side
        !          1458:                 * check out that header
        !          1459:                 */
        !          1460: 
        !          1461:                while(zmodem_data_waiting(zm, zm->consecutive_errors ? 1000:0) 
        !          1462:                        && !is_cancelled(zm) && is_connected(zm)) {
        !          1463:                        int type;
        !          1464:                        int c;
        !          1465:                        lprintf(zm,LOG_DEBUG,"Back-channel traffic detected:");
        !          1466:                        if((c = zmodem_recv_raw(zm)) < 0)
        !          1467:                                return(c);
        !          1468:                        if(c == ZPAD) {
        !          1469:                                type = zmodem_recv_header(zm);
        !          1470:                                if(type != TIMEOUT && type != ZACK) {
        !          1471:                                        return type;
        !          1472:                                }
        !          1473:                        } else
        !          1474:                                lprintf(zm,LOG_DEBUG,"Received: %s",chr(c));
        !          1475:                }
        !          1476:                if(is_cancelled(zm))
        !          1477:                        return(ZCAN);
        !          1478: 
        !          1479:                zm->consecutive_errors = 0;
        !          1480: 
        !          1481:                if(zm->block_size < zm->max_block_size) {
        !          1482:                        zm->block_size*=2;
        !          1483:                        if(zm->block_size > zm->max_block_size)
        !          1484:                                zm->block_size = zm->max_block_size;
        !          1485:                }
        !          1486: 
        !          1487:                if(type == ZCRCW || type == ZCRCE)      /* end-of-frame */
        !          1488:                        zmodem_send_pos_header(zm, ZDATA, ftell(fp), /* Hex? */ FALSE);
        !          1489:        }
        !          1490: 
        !          1491:        lprintf(zm,LOG_DEBUG,"send_from: returning unexpectedly!");
        !          1492: 
        !          1493:        /*
        !          1494:         * end of file reached.
        !          1495:         * should receive something... so fake ZACK
        !          1496:         */
        !          1497: 
        !          1498:        return ZACK;
        !          1499: }
        !          1500: 
        !          1501: /*
        !          1502:  * send a file; returns true when session is aborted.
        !          1503:  * (using ZABORT frame)
        !          1504:  */
        !          1505: 
        !          1506: BOOL zmodem_send_file(zmodem_t* zm, char* fname, FILE* fp, BOOL request_init, time_t* start, ulong* sent)
        !          1507: {
        !          1508:        BOOL    success=FALSE;
        !          1509:        ulong   pos=0;
        !          1510:        ulong   sent_bytes;
        !          1511:        struct  stat s;
        !          1512:        unsigned char * p;
        !          1513:        uchar   zfile_frame[] = { ZFILE, 0, 0, 0, 0 };
        !          1514:        int             type;
        !          1515:        int             i;
        !          1516:        unsigned attempts;
        !          1517: 
        !          1518:        if(zm->block_size == 0)
        !          1519:                zm->block_size = ZBLOCKLEN;     
        !          1520: 
        !          1521:        if(zm->block_size < 128)
        !          1522:                zm->block_size = 128;   
        !          1523: 
        !          1524:        if(zm->block_size > sizeof(zm->tx_data_subpacket))
        !          1525:                zm->block_size = sizeof(zm->tx_data_subpacket);
        !          1526: 
        !          1527:        if(zm->max_block_size < zm->block_size)
        !          1528:                zm->max_block_size = zm->block_size;
        !          1529: 
        !          1530:        if(zm->max_block_size > sizeof(zm->rx_data_subpacket))
        !          1531:                zm->max_block_size = sizeof(zm->rx_data_subpacket);
        !          1532: 
        !          1533:        if(sent!=NULL)  
        !          1534:                *sent=0;
        !          1535: 
        !          1536:        if(start!=NULL)         
        !          1537:                *start=time(NULL);
        !          1538: 
        !          1539:        zm->file_skipped=FALSE;
        !          1540: 
        !          1541:        if(zm->no_streaming)
        !          1542:                lprintf(zm,LOG_WARNING,"Streaming disabled");
        !          1543: 
        !          1544:        if(request_init) {
        !          1545:                for(zm->errors=0; zm->errors<=zm->max_errors && !is_cancelled(zm) && is_connected(zm); zm->errors++) {
        !          1546:                        lprintf(zm,LOG_INFO,"Sending ZRQINIT (%u of %u)"
        !          1547:                                ,zm->errors+1,zm->max_errors+1);
        !          1548:                        i = zmodem_get_zrinit(zm);
        !          1549:                        if(i == ZRINIT) {
        !          1550:                                zmodem_parse_zrinit(zm);
        !          1551:                                break;
        !          1552:                        }
        !          1553:                        lprintf(zm,LOG_WARNING,"send_file: received header type %s"
        !          1554:                                ,frame_desc(i));
        !          1555:                }
        !          1556:                if(zm->errors>=zm->max_errors || is_cancelled(zm))
        !          1557:                        return(FALSE);
        !          1558:        }
        !          1559: 
        !          1560:        fstat(fileno(fp),&s);
        !          1561:        zm->current_file_size = s.st_size;
        !          1562:        SAFECOPY(zm->current_file_name, getfname(fname));
        !          1563: 
        !          1564:        /*
        !          1565:         * the file exists. now build the ZFILE frame
        !          1566:         */
        !          1567: 
        !          1568:        /*
        !          1569:         * set conversion option
        !          1570:         * (not used; always binary)
        !          1571:         */
        !          1572: 
        !          1573:        zfile_frame[ZF0] = ZF0_ZCBIN;
        !          1574: 
        !          1575:        /*
        !          1576:         * management option
        !          1577:         */
        !          1578: 
        !          1579:        if(zm->management_protect) {
        !          1580:                zfile_frame[ZF1] = ZF1_ZMPROT;          
        !          1581:                lprintf(zm,LOG_DEBUG,"send_file: protecting destination");
        !          1582:        }
        !          1583:        else if(zm->management_clobber) {
        !          1584:                zfile_frame[ZF1] = ZF1_ZMCLOB;
        !          1585:                lprintf(zm,LOG_DEBUG,"send_file: overwriting destination");
        !          1586:        }
        !          1587:        else if(zm->management_newer) {
        !          1588:                zfile_frame[ZF1] = ZF1_ZMNEW;
        !          1589:                lprintf(zm,LOG_DEBUG,"send_file: overwriting destination if newer");
        !          1590:        }
        !          1591:        else
        !          1592:                zfile_frame[ZF1] = ZF1_ZMCRC;
        !          1593: 
        !          1594:        /*
        !          1595:         * transport options
        !          1596:         * (just plain normal transfer)
        !          1597:         */
        !          1598: 
        !          1599:        zfile_frame[ZF2] = ZF2_ZTNOR;
        !          1600: 
        !          1601:        /*
        !          1602:         * extended options
        !          1603:         */
        !          1604: 
        !          1605:        zfile_frame[ZF3] = 0;
        !          1606: 
        !          1607:        /*
        !          1608:         * now build the data subpacket with the file name and lots of other
        !          1609:         * useful information.
        !          1610:         */
        !          1611: 
        !          1612:        /*
        !          1613:         * first enter the name and a 0
        !          1614:         */
        !          1615: 
        !          1616:        p = zm->tx_data_subpacket;
        !          1617: 
        !          1618:        strcpy(p,getfname(fname));
        !          1619: 
        !          1620:        p += strlen(p) + 1;
        !          1621: 
        !          1622:        sprintf(p,"%lu %lo %lo %d %u %lu %d"
        !          1623:                ,zm->current_file_size
        !          1624:                ,s.st_mtime
        !          1625:                ,0                                              /* file mode */
        !          1626:                ,0                                              /* serial number */
        !          1627:                ,zm->files_remaining
        !          1628:                ,zm->bytes_remaining
        !          1629:                ,0                                              /* file type */
        !          1630:                );
        !          1631: 
        !          1632:        p += strlen(p) + 1;
        !          1633: 
        !          1634:        do {
        !          1635:                /*
        !          1636:                 * send the header and the data
        !          1637:                 */
        !          1638: 
        !          1639:                lprintf(zm,LOG_DEBUG,"Sending ZFILE header block: '%s'"
        !          1640:                        ,zm->tx_data_subpacket+strlen(zm->tx_data_subpacket)+1);
        !          1641: 
        !          1642:                zmodem_send_bin_header(zm,zfile_frame);
        !          1643:                zmodem_send_data(zm,ZCRCW,zm->tx_data_subpacket,p - zm->tx_data_subpacket);
        !          1644:        
        !          1645:                /*
        !          1646:                 * wait for anything but an ZACK packet
        !          1647:                 */
        !          1648: 
        !          1649:                do {
        !          1650:                        type = zmodem_recv_header(zm);
        !          1651:                        if(is_cancelled(zm))
        !          1652:                                return(FALSE);
        !          1653:                } while(type == ZACK && is_connected(zm));
        !          1654: 
        !          1655:                if(!is_connected(zm))
        !          1656:                        return(FALSE);
        !          1657: 
        !          1658: #if 0
        !          1659:                lprintf(zm,LOG_INFO,"type : %d",type);
        !          1660: #endif
        !          1661: 
        !          1662:                if(type == ZSKIP) {
        !          1663:                        zm->file_skipped=TRUE;
        !          1664:                        lprintf(zm,LOG_WARNING,"File skipped by receiver");
        !          1665:                        return(FALSE);
        !          1666:                }
        !          1667: 
        !          1668:                if(type == ZCRC) {
        !          1669:                        if(zm->crc_request==0)
        !          1670:                                lprintf(zm,LOG_NOTICE,"Receiver requested CRC of entire file");
        !          1671:                        else
        !          1672:                                lprintf(zm,LOG_NOTICE,"Receiver requested CRC of first %lu bytes"
        !          1673:                                        ,zm->crc_request);
        !          1674:                        zmodem_send_pos_header(zm,ZCRC,fcrc32(fp,zm->crc_request),TRUE);
        !          1675:                        type = zmodem_recv_header(zm);
        !          1676:                }
        !          1677: 
        !          1678:        } while(type != ZRPOS);
        !          1679: 
        !          1680:        zm->transfer_start_time = time(NULL);
        !          1681:        zm->transfer_start_pos = 0;
        !          1682:        if(zm->rxd_header_pos && zm->rxd_header_pos <= zm->current_file_size) {
        !          1683:                pos = zm->transfer_start_pos = zm->rxd_header_pos;
        !          1684:                lprintf(zm,LOG_INFO,"Starting transfer at offset: %lu (resume)", pos);
        !          1685:        }
        !          1686: 
        !          1687:        if(start!=NULL)         
        !          1688:                *start=zm->transfer_start_time;
        !          1689: 
        !          1690:        rewind(fp);
        !          1691:        zm->errors = 0;
        !          1692:        zm->consecutive_errors = 0;
        !          1693:        do {
        !          1694:                /*
        !          1695:                 * and start sending
        !          1696:                 */
        !          1697: 
        !          1698:                type = zmodem_send_from(zm, fp, pos, &sent_bytes);
        !          1699: 
        !          1700:                if(!is_connected(zm))
        !          1701:                        return(FALSE);
        !          1702: 
        !          1703:                if(type == ZFERR || type == ZABORT || is_cancelled(zm))
        !          1704:                        return(FALSE);
        !          1705: 
        !          1706:                if(sent != NULL)
        !          1707:                        *sent += sent_bytes;
        !          1708: 
        !          1709:                pos += sent_bytes;
        !          1710: 
        !          1711:                if(type == ZACK)        /* success */
        !          1712:                        break;
        !          1713: 
        !          1714:                lprintf(zm,LOG_ERR,"%s at offset: %lu", chr(type), pos);
        !          1715: 
        !          1716:                if(zm->block_size == zm->max_block_size && zm->max_block_size > ZBLOCKLEN)
        !          1717:                        zm->max_block_size /= 2;
        !          1718: 
        !          1719:                if(zm->block_size > 128)
        !          1720:                        zm->block_size /= 2; 
        !          1721: 
        !          1722:                zm->errors++;
        !          1723:                if(++zm->consecutive_errors > zm->max_errors)
        !          1724:                        return(FALSE);
        !          1725: 
        !          1726:                /*
        !          1727:                 * fetch pos from the ZRPOS header
        !          1728:                 */
        !          1729: 
        !          1730:                if(type == ZRPOS) {
        !          1731:                        if(zm->rxd_header_pos <= zm->current_file_size) {
        !          1732:                                if(pos != zm->rxd_header_pos) {
        !          1733:                                        pos = zm->rxd_header_pos;
        !          1734:                                        lprintf(zm,LOG_INFO,"Resuming transfer from offset: %lu", pos);
        !          1735:                                }
        !          1736:                        } else
        !          1737:                                lprintf(zm,LOG_WARNING,"Invalid ZRPOS offset: %lu", zm->rxd_header_pos);
        !          1738:                }
        !          1739: 
        !          1740:        } while(type == ZRPOS || type == ZNAK || type==TIMEOUT);
        !          1741: 
        !          1742: 
        !          1743:        lprintf(zm,LOG_INFO,"Finishing transfer on receipt of header: %s", chr(type));
        !          1744:        if(sent!=NULL)
        !          1745:                lprintf(zm,LOG_DEBUG,"Sent %lu total bytes", *sent);
        !          1746: 
        !          1747:        if(type==ZACK) {
        !          1748:                /*
        !          1749:                 * file sent. send end of file frame
        !          1750:                 * and wait for zrinit. if it doesnt come then try again
        !          1751:                 */
        !          1752: 
        !          1753:                for(attempts=0;attempts<=zm->max_errors && !is_cancelled(zm) && is_connected(zm);attempts++) {
        !          1754:                        lprintf(zm,LOG_INFO,"Sending End-of-File (ZEOF) frame (%u of %u)"
        !          1755:                                ,attempts+1, zm->max_errors+1);
        !          1756:                        zmodem_send_zeof(zm);
        !          1757:                        if(zmodem_recv_header(zm)==ZRINIT) {
        !          1758:                                success=TRUE;
        !          1759:                                break;
        !          1760:                        }
        !          1761:                }
        !          1762:        }
        !          1763:        return(success);
        !          1764: }
        !          1765: 
        !          1766: int zmodem_recv_files(zmodem_t* zm, const char* download_dir, ulong* bytes_received)
        !          1767: {
        !          1768:        char            fpath[MAX_PATH+1];
        !          1769:        FILE*           fp;
        !          1770:        long            l;
        !          1771:        BOOL            skip;
        !          1772:        ulong           b;
        !          1773:        ulong           crc;
        !          1774:        ulong           rcrc;
        !          1775:        ulong           bytes;
        !          1776:        ulong           kbytes;
        !          1777:        ulong           start_bytes;
        !          1778:        unsigned        files_received=0;
        !          1779:        time_t          t;
        !          1780:        unsigned        cps;
        !          1781:        unsigned        timeout;
        !          1782:        unsigned        errors;
        !          1783: 
        !          1784:        if(bytes_received!=NULL)
        !          1785:                *bytes_received=0;
        !          1786:        zm->current_file_num=1;
        !          1787:        while(zmodem_recv_init(zm)==ZFILE) {
        !          1788:                bytes=zm->current_file_size;
        !          1789:                kbytes=bytes/1024;
        !          1790:                if(kbytes<1) kbytes=0;
        !          1791:                lprintf(zm,LOG_INFO,"Downloading %s (%lu KBytes) via Zmodem", zm->current_file_name, kbytes);
        !          1792: 
        !          1793:                do {    /* try */
        !          1794:                        skip=TRUE;
        !          1795: 
        !          1796:                        sprintf(fpath,"%s/%s",download_dir,zm->current_file_name);
        !          1797:                        lprintf(zm,LOG_DEBUG,"fpath=%s",fpath);
        !          1798:                        if(fexist(fpath)) {
        !          1799:                                l=flength(fpath);
        !          1800:                                lprintf(zm,LOG_WARNING,"%s already exists (%lu bytes)",fpath,l);
        !          1801:                                if(l>=(long)bytes) {
        !          1802:                                        lprintf(zm,LOG_WARNING,"Local file size >= remote file size (%ld)"
        !          1803:                                                ,bytes);
        !          1804:                                        break;
        !          1805:                                }
        !          1806:                                if((fp=fopen(fpath,"rb"))==NULL) {
        !          1807:                                        lprintf(zm,LOG_ERR,"Error %d opening %s", errno, fpath);
        !          1808:                                        break;
        !          1809:                                }
        !          1810:                                setvbuf(fp,NULL,_IOFBF,0x10000);
        !          1811: 
        !          1812:                                lprintf(zm,LOG_INFO,"Calculating CRC of: %s", fpath);
        !          1813:                                crc=fcrc32(fp,l);
        !          1814:                                fclose(fp);
        !          1815:                                lprintf(zm,LOG_INFO,"CRC of %s (%lu bytes): %08lX"
        !          1816:                                        ,getfname(fpath), l, crc);
        !          1817:                                lprintf(zm,LOG_INFO,"Requesting CRC of remote file: %s", zm->current_file_name);
        !          1818:                                if(!zmodem_get_crc(zm,l,&rcrc)) {
        !          1819:                                        lprintf(zm,LOG_ERR,"Failed to get CRC of remote file");
        !          1820:                                        break;
        !          1821:                                }
        !          1822:                                if(crc!=rcrc) {
        !          1823:                                        lprintf(zm,LOG_WARNING,"Remote file has different CRC value: %08lX", rcrc);
        !          1824:                                        break;
        !          1825:                                }
        !          1826:                                lprintf(zm,LOG_INFO,"Resuming download of %s",fpath);
        !          1827:                        }
        !          1828: 
        !          1829:                        if((fp=fopen(fpath,"ab"))==NULL) {
        !          1830:                                lprintf(zm,LOG_ERR,"Error %d opening/creating/appending %s",errno,fpath);
        !          1831:                                break;
        !          1832:                        }
        !          1833:                        start_bytes=filelength(fileno(fp));
        !          1834: 
        !          1835:                        skip=FALSE;
        !          1836:                        errors=zmodem_recv_file_data(zm,fp,flength(fpath));
        !          1837: 
        !          1838:                        for(;errors<=zm->max_errors && !is_cancelled(zm); errors++) {
        !          1839:                                if(zmodem_recv_header_and_check(zm))
        !          1840:                                        break;
        !          1841:                        }
        !          1842:                        fclose(fp);
        !          1843:                        l=flength(fpath);
        !          1844:                        if(errors && l==0)      {       /* aborted/failed download */
        !          1845:                                if(remove(fpath))       /* don't save 0-byte file */
        !          1846:                                        lprintf(zm,LOG_ERR,"Error %d removing %s",errno,fpath);
        !          1847:                                else
        !          1848:                                        lprintf(zm,LOG_INFO,"Deleted 0-byte file %s",fpath);
        !          1849:                        }
        !          1850:                        else {
        !          1851:                                if(l!=(long)bytes) {
        !          1852:                                        lprintf(zm,LOG_WARNING,"Incomplete download (%ld bytes received, expected %lu)"
        !          1853:                                                ,l,bytes);
        !          1854:                                } else {
        !          1855:                                        if((t=time(NULL)-zm->transfer_start_time)<=0)
        !          1856:                                                t=1;
        !          1857:                                        b=l-start_bytes;
        !          1858:                                        if((cps=b/t)==0)
        !          1859:                                                cps=1;
        !          1860:                                        lprintf(zm,LOG_INFO,"Received %lu bytes successfully (%u CPS)",b,cps);
        !          1861:                                        files_received++;
        !          1862:                                        if(bytes_received!=NULL)
        !          1863:                                                *bytes_received+=b;
        !          1864:                                }
        !          1865:                                if(zm->current_file_time)
        !          1866:                                        setfdate(fpath,zm->current_file_time);
        !          1867:                        }
        !          1868: 
        !          1869:                } while(0);
        !          1870:                /* finally */
        !          1871: 
        !          1872:                if(skip) {
        !          1873:                        lprintf(zm,LOG_WARNING,"Skipping file");
        !          1874:                        zmodem_send_zskip(zm);
        !          1875:                }
        !          1876:                zm->current_file_num++;
        !          1877:        }
        !          1878:        if(zm->local_abort)
        !          1879:                zmodem_abort_receive(zm);
        !          1880: 
        !          1881:        /* wait for "over-and-out" */
        !          1882:        timeout=zm->recv_timeout;
        !          1883:        zm->recv_timeout=2;
        !          1884:        if(zmodem_rx(zm)=='O')
        !          1885:                zmodem_rx(zm);
        !          1886:        zm->recv_timeout=timeout;
        !          1887: 
        !          1888:        return(files_received);
        !          1889: }
        !          1890: 
        !          1891: int zmodem_recv_init(zmodem_t* zm)
        !          1892: {
        !          1893:        int                     type=CAN;
        !          1894:        unsigned        errors;
        !          1895: 
        !          1896:        lprintf(zm,LOG_DEBUG,"recv_init");
        !          1897: 
        !          1898: #if 0
        !          1899:        while(is_connected(zm) && !is_cancelled(zm) && (ch=zm->recv_byte(zm,0))!=NOINP)
        !          1900:                lprintf(zm,LOG_DEBUG,"Throwing out received: %s",chr((uchar)ch));
        !          1901: #endif
        !          1902: 
        !          1903:        for(errors=0; errors<=zm->max_errors && !is_cancelled(zm) && is_connected(zm); errors++) {
        !          1904:                lprintf(zm,LOG_DEBUG,"Sending ZRINIT (%u of %u)"
        !          1905:                        ,errors+1, zm->max_errors+1);
        !          1906:                zmodem_send_zrinit(zm);
        !          1907: 
        !          1908:                type = zmodem_recv_header(zm);
        !          1909: 
        !          1910:                if(type==TIMEOUT)
        !          1911:                        continue;
        !          1912: 
        !          1913:                lprintf(zm,LOG_DEBUG,"Received header: %s",chr(type));
        !          1914: 
        !          1915:                if(type==ZFILE) {
        !          1916:                        zmodem_parse_zfile_subpacket(zm);
        !          1917:                        return(type);
        !          1918:                }
        !          1919: 
        !          1920:                if(type==ZFIN) {
        !          1921:                        zmodem_send_zfin(zm);   /* ACK */
        !          1922:                        return(type);
        !          1923:                }
        !          1924: 
        !          1925:                lprintf(zm,LOG_WARNING,"Received frame: %s, expected ZFILE or ZFIN"
        !          1926:                        ,frame_desc(type));
        !          1927:                lprintf(zm,LOG_DEBUG,"ZF0=%02X ZF1=%02X ZF2=%02X ZF3=%02X"
        !          1928:                        ,zm->rxd_header[ZF0],zm->rxd_header[ZF1],zm->rxd_header[ZF2],zm->rxd_header[ZF3]);
        !          1929:        }
        !          1930: 
        !          1931:        return(type);
        !          1932: }
        !          1933: 
        !          1934: void zmodem_parse_zfile_subpacket(zmodem_t* zm)
        !          1935: {
        !          1936:        int                     i;
        !          1937:        long            mode=0;
        !          1938:        long            serial=-1;
        !          1939: 
        !          1940:        SAFECOPY(zm->current_file_name,getfname(zm->rx_data_subpacket));
        !          1941: 
        !          1942:        zm->current_file_size = 0;
        !          1943:        zm->current_file_time = 0;
        !          1944:        zm->files_remaining = 0;
        !          1945:        zm->bytes_remaining = 0;
        !          1946: 
        !          1947:        i=sscanf(zm->rx_data_subpacket+strlen(zm->rx_data_subpacket)+1,"%lu %lo %lo %lo %lu %lu"
        !          1948:                ,&zm->current_file_size /* file size (decimal) */
        !          1949:                ,&zm->current_file_time /* file time (octal unix format) */
        !          1950:                ,&mode                                  /* file mode */
        !          1951:                ,&serial                                /* program serial number */
        !          1952:                ,&zm->files_remaining   /* remaining files to be sent */
        !          1953:                ,&zm->bytes_remaining   /* remaining bytes to be sent */
        !          1954:                );
        !          1955: 
        !          1956:        lprintf(zm,LOG_DEBUG,"Zmodem header (%u fields): %s"
        !          1957:                ,i, zm->rx_data_subpacket+strlen(zm->rx_data_subpacket)+1);
        !          1958: 
        !          1959:        if(!zm->files_remaining)
        !          1960:                zm->files_remaining = 1;
        !          1961:        if(!zm->bytes_remaining)
        !          1962:                zm->bytes_remaining = zm->current_file_size;
        !          1963: 
        !          1964:        if(!zm->total_files)
        !          1965:                zm->total_files = zm->files_remaining;
        !          1966:        if(!zm->total_bytes)
        !          1967:                zm->total_bytes = zm->bytes_remaining;
        !          1968: }
        !          1969: 
        !          1970: /*
        !          1971:  * receive file data until the end of the file or until something goes wrong.
        !          1972:  * the name is only used to show progress
        !          1973:  */
        !          1974: 
        !          1975: unsigned zmodem_recv_file_data(zmodem_t* zm, FILE* fp, ulong offset)
        !          1976: {
        !          1977:        int                     i=0;
        !          1978:        unsigned        errors=0;
        !          1979: 
        !          1980:        zm->transfer_start_pos=offset;
        !          1981:        zm->transfer_start_time=time(NULL);
        !          1982: 
        !          1983:        fseek(fp,offset,SEEK_SET);
        !          1984: 
        !          1985:        while(errors<=zm->max_errors && is_connected(zm)
        !          1986:                && (ulong)ftell(fp) < zm->current_file_size && !is_cancelled(zm)) {
        !          1987: 
        !          1988:                if(i!=ENDOFFRAME)
        !          1989:                        zmodem_send_pos_header(zm, ZRPOS, ftell(fp), /* Hex? */ TRUE);
        !          1990: 
        !          1991:                if((i = zmodem_recv_file_frame(zm,fp)) == ZEOF)
        !          1992:                        break;
        !          1993:                if(i!=ENDOFFRAME) {
        !          1994:                        if(i>0)
        !          1995:                                lprintf(zm,LOG_ERR,"%s at offset: %lu", chr(i), ftell(fp));
        !          1996:                        errors++;
        !          1997:                }
        !          1998:        }
        !          1999:        return(errors);
        !          2000: }
        !          2001: 
        !          2002: 
        !          2003: int zmodem_recv_file_frame(zmodem_t* zm, FILE* fp)
        !          2004: {
        !          2005:        unsigned n;
        !          2006:        int type;
        !          2007: 
        !          2008:        /*
        !          2009:         * wait for a ZDATA header with the right file offset
        !          2010:         * or a timeout or a ZFIN
        !          2011:         */
        !          2012: 
        !          2013:        do {
        !          2014:                do {
        !          2015:                        type = zmodem_recv_header(zm);
        !          2016:                        if (type == TIMEOUT) {
        !          2017:                                return TIMEOUT;
        !          2018:                        }
        !          2019:                        if(is_cancelled(zm))
        !          2020:                                return(ZCAN);
        !          2021: 
        !          2022:                } while(type != ZDATA);
        !          2023: 
        !          2024:                if(zm->rxd_header_pos==(ulong)ftell(fp))
        !          2025:                        break;
        !          2026:                lprintf(zm,LOG_WARNING,"Wrong ZDATA block (%lu vs %lu)", zm->rxd_header_pos, ftell(fp));
        !          2027: 
        !          2028:        } while(!is_cancelled(zm) && is_connected(zm));
        !          2029:                
        !          2030:        do {
        !          2031:                type = zmodem_recv_data(zm,zm->rx_data_subpacket,sizeof(zm->rx_data_subpacket),&n,TRUE);
        !          2032: 
        !          2033: /*             fprintf(stderr,"packet len %d type %d\n",n,type);
        !          2034: */
        !          2035:                if (type == ENDOFFRAME || type == FRAMEOK) {
        !          2036:                        fwrite(zm->rx_data_subpacket,1,n,fp);
        !          2037:                }
        !          2038: 
        !          2039:                if(type==FRAMEOK)
        !          2040:                        zm->block_size = n;
        !          2041: 
        !          2042:                if(zm->progress!=NULL)
        !          2043:                        zm->progress(zm->cbdata,ftell(fp));
        !          2044: 
        !          2045:                if(is_cancelled(zm))
        !          2046:                        return(ZCAN);
        !          2047: 
        !          2048:        } while(type == FRAMEOK);
        !          2049: 
        !          2050:        return type;
        !          2051: }
        !          2052: 
        !          2053: const char* zmodem_source(void)
        !          2054: {
        !          2055:        return(__FILE__);
        !          2056: }
        !          2057: 
        !          2058: char* zmodem_ver(char *buf)
        !          2059: {
        !          2060:        sscanf("$Revision: 1.71 $", "%*s %s", buf);
        !          2061: 
        !          2062:        return(buf);
        !          2063: }
        !          2064: 
        !          2065: void zmodem_init(zmodem_t* zm, void* cbdata
        !          2066:                                ,int    (*lputs)(void*, int level, const char* str)
        !          2067:                                ,void   (*progress)(void* unused, ulong)
        !          2068:                                ,int    (*send_byte)(void*, uchar ch, unsigned timeout)
        !          2069:                                ,int    (*recv_byte)(void*, unsigned timeout)
        !          2070:                                ,BOOL   (*is_connected)(void*)
        !          2071:                                ,BOOL   (*is_cancelled)(void*)
        !          2072:                                ,BOOL   (*data_waiting)(void*, unsigned timeout))
        !          2073: {
        !          2074:        memset(zm,0,sizeof(zmodem_t));
        !          2075: 
        !          2076:        /* Use sane default values */
        !          2077:        zm->init_timeout=10;            /* seconds */
        !          2078:        zm->send_timeout=15;            /* seconds */
        !          2079:        zm->recv_timeout=20;            /* seconds */
        !          2080:        zm->crc_timeout=60;                     /* seconds */
        !          2081: #if 0
        !          2082:        zm->byte_timeout=3;                     /* seconds */
        !          2083:        zm->ack_timeout=10;                     /* seconds */
        !          2084: #endif
        !          2085:        zm->block_size=ZBLOCKLEN;
        !          2086:        zm->max_block_size=ZBLOCKLEN;
        !          2087:        zm->max_errors=9;
        !          2088: 
        !          2089:        zm->cbdata=cbdata;
        !          2090:        zm->lputs=lputs;
        !          2091:        zm->progress=progress;
        !          2092:        zm->send_byte=send_byte;
        !          2093:        zm->recv_byte=recv_byte;
        !          2094:        zm->is_connected=is_connected;
        !          2095:        zm->is_cancelled=is_cancelled;
        !          2096:        zm->data_waiting=data_waiting;
        !          2097: }

unix.superglobalmegacorp.com

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