|
|
1.1 ! root 1: /* xmodem.c */ ! 2: ! 3: /* Synchronet X/YMODEM Functions */ ! 4: ! 5: /* $Id: xmodem.c,v 1.3 2003/09/17 03:51:58 rswindell Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This program is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU General Public License for more details: gpl.txt or * ! 18: * http://www.fsf.org/copyleft/gpl.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include "sexyz.h" ! 39: #include "genwrap.h" /* YIELD */ ! 40: #include "conwrap.h" /* kbhit */ ! 41: ! 42: #define getcom(t) recv_byte(xm->sock,t,xm->mode) ! 43: #define putcom(ch) send_byte(xm->sock,ch,10,xm->mode) ! 44: #define newline() fprintf(xm->statfp,"\n"); ! 45: ! 46: void xmodem_put_nak(xmodem_t* xm) ! 47: { ! 48: while(getcom(1)!=NOINP) ! 49: ; /* wait for any trailing data */ ! 50: putcom(NAK); ! 51: } ! 52: ! 53: void xmodem_cancel(xmodem_t* xm) ! 54: { ! 55: int i; ! 56: ! 57: for(i=0;i<8;i++) ! 58: putcom(CAN); ! 59: for(i=0;i<10;i++) ! 60: putcom('\b'); ! 61: } ! 62: ! 63: /****************************************************************************/ ! 64: /* Receive a X/Ymodem block (sector) from COM port */ ! 65: /* hdrblock is 1 if attempting to get Ymodem header block, 0 if data block */ ! 66: /* Returns blocknum if all went well, -1 on error or CAN, and -EOT if EOT */ ! 67: /****************************************************************************/ ! 68: int xmodem_get_block(xmodem_t* xm, uchar* block, uint block_size, BOOL hdrblock) ! 69: { ! 70: uchar block_num; /* Block number received in header */ ! 71: uchar chksum,calc_chksum; ! 72: int i,errors,eot=0,can=0; ! 73: uint b; ! 74: ushort crc,calc_crc; ! 75: ! 76: for(errors=0;errors<MAXERRORS;errors++) { ! 77: i=getcom(10); ! 78: if(eot && i!=EOT) ! 79: eot=0; ! 80: if(can && i!=CAN) ! 81: can=0; ! 82: switch(i) { ! 83: case SOH: /* 128 byte blocks */ ! 84: block_size=128; ! 85: break; ! 86: case STX: /* 1024 byte blocks */ ! 87: block_size=1024; ! 88: break; ! 89: case EOT: ! 90: if((xm->mode&(YMODEM|GMODE))==YMODEM && !eot) { ! 91: eot=1; ! 92: xmodem_put_nak(xm); /* chuck's double EOT trick */ ! 93: continue; ! 94: } ! 95: return(-EOT); ! 96: case CAN: ! 97: newline(); ! 98: if(!can) { /* must get two CANs in a row */ ! 99: can=1; ! 100: fprintf(xm->statfp,"Received CAN Expected SOH, STX, or EOT\n"); ! 101: continue; ! 102: } ! 103: fprintf(xm->statfp,"Cancelled remotely\n"); ! 104: bail(-1); ! 105: break; ! 106: case NOINP: /* Nothing came in */ ! 107: continue; ! 108: default: ! 109: newline(); ! 110: fprintf(xm->statfp,"Received %s Expected SOH, STX, or EOT\n",chr((uchar)i)); ! 111: if(hdrblock) /* Trying to get Ymodem header block */ ! 112: return(-1); ! 113: xmodem_put_nak(xm); ! 114: continue; ! 115: } ! 116: i=getcom(1); ! 117: if(i==NOINP) { ! 118: xmodem_put_nak(xm); ! 119: continue; ! 120: } ! 121: block_num=i; ! 122: i=getcom(1); ! 123: if(i==NOINP) { ! 124: xmodem_put_nak(xm); ! 125: continue; ! 126: } ! 127: if(block_num!=(uchar)~i) { ! 128: newline(); ! 129: fprintf(xm->statfp,"Block number error\n"); ! 130: xmodem_put_nak(xm); ! 131: continue; ! 132: } ! 133: calc_crc=calc_chksum=0; ! 134: for(b=0;b<block_size;b++) { ! 135: i=getcom(1); ! 136: if(i==NOINP) ! 137: break; ! 138: block[b]=i; ! 139: if(xm->mode&CRC) ! 140: calc_crc=ucrc16(block[b],calc_crc); ! 141: else ! 142: calc_chksum+=block[b]; ! 143: } ! 144: ! 145: if(b<block_size) { ! 146: xmodem_put_nak(xm); ! 147: continue; ! 148: } ! 149: ! 150: if(xm->mode&CRC) { ! 151: crc=getcom(1)<<8; ! 152: crc|=getcom(1); ! 153: } ! 154: else ! 155: chksum=getcom(1); ! 156: ! 157: if(xm->mode&CRC) { ! 158: if(crc==calc_crc) ! 159: break; ! 160: newline(); ! 161: fprintf(xm->statfp,"CRC error\n"); ! 162: } ! 163: else /* CHKSUM */ ! 164: { ! 165: if(chksum==calc_chksum) ! 166: break; ! 167: newline(); ! 168: fprintf(xm->statfp,"Checksum error\n"); ! 169: } ! 170: ! 171: if(xm->mode&GMODE) { /* Don't bother sending a NAK. He's not listening */ ! 172: xmodem_cancel(xm); ! 173: bail(1); ! 174: } ! 175: xmodem_put_nak(xm); ! 176: } ! 177: ! 178: if(errors>=MAXERRORS) { ! 179: newline(); ! 180: fprintf(xm->statfp,"Too many errors\n"); ! 181: return(-1); ! 182: } ! 183: return(block_num); ! 184: } ! 185: ! 186: /*****************/ ! 187: /* Sends a block */ ! 188: /*****************/ ! 189: void xmodem_put_block(xmodem_t* xm, uchar* block, uint block_size, ulong block_num) ! 190: { ! 191: uchar ch,chksum; ! 192: uint i; ! 193: ushort crc; ! 194: ! 195: if(block_size==128) ! 196: putcom(SOH); ! 197: else /* 1024 */ ! 198: putcom(STX); ! 199: ch=(uchar)(block_num&0xff); ! 200: putcom(ch); ! 201: putcom((uchar)~ch); ! 202: chksum=0; ! 203: crc=0; ! 204: for(i=0;i<block_size;i++) { ! 205: putcom(block[i]); ! 206: if(xm->mode&CRC) ! 207: crc=ucrc16(block[i],crc); ! 208: else ! 209: chksum+=block[i]; ! 210: } ! 211: ! 212: if(xm->mode&CRC) { ! 213: putcom((uchar)(crc >> 8)); ! 214: putcom((uchar)(crc&0xff)); ! 215: } ! 216: else ! 217: putcom(chksum); ! 218: YIELD(); ! 219: } ! 220: ! 221: /************************************************************/ ! 222: /* Gets an acknowledgement - usually after sending a block */ ! 223: /* Returns 1 if ack received, 0 otherwise. */ ! 224: /************************************************************/ ! 225: int xmodem_get_ack(xmodem_t* xm, int tries) ! 226: { ! 227: int i,errors,can=0; ! 228: ! 229: for(errors=0;errors<tries;errors++) { ! 230: ! 231: if(xm->mode&GMODE) { /* Don't wait for ACK on Ymodem-G */ ! 232: if(getcom(0)==CAN) { ! 233: newline(); ! 234: fprintf(xm->statfp,"Cancelled remotely\n"); ! 235: xmodem_cancel(xm); ! 236: bail(1); ! 237: } ! 238: return(1); ! 239: } ! 240: ! 241: i=getcom(10); ! 242: if(can && i!=CAN) ! 243: can=0; ! 244: if(i==ACK) ! 245: return(1); ! 246: if(i==CAN) { ! 247: if(can) { ! 248: newline(); ! 249: fprintf(xm->statfp,"Cancelled remotely\n"); ! 250: xmodem_cancel(xm); ! 251: bail(1); ! 252: } ! 253: can=1; ! 254: } ! 255: if(i!=NOINP) { ! 256: newline(); ! 257: fprintf(xm->statfp,"Received %s Expected ACK\n",chr((uchar)i)); ! 258: if(i!=CAN) ! 259: return(0); ! 260: } ! 261: } ! 262: ! 263: return(0); ! 264: } ! 265: ! 266: const char* xmodem_source(void) ! 267: { ! 268: return(__FILE__); ! 269: } ! 270: ! 271: char* xmodem_ver(char *buf) ! 272: { ! 273: sscanf("$Revision: 1.3 $", "%*s %s", buf); ! 274: ! 275: return(buf); ! 276: } ! 277:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.