📄 zmodemt.c
字号:
switch( c ) { case 'C': case 'G': /* protocol failure, resend filename */ if( info->Protocol == YMODEM ) { ZStatus(DataErr, ++info->errCount, NULL) ; info->state = YTFile ; ZFileSeek(info->file, 0, info); return YSendFilename(info) ; } /* else XModem, treat it like a NAK */ case NAK: ZStatus(DataErr, ++info->errCount, NULL) ; return YXmitData(info->buffer + info->bufp, info->ylen, info) ; case ACK: info->offset += info->ylen ; info->bufp += info->ylen ; info->chrCount -= info->ylen ; ZStatus(SndByteCount, info->offset, NULL) ; return YSendData(info) ; default: return 0 ; } case YTEOF: /* sent EOF, waiting for ACK or NAK */ switch( c ) { case NAK: return ZXmitStr(eotstr, 1, info) ; case ACK:// if(info->Protocol == YMODEM) { info->state = YTStart; } else { info->state = Done; } return ZmDone ; default: return 0 ; } case YTFin: /* sent Fin, waiting for ACK or NAK */ switch( c ) { case NAK: return YSendFin(info) ; case ACK: return ZmDone ; default: return 0 ; } default: return 0 ; }}static int YXmitData( u_char *buffer, int len, ZModem *info ){ u_char hdr[3] ; u_char trail[2] ; u_long crc = 0 ; int i, err ; hdr[0] = len == 1024 ? STX : SOH ; hdr[1] = info->packetCount ; hdr[2] = ~hdr[1] ; err = ZXmitStr(hdr, 3, info); if(err) { return(err); } err = ZXmitStr(buffer, len, info); if(err) { return err; } if( info->PacketType == NAK ) { /* checksum */ for(i=0; i<len; ++i) crc += buffer[i] ; trail[0] = crc % 256 ; return ZXmitStr(trail,1, info) ; } else { for(i=0; i<len; ++i) crc = updcrc(buffer[i], crc) ; crc = updcrc(0,crc) ; crc = updcrc(0,crc) ; trail[0] = crc / 256 ; trail[1] = crc % 256 ; return ZXmitStr(trail,2, info) ; }}static int YSendFilename( ZModem *info ){ int i,len ; u_char obuf[1024] ; u_char *ptr = obuf ; int pos; if(info->PacketType != 'G') { info->state = YTFile; } else { info->state = YTDataWait; } info->packetCount = 0 ; info->offset = 0 ;/* copy rfilename to obuf */ pos = 0; while(1) { *(ptr + pos) = *(info->rfilename +pos); if(*(ptr + pos) == '\0') { break; } if(pos >= 1024 - 64) { *(ptr + pos) = '\0'; break; }// pos += 1; } if(pos < 1023) { pos += 1; /* skip terminating zero */ } ZmPutLong(obuf, & pos, 1024, info->len , 10); /* %d */ ZmPutStr (obuf, & pos, 1024, " "); ZmPutLong(obuf, & pos, 1024, info->date, 8); /* %lo */ ZmPutStr (obuf, & pos, 1024, " "); ZmPutLong(obuf, & pos, 1024, info->mode, 8); /* %o */ ZmPutStr (obuf, & pos, 1024, " "); ZmPutLong(obuf, & pos, 1024, 0, 10); /* 0 */ if(pos < 1023) { pos += 1; /* skip terminating zero */ } ptr += pos; *ptr++ = '\0' ;/* pad out to 128 bytes or 1024 bytes */ i = ptr - obuf; len = i > 128 ? 1024 : 128; for(; i < len; ++i) *ptr++ = '\0'; return(YXmitData(obuf, len, info));} /* send next buffer of data */static int YSendData( ZModem *info ){ int len; /* are there characters still in the read buffer? */ if( info->chrCount <= 0 ) { info->bufp = 0 ; info->chrCount = ZFileRead(info->buffer, info->packetsize, info->file, info); info->fileEof = ZFileEof(info->file,info) ; } if( info->chrCount <= 0 ) { ZCloseFile(info->file,info); info->state = YTEOF ; return ZXmitStr(eotstr, 1, info) ; } /* pad out to 128 bytes if needed */ if( info->chrCount < 128 ) { int pos; len = 128 - info->chrCount; pos = 0; while(pos < len) { *(info->buffer + info->bufp + info->chrCount + pos) = 0x1a; } info->chrCount = 128 ; } info->ylen = info->chrCount >= 1024 ? 1024 : 128 ; ++info->packetCount ; info->state = YTData ; return YXmitData(info->buffer + info->bufp, info->ylen, info) ;}static int YSendFin( ZModem *info ){ u_char obuf[128]; int pos; info->state = YTFin; info->packetCount = 0; for(pos = 0; pos < 128; ++pos) { obuf[pos] = 0; } return(YXmitData(obuf, 128, info));} /* utility: send a chunk of file data. Whether this is followed * by a ZCRCE, ZCRCG, ZCRCQ or ZCRCW depends on all * sorts of protocol flags, plus 'waitflag'. Exact amount of file * data transmitted is variable, as escape sequences may pad out * the buffer. */int ZmSendMoreFileData( ZModem *info ){ int type; int qfull = 0; int err; int len; /* max # chars to send this packet */ long pending; /* # of characters sent but not acknowledged *//* ZCRCE: CRC next, frame ends, header follows * ZCRCG: CRC next, frame continues nonstop * ZCRCQ: CRC next, send ZACK, frame continues nonstop * ZCRCW: CRC next, send ZACK, frame ends, header follows */ if( info->interrupt ) { /* Bugger, receiver sent an interrupt. Enter a wait state * and see what they want. Next header *should* be ZRPOS. */ info->state = SendWait; info->timeout = 60; return(0); }/* Find out how many bytes we can transfer in the next packet */ len = info->packetsize; pending = info->offset - info->lastOffset; if( info->windowsize != 0 && info->windowsize - pending <= len ) { len = info->windowsize - pending ; qfull = 1 ; } if( info->bufsize != 0 && info->bufsize - pending <= len ) { len = info->bufsize - pending ; qfull = 1 ; } if( len == 0 ) { /* window still full, keep waiting */ info->state = SendWait; info->timeout = 60; return(0); }/* OK, we can safely transmit 'len' bytes of data. Start reading * file until buffer is full. */ len -= 10; /* Pre-deduct 10 bytes for trailing CRC *//* find out what kind of packet to send */ if( info->waitflag ) { type = ZCRCW; info->waitflag = 0; }#ifdef COMMENT else if( info->fileEof ) type = ZCRCE ;#endif /* COMMENT */ else if( qfull ) type = ZCRCW ; else switch( info->Streaming ) { case Full: case Segmented: type = ZCRCG ; break ; case StrWindow: if( (info->windowCount += len) < info->windowsize/4 ) type = ZCRCG ; else { type = ZCRCQ ; info->windowCount = 0 ; } break ; default: case SlidingWindow: type = ZCRCQ ; break ; } { int crc32 = info->crc32 ; int c=0, c2, atSign=0 ; u_long crc ; u_char *ptr = info->buffer ; crc = crc32 ? 0xffffffff : 0 ; /* read characters from file and put into buffer until buffer is * full or file is exhausted */ while( len > 0 ) /* && (c = getc(info->file)) != EOF */ { u_char ch; ZFileRead(&ch, 1, info->file, info); if(ZFileEof(info->file, info)) { break; } c = ch; if( !crc32 ) crc = updcrc(c, crc) ; else crc = UPDC32(c, crc) ; /* zmodem protocol requires that CAN(ZDLE), DLE, XON, XOFF and * a CR following '@' be escaped. In addition, I escape '^]' * to protect telnet, "<CR>~." to protect rlogin, and ESC for good * measure. */ c2 = c & 0177 ; if( c == ZDLE || c2 == 020 || c2 == 021 || c2 == 023 || c2 == 0177 || c2 == '\r' || c2 == '\n' || c2 == 033 || c2 == 035 || (c2 < 040 && info->escCtrl) ) { *ptr++ = ZDLE ; if( c == 0177 ) *ptr = ZRUB0 ; else if( c == 0377 ) *ptr = ZRUB1 ; else *ptr = c^0100 ; len -= 2 ; } else { *ptr = c ; --len ; } ++ptr ; atSign = c2 == '@' ; ++info->offset ; } /* if we've reached file end, a ZEOF header will follow. If * there's room in the outgoing buffer for it, end the packet * with ZCRCE and append the ZEOF header. If there isn't room, * we'll have to do a ZCRCW */// if(ZFileEof(info->file, info)) { info->fileEof = 1; } else { info->fileEof = 0; }// if(info->fileEof) { if( qfull || (info->bufsize != 0 && len < 24) ) type = ZCRCW ; else type = ZCRCE ; } *ptr++ = ZDLE ; if( !crc32 ) crc = updcrc(type, crc) ; else crc = UPDC32(type, crc) ; *ptr++ = type ; if( !crc32 ) { crc = updcrc(0,crc) ; crc = updcrc(0,crc) ; ptr = putZdle(ptr, (crc>>8)&0xff, info) ; ptr = putZdle(ptr, crc&0xff, info) ; } else { crc = ~crc ; for(len=4; --len >= 0; crc >>= 8) ptr = putZdle(ptr, crc&0xff, info) ; } len = ptr - info->buffer ; } ZStatus(SndByteCount, info->offset, NULL) ; err = ZXmitStr(info->buffer, len, info); if(err) { return(err); }#ifdef COMMENT if( (err = ZXmitData(ZBIN, info->buffer, len, type, info)) ) return err ;#endif /* COMMENT *//* finally, do we want to wait after this packet? */ switch( type ) { case ZCRCE: info->state = SendEof ; info->timeout = 60 ; return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ; case ZCRCW: if(info->fileEof) { info->state = SendDone; } else { info->state = SendWait; } info->timeout = 60 ; break ; default: info->state = Sending ; info->timeout = 0 ; break ; }#ifdef COMMENT if( info->fileEof ) { /* Yes, file is done, send EOF and wait */ info->state = SendEof ; info->timeout = 60 ; return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info) ; } else if( type == ZCRCW ) { info->state = SendWait ; info->timeout = 60 ; } else { info->state = Sending ; info->timeout = 0 ; }#endif /* COMMENT */ return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -