diff --git a/src/sbbs3/xmodem.c b/src/sbbs3/xmodem.c
index 8a91cb088e281cf61c7fe96573d49795d0374a4d..17c534937f3ec95d88d901550ea09da2c0620d17 100644
--- a/src/sbbs3/xmodem.c
+++ b/src/sbbs3/xmodem.c
@@ -120,10 +120,13 @@ void xmodem_cancel(xmodem_t* xm)
 {
 	int i;
 
-	for(i=0;i<8;i++)
-		putcom(CAN);
-	for(i=0;i<10;i++)
-		putcom('\b');
+	if(!xm->cancelled) {
+		for(i=0;i<8;i++)
+			putcom(CAN);
+		for(i=0;i<10;i++)
+			putcom('\b');
+		xm->cancelled=TRUE;
+	}
 }
 
 /****************************************************************************/
@@ -302,7 +305,6 @@ BOOL xmodem_get_ack(xmodem_t* xm, unsigned tries, unsigned block_num)
 			return(TRUE);
 		if(i==CAN) {
 			if(can) {
-				xm->cancelled=TRUE;
 				lprintf(xm,LOG_WARNING,"Block %u: !Cancelled remotely", block_num);
 				xmodem_cancel(xm);
 				return(FALSE); 
@@ -347,7 +349,7 @@ BOOL xmodem_get_mode(xmodem_t* xm)
 				return(TRUE); 
 			case CAN:
 				if(can) {
-					lprintf(xm,LOG_WARNING,"Receiver cancelled");
+					lprintf(xm,LOG_WARNING,"Cancelled remotely");
 					return(FALSE); 
 				}
 				can=1; 
@@ -369,6 +371,7 @@ BOOL xmodem_put_eot(xmodem_t* xm)
 {
 	int ch;
 	unsigned errors;
+	unsigned cans=0;
 
 	for(errors=0;errors<xm->max_errors;errors++) {
 
@@ -380,9 +383,11 @@ BOOL xmodem_put_eot(xmodem_t* xm)
 		putcom(EOT);
 		if((ch=getcom(xm->recv_timeout))==NOINP)
 			continue;
-		lprintf(xm,LOG_INFO,"Received %s ",chr((uchar)ch)); 
+		lprintf(xm,LOG_INFO,"Received %s",chr((uchar)ch)); 
 		if(ch==ACK)
 			return(TRUE);
+		if(ch==CAN && ++cans>1)
+			break;
 		if(ch==NAK && errors==0 && (*(xm->mode)&(YMODEM|GMODE))==YMODEM) {
 			continue;  /* chuck's double EOT trick so don't complain */
 		}
@@ -418,77 +423,81 @@ BOOL xmodem_send_file(xmodem_t* xm, const char* fname, FILE* fp, time_t* start,
 	if(xm->total_bytes==0)
 		xm->total_bytes=st.st_size;
 
-	if(*(xm->mode)&YMODEM) {
+	do {
+	/* try */
+		if(*(xm->mode)&YMODEM) {
 
-		if(!xmodem_get_mode(xm)) {
-			xmodem_cancel(xm);
-			return(0);
-		}
+			if(!xmodem_get_mode(xm))
+				break;
 
-		memset(block,0,sizeof(block));
-		SAFECOPY(block,getfname(fname));
-		i=sprintf(block+strlen(block)+1,"%lu %lo 0 0 %d %ld"
-			,st.st_size
-			,st.st_mtime
-			,xm->total_files-xm->sent_files
-			,xm->total_bytes-xm->sent_bytes);
-		
-		lprintf(xm,LOG_INFO,"Sending Ymodem header block: '%s'",block+strlen(block)+1);
-		
-		block_len=strlen(block)+1+i;
-		for(errors=0;errors<xm->max_errors;errors++) {
-			xmodem_put_block(xm, block, block_len <=128 ? 128:1024, 0  /* block_num */);
-			if(xmodem_get_ack(xm,1,0))
-				break; 
-		}
-		if(errors==xm->max_errors) {
-			lprintf(xm,LOG_ERR,"Failed to send header block");
-			xmodem_cancel(xm);
-			return(0); 
-		}
-		if(!xmodem_get_mode(xm)) {
-			xmodem_cancel(xm);
-			return(0);
+			memset(block,0,sizeof(block));
+			SAFECOPY(block,getfname(fname));
+			i=sprintf(block+strlen(block)+1,"%lu %lo 0 0 %d %ld"
+				,st.st_size
+				,st.st_mtime
+				,xm->total_files-xm->sent_files
+				,xm->total_bytes-xm->sent_bytes);
+			
+			lprintf(xm,LOG_INFO,"Sending Ymodem header block: '%s'",block+strlen(block)+1);
+			
+			block_len=strlen(block)+1+i;
+			for(errors=0;errors<xm->max_errors && !xm->cancelled;errors++) {
+				xmodem_put_block(xm, block, block_len <=128 ? 128:1024, 0  /* block_num */);
+				if(xmodem_get_ack(xm,1,0))
+					break; 
+			}
+			if(errors>=xm->max_errors || xm->cancelled) {
+				lprintf(xm,LOG_ERR,"Failed to send header block");
+				break;
+			}
 		}
-	}
-	startfile=time(NULL);	/* reset time, don't count header block */
-	if(start!=NULL)
-		*start=startfile;
-
-	block_num=1;
-	errors=0;
-	while(sent_bytes < (ulong)st.st_size && errors<xm->max_errors && !xm->cancelled) {
-		fseek(fp,sent_bytes,SEEK_SET);
-		memset(block,CPMEOF,xm->block_size);
-		if((rd=fread(block,1,xm->block_size,fp))!=xm->block_size 
-			&& (long)(block_num*xm->block_size) < st.st_size) {
-			lprintf(xm,LOG_ERR,"READ ERROR %d instead of %d at offset %lu"
-				,rd,xm->block_size,(block_num-1)*(long)xm->block_size);
-			errors++;
-			continue;
+
+		if(!xmodem_get_mode(xm))
+			break;
+
+		startfile=time(NULL);	/* reset time, don't count header block */
+		if(start!=NULL)
+			*start=startfile;
+
+		block_num=1;
+		errors=0;
+		while(sent_bytes < (ulong)st.st_size && errors<xm->max_errors && !xm->cancelled) {
+			fseek(fp,sent_bytes,SEEK_SET);
+			memset(block,CPMEOF,xm->block_size);
+			if((rd=fread(block,1,xm->block_size,fp))!=xm->block_size 
+				&& (long)(block_num*xm->block_size) < st.st_size) {
+				lprintf(xm,LOG_ERR,"READ ERROR %d instead of %d at offset %lu"
+					,rd,xm->block_size,(block_num-1)*(long)xm->block_size);
+				errors++;
+				continue;
+			}
+			if(xm->progress!=NULL)
+				xm->progress(xm->cbdata,block_num,ftell(fp),st.st_size,startfile);
+			xmodem_put_block(xm, block, xm->block_size, block_num);
+			if(!xmodem_get_ack(xm,5,block_num)) {
+				errors++;
+				lprintf(xm,LOG_WARNING,"Error #%d at offset %ld"
+					,errors,ftell(fp)-xm->block_size);
+			} else {
+				block_num++; 
+				sent_bytes+=rd;
+			}
 		}
-		if(xm->progress!=NULL)
-			xm->progress(xm->cbdata,block_num,ftell(fp),st.st_size,startfile);
-		xmodem_put_block(xm, block, xm->block_size, block_num);
-		if(!xmodem_get_ack(xm,5,block_num)) {
-			errors++;
-			lprintf(xm,LOG_WARNING,"Error #%d at offset %ld"
-				,errors,ftell(fp)-xm->block_size);
-		} else {
-			block_num++; 
-			sent_bytes+=rd;
+		if(sent_bytes >= (ulong)st.st_size && !xm->cancelled) {
+
+	#if 0 /* !SINGLE_THREADED */
+			lprintf(LOG_DEBUG,"Waiting for output buffer to empty... ");
+			if(WaitForEvent(outbuf_empty,5000)!=WAIT_OBJECT_0)
+				lprintf(xm,LOG_WARNING,"FAILURE");
+	#endif
+			if(xmodem_put_eot(xm))	/* end-of-text, wait for ACK */
+				success=TRUE;
 		}
-	}
-	if(sent_bytes >= (ulong)st.st_size && !xm->cancelled) {
-
-#if 0 /* !SINGLE_THREADED */
-		lprintf(LOG_DEBUG,"Waiting for output buffer to empty... ");
-		if(WaitForEvent(outbuf_empty,5000)!=WAIT_OBJECT_0)
-			lprintf(xm,LOG_WARNING,"FAILURE");
-#endif
-		if(xmodem_put_eot(xm))	/* end-of-text, wait for ACK */
-			success=TRUE;
-	}
+	} while(0);
+	/* finally */
+
+	if(!success)
+		xmodem_cancel(xm);
 
 	if(sent!=NULL)
 		*sent=sent_bytes;