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