#include "stdio.h" #include "fcntl.h" #include "setjmp.h" #define FALSE 0 #define TRUE 1 #define DOTS 50 /* Sector counting dots per line */ #define SECSIZ 0x80 #define BufSize 0x1000 /* Text buffer */ #define ERRORMAX 20 /* Max errors before abort */ #define RETRYMAX 15 /* Maximum retrys before abort */ #define SOH 1 /* Start of sector char */ #define EOT 4 /* end of transmission char */ #define ACK 6 /* acknowledge sector transmission */ #define NAK 21 /* error in transmission detected */ static char bufr[BufSize]; static int fd, mtimeout; static long bytes_xferred; extern jmp_buf abort_env, env; static mdmini() { mtimeout = 60; bytes_xferred = 0L; } XMODEM_Read_File(file) char *file; { int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag; unsigned int checksum, j, bufptr; mdmini (); if ((fd = creat(file, 0)) < 0) { printf("cannot open %s (%x)\n", file, fd); return FALSE; } else printf("receiving %s\n", file); sectnum = errors = bufptr = 0; Start_Timer(0); flushinput(); sendchar(NAK); if (setjmp(&env)) return FALSE; /* timeout */ if (setjmp(&abort_env)) return FALSE; while (firstchar != EOT && errors != ERRORMAX) { errorflag = FALSE; Start_Timer (mtimeout); /* set timeout trap */ do /* get sync char */ firstchar = readchar(); while (firstchar != SOH && firstchar != EOT); if (firstchar == SOH) { sectcurr = readchar(); sectcomp = readchar(); if ((sectcurr + sectcomp) == 255) { if (sectcurr == (sectnum + 1 & 0xff)) { checksum = 0; for (j = bufptr; j < (bufptr + SECSIZ); j++) { bufr[j] = readchar(); checksum = (checksum + bufr[j]) & 0xff; } if (checksum == readchar()) { errors = 0; sectnum++; bufptr += SECSIZ; bytes_xferred += SECSIZ; printf(" %d\r", bytes_xferred); if (bufptr == BufSize) { bufptr = 0; if (write(fd, bufr, BufSize) == EOF) { printf("error writing file\n"); close(fd); return FALSE; }; }; flushinput (); sendchar(ACK); } else errorflag = TRUE; } else { if (sectcurr == (sectnum & 0xff)) { printf("received duplicate sector %d\n", sectnum); flushinput(); sendchar(ACK); } else errorflag = TRUE; } } else errorflag = TRUE; } if (errorflag == TRUE) { errors++; printf("error %d\n", errors); flushinput(); sendchar(NAK); } }; /* end while */ if ((firstchar == EOT) && (errors < ERRORMAX)) { sendchar(ACK); write(fd, bufr, bufptr); close(fd); return TRUE; } return FALSE; } XMODEM_Send_File(file) char *file; { int sectnum, bytes_to_send, size, attempts; unsigned checksum, j, bufptr; char c; mdmini (); if ((fd = open(file, O_RDONLY | O_RAW)) < 0) { printf("cannot open %s\n", file); return FALSE; } else printf("sending %s\n", file); attempts = 0; sectnum = 1; j = 0; if (setjmp(&env)) return FALSE; if (setjmp(&abort_env)) return FALSE; Start_Timer(mtimeout); while (((c = readchar ()) != NAK) && (j++ < (ERRORMAX*2))); if (j >= (ERRORMAX*2)) { printf("Receiver not sending NAKs\n"); return FALSE; }; flushinput (); Start_Timer(mtimeout); while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX) { if (bytes_to_send == EOF) { printf("error reading file\n"); close(fd); return FALSE; }; bufptr = 0; while (bytes_to_send > 0 && attempts != RETRYMAX) { attempts = 0; do { Start_Timer(mtimeout); sendchar(SOH); sendchar(sectnum); sendchar(~sectnum); checksum = 0; size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send; bytes_to_send -= size; for (j = bufptr; j < (bufptr + SECSIZ); j++) if (j < (bufptr + size)) { sendchar(bufr[j]); checksum += bufr[j]; } else sendchar(0); sendchar(checksum); flushinput(); attempts++; c = readchar(); } while ((c != ACK) && (attempts != RETRYMAX)); bufptr += size; bytes_xferred += size; printf(" %d\r", bytes_xferred); sectnum++; } } close(fd); if (attempts == RETRYMAX) { printf("no acknowledgment of sector, aborting\n"); return FALSE; } else { attempts = 0; do { sendchar(EOT); attempts++; } while ((readchar() != ACK) && (attempts != RETRYMAX)); if (attempts == RETRYMAX) printf("no acknowledgment of end of file\n"); }; return TRUE; }