/* Comm WXMODEM receive file routines */ #define WXMDMRECV 1 #include "globals.h" #include extern int WXch(), timedch(); extern void send_proto(), emits_rx(); extern int readchar(); static short eotflg, NAKsent, dirty; static int index, errsect, naks; WXmodem_rec(file) UBYTE *file; { unsigned crchi, crclo, sect, comp; int ch, secerrs; unsigned count; void chop_file(); ULONG bytes; secerrs = errsect = naks = index = bytes = 0; sector = 1; cancel = eotflg = abort = dirty = FALSE; while(secerrs < RETRYMAX) { if(abort) /* keyboard abort (ESC) */ { abortxfer(); return FALSE; } if(cancel) /* remote sent CAN */ { send_proto(ACK); chop_file(index); close( fd ); if(( ch = timedch(5)) == CAN) send_proto(ACK); return TRUE; } /* start of block */ do { /* look for SYN/CAN/EOT */ ch = timedch(10); if( ch == ERROR ) { secerrs++; send_proto(NAK); send_proto(errsect & 3); } if( (secerrs > RETRYMAX) || abort || cancel) { abortxfer(); return FALSE; } if(ch == EOT) { send_proto(NAK); ch = timedch(5); if(ch == EOT || ch == ERROR) { send_proto(ACK); chop_file(index); close( fd ); return TRUE; } } } while (ch != SYN); /* got one SYN character -- gobble up the others */ while((ch = timedch(10)) == SYN) ; /* we got a non SYN character if SOH, then we have a block, if not...who knows, so start over again */ if(ch != SOH) continue; /* block number and compliment */ sect = WXch(10); emit_rx_protocol((UBYTE)sect); comp = WXch(10); emit_rx_protocol((UBYTE)comp); if( sect == ERROR || comp == ERROR) { Nak(); continue; } /* start of data clear out the last block and start a new one */ if(dirty) { movmem(xbuffer,&diskbuff[index++ * SECSIZ],SECSIZ); dirty = FALSE; } crc = count = 0; while( count < SECSIZ ) { ch = WXch(10); if( ch == ERROR ) break; do_crc(ch); xbuffer[ count++ ] = ch; if(viewflg) emit_vw(ch); } if( ch == ERROR ) { Nak(); continue; } /* first CRC byte */ if((crchi = WXch(10)) == ERROR) { Nak(); continue; } do_crc(crchi); /* second CRC byte */ if((crclo = WXch(10)) == ERROR) { Nak(); continue; } /* see if checksum is valid */ if(!verify_checksum( crclo )) { emits_rx(" Checksum error\n"); Nak(); secerrs++; status(file,bytes,naks,errsect); continue; } /* does the block number match the compliment? */ if((UBYTE)sect != (UBYTE)~comp) { Nak(); secerrs++; continue; /* no: this isn't a real block! */ } /* if this isn't the sector we're waiting for, try again */ if( (UBYTE)sect != (UBYTE)sector ) { Nak(); continue; } /* otherwise, this must be a good sector and it must have good data, so ACK it */ Ack(sect); NAKsent = FALSE; secerrs = 0; sprintf(sbuff,"\rReceived block %d",sector); emits_rx(sbuff); /* accept the sector */ sector++; dirty = TRUE; bytes += SECSIZ; status(file,bytes,naks,errsect); if(index == numbufs) { sendchar(XOFF); if(write(fd,diskbuff,numbufs * SECSIZ) != numbufs * SECSIZ) { emits_rx("\nERROR writing to file\n"); abortxfer(); return FALSE; } index = 0; sendchar(XON); } } abortxfer(); return FALSE; } /* send ACK */ Ack(sect) int sect; { send_proto(ACK); send_proto(sect & 3); } /* Send NAK unless we've already done so */ Nak() { if(!NAKsent) { send_proto(NAK); send_proto(sector & 3); errsect = sector; NAKsent = TRUE; } naks++; } timedch(time) int time; { int ch; Process_window_event(); if(abort) return ERROR; ch = readchar(time,0); if(ch == TIMEOUT) return ERROR; emit_rx_protocol(ch); return ch; } WXch(time) int time; { int gotdle,ch; gotdle = 0; Process_window_event(); if(abort) return ERROR; while(TRUE) { ch = readchar(time,0); if(ch == TIMEOUT) return ERROR; switch (ch) { case DLE: gotdle = 64; continue; case SYN: return ERROR; default: return (ch ^ gotdle); } } } abortxfer() { int ch; sendchar(XOFF); chop_file(index); sendchar(XON); send_proto(CAN); send_proto(CAN); send_proto(CAN); if(waitcan() == TRUE) return TRUE; return FALSE; } waitcan() { int ch,err; err = 0; emits_rx("\nAborting...Wait...\n"); while (readchar(2,0) != TIMEOUT) ; send_proto(CAN); send_proto(CAN); ch = readchar(5,0); ch = readchar(5,0); do { if(err++ == 3) break; send_proto(ACK); emits_rx("Sending abort...\n"); Delay(50L); send_proto(CAN); send_proto(CAN); ch = readchar(3,0); } while( ch != CAN ); send_proto(ACK); return TRUE; } sendWs() { int ch,err; err = 0; send_proto('W'); do { ch = timedch(3); if(ch == SYN) return TRUE; if(ch == ERROR) send_proto('W'); } while ( err++ < 3 ); return FALSE; }