From 5e3b1b09d5044a2a65d0eeb2bfaa3d44968b3f1a Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Mon, 8 Nov 2004 12:24:36 +0000 Subject: [PATCH] Updated zmodem sources --- mbsebbs/Makefile | 12 +- mbsebbs/transfer.c | 5 +- mbsebbs/transfer.h | 2 +- mbsebbs/zmmisc.c | 1 - mbsebbs/zmmisc.h | 167 +++++++++++ mbsebbs/zmodem.h | 201 ------------- mbsebbs/zmrecv.c | 585 ++++++++++++++++++++++++++++++++++++++ mbsebbs/zmrecv.h | 9 + mbsebbs/zmrle.c | 2 - mbsebbs/zmsend.c | 684 +++++++++++++++++++++++++++++++++++++++++++++ mbsebbs/zmsend.h | 10 + 11 files changed, 1467 insertions(+), 211 deletions(-) delete mode 100644 mbsebbs/zmodem.h create mode 100644 mbsebbs/zmrecv.c create mode 100644 mbsebbs/zmrecv.h create mode 100644 mbsebbs/zmsend.c create mode 100644 mbsebbs/zmsend.h diff --git a/mbsebbs/Makefile b/mbsebbs/Makefile index 4bc5f799..050e50db 100644 --- a/mbsebbs/Makefile +++ b/mbsebbs/Makefile @@ -13,7 +13,7 @@ SRCS = signature.c filesub.c language.c mbtoberep.c \ timeout.c chat.c file.c misc.c \ offline.c user.c mbnewusr.c input.c whoson.c \ door.c dispfile.c userlist.c timestats.c logentry.c \ - zmrle.c zmmisc.c + zmrle.c zmmisc.c zmsend.c zmrecv.c HDRS = signature.h filesub.h language.h mbsebbs.h misc.h offline.h \ timeout.h bbslist.h email.h fsedit.h lineedit.h \ msgutil.h oneline.h user.h bye.h morefile.h \ @@ -22,14 +22,14 @@ HDRS = signature.h filesub.h language.h mbsebbs.h misc.h offline.h \ pinfo.h chat.h file.h menu.h transfer.h \ pop3.h timecheck.h mbnewusr.h input.h whoson.h \ door.h dispfile.h userlist.h timestats.h logentry.h lastcallers.h \ - zmrle.h zmmisc.h zmodem.h + zmrle.h zmmisc.h zmsend.h zmrecv.h MBSEBBS_OBJS = signature.o bbslist.o chat.o file.o funcs.o mail.o menu.o \ misc.o pinfo.o oneline.o page.o fsedit.o transfer.o \ bye.o change.o mbsebbs.o timeout.o user.o timecheck.o \ exitinfo.o filesub.o lineedit.o offline.o language.o msgutil.o \ pop3.o email.o input.o whoson.o door.o dispfile.o userlist.o timestats.o \ logentry.o morefile.o lastcallers.o term.o ttyio.o openport.o \ - zmrle.o zmmisc.o + zmrle.o zmmisc.o zmsend.o zmrecv.o MBSEBBS_LIBS = ../lib/libmbse.a ../lib/libmsgbase.a ../lib/libdbase.a ../lib/libmbinet.a ../lib/libnodelist.a MBNEWUSR_OBJS = mbnewusr.o newuser.o language.o timeout.o dispfile.o oneline.o ttyio.o \ timecheck.o input.o exitinfo.o funcs.o misc.o change.o door.o term.o openport.o \ @@ -132,6 +132,8 @@ dispfile.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ../lib/users.h ../lib/msg userlist.o: ../config.h ../lib/mbselib.h ../lib/mbse.h ../lib/users.h userlist.h language.h input.h timeout.h term.h ttyio.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 -zmrle.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h zmodem.h zmrle.h zmmisc.h -zmmisc.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h zmodem.h zmrle.h zmmisc.h +zmrle.o: ../config.h ../lib/mbselib.h ttyio.h zmrle.h zmmisc.h +zmmisc.o: ../config.h ../lib/mbselib.h ../lib/nodelist.h ttyio.h zmrle.h zmmisc.h +zmsend.o: ../config.h ../lib/mbselib.h ttyio.h zmmisc.h zmrle.h transfer.h +zmrecv.o: ../config.h ../lib/mbselib.h ../lib/users.h ttyio.h transfer.h zmmisc.h zmrecv.h # End of generated dependencies diff --git a/mbsebbs/transfer.c b/mbsebbs/transfer.c index 9ab1e700..b5e4b3e3 100644 --- a/mbsebbs/transfer.c +++ b/mbsebbs/transfer.c @@ -66,7 +66,10 @@ */ -char *transfertime(struct timeval, struct timeval, long bytes, int); + +int sentbytes = 0; +int rcvdbytes = 0; + int ForceProtocol() diff --git a/mbsebbs/transfer.h b/mbsebbs/transfer.h index a1c95cc9..9a4fc66c 100644 --- a/mbsebbs/transfer.h +++ b/mbsebbs/transfer.h @@ -38,6 +38,6 @@ void tidy_download(down_list **); int download(down_list *); void tidy_upload(up_list **); int upload(up_list **); - +char *transfertime(struct timeval, struct timeval, long bytes, int); #endif diff --git a/mbsebbs/zmmisc.c b/mbsebbs/zmmisc.c index f0c07214..69cbfd59 100644 --- a/mbsebbs/zmmisc.c +++ b/mbsebbs/zmmisc.c @@ -67,7 +67,6 @@ static void garbitch(void); #include "../lib/mbselib.h" #include "../lib/nodelist.h" #include "ttyio.h" -#include "zmodem.h" #include "zmrle.h" #include "zmmisc.h" diff --git a/mbsebbs/zmmisc.h b/mbsebbs/zmmisc.h index 7b489f0a..53beaa05 100644 --- a/mbsebbs/zmmisc.h +++ b/mbsebbs/zmmisc.h @@ -3,6 +3,167 @@ /* $Id$ */ + +#ifndef OK +#define OK 0 +#endif + +#define MAXBLOCK 8192 + + +/* + * Z M O D E M . H Manifest constants for ZMODEM + * application to application file transfer protocol + * 04-17-89 Chuck Forsberg Omen Technology Inc + */ +#define ZPAD '*' /* 052 Padding character begins frames */ +#define ZDLE 030 /* Ctrl-X Zmodem escape - `ala BISYNC DLE */ +#define ZDLEE (ZDLE^0100) /* Escaped ZDLE as transmitted */ +#define ZBIN 'A' /* Binary frame indicator (CRC-16) */ +#define ZHEX 'B' /* HEX frame indicator */ +#define ZBIN32 'C' /* Binary frame with 32 bit FCS */ +#define ZBINR32 'D' /* RLE packed Binary frame with 32 bit FCS */ +#define ZVBIN 'a' /* Binary frame indicator (CRC-16) */ +#define ZVHEX 'b' /* HEX frame indicator */ +#define ZVBIN32 'c' /* Binary frame with 32 bit FCS */ +#define ZVBINR32 'd' /* RLE packed Binary frame with 32 bit FCS */ +#define ZRESC 0176 /* RLE flag/escape character */ +#define ZMAXHLEN 16 /* Max header information length NEVER CHANGE */ +#define ZMAXSPLEN 1024 /* Max subpacket length NEVER CHANGE */ + + +/* Frame types (see array "frametypes" in zm.c) */ +#define ZRQINIT 0 /* Request receive init */ +#define ZRINIT 1 /* Receive init */ +#define ZSINIT 2 /* Send init sequence (optional) */ +#define ZACK 3 /* ACK to above */ +#define ZFILE 4 /* File name from sender */ +#define ZSKIP 5 /* To sender: skip this file */ +#define ZNAK 6 /* Last packet was garbled */ +#define ZABORT 7 /* Abort batch transfers */ +#define ZFIN 8 /* Finish session */ +#define ZRPOS 9 /* Resume data trans at this position */ +#define ZDATA 10 /* Data packet(s) follow */ +#define ZEOF 11 /* End of file */ +#define ZFERR 12 /* Fatal Read or Write error Detected */ +#define ZCRC 13 /* Request for file CRC and response */ +#define ZCHALLENGE 14 /* Receiver's Challenge */ +#define ZCOMPL 15 /* Request is complete */ +#define ZCAN 16 /* Other end canned session with CAN*5 */ +#define ZFREECNT 17 /* Request for free bytes on filesystem */ +#define ZCOMMAND 18 /* Command from sending program */ +#define ZSTDERR 19 /* Output to standard error, data follows */ + +/* ZDLE sequences */ +#define ZCRCE 'h' /* CRC next, frame ends, header packet follows */ +#define ZCRCG 'i' /* CRC next, frame continues nonstop */ +#define ZCRCQ 'j' /* CRC next, frame continues, ZACK expected */ +#define ZCRCW 'k' /* CRC next, ZACK expected, end of frame */ +#define ZRUB0 'l' /* Translate to rubout 0177 */ +#define ZRUB1 'm' /* Translate to rubout 0377 */ + +/* zdlread return values (internal) */ +/* -1 is general error, -2 is timeout */ +#define GOTOR 0400 +#define GOTCRCE (ZCRCE|GOTOR) /* ZDLE-ZCRCE received */ +#define GOTCRCG (ZCRCG|GOTOR) /* ZDLE-ZCRCG received */ +#define GOTCRCQ (ZCRCQ|GOTOR) /* ZDLE-ZCRCQ received */ +#define GOTCRCW (ZCRCW|GOTOR) /* ZDLE-ZCRCW received */ +#define GOTCAN (GOTOR|030) /* CAN*5 seen */ + +/* Byte positions within header array */ +#define ZF0 3 /* First flags byte */ +#define ZF1 2 +#define ZF2 1 +#define ZF3 0 +#define ZP0 0 /* Low order 8 bits of position */ +#define ZP1 1 +#define ZP2 2 +#define ZP3 3 /* High order 8 bits of file position */ + +/* Parameters for ZRINIT header */ +#define ZRPXWN 8 /* 9th byte in header contains window size/256 */ +#define ZRPXQQ 9 /* 10th to 14th bytes contain quote mask */ +/* Bit Masks for ZRINIT flags byte ZF0 */ +#define CANFDX 01 /* Rx can send and receive true FDX */ +#define CANOVIO 02 /* Rx can receive data during disk I/O */ +#define CANBRK 04 /* Rx can send a break signal */ +#define CANRLE 010 /* Receiver can decode RLE */ +#define CANLZW 020 /* Receiver can uncompress */ +#define CANFC32 040 /* Receiver can use 32 bit Frame Check */ +#define ESCCTL 0100 /* Receiver expects ctl chars to be escaped */ +#define ESC8 0200 /* Receiver expects 8th bit to be escaped */ + +/* Bit Masks for ZRINIT flags byte ZF1 */ +#define CANVHDR 01 /* Variable headers OK */ +#define ZRRQWN 8 /* Receiver specified window size in ZRPXWN */ +#define ZRRQQQ 16 /* Additional control chars to quote in ZRPXQQ */ +#define ZRQNVH (ZRRQWN|ZRRQQQ) /* Variable len hdr reqd to access info */ + +/* Parameters for ZSINIT frame */ +#define ZATTNLEN 32 /* Max length of attention string */ +#define ALTCOFF ZF1 /* Offset to alternate canit string, 0 if not used */ +/* Bit Masks for ZSINIT flags byte ZF0 */ +#define TESCCTL 0100 /* Transmitter expects ctl chars to be escaped */ +#define TESC8 0200 /* Transmitter expects 8th bit to be escaped */ + +/* Parameters for ZFILE frame */ +/* Conversion options one of these in ZF0 */ +#define ZCBIN 1 /* Binary transfer - inhibit conversion */ +#define ZCNL 2 /* Convert NL to local end of line convention */ +#define ZCRESUM 3 /* Resume interrupted file transfer */ +/* Management include options, one of these ored in ZF1 */ +#define ZMSKNOLOC 0200 /* Skip file if not present at rx */ +/* Management options, one of these ored in ZF1 */ +#define ZMMASK 037 /* Mask for the choices below */ +#define ZMNEWL 1 /* Transfer if source newer or longer */ +#define ZMCRC 2 /* Transfer if different file CRC or length */ +#define ZMAPND 3 /* Append contents to existing file (if any) */ +#define ZMCLOB 4 /* Replace existing file */ +#define ZMNEW 5 /* Transfer if source newer */ + /* Number 5 is alive ... */ +#define ZMDIFF 6 /* Transfer if dates or lengths different */ +#define ZMPROT 7 /* Protect destination file */ +#define ZMCHNG 8 /* Change filename if destination exists */ +/* Transport options, one of these in ZF2 */ +#define ZTLZW 1 /* Lempel-Ziv compression */ +#define ZTRLE 3 /* Run Length encoding */ +/* Extended options for ZF3, bit encoded */ +#define ZXSPARS 64 /* Encoding for sparse file operations */ +#define ZCANVHDR 01 /* Variable headers OK */ +/* Receiver window size override */ +#define ZRWOVR 4 /* byte position for receive window override/256 */ + +/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */ +#define ZCACK1 1 /* Acknowledge, then do command */ + +long rclhdr(register char *); + +/* Globals used by ZMODEM functions */ +extern int Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame */ +extern int Rxtype; /* Type of header received */ +extern int Rxcount; /* Count of data bytes received */ +extern int long Rxpos; /* Received file position */ +extern int long Txpos; /* Transmitted file position */ +extern int Txfcs32; /* TURE means send binary frames with 32 bit FCS */ +extern int Crc32t; /* Display flag indicating 32 bit CRC being sent */ +extern int Crc32r; /* Display flag indicating 32 bit CRC being received */ +extern int Crc32; /* Display flag indicating 32 bit CRC being received */ +extern int Znulls; /* Number of nulls to send at beginning of ZDATA hdr */ +extern char Rxhdr[]; +extern char Txhdr[]; +extern char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ +extern char *Altcan; /* Alternate canit string */ +extern char *Zendnames[]; +extern char *txbuf; +extern char *rxbuf; + +char Zsendmask[33]; /* Additional control characters to mask */ + +extern int Zctlesc; +extern char *frametypes[]; + + void get_frame_buffer(void); void free_frame_buffer(void); void zsbhdr(int, int, register char *); @@ -17,5 +178,11 @@ int zdlread(void); void stohdr(long); long rclhdr(register char *); +#define FTOFFSET 16 + +extern unsigned short crc16xmodemtab[]; +extern unsigned long crc32tab[]; +#define updcrc16(cp,crc) (crc16xmodemtab[(((int)crc >> 8) & 0xff)] ^ (crc << 8) ^ cp) +#define updcrc32(cp,crc) (crc32tab[((int)crc ^ cp) & 0xff] ^ ((crc >> 8) & 0x00ffffff)) #endif diff --git a/mbsebbs/zmodem.h b/mbsebbs/zmodem.h deleted file mode 100644 index 303eb14e..00000000 --- a/mbsebbs/zmodem.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef ZMODEM_H -#define ZMODEM_H - -/* $Id$ */ - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef OK -#define OK 0 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#define RETRYMAX 10 -#define MAXBLOCK 8192 - -/* - * Z M O D E M . H Manifest constants for ZMODEM - * application to application file transfer protocol - * 04-17-89 Chuck Forsberg Omen Technology Inc - */ -#define ZPAD '*' /* 052 Padding character begins frames */ -#define ZDLE 030 /* Ctrl-X Zmodem escape - `ala BISYNC DLE */ -#define ZDLEE (ZDLE^0100) /* Escaped ZDLE as transmitted */ -#define ZBIN 'A' /* Binary frame indicator (CRC-16) */ -#define ZHEX 'B' /* HEX frame indicator */ -#define ZBIN32 'C' /* Binary frame with 32 bit FCS */ -#define ZBINR32 'D' /* RLE packed Binary frame with 32 bit FCS */ -#define ZVBIN 'a' /* Binary frame indicator (CRC-16) */ -#define ZVHEX 'b' /* HEX frame indicator */ -#define ZVBIN32 'c' /* Binary frame with 32 bit FCS */ -#define ZVBINR32 'd' /* RLE packed Binary frame with 32 bit FCS */ -#define ZRESC 0176 /* RLE flag/escape character */ -#define ZMAXHLEN 16 /* Max header information length NEVER CHANGE */ -#define ZMAXSPLEN 1024 /* Max subpacket length NEVER CHANGE */ - -/* Frame types (see array "frametypes" in zm.c) */ -#define ZRQINIT 0 /* Request receive init */ -#define ZRINIT 1 /* Receive init */ -#define ZSINIT 2 /* Send init sequence (optional) */ -#define ZACK 3 /* ACK to above */ -#define ZFILE 4 /* File name from sender */ -#define ZSKIP 5 /* To sender: skip this file */ -#define ZNAK 6 /* Last packet was garbled */ -#define ZABORT 7 /* Abort batch transfers */ -#define ZFIN 8 /* Finish session */ -#define ZRPOS 9 /* Resume data trans at this position */ -#define ZDATA 10 /* Data packet(s) follow */ -#define ZEOF 11 /* End of file */ -#define ZFERR 12 /* Fatal Read or Write error Detected */ -#define ZCRC 13 /* Request for file CRC and response */ -#define ZCHALLENGE 14 /* Receiver's Challenge */ -#define ZCOMPL 15 /* Request is complete */ -#define ZCAN 16 /* Other end canned session with CAN*5 */ -#define ZFREECNT 17 /* Request for free bytes on filesystem */ -#define ZCOMMAND 18 /* Command from sending program */ -#define ZSTDERR 19 /* Output to standard error, data follows */ - -/* ZDLE sequences */ -#define ZCRCE 'h' /* CRC next, frame ends, header packet follows */ -#define ZCRCG 'i' /* CRC next, frame continues nonstop */ -#define ZCRCQ 'j' /* CRC next, frame continues, ZACK expected */ -#define ZCRCW 'k' /* CRC next, ZACK expected, end of frame */ -#define ZRUB0 'l' /* Translate to rubout 0177 */ -#define ZRUB1 'm' /* Translate to rubout 0377 */ - -/* zdlread return values (internal) */ -/* -1 is general error, -2 is timeout */ -#define GOTOR 0400 -#define GOTCRCE (ZCRCE|GOTOR) /* ZDLE-ZCRCE received */ -#define GOTCRCG (ZCRCG|GOTOR) /* ZDLE-ZCRCG received */ -#define GOTCRCQ (ZCRCQ|GOTOR) /* ZDLE-ZCRCQ received */ -#define GOTCRCW (ZCRCW|GOTOR) /* ZDLE-ZCRCW received */ -#define GOTCAN (GOTOR|030) /* CAN*5 seen */ - -/* Byte positions within header array */ -#define ZF0 3 /* First flags byte */ -#define ZF1 2 -#define ZF2 1 -#define ZF3 0 -#define ZP0 0 /* Low order 8 bits of position */ -#define ZP1 1 -#define ZP2 2 -#define ZP3 3 /* High order 8 bits of file position */ - -/* Parameters for ZRINIT header */ -#define ZRPXWN 8 /* 9th byte in header contains window size/256 */ -#define ZRPXQQ 9 /* 10th to 14th bytes contain quote mask */ -/* Bit Masks for ZRINIT flags byte ZF0 */ -#define CANFDX 01 /* Rx can send and receive true FDX */ -#define CANOVIO 02 /* Rx can receive data during disk I/O */ -#define CANBRK 04 /* Rx can send a break signal */ -#define CANRLE 010 /* Receiver can decode RLE */ -#define CANLZW 020 /* Receiver can uncompress */ -#define CANFC32 040 /* Receiver can use 32 bit Frame Check */ -#define ESCCTL 0100 /* Receiver expects ctl chars to be escaped */ -#define ESC8 0200 /* Receiver expects 8th bit to be escaped */ - -/* Bit Masks for ZRINIT flags byte ZF1 */ -#define CANVHDR 01 /* Variable headers OK */ -#define ZRRQWN 8 /* Receiver specified window size in ZRPXWN */ -#define ZRRQQQ 16 /* Additional control chars to quote in ZRPXQQ */ -#define ZRQNVH (ZRRQWN|ZRRQQQ) /* Variable len hdr reqd to access info */ - -/* Parameters for ZSINIT frame */ -#define ZATTNLEN 32 /* Max length of attention string */ -#define ALTCOFF ZF1 /* Offset to alternate canit string, 0 if not used */ -/* Bit Masks for ZSINIT flags byte ZF0 */ -#define TESCCTL 0100 /* Transmitter expects ctl chars to be escaped */ -#define TESC8 0200 /* Transmitter expects 8th bit to be escaped */ - -/* Parameters for ZFILE frame */ -/* Conversion options one of these in ZF0 */ -#define ZCBIN 1 /* Binary transfer - inhibit conversion */ -#define ZCNL 2 /* Convert NL to local end of line convention */ -#define ZCRESUM 3 /* Resume interrupted file transfer */ -/* Management include options, one of these ored in ZF1 */ -#define ZMSKNOLOC 0200 /* Skip file if not present at rx */ -/* Management options, one of these ored in ZF1 */ -#define ZMMASK 037 /* Mask for the choices below */ -#define ZMNEWL 1 /* Transfer if source newer or longer */ -#define ZMCRC 2 /* Transfer if different file CRC or length */ -#define ZMAPND 3 /* Append contents to existing file (if any) */ -#define ZMCLOB 4 /* Replace existing file */ -#define ZMNEW 5 /* Transfer if source newer */ - /* Number 5 is alive ... */ -#define ZMDIFF 6 /* Transfer if dates or lengths different */ -#define ZMPROT 7 /* Protect destination file */ -#define ZMCHNG 8 /* Change filename if destination exists */ -/* Transport options, one of these in ZF2 */ -#define ZTLZW 1 /* Lempel-Ziv compression */ -#define ZTRLE 3 /* Run Length encoding */ -/* Extended options for ZF3, bit encoded */ -#define ZXSPARS 64 /* Encoding for sparse file operations */ -#define ZCANVHDR 01 /* Variable headers OK */ -/* Receiver window size override */ -#define ZRWOVR 4 /* byte position for receive window override/256 */ - -/* Parameters for ZCOMMAND frame ZF0 (otherwise 0) */ -#define ZCACK1 1 /* Acknowledge, then do command */ - -long rclhdr(register char *); - -/* Globals used by ZMODEM functions */ -extern int Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame */ -extern int Rxtype; /* Type of header received */ -extern int Rxcount; /* Count of data bytes received */ -extern int long Rxpos; /* Received file position */ -extern int long Txpos; /* Transmitted file position */ -extern int Txfcs32; /* TURE means send binary frames with 32 bit FCS */ -extern int Crc32t; /* Display flag indicating 32 bit CRC being sent */ -extern int Crc32r; /* Display flag indicating 32 bit CRC being received */ -extern int Crc32; /* Display flag indicating 32 bit CRC being received */ -extern int Znulls; /* Number of nulls to send at beginning of ZDATA hdr */ -extern char Rxhdr[]; -extern char Txhdr[]; -extern char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */ -extern char *Altcan; /* Alternate canit string */ -extern char *Zendnames[]; -extern char *txbuf; -extern char *rxbuf; - -/* End of ZMODEM.H */ - -char Zsendmask[33]; /* Additional control characters to mask */ - -extern int Effbaud; -extern int Zmodem; -extern int Zctlesc; -extern int Filesleft; -extern long Totalleft; - -extern char *frametypes[]; -#define FTOFFSET 16 - -//extern void zsbhdr(int,int,char*); -//extern void zshhdr(int,int,char*); -//extern int zgethdr(char*); -//extern void zsdata(char*,int,int); -//extern int zrdata(char*,int); -//extern void stohdr(long); - -//extern void zsendline(int); -//extern void zsdar32(char*,int,int); -//extern int zrdatr32(char*,int); -//extern int zdlread(void); - -extern unsigned short crc16xmodemtab[]; -extern unsigned long crc32tab[]; -#define updcrc16(cp,crc) (crc16xmodemtab[(((int)crc >> 8) & 0xff)] ^ (crc << 8) ^ cp) -#define updcrc32(cp,crc) (crc32tab[((int)crc ^ cp) & 0xff] ^ ((crc >> 8) & 0x00ffffff)) - -//int zmsndfiles(file_list *); -int zmrcvfiles(void); - -#endif - diff --git a/mbsebbs/zmrecv.c b/mbsebbs/zmrecv.c new file mode 100644 index 00000000..b798963f --- /dev/null +++ b/mbsebbs/zmrecv.c @@ -0,0 +1,585 @@ +/***************************************************************************** + * + * $Id$ + * Purpose ...............: Zmodem receive + * + ***************************************************************************** + * Copyright (C) 1997-2003 + * + * Michiel Broek FIDO: 2:280/2802 + * Beekmansbos 10 + * 1971 BV IJmuiden + * the Netherlands + * + * This file is part of MBSE BBS. + * + * This BBS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * MBSE BBS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MBSE BBS; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "../config.h" +#include "../lib/mbselib.h" +#include "../lib/users.h" +#include "ttyio.h" +#include "transfer.h" +#include "zmmisc.h" +#include "zmrecv.h" + + +static FILE *fout = NULL; +char *curfile = NULL; + +static int Usevhdrs; +static off_t rxbytes; +static int Eofseen; /* indicates cpm eof (^Z) has been received */ +static int errors; +static long sbytes; +struct timeval starttime, endtime; +struct timezone tz; + +#define DEFBYTL 2000000000L /* default rx file size */ +static long Bytesleft; /* number of bytes of incoming file left */ +static long Modtime; /* Unix style mod time for incoming file */ +static int Filemode; /* Unix style mode for incoming file */ + +static int Thisbinary; /* current file is to be received in bin mode */ +char Lzconv; /* Local ZMODEM file conversion request */ +char Lzmanag; /* Local file management request */ + +static char *secbuf=0; + +static int tryzhdrtype; +static char zconv; /* ZMODEM file conversion request */ +static char zmanag; /* ZMODEM file management request */ +static char ztrans; /* ZMODEM file transport request */ + +static int tryz(void); +static int rzfiles(void); +static int rzfile(void); +static void zmputs(char*); +int closeit(int); +static int putsec(char*,int); +static int procheader(char*); +static int ackbibi(void); +static long getfree(void); + + +void get_frame_buffer(void); +void free_frame_buffer(void); + +extern unsigned long rcvdbytes; + + + +int zmrcvfiles(void) +{ + int rc; + + Syslog('+', "Zmodem: start Zmodem receive"); + + get_frame_buffer(); + + if (secbuf == NULL) + secbuf = malloc(MAXBLOCK+1); + tryzhdrtype = ZRINIT; + if ((rc = tryz()) < 0) { + Syslog('+', "Zmodem: could not initiate receive, rc=%d",rc); + } else + switch (rc) { + case ZCOMPL: rc = 0; break; + case ZFILE: rc = rzfiles(); break; + } + + if (fout) { + if (closeit(0)) { + WriteError("Zmodem: Error closing file"); + } + } + + if (secbuf) + free(secbuf); + secbuf = NULL; + free_frame_buffer(); + + Syslog('z', "Zmodem: receive rc=%d",rc); + return abs(rc); +} + + + +/* + * Initialize for Zmodem receive attempt, try to activate Zmodem sender + * Handles ZSINIT frame + * Return ZFILE if Zmodem filename received, -1 on error, + * ZCOMPL if transaction finished, else 0 + */ +int tryz(void) +{ + int c, n; + int cmdzack1flg; + + for (n = 15; --n >= 0; ) { + /* + * Set buffer length (0) and capability flags + */ + Syslog('z', "tryz attempt %d", n); + stohdr(0L); + Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO; + if (Zctlesc) + Txhdr[ZF0] |= TESCCTL; + Txhdr[ZF0] |= CANRLE; + Txhdr[ZF1] = CANVHDR; + zshhdr(4, tryzhdrtype, Txhdr); + if (tryzhdrtype == ZSKIP) /* Don't skip too far */ + tryzhdrtype = ZRINIT; /* CAF 8-21-87 */ +again: + switch (zgethdr(Rxhdr)) { + case ZRQINIT: + if (Rxhdr[ZF3] & 0x80) + Usevhdrs = TRUE; /* we can var header */ + continue; + case ZEOF: + continue; + case TIMEOUT: + Syslog('+', "Zmodem: tryz() timeout attempt %d", n); + continue; + case ZFILE: + zconv = Rxhdr[ZF0]; + zmanag = Rxhdr[ZF1]; + ztrans = Rxhdr[ZF2]; + if (Rxhdr[ZF3] & ZCANVHDR) + Usevhdrs = TRUE; + tryzhdrtype = ZRINIT; + c = zrdata(secbuf, MAXBLOCK); + if (c == GOTCRCW) + return ZFILE; + zshhdr(4,ZNAK, Txhdr); + goto again; + case ZSINIT: + Zctlesc = TESCCTL & Rxhdr[ZF0]; + if (zrdata(Attn, ZATTNLEN) == GOTCRCW) { + stohdr(1L); + zshhdr(4,ZACK, Txhdr); + goto again; + } + zshhdr(4,ZNAK, Txhdr); + goto again; + case ZFREECNT: + stohdr(getfree()); + zshhdr(4,ZACK, Txhdr); + goto again; + case ZCOMMAND: + cmdzack1flg = Rxhdr[ZF0]; + if (zrdata(secbuf, MAXBLOCK) == GOTCRCW) { + if (cmdzack1flg & ZCACK1) + stohdr(0L); + else + Syslog('+', "Zmodem: request for command \"%s\" ignored", printable(secbuf,-32)); + stohdr(0L); + do { + zshhdr(4,ZCOMPL, Txhdr); + } while (++errors<20 && zgethdr(Rxhdr) != ZFIN); + return ackbibi(); + } + zshhdr(4,ZNAK, Txhdr); goto again; + case ZCOMPL: + goto again; + case ZRINIT: + case ZFIN: /* do not beleive in first ZFIN */ + ackbibi(); return ZCOMPL; + case TERROR: + case HANGUP: + case ZCAN: + return TERROR; + default: + continue; + } + } + return 0; +} + + + +/* + * Receive 1 or more files with ZMODEM protocol + */ +int rzfiles(void) +{ + int c; + + Syslog('z', "rzfiles"); + + for (;;) { + switch (c = rzfile()) { + case ZEOF: + case ZSKIP: + case ZFERR: + switch (tryz()) { + case ZCOMPL: + return OK; + default: + return TERROR; + case ZFILE: + break; + } + continue; + default: + return c; + case TERROR: + return TERROR; + } + } + /* NOTREACHED */ +} + + + +/* + * Receive a file with ZMODEM protocol + * Assumes file name frame is in secbuf + */ +int rzfile(void) +{ + int c, n; + + Syslog('z', "rzfile"); + + Eofseen=FALSE; + rxbytes = 0l; + if ((c = procheader(secbuf))) { + return (tryzhdrtype = c); + } + + n = 20; + + for (;;) { + stohdr(rxbytes); + zshhdr(4,ZRPOS, Txhdr); +nxthdr: + switch (c = zgethdr(Rxhdr)) { + default: + Syslog('z', "rzfile: Wrong header %d", c); + if ( --n < 0) { + Syslog('+', "Zmodem: wrong header %d", c); + return TERROR; + } + continue; + case ZCAN: + Syslog('+', "Zmodem: sender CANcelled"); + return TERROR; + case ZNAK: + if ( --n < 0) { + Syslog('+', "Zmodem: Got ZNAK"); + return TERROR; + } + continue; + case TIMEOUT: + if ( --n < 0) { + Syslog('+', "Zmodem: TIMEOUT"); + return TERROR; + } + continue; + case ZFILE: + zrdata(secbuf, MAXBLOCK); + continue; + case ZEOF: + if (rclhdr(Rxhdr) != rxbytes) { + /* + * Ignore eof if it's at wrong place - force + * a timeout because the eof might have gone + * out before we sent our zrpos. + */ + errors = 0; + goto nxthdr; + } + if (closeit(1)) { + tryzhdrtype = ZFERR; + Syslog('+', "Zmodem: error closing file"); + return TERROR; + } + fout=NULL; + Syslog('z', "rzfile: normal EOF"); + return c; + case HANGUP: + Syslog('+', "Zmodem: Lost Carrier"); + return TERROR; + case TERROR: /* Too much garbage in header search error */ + if (--n < 0) { + Syslog('+', "Zmodem: Too many errors"); + return TERROR; + } + zmputs(Attn); + continue; + case ZSKIP: + Modtime = 1; + closeit(1); + Syslog('+', "Zmodem: Sender SKIPPED file"); + return c; + case ZDATA: + if (rclhdr(Rxhdr) != rxbytes) { + if ( --n < 0) { + Syslog('+', "Zmodem: Data has bad address"); + return TERROR; + } + zmputs(Attn); continue; + } +moredata: + Syslog('z', "%7ld ZMODEM%s ", + rxbytes, Crc32r?" CRC-32":""); + Nopper(); + switch (c = zrdata(secbuf, MAXBLOCK)) { + case ZCAN: + Syslog('+', "Zmodem: sender CANcelled"); + return TERROR; + case HANGUP: + Syslog('+', "Zmodem: Lost Carrier"); + return TERROR; + case TERROR: /* CRC error */ + if (--n < 0) { + Syslog('+', "Zmodem: Too many errors"); + return TERROR; + } + zmputs(Attn); + continue; + case TIMEOUT: + if ( --n < 0) { + Syslog('+', "Zmodem: TIMEOUT"); + return TERROR; + } + continue; + case GOTCRCW: + n = 20; + putsec(secbuf, Rxcount); + rxbytes += Rxcount; + stohdr(rxbytes); + PUTCHAR(XON); + zshhdr(4,ZACK, Txhdr); + goto nxthdr; + case GOTCRCQ: + n = 20; + putsec(secbuf, Rxcount); + rxbytes += Rxcount; + stohdr(rxbytes); + zshhdr(4,ZACK, Txhdr); + goto moredata; + case GOTCRCG: + n = 20; + putsec(secbuf, Rxcount); + rxbytes += Rxcount; + goto moredata; + case GOTCRCE: + n = 20; + putsec(secbuf, Rxcount); + rxbytes += Rxcount; + goto nxthdr; + } + } + } +} + + + +/* + * Send a string to the modem, processing for \336 (sleep 1 sec) + * and \335 (break signal) + */ +void zmputs(char *s) +{ + int c; + + Syslog('z', "zmputs: \"%s\"", printable(s, strlen(s))); + + while (*s) { + switch (c = *s++) { + case '\336': + Syslog('z', "zmputs: sleep(1)"); + sleep(1); continue; + case '\335': + Syslog('z', "zmputs: send break"); + sendbrk(); continue; + default: + PUTCHAR(c); + } + } +} + + + +int closeit(int success) +{ + struct utimbuf ut; + int rc; + + rc = fclose(fout); + fout = NULL; + + if (rc == 0) { + ut.actime = Modtime; + ut.modtime = Modtime; + if ((rc = utime(curfile, &ut))) + WriteError("$utime failed"); + } + free(curfile); + curfile = NULL; + + sbytes = rxbytes - sbytes; + gettimeofday(&endtime, &tz); + if (success) + Syslog('+', "Zmodem: OK %s", transfertime(starttime, endtime, sbytes, FALSE)); + else + Syslog('+', "Zmodem: dropped after %lu bytes", sbytes); + rcvdbytes += sbytes; + return rc; +} + + + +/* + * Ack a ZFIN packet, let byegones be byegones + */ +int ackbibi(void) +{ + int n; + int c; + + Syslog('z', "ackbibi:"); + stohdr(0L); + for (n=3; --n>=0; ) { + zshhdr(4,ZFIN, Txhdr); + switch ((c=GETCHAR(10))) { + case 'O': + GETCHAR(1); /* Discard 2nd 'O' */ + Syslog('z', "Zmodem: ackbibi complete"); + return ZCOMPL; + case TERROR: + case HANGUP: + Syslog('z', "Zmodem: ackbibi got %d, ignore",c); + return 0; + case TIMEOUT: + default: + Syslog('z', "Zmodem: ackbibi got '%s', continue", printablec(c)); + break; + } + } + return ZCOMPL; +} + + + +/* + * Process incoming file information header + */ +int procheader(char *Name) +{ + register char *openmode, *p; + static int dummy; + char ctt[32]; + + Syslog('z', "procheader \"%s\"",printable(Name,0)); + /* set default parameters and overrides */ + openmode = (char *)"w"; + + /* + * Process ZMODEM remote file management requests + */ + Thisbinary = (zconv != ZCNL); /* Remote ASCII override */ + if (zmanag == ZMAPND) + openmode = (char *)"a"; + + Bytesleft = DEFBYTL; + Filemode = 0; + Modtime = 0L; + + p = Name + 1 + strlen(Name); + sscanf(p, "%ld%lo%o%o%d%d%d%d", &Bytesleft, &Modtime, &Filemode, &dummy, &dummy, &dummy, &dummy, &dummy); + strcpy(ctt, rfcdate(Modtime)); + Syslog('+', "Zmodem: \"%s\" %ld bytes, %s mode %o", Name, Bytesleft, ctt, Filemode); + + if (curfile) + free(curfile); + curfile = NULL; + + curfile = xstrcpy(CFG.bbs_usersdir); + curfile = xstrcat(curfile, (char *)"/"); + curfile = xstrcat(curfile, exitinfo.Name); + curfile = xstrcat(curfile, (char *)"/upl/"); + curfile = xstrcat(curfile, Name); + fout = fopen(curfile, openmode); + gettimeofday(&starttime, &tz); + sbytes = rxbytes; + +/* if (Bytesleft == rxbytes) { FIXME: if file already received, use this. + Syslog('+', "Zmodem: Skipping %s", Name); + fout = NULL; + return ZSKIP; + } else */ if (!fout) + return ZFERR; + else + return 0; +} + + + +/* + * Putsec writes the n characters of buf to receive file fout. + * If not in binary mode, carriage returns, and all characters + * starting with CPMEOF are discarded. + */ +int putsec(char *buf, int n) +{ + register char *p; + + if (n == 0) + return OK; + + if (Thisbinary) { + for (p = buf; --n>=0; ) + putc( *p++, fout); + } else { + if (Eofseen) + return OK; + for (p = buf; --n>=0; ++p ) { + if ( *p == '\r') + continue; + if (*p == SUB) { + Eofseen=TRUE; + return OK; + } + putc(*p ,fout); + } + } + return OK; +} + + + +long getfree(void) +{ + struct statfs sfs; + char *temp; + + temp = calloc(PATH_MAX, sizeof(char)); + sprintf(temp, "%s/%s/upl", CFG.bbs_usersdir, exitinfo.Name); + + if (statfs(temp, &sfs) != 0) { + WriteError("$cannot statfs \"%s\", assume enough space", temp); + free(temp); + return -1L; + } + + free(temp); + return (sfs.f_bsize * sfs.f_bfree); +} + + diff --git a/mbsebbs/zmrecv.h b/mbsebbs/zmrecv.h new file mode 100644 index 00000000..1fbc2274 --- /dev/null +++ b/mbsebbs/zmrecv.h @@ -0,0 +1,9 @@ +#ifndef ZMRECV_H +#define ZMRECV_H + +/* $Id$ */ + +int zmrcvfiles(void); + + +#endif diff --git a/mbsebbs/zmrle.c b/mbsebbs/zmrle.c index 31b3a7ba..7717b410 100644 --- a/mbsebbs/zmrle.c +++ b/mbsebbs/zmrle.c @@ -39,9 +39,7 @@ #include "../config.h" #include "../lib/mbselib.h" -#include "../lib/nodelist.h" #include "ttyio.h" -#include "zmodem.h" #include "zmrle.h" #include "zmmisc.h" diff --git a/mbsebbs/zmsend.c b/mbsebbs/zmsend.c new file mode 100644 index 00000000..cf79ad4c --- /dev/null +++ b/mbsebbs/zmsend.c @@ -0,0 +1,684 @@ +/***************************************************************************** + * + * $Id$ + * Purpose ...............: Zmodem sender + * + ***************************************************************************** + * Copyright (C) 1997-2004 + * + * Michiel Broek FIDO: 2:280/2802 + * Beekmansbos 10 + * 1971 BV IJmuiden + * the Netherlands + * + * This file is part of MBSE BBS. + * + * This BBS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * MBSE BBS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MBSE BBS; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "../config.h" +#include "../lib/mbselib.h" +#include "ttyio.h" +#include "zmmisc.h" +#include "zmrle.h" +#include "transfer.h" + +static int initsend(void); +static int sendzfile(char*,char*); +static int finsend(void); + +static int getzrxinit(void); +static int sendzsinit(void); +static int zfilbuf(void); +static int zsendfile(char*,int); +static int zsendfdata(void); +static int getinsync(int); +void initzsendmsk(char *); + +static FILE *in; +static int Eofseen; /* EOF seen on input set by zfilbuf */ +static int Rxflags = 0; +static int Usevhdrs; +static int Wantfcs32=TRUE; /* Want to send 32 bit FCS */ +static int Rxbuflen; +static unsigned Txwindow; /* Control the size of the transmitted window */ +static unsigned Txwspac; /* Spacing between zcrcq requests */ +static unsigned Txwcnt; /* Counter used to space ack requests */ +//static long Tframlen = 0; /* Override for tx frame length */ +static int blklen = 128; /* Length of transmitted records */ +static int blkopt; /* Override value for zmodem blklen */ +static int errors; +static int Lastsync; +static long bytcnt; +static int Lrxpos=0; +static int Lztrans=0; +static int Lzmanag=0; +static int Lskipnocor=0; +static int Lzconv=0; +static int Beenhereb4; +static char Myattn[]={0}; +static long skipsize; +struct timeval starttime, endtime; +struct timezone tz; + +extern unsigned long sentbytes; +extern int Rxhlen; +extern void get_frame_buffer(void); +extern void free_frame_buffer(void); + + +int zmsndfiles(down_list *lst) +{ + int rc, maxrc = 0; + down_list *tmpf; + + Syslog('+', "Zmodem: start Zmodem send"); + + get_frame_buffer(); + + if ((rc = initsend())) { + if (txbuf) + free(txbuf); + txbuf = NULL; + free_frame_buffer(); + return abs(rc); + } + + for (tmpf = lst; tmpf && (maxrc < 2); tmpf = tmpf->next) { + if (tmpf->remote) { + rc = sendzfile(tmpf->local, tmpf->remote); + rc = abs(rc); + if (rc > maxrc) + maxrc = rc; + if (rc == 0) + unlink(tmpf->remote); + } else if (maxrc == 0) + unlink(tmpf->remote); + } + + if (maxrc < 2) { + rc = finsend(); + rc = abs(rc); + } + + if (rc > maxrc) + maxrc = rc; + + if (txbuf) + free(txbuf); + txbuf = NULL; + free_frame_buffer(); + + Syslog('z', "Zmodem: send rc=%d", maxrc); + return (maxrc < 2)?0:maxrc; +} + + + +static int initsend(void) +{ + Syslog('z', "Zmodem: initsend"); + + PUTSTR((char *)"rz\r"); + stohdr(0x80L); /* Show we can do var header */ + zshhdr(4, ZRQINIT, Txhdr); + + if (getzrxinit()) { + Syslog('+', "Zmodem: Unable to initiate send"); + return 1; + } + + return 0; +} + + + +/* + * Say "bibi" to the receiver, try to do it cleanly + */ +static int finsend(void) +{ + int i, rc = 0; + + Syslog('z', "Zmodem: finsend"); + while (GETCHAR(1) >= 0) /*nothing*/; + for (i = 0; i < 30; i++) { + stohdr(0L); + zshhdr(4, ZFIN, Txhdr); + if ((rc = zgethdr(Rxhdr)) == ZFIN) + PUTSTR((char *)"OO"); + if ((rc == ZFIN) || (rc == ZCAN) || (rc < 0)) + break; + } + return (rc != ZFIN); +} + + + +static int sendzfile(char *ln, char *rn) +{ + int rc=0; + struct stat st; + struct flock fl; + int bufl; + int sverr; + + fl.l_type = F_RDLCK; + fl.l_whence = 0; + fl.l_start = 0L; + fl.l_len = 0L; + if (txbuf == NULL) + txbuf = malloc(MAXBLOCK); + + skipsize = 0L; + if ((in = fopen(ln, "r")) == NULL) { + sverr = errno; + if ((sverr == ENOENT) || (sverr == EINVAL)) { + Syslog('+', "File %s doesn't exist, removing", MBSE_SS(ln)); + return 0; + } else { + WriteError("$Zmodem: cannot open file %s, skipping", MBSE_SS(ln)); + return 1; + } + } + + if (fcntl(fileno(in),F_SETLK,&fl) != 0) { + Syslog('+', "$Zmodem: cannot lock file %s, skipping",MBSE_SS(ln)); + fclose(in); + return 1; + } + + if (stat(ln,&st) != 0) { + Syslog('+', "$Zmodem: cannot access \"%s\", skipping",MBSE_SS(ln)); + fclose(in); + return 1; + } + + Syslog('+', "Zmodem: send \"%s\" as \"%s\"", MBSE_SS(ln), MBSE_SS(rn)); + Syslog('+', "Zmodem: size %lu bytes, dated %s", (unsigned long)st.st_size, rfcdate(st.st_mtime)); + gettimeofday(&starttime, &tz); + + sprintf(txbuf,"%s %lu %lo %o 0 0 0", rn,(unsigned long)st.st_size, st.st_mtime+(st.st_mtime%2), st.st_mode); + bufl = strlen(txbuf); + *(strchr(txbuf,' ')) = '\0'; /*hope no blanks in filename*/ + + Eofseen = 0; + rc = zsendfile(txbuf,bufl); + if (rc == ZSKIP) { + Syslog('+', "Zmodem: remote skipped %s, is OK",MBSE_SS(ln)); + return 0; + } else if ((rc == OK) && (st.st_size - skipsize)) { + gettimeofday(&endtime, &tz); + Syslog('+', "Zmodem: OK %s", transfertime(starttime, endtime, (unsigned long)st.st_size - skipsize, TRUE)); + sentbytes += (unsigned long)st.st_size - skipsize; + return 0; + } else + return 2; +} + + + +/* + * Get the receiver's init parameters + */ +int getzrxinit(void) // CHECKED BUT NOT WELL TESTED +{ + int n; + + Syslog('z', "getzrxinit"); + for (n=10; --n>=0; ) { + + switch (zgethdr(Rxhdr)) { + case ZCHALLENGE: /* Echo receiver's challenge numbr */ + stohdr(Rxpos); + zshhdr(4, ZACK, Txhdr); + continue; + case ZCOMMAND: /* They didn't see out ZRQINIT */ + stohdr(0L); + zshhdr(4, ZRQINIT, Txhdr); + continue; + case ZRINIT: + Rxflags = 0377 & Rxhdr[ZF0]; + Usevhdrs = Rxhdr[ZF1] & CANVHDR; + Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); + Zctlesc |= Rxflags & TESCCTL; + Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); + if ( !(Rxflags & CANFDX)) + Txwindow = 0; + Syslog('z', "Zmodem: Remote allowed Rxbuflen=%d", Rxbuflen); + + /* Set initial subpacket length */ + if (blklen < 1024) { /* Command line override? */ + blklen = 1024; + } + if (Rxbuflen && blklen>Rxbuflen) + blklen = Rxbuflen; + if (blkopt && blklen > blkopt) + blklen = blkopt; + Syslog('z', "Rxbuflen=%d blklen=%d", Rxbuflen, blklen); + Syslog('z', "Txwindow = %u Txwspac = %d", Txwindow, Txwspac); + + if (Lztrans == ZTRLE && (Rxflags & CANRLE)) + Txfcs32 = 2; + else + Lztrans = 0; + + return (sendzsinit()); + case ZCAN: + case TIMEOUT: + return TERROR; + case HANGUP: + return HANGUP; + case ZRQINIT: + if (Rxhdr[ZF0] == ZCOMMAND) + continue; + default: + zshhdr(4, ZNAK, Txhdr); + continue; + } + } + return TERROR; +} + + + +/* + * Send send-init information + */ +int sendzsinit(void) +{ + int c; + + if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL))) + return OK; + errors = 0; + for (;;) { + stohdr(0L); + if (Zctlesc) { + Txhdr[ZF0] |= TESCCTL; zshhdr(4, ZSINIT, Txhdr); + } + else + zsbhdr(4, ZSINIT, Txhdr); + zsdata(Myattn, ZATTNLEN, ZCRCW); + c = zgethdr(Rxhdr); + switch (c) { + case ZCAN: + return TERROR; + case HANGUP: + return HANGUP; + case ZACK: + return OK; + default: + if (++errors > 19) + return TERROR; + continue; + } + } +} + + + +/* + * Fill buffer with blklen chars + */ +int zfilbuf(void) +{ + int n; + + n = fread(txbuf, 1, blklen, in); + if (n < blklen) { + Eofseen = 1; + Syslog('z', "zfilbuf return %d", n); + } + + return n; +} + + + +/* + * Send file name and related info + */ +int zsendfile(char *buf, int blen) +{ + int c; + register unsigned long crc = -1; + long lastcrcrq = -1; + + Syslog('z', "zsendfile %s (%d)", buf, blen); + for (errors=0; ++errors<11;) { + Txhdr[ZF0] = Lzconv; /* file conversion request */ + Txhdr[ZF1] = Lzmanag; /* file management request */ + if (Lskipnocor) + Txhdr[ZF1] |= ZMSKNOLOC; + Txhdr[ZF2] = Lztrans; /* file transport request */ + Txhdr[ZF3] = 0; + zsbhdr(4, ZFILE, Txhdr); + zsdata(buf, blen, ZCRCW); +again: + c = zgethdr(Rxhdr); + switch (c) { + case ZRINIT: + while ((c = GETCHAR(5)) > 0) + if (c == ZPAD) { + goto again; + } + continue; + case ZCAN: + case TIMEOUT: + case ZABORT: + case ZFIN: + Syslog('+', "Zmodem: Got %s on pathname", frametypes[c+FTOFFSET]); + return TERROR; + default: + Syslog('+', "Zmodem: Got %d frame type on pathname", c); + continue; + case TERROR: + case ZNAK: + continue; + case ZCRC: + if (Rxpos != lastcrcrq) { + lastcrcrq = Rxpos; + crc = 0xFFFFFFFFL; + fseek(in, 0L, 0); + while (((c = getc(in)) != EOF) && --lastcrcrq) + crc = updcrc32(c, crc); + crc = ~crc; + clearerr(in); /* Clear possible EOF */ + lastcrcrq = Rxpos; + } + stohdr(crc); + zsbhdr(4, ZCRC, Txhdr); + goto again; + case ZFERR: + case ZSKIP: + Syslog('+', "Zmodem: File skipped by receiver request"); + fclose(in); return c; + case ZRPOS: + /* + * Suppress zcrcw request otherwise triggered by + * lastyunc==bytcnt + */ + if (Rxpos > 0) + skipsize = Rxpos; + if (fseek(in, Rxpos, 0)) + return TERROR; + Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1; + return zsendfdata(); + } + } + fclose(in); return TERROR; +} + + + +/* + * Send the data in the file + */ +int zsendfdata(void) +{ + int c=0, e, n; + int newcnt; + int tcount = 0; + int junkcount; /* Counts garbage chars received by TX */ + int maxblklen, goodblks = 0, goodneeded = 8; + + maxblklen = 1024; // FIXME: 8K variant set this to 8K + Syslog('z', "zsendfdata() maxblklen=%d", maxblklen); + + junkcount = 0; + Beenhereb4 = 0; +somemore: + if (0) { +waitack: + junkcount = 0; + c = getinsync(0); +gotack: + switch (c) { + default: + case ZCAN: + fclose(in); + return TERROR; + case ZRINIT: + fclose(in); + return ZSKIP; + case ZSKIP: + fclose(in); + return c; + case ZACK: + break; // Possible bug, added 23-08-99 + case ZRPOS: + blklen = ((blklen >> 2) > 64) ? (blklen >> 2) : 64; + goodblks = 0; + goodneeded = ((goodneeded << 1) > 16) ? 16 : goodneeded << 1; + Syslog('z', "zmsend: blocklen now %d", blklen); + break; + case TIMEOUT: /* Put back here 08-09-1999 mb */ + Syslog('z', "zmsend: zsendfdata TIMEOUT"); + goto to; + case HANGUP: /* New, added 08-09-1999 mb */ + Syslog('z', "zmsend: zsendfdata HANGUP"); + fclose(in); + return c; + } + /* + * If the reverse channel can be tested for data, + * this logic may be used to detect error packets + * sent by the receiver, in place of setjmp/longjmp + * rdchk(fd) returns non 0 if a character is available + */ + if (TCHECK()) { + c = GETCHAR(1); + Syslog('z', "zsendfdata(): check getchar(1)=%d", c); + if (c < 0) { + return c; + } else switch (c) { + case CAN: + case ZPAD: + c = getinsync(1); + goto gotack; + case XOFF: /* Wait a while for an XON */ + case XOFF|0200: + GETCHAR(10); + } + } + } +to: + newcnt = Rxbuflen; + Txwcnt = 0; + stohdr(Txpos); + zsbhdr(4, ZDATA, Txhdr); + + do { + n = zfilbuf(); + if (Eofseen) + e = ZCRCE; + else if (junkcount > 3) + e = ZCRCW; + else if (bytcnt == Lastsync) + e = ZCRCW; + else if (Rxbuflen && (newcnt -= n) <= 0) + e = ZCRCW; + else if (Txwindow && (Txwcnt += n) >= Txwspac) { + Txwcnt = 0; e = ZCRCQ; + } else + e = ZCRCG; + Syslog('z', "%7ld ZMODEM%s ", + Txpos, Crc32t?" CRC-32":""); + Nopper(); + zsdata(txbuf, n, e); + bytcnt = Txpos += n; + + if ((blklen < maxblklen) && (++goodblks > goodneeded)) { + blklen = ((blklen << 1) < maxblklen) ? blklen << 1 : maxblklen; + goodblks = 0; + Syslog('z', "zmsend: blocklen now %d", blklen); + } + + if (e == ZCRCW) + goto waitack; + /* + * If the reverse channel can be tested for data, + * this logic may be used to detect error packets + * sent by the receiver, in place of setjmp/longjmp + * rdchk(fd) returns non 0 if a character is available + */ + if (TCHECK()) { + c = GETCHAR(1); + if (c < 0) { + return c; + } else switch (c) { + case CAN: + case ZPAD: + c = getinsync(1); + if (c == ZACK) + break; + /* zcrce - dinna wanna starta ping-pong game */ + zsdata(txbuf, 0, ZCRCE); + goto gotack; + case XOFF: /* Wait a while for an XON */ + case XOFF|0200: + GETCHAR(10); + default: + ++junkcount; + } + } + if (Txwindow) { + while ((tcount = (Txpos - Lrxpos)) >= Txwindow) { + Syslog('z', "%ld window >= %u", tcount, Txwindow); + if (e != ZCRCQ) + zsdata(txbuf, 0, e = ZCRCQ); + c = getinsync(1); + if (c != ZACK) { + zsdata(txbuf, 0, ZCRCE); + goto gotack; + } + } + Syslog('z', "window = %ld", tcount); + } + } while (!Eofseen); + + for (;;) { + stohdr(Txpos); + zsbhdr(4, ZEOF, Txhdr); +egotack: + switch (getinsync(0)) { + case ZACK: + Syslog('z', "zsendfdata() ZACK"); + goto egotack; // continue in old source + case ZRPOS: + goto somemore; + case ZRINIT: + fclose(in); + return OK; + case ZSKIP: + fclose(in); + Syslog('+', "Zmodem: File skipped by receiver request"); + return ZSKIP; + default: + Syslog('+', "Zmodem: Got %d trying to send end of file", c); + case TERROR: + fclose(in); + return TERROR; + } + } +} + + + +/* + * Respond to receiver's complaint, get back in sync with receiver + */ +int getinsync(int flag) +{ + int c = 0; + + Syslog('z', "getinsync(%d)", flag); + + for (;;) { + c = zgethdr(Rxhdr); + switch (c) { + case HANGUP: + return HANGUP; + case ZCAN: + case ZABORT: + case ZFIN: + case TERROR: + case TIMEOUT: + Syslog('+', "Zmodem: Got %s sending data", frametypes[c+FTOFFSET]); + return TERROR; + case ZRPOS: + /* ************************************* */ + /* If sending to a buffered modem, you */ + /* might send a break at this point to */ + /* dump the modem's buffer. */ + clearerr(in); /* In case file EOF seen */ + if (fseek(in, Rxpos, 0)) { + Syslog('+', "Zmodem: Bad Seek to %ld", Rxpos); + return TERROR; + } + Eofseen = 0; + bytcnt = Lrxpos = Txpos = Rxpos; + if (Lastsync == Rxpos) { + if (++Beenhereb4 > 12) { + Syslog('+', "Zmodem: Can't send block"); + return TERROR; + } + if (Beenhereb4 > 4) + if (blklen > 32) { + blklen /= 2; + Syslog('z', "Zmodem: blocklen now %d", blklen); + } + } + else + Beenhereb4=0; + Lastsync = Rxpos; + return c; + case ZACK: + Lrxpos = Rxpos; + if (flag || Txpos == Rxpos) + return ZACK; + continue; + case ZRINIT: + return c; + case ZSKIP: + Syslog('+', "Zmodem: File skipped by receiver request"); + return c; + default: + zsbhdr(4, ZNAK, Txhdr); + continue; + } + } +} + + + +/* + * Set additional control chars to mask in Zsendmask + * according to bit array stored in char array at p + */ +void initzsendmsk(register char *p) +{ + int c; + + for (c = 0; c < 33; ++c) { + if (p[c>>3] & (1 << (c & 7))) { + Zsendmask[c] = 1; + Syslog('z', "Zmodem: Escaping %02o", c); + } + } +} + + diff --git a/mbsebbs/zmsend.h b/mbsebbs/zmsend.h new file mode 100644 index 00000000..18b157dc --- /dev/null +++ b/mbsebbs/zmsend.h @@ -0,0 +1,10 @@ +#ifndef _ZMSEND_H +#define _ZMSEND_H + +/* $Id$ */ + + +int zmsndfiles(down_list *lst) + + +#endif