|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.