|
|
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.