From dd98697a3419bc40f5ccd3e1aefcc2b6c384f180 Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sat, 27 Nov 2004 22:04:12 +0000 Subject: [PATCH] Fixed the ymodem bugs, but most problems were caused by the buggy Dynacomm client --- mbsebbs/Makefile | 2 +- mbsebbs/transfer.c | 21 +++++++++++--- mbsebbs/ymrecv.c | 70 +++++++++++++++++++++++++++++----------------- mbsebbs/ymrecv.h | 3 +- mbsebbs/ymsend.c | 49 +++++++++++++++++--------------- mbsebbs/ymsend.h | 6 ++-- mbsebbs/zmrecv.c | 10 ++++--- mbsebbs/zmrecv.h | 2 +- 8 files changed, 100 insertions(+), 63 deletions(-) diff --git a/mbsebbs/Makefile b/mbsebbs/Makefile index 5ddc3224..fd1cbd19 100644 --- a/mbsebbs/Makefile +++ b/mbsebbs/Makefile @@ -133,7 +133,7 @@ userlist.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ../lib/users.h userlist.h timestats.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ../lib/users.h timestats.h funcs.h language.h input.h exitinfo.h term.h logentry.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ../lib/users.h logentry.h ymsend.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ttyio.h zmmisc.h transfer.h openport.h timeout.h term.h ymsend.h -ymrecv.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ttyio.h timeout.h zmmisc.h zmrecv.h ymrecv.h +ymrecv.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ttyio.h timeout.h transfer.h zmmisc.h zmrecv.h ymsend.h ymrecv.h zmmisc.o: ../config.h ../lib/mbselib.h ttyio.h input.h zmmisc.h zmsend.o: ../config.h ../lib/mbselib.h ttyio.h zmmisc.h transfer.h openport.h timeout.h zmrecv.o: ../config.h ../lib/mbselib.h ../lib/users.h ttyio.h transfer.h zmmisc.h zmrecv.h ymrecv.h openport.h timeout.h input.h diff --git a/mbsebbs/transfer.c b/mbsebbs/transfer.c index 6753175b..ffd4b92b 100644 --- a/mbsebbs/transfer.c +++ b/mbsebbs/transfer.c @@ -305,6 +305,8 @@ int download(down_list *download_list) } closedir(dirp); } + + purgeline(200); /* Wait a while, some Wintendo programs ignore input for a few seconds */ Altime(0); alarm_off(); alarm_on(); @@ -389,7 +391,7 @@ int upload(up_list **upload_list) struct timeval starttime, endtime; struct timezone tz; unsigned long Size = 0; - int err, Count = 0, rc = 0, want1k = FALSE; + int err, Count = 0, rc = 0, want1k = FALSE, wantg = FALSE; up_list *tmp, *ta; /* @@ -417,7 +419,10 @@ int upload(up_list **upload_list) sleep(2); if (uProtInternal) { - if ((strncasecmp(sProtName, "zmodem", 6) == 0) || (strncasecmp(sProtName, "ymodem", 6) == 0)) { + if ((strncasecmp(sProtName, "zmodem", 6) == 0) || + (strncasecmp(sProtName, "ymodem", 6) == 0) || + (strncasecmp(sProtName, "xmodem", 6) == 0)) { + if (strncasecmp(sProtName, "zmodem", 6) == 0) { zmodem_requested = TRUE; protocol = ZM_ZMODEM; @@ -426,10 +431,18 @@ int upload(up_list **upload_list) } if (strncasecmp(sProtName, "ymodem", 6) == 0) protocol = ZM_YMODEM; + if (strncasecmp(sProtName, "xmodem", 6) == 0) + protocol = ZM_XMODEM; - if (strstr(sProtName, "1K") || strstr(sProtName, "1k")) + if ((strstr(sProtName, "1K") || strstr(sProtName, "1k")) && (protocol != ZM_ZMODEM)) { + Syslog('x', "%s: want 1K blocks", protname()); want1k = TRUE; - rc = zmrcvfiles(want1k); + } + if ((strstr(sProtName, "G")) && (protocol == ZM_YMODEM)) { + Syslog('x', "%s: want Ymodem-G", protname()); + wantg = TRUE; + } + rc = zmrcvfiles(want1k, wantg); Syslog('b', "Begin dir processing"); if ((dirp = opendir(".")) == NULL) { diff --git a/mbsebbs/ymrecv.c b/mbsebbs/ymrecv.c index f20418dc..6c24df8b 100644 --- a/mbsebbs/ymrecv.c +++ b/mbsebbs/ymrecv.c @@ -33,8 +33,10 @@ #include "../lib/mbse.h" #include "ttyio.h" #include "timeout.h" +#include "transfer.h" #include "zmmisc.h" #include "zmrecv.h" +#include "ymsend.h" #include "ymrecv.h" @@ -42,6 +44,8 @@ static int Firstsec; static int eof_seen; static int errors; +static int Gflg = FALSE; +static char NAKchar; extern long Bytesleft; extern off_t rxbytes; @@ -50,22 +54,38 @@ extern char Lastrx; extern char *secbuf; -#define sendline(c) PUTCHAR((c) & 0377) +#define sendline(c) PUTCHAR((c & 0377)) int wcgetsec(size_t *, char *, unsigned int); -int wcrxpn(char *, int); +int wcrxpn(char *); int wcrx(void); -int ymrcvfiles(int want1k) +int ymrcvfiles(int want1k, int wantG) { int rc = 0; - Syslog('x', "%s: ymrcvfiles(%s)", protname(), want1k ? "TRUE":"FALSE"); + NAKchar = NAK; + Crcflg = Gflg = FALSE; + if (protocol == ZM_YMODEM) { + NAKchar = WANTCRC; + Crcflg = TRUE; + } + if (want1k) { + Crcflg = TRUE; + NAKchar = WANTCRC; + } + if (wantG) { + Crcflg = Gflg = TRUE; + NAKchar = WANTG; + } + + Syslog('x', "%s: ymrcvfiles(%s, %s)", protname(), want1k ? "TRUE":"FALSE", wantG ? "TRUE":"FALSE"); + Syslog('x', "%s: NAK character will be %s", protname(), printablec(NAKchar)); for (;;) { rxbytes = 0l; - if (wcrxpn(secbuf, want1k) == TERROR) { + if (wcrxpn(secbuf) == TERROR) { rc = 2; break; } @@ -95,26 +115,26 @@ int ymrcvfiles(int want1k) * Length is indeterminate as long as less than Blklen * A null string represents no more files (YMODEM) */ -int wcrxpn(char *rpn, int want1k) +int wcrxpn(char *rpn) { register int c; size_t Blklen = 0; /* record length of received packets */ - Crcflg = want1k; purgeline(0); Syslog('x', "%s: wcrxpn() crc=%s", protname(), Crcflg ? "true":"false"); et_tu: Firstsec = TRUE; eof_seen = FALSE; - sendline(Crcflg?WANTCRC:NAK); - ioctl(1, TCFLSH, 0); + Syslog('x', "Send %s", printablec(NAKchar)); + sendline(NAKchar); +// ioctl(1, TCFLSH, 0); purgeline(0); /* Do read next time ... */ while ((c = wcgetsec(&Blklen, rpn, 10)) != 0) { if (c == WCEOT) { Syslog('x', "Pathname fetch returned EOT"); sendline(ACK); - ioctl(1, TCFLSH, 0); +// ioctl(1, TCFLSH, 0); purgeline(0); /* Do read next time ... */ goto et_tu; } @@ -136,13 +156,13 @@ int wcrx(void) Firstsec = TRUE; sectnum = 0; eof_seen = FALSE; - sendchar = Crcflg ? WANTCRC:NAK; + sendchar = NAKchar; - Syslog('x', "%s: wcrx", protname()); + Syslog('x', "%s: wcrx, request type %s", protname(), printablec(sendchar)); for (;;) { sendline(sendchar); /* send it now, we're ready! */ - ioctl(1, TCFLSH, 0); +// ioctl(1, TCFLSH, 0); purgeline(0); /* Do read next time ... */ /* @@ -164,19 +184,18 @@ int wcrx(void) if (putsec(secbuf, Blklen) == ERROR) return ERROR; sendchar = ACK; - } - else if (sectcurr == (sectnum & 0377)) { + } else if (sectcurr == (sectnum & 0377)) { Syslog('x', "Received dup Sector"); sendchar = ACK; } else if (sectcurr == WCEOT) { if (closeit(1)) return ERROR; sendline(ACK); - ioctl(1, TCFLSH, 0); +// ioctl(1, TCFLSH, 0); purgeline(0); /* Do read next time ... */ return OK; } - else if (sectcurr == ERROR) + else if (sectcurr == TERROR) return ERROR; else { Syslog('x', "Sync Error"); @@ -202,6 +221,7 @@ int wcgetsec(size_t *Blklen, char *rxbuf, unsigned int maxtime) if (firstch == SOH) { *Blklen=128; get2: + Syslog('x', "wcgetsec: firstch=%s, maxtime=%d, check=%s", printablec(firstch), maxtime, Crcflg?"CRC":"Checksum"); sectcurr = GETCHAR(1); if ((sectcurr + (oldcrc = GETCHAR(1))) == 0377) { oldcrc = Checksum = 0; @@ -237,8 +257,8 @@ get2: return WCEOT; else if (firstch == CAN) { if (Lastrx == CAN) { - Syslog('x', "Sender Cancelled"); - return ERROR; + Syslog('+', "%s: sender Cancelled during transfer", protname()); + return TERROR; } else { Lastrx=CAN; continue; @@ -258,21 +278,21 @@ humbug: } if (Firstsec) { - sendline(Crcflg ? WANTCRC:NAK); - ioctl(1, TCFLSH, 0); - Syslog('x', "%s: send %s", protname(), Crcflg ? "WANTCRC":"NAK"); + sendline(NAKchar); +// ioctl(1, TCFLSH, 0); + Syslog('x', "%s: send %s", protname(), printablec(NAKchar)); purgeline(0); /* Do read next time ... */ } else { - maxtime = 40; + maxtime = 5; sendline(NAK); Syslog('x', "%s: send NAK", protname()); - ioctl(1, TCFLSH, 0); +// ioctl(1, TCFLSH, 0); purgeline(0); /* Do read next time ... */ } } /* try to stop the bubble machine. */ canit(STDOUT_FILENO); - return ERROR; + return TERROR; } diff --git a/mbsebbs/ymrecv.h b/mbsebbs/ymrecv.h index d5e85b49..4e1e573b 100644 --- a/mbsebbs/ymrecv.h +++ b/mbsebbs/ymrecv.h @@ -3,13 +3,12 @@ /* $Id$ */ -#define WANTCRC 0103 /* send C not NAK to get crc not checksum */ #define WCEOT (-10) #define RETRYMAX 10 -int ymrcvfiles(int); +int ymrcvfiles(int, int); #endif diff --git a/mbsebbs/ymsend.c b/mbsebbs/ymsend.c index da943c22..ad9e8ea6 100644 --- a/mbsebbs/ymsend.c +++ b/mbsebbs/ymsend.c @@ -41,7 +41,7 @@ #define MAX_BLOCK 8192 -#define sendline(c) PUTCHAR((c) & 0377) +#define sendline(c) PUTCHAR((c & 0377)) FILE *input_f; @@ -94,6 +94,13 @@ int ymsndfiles(down_list *lst, int use1k) } Syslog('x', "%s: %d files, size %d bytes", protname(), Filesleft, Totalleft); + /* + * This is not documented as auto start sequence, but a lot of terminal + * programs seem to react on this. + */ + if (protocol == ZM_YMODEM) + PUTSTR((char *)"rb\r"); + for (tmpf = lst; tmpf && (maxrc < 2); tmpf = tmpf->next) { if (tmpf->remote) { bytes_sent = 0; @@ -217,6 +224,7 @@ static int wctxpn(char *fname) if ((input_f != stdin) && *fname) sprintf(p, "%lu %lo %o 0 %d %ld", (long) f.st_size, f.st_mtime, (unsigned int)((no_unixmode) ? 0 : f.st_mode), Filesleft, Totalleft); +// sprintf(p, "%lu %lo 0 0 0 0", (long) f.st_size, f.st_mtime); Totalleft -= f.st_size; if (--Filesleft <= 0) @@ -224,18 +232,9 @@ static int wctxpn(char *fname) if (Totalleft < 0) Totalleft = 0; - /* force 1k blocks if name won't fit in 128 byte block */ - if (txbuf[125]) - blklen=1024; - else { /* A little goodie for IMP/KMD */ - txbuf[127] = (f.st_size + 127) >>7; - txbuf[126] = (f.st_size + 127) >>15; - } -// if (zmodem_requested) -// return zsendfile(zi,txbuf, 1+strlen(p)+(p-txbuf)); + purgeline(1); if (wcputsec(txbuf, 0, 128) == TERROR) { - PUTSTR((char *)"wcputsec failed"); - Syslog('+', "%s/%s: wcputsec failed", fname,protname()); + Syslog('+', "%s: failed to send filename", protname()); return TERROR; } return OK; @@ -243,6 +242,9 @@ static int wctxpn(char *fname) +/* + * Get NAK, C or G + */ static int getnak(void) { int firstch; @@ -261,7 +263,7 @@ static int getnak(void) // return FALSE; case TIMEOUT: Syslog('x', "getnak: timeout try %d", tries); - /* 50 seconds are enough */ + /* 50 seconds are enough (was 30, 26-11-2004 MB) */ if (tries == 5) { Syslog('x', "Timeout on pathname"); return TRUE; @@ -283,16 +285,21 @@ static int getnak(void) io_mode(0, 2); /* Set cbreak, XON/XOFF, etc. */ Optiong = TRUE; blklen=1024; + Crcflg = TRUE; + return FALSE; case WANTCRC: Syslog('x', "getnak: got WANTCRC"); Crcflg = TRUE; + return FALSE; case NAK: Syslog('x', "getnak: got NAK"); return FALSE; case CAN: Syslog('x', "getnak: got CAN"); - if ((firstch = GETCHAR(2)) == CAN && Lastrx == CAN) + if ((firstch = GETCHAR(2)) == CAN && Lastrx == CAN) { + Syslog('+', "%s: Receiver cancelled", protname()); return TRUE; + } default: Syslog('x', "got %d", firstch); break; @@ -316,7 +323,7 @@ static int wctx(long bytes_total) while ((firstch = GETCHAR(Rxtimeout)) != NAK && firstch != WANTCRC && firstch != WANTG && firstch != TIMEOUT && firstch != CAN); if (firstch == CAN) { - Syslog('x', "Receiver Cancelled"); + Syslog('+', "%s: receiver Cancelled during transfer", protname()); return TERROR; } @@ -348,7 +355,6 @@ static int wctx(long bytes_total) do { purgeline(5); PUTCHAR(EOT); - ioctl(1, TCFLSH, 0); ++attempts; } while ((firstch = (GETCHAR(Rxtimeout)) != ACK) && attempts < RETRYMAX); if (attempts == RETRYMAX) { @@ -373,11 +379,10 @@ static int wcputsec(char *buf, int sectnum, size_t cseclen) Syslog('x', "%s: wcputsec: sectnum %d, len %d, %s", protname(), sectnum, cseclen, Crcflg ? "crc":"checksum"); for (attempts = 0; attempts <= RETRYMAX; attempts++) { - Syslog('x', "send sector"); Lastrx = firstch; sendline(cseclen == 1024 ? STX:SOH); sendline(sectnum); - sendline(-sectnum -1); + sendline((-sectnum -1)); oldcrc = Checksum = 0; for (wcj = cseclen, cp = buf; --wcj >= 0; ) { sendline(*cp); @@ -388,11 +393,10 @@ static int wcputsec(char *buf, int sectnum, size_t cseclen) oldcrc = updcrc16(0, updcrc16(0, oldcrc)); sendline((int)oldcrc >> 8); sendline((int)oldcrc); - } - else + } else { sendline(Checksum); + } - ioctl(1, TCFLSH, 0); if (Optiong) { firstsec = FALSE; return OK; @@ -416,10 +420,9 @@ cancan: Crcflg = TRUE; case NAK: Syslog('+', "%s: got NAK on sector %d", protname(), sectnum); - purgeline(10); + purgeline(20); continue; case ACK: - Syslog('x', "Got ACK"); firstsec=FALSE; Totsecs += (cseclen>>7); return OK; diff --git a/mbsebbs/ymsend.h b/mbsebbs/ymsend.h index f18c8524..a82130d0 100644 --- a/mbsebbs/ymsend.h +++ b/mbsebbs/ymsend.h @@ -5,9 +5,9 @@ #define RETRYMAX 10 -#define CPMEOF 032 -#define WANTCRC 0103 /* send C not NAK to get crc not checksum */ -#define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */ +#define CPMEOF 032 /* CP/M EOF, Ctrl-Z */ +#define WANTCRC 'C' /* send C not NAK to get crc not checksum */ +#define WANTG 'G' /* Send G not NAK to get nonstop batch xmsn */ int ymsndfiles(down_list *, int); diff --git a/mbsebbs/zmrecv.c b/mbsebbs/zmrecv.c index 7328fa1b..28e494e5 100644 --- a/mbsebbs/zmrecv.c +++ b/mbsebbs/zmrecv.c @@ -80,7 +80,7 @@ extern int zmodem_requested; * This receiver will figure out what to do, you should * be able to send anything. */ -int zmrcvfiles(int want1k) +int zmrcvfiles(int want1k, int wantg) { int rc; @@ -99,7 +99,7 @@ int zmrcvfiles(int want1k) Syslog('+', "%s: switching to Ymodem", protname()); protocol = ZM_YMODEM; } - rc = ymrcvfiles(want1k); + rc = ymrcvfiles(want1k, wantg); goto fubar; } @@ -128,8 +128,10 @@ fubar: io_mode(0, 1); /* Normal raw mode */ /* * Some programs send some garbage after the transfer, eat these. + * This also introduces a pause after the transfer, some clients + * need this. */ - purgeline(100); + purgeline(200); Syslog('+', "%s: end receive rc=%d", protname(), rc); return abs(rc); @@ -151,7 +153,7 @@ int tryz(void) if (protocol != ZM_ZMODEM) return 0; - for (n = zmodem_requested ?15:5; --n >= 0; ) { + for (n = zmodem_requested ?15:10; --n >= 0; ) { /* * Set buffer length (0) and capability flags */ diff --git a/mbsebbs/zmrecv.h b/mbsebbs/zmrecv.h index 6337789f..3d473e51 100644 --- a/mbsebbs/zmrecv.h +++ b/mbsebbs/zmrecv.h @@ -4,7 +4,7 @@ /* $Id$ */ int procheader(char*); -int zmrcvfiles(int); +int zmrcvfiles(int, int); int putsec(char*,int); int closeit(int);