This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbsebbs/zmsend.c

689 lines
16 KiB
C
Raw Normal View History

2004-11-08 12:24:36 +00:00
/*****************************************************************************
*
* $Id$
* Purpose ...............: Zmodem sender
*
*****************************************************************************
* Copyright (C) 1997-2006
2004-11-08 12:24:36 +00:00
*
* 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 "transfer.h"
2004-11-20 13:30:13 +00:00
#include "openport.h"
2004-11-20 18:31:13 +00:00
#include "timeout.h"
2004-11-20 13:30:13 +00:00
2004-11-08 12:24:36 +00:00
static int initsend(void);
2004-11-08 14:36:34 +00:00
static int sendzfile(char*);
2004-11-08 12:24:36 +00:00
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 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 int blklen = 128; /* Length of transmitted records */
static int blkopt; /* Override value for zmodem blklen */
static int errors;
static int Lastsync;
2005-10-11 20:49:41 +00:00
static int bytcnt;
2004-11-08 12:24:36 +00:00
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};
2005-10-11 20:49:41 +00:00
static int skipsize;
2004-11-08 12:24:36 +00:00
struct timeval starttime, endtime;
struct timezone tz;
2004-11-21 12:06:55 +00:00
static int use8k = FALSE;
2005-10-11 20:49:41 +00:00
extern unsigned int sentbytes;
2004-11-08 12:24:36 +00:00
extern int Rxhlen;
2006-02-20 09:55:23 +00:00
extern int Rxtimeout;
2004-11-12 21:25:59 +00:00
extern char *txbuf;
extern char *frametypes[];
2004-11-08 12:24:36 +00:00
2004-11-20 15:34:07 +00:00
extern unsigned Baudrate;
2004-11-08 12:24:36 +00:00
2004-11-21 12:06:55 +00:00
int zmsndfiles(down_list *lst, int try8)
2004-11-08 12:24:36 +00:00
{
2004-11-08 14:36:34 +00:00
int rc, maxrc = 0;
down_list *tmpf;
2004-11-08 12:24:36 +00:00
2004-11-21 12:06:55 +00:00
Syslog('+', "Zmodem: start Zmodem%s send", try8 ? "-8K":"");
get_frame_buffer();
2004-11-21 12:06:55 +00:00
use8k = try8;
2004-11-21 11:20:08 +00:00
protocol = ZM_ZMODEM;
2006-02-20 09:55:23 +00:00
Rxtimeout = 60;
2004-11-21 12:06:55 +00:00
2004-11-08 14:36:34 +00:00
if ((rc = initsend())) {
if (txbuf)
free(txbuf);
txbuf = NULL;
del_frame_buffer();
2004-11-08 14:36:34 +00:00
return abs(rc);
}
for (tmpf = lst; tmpf && (maxrc < 2); tmpf = tmpf->next) {
if (tmpf->remote) {
rc = sendzfile(tmpf->remote);
rc = abs(rc);
if (rc > maxrc)
maxrc = rc;
if (rc == 0) {
tmpf->sent = TRUE;
} else {
tmpf->failed = TRUE;
}
} else if (maxrc == 0) {
tmpf->failed = TRUE;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
Syslog('z', "zmsndfiles: unlink(%s) returns %d", tmpf->remote, unlink(tmpf->remote));
}
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
if (maxrc < 2) {
rc = finsend();
rc = abs(rc);
}
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
if (rc > maxrc)
maxrc = rc;
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
if (txbuf)
free(txbuf);
txbuf = NULL;
del_frame_buffer();
2004-11-20 15:34:07 +00:00
io_mode(0, 1);
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
Syslog('z', "Zmodem: send rc=%d", maxrc);
return (maxrc < 2)?0:maxrc;
2004-11-08 12:24:36 +00:00
}
static int initsend(void)
{
2004-11-08 14:36:34 +00:00
Syslog('z', "Zmodem: initsend");
2004-11-08 12:24:36 +00:00
2004-11-20 13:30:13 +00:00
io_mode(0, 1);
2004-11-08 14:36:34 +00:00
PUTSTR((char *)"rz\r");
2004-11-20 15:34:07 +00:00
stohdr(0L);
2004-11-20 13:30:13 +00:00
zshhdr(ZRQINIT, Txhdr);
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
if (getzrxinit()) {
Syslog('+', "Zmodem: Unable to initiate send");
return 1;
}
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
return 0;
2004-11-08 12:24:36 +00:00
}
/*
* Say "bibi" to the receiver, try to do it cleanly
*/
static int finsend(void)
{
2004-11-08 14:36:34 +00:00
int i, rc = 0;
Syslog('z', "Zmodem: finsend");
while (GETCHAR(1) >= 0) /*nothing*/;
for (i = 0; i < 30; i++) {
stohdr(0L);
2004-11-20 13:30:13 +00:00
zshhdr(ZFIN, Txhdr);
2004-11-08 14:36:34 +00:00
if ((rc = zgethdr(Rxhdr)) == ZFIN)
PUTSTR((char *)"OO");
if ((rc == ZFIN) || (rc == ZCAN) || (rc < 0))
break;
}
return (rc != ZFIN);
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
static int sendzfile(char *rn)
2004-11-08 12:24:36 +00:00
{
2004-11-08 14:36:34 +00:00
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)
2004-11-21 12:06:55 +00:00
txbuf = malloc(MAXBLOCK + 1024);
2004-11-08 14:36:34 +00:00
skipsize = 0L;
if ((in = fopen(rn, "r")) == NULL) {
sverr = errno;
if ((sverr == ENOENT) || (sverr == EINVAL)) {
Syslog('+', "File %s doesn't exist, removing", MBSE_SS(rn));
return 0;
} else {
WriteError("$Zmodem: cannot open file %s, skipping", MBSE_SS(rn));
return 1;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
if (stat(rn,&st) != 0) {
Syslog('+', "$Zmodem: cannot access \"%s\", skipping",MBSE_SS(rn));
fclose(in);
return 1;
}
Syslog('+', "Zmodem: send \"%s\"", MBSE_SS(rn));
2005-10-11 20:49:41 +00:00
Syslog('+', "Zmodem: size %lu bytes, dated %s", (unsigned int)st.st_size, rfcdate(st.st_mtime));
2004-11-08 14:36:34 +00:00
gettimeofday(&starttime, &tz);
2005-10-11 20:49:41 +00:00
snprintf(txbuf,MAXBLOCK + 1024,"%s %u %o %o 0 0 0", rn,
(unsigned int)st.st_size, (int)st.st_mtime + (int)(st.st_mtime % 2), st.st_mode);
2004-11-08 14:36:34 +00:00
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(rn));
return 0;
} else if ((rc == OK) && (st.st_size - skipsize)) {
gettimeofday(&endtime, &tz);
2005-10-11 20:49:41 +00:00
Syslog('+', "Zmodem: OK %s", transfertime(starttime, endtime, (unsigned int)st.st_size - skipsize, TRUE));
sentbytes += (unsigned int)st.st_size - skipsize;
2004-11-08 14:36:34 +00:00
return 0;
} else
return 2;
2004-11-08 12:24:36 +00:00
}
/*
* Get the receiver's init parameters
*/
2004-11-21 11:20:08 +00:00
int getzrxinit(void)
2004-11-08 12:24:36 +00:00
{
2006-02-20 09:55:23 +00:00
int n, timeouts = 0;
int old_timeout = Rxtimeout;
Rxtimeout = 10;
for (n = 10; --n >= 0; ) {
Syslog('z', "getzrxinit n=%d", n);
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
switch (zgethdr(Rxhdr)) {
case ZCHALLENGE: /* Echo receiver's challenge numbr */
2004-11-08 12:24:36 +00:00
stohdr(Rxpos);
2004-11-20 13:30:13 +00:00
zshhdr(ZACK, Txhdr);
2004-11-08 12:24:36 +00:00
continue;
2004-11-08 14:36:34 +00:00
case ZCOMMAND: /* They didn't see out ZRQINIT */
2004-11-20 15:34:07 +00:00
/* A receiver cannot send a command */
2004-11-08 12:24:36 +00:00
continue;
2004-11-08 14:36:34 +00:00
case ZRINIT:
2004-11-08 12:24:36 +00:00
Rxflags = 0377 & Rxhdr[ZF0];
Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
// {
// int old = Zctlesc;
2004-11-28 17:25:08 +00:00
Zctlesc |= Rxflags & TESCCTL;
// /* update table - was initialised to not escape */
// if (Zctlesc && !old)
// zsendline_init();
// }
2004-11-08 12:24:36 +00:00
Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
if ( !(Rxflags & CANFDX))
2004-11-20 15:34:07 +00:00
Txwindow = 0;
2004-11-08 12:24:36 +00:00
Syslog('z', "Zmodem: Remote allowed Rxbuflen=%d", Rxbuflen);
2004-11-20 15:34:07 +00:00
io_mode(0, 2); /* Set cbreak, XON/XOFF, etc. */
2004-11-08 12:24:36 +00:00
/* Set initial subpacket length */
if (blklen < 1024) { /* Command line override? */
2004-11-20 15:34:07 +00:00
if (Baudrate > 300)
blklen = 256;
if (Baudrate > 1200)
blklen = 512;
if (Baudrate > 2400)
2004-11-08 12:24:36 +00:00
blklen = 1024;
}
if (Rxbuflen && blklen>Rxbuflen)
2004-11-20 15:34:07 +00:00
blklen = Rxbuflen;
2004-11-08 12:24:36 +00:00
if (blkopt && blklen > blkopt)
2004-11-20 15:34:07 +00:00
blklen = blkopt;
2004-11-08 12:24:36 +00:00
Syslog('z', "Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
Syslog('z', "Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
2004-11-20 15:34:07 +00:00
Lztrans = 0;
2006-02-20 09:55:23 +00:00
Rxtimeout = old_timeout;
2004-11-08 12:24:36 +00:00
return (sendzsinit());
2004-11-08 14:36:34 +00:00
case ZCAN:
case TIMEOUT:
2006-02-20 09:55:23 +00:00
if (timeouts++==0)
continue;
2004-11-08 12:24:36 +00:00
return TERROR;
2004-11-08 14:36:34 +00:00
case HANGUP:
2004-11-08 12:24:36 +00:00
return HANGUP;
2004-11-08 14:36:34 +00:00
case ZRQINIT:
2004-11-08 12:24:36 +00:00
if (Rxhdr[ZF0] == ZCOMMAND)
2004-11-20 15:34:07 +00:00
continue;
2004-11-08 14:36:34 +00:00
default:
2004-11-20 13:30:13 +00:00
zshhdr(ZNAK, Txhdr);
2004-11-08 12:24:36 +00:00
continue;
}
2004-11-08 14:36:34 +00:00
}
return TERROR;
2004-11-08 12:24:36 +00:00
}
/*
* Send send-init information
*/
int sendzsinit(void)
{
2004-11-08 14:36:34 +00:00
int c;
if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
return OK;
errors = 0;
for (;;) {
stohdr(0L);
if (Zctlesc) {
2004-11-20 13:30:13 +00:00
Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr);
2004-11-08 14:36:34 +00:00
} else
2004-11-20 13:30:13 +00:00
zsbhdr(ZSINIT, Txhdr);
2006-02-20 09:55:23 +00:00
// zsdata(Myattn, ZATTNLEN, ZCRCW);
zsdata(Myattn, 1 + strlen(Myattn), ZCRCW);
2004-11-08 14:36:34 +00:00
c = zgethdr(Rxhdr);
switch (c) {
case ZCAN: return TERROR;
case HANGUP: return HANGUP;
case ZACK: return OK;
default: if (++errors > 19)
2004-11-08 12:24:36 +00:00
return TERROR;
2004-11-08 14:36:34 +00:00
continue;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
2004-11-08 12:24:36 +00:00
}
/*
* Fill buffer with blklen chars
*/
int zfilbuf(void)
{
2004-11-08 14:36:34 +00:00
int n;
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
n = fread(txbuf, 1, blklen, in);
if (n < blklen) {
Eofseen = 1;
2004-11-20 15:34:07 +00:00
Syslog('z', "zfilbuf return %d", n);
2004-11-08 14:36:34 +00:00
}
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
return n;
2004-11-08 12:24:36 +00:00
}
/*
* Send file name and related info
*/
int zsendfile(char *buf, int blen)
{
2004-11-08 14:36:34 +00:00
int c;
2005-10-11 20:49:41 +00:00
register unsigned int crc = -1;
int lastcrcrq = -1;
2004-11-08 14:36:34 +00:00
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;
2004-11-20 13:30:13 +00:00
zsbhdr(ZFILE, Txhdr);
2004-11-08 14:36:34 +00:00
zsdata(buf, blen, ZCRCW);
2004-11-08 12:24:36 +00:00
again:
2004-11-08 14:36:34 +00:00
c = zgethdr(Rxhdr);
switch (c) {
case ZRINIT:
2004-11-08 12:24:36 +00:00
while ((c = GETCHAR(5)) > 0)
2004-11-20 15:34:07 +00:00
if (c == ZPAD) {
goto again;
}
2004-11-08 12:24:36 +00:00
continue;
2004-11-20 15:34:07 +00:00
case ZRQINIT:
Syslog('+', "got ZRQINIT, a zmodem sender talks to this sender");
return TERROR;
2004-11-08 14:36:34 +00:00
case ZCAN:
case TIMEOUT:
case ZABORT:
case ZFIN:
2004-11-08 12:24:36 +00:00
Syslog('+', "Zmodem: Got %s on pathname", frametypes[c+FTOFFSET]);
return TERROR;
2004-11-08 14:36:34 +00:00
default:
2004-11-08 12:24:36 +00:00
Syslog('+', "Zmodem: Got %d frame type on pathname", c);
continue;
2004-11-08 14:36:34 +00:00
case TERROR:
case ZNAK:
2004-11-08 12:24:36 +00:00
continue;
2004-11-08 14:36:34 +00:00
case ZCRC:
2004-11-08 12:24:36 +00:00
if (Rxpos != lastcrcrq) {
2004-11-20 15:34:07 +00:00
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;
2004-11-08 12:24:36 +00:00
}
stohdr(crc);
2004-11-20 13:30:13 +00:00
zsbhdr(ZCRC, Txhdr);
2004-11-08 12:24:36 +00:00
goto again;
2004-11-08 14:36:34 +00:00
case ZFERR:
case ZSKIP:
2004-11-08 12:24:36 +00:00
Syslog('+', "Zmodem: File skipped by receiver request");
fclose(in); return c;
2004-11-08 14:36:34 +00:00
case ZRPOS:
2004-11-08 12:24:36 +00:00
/*
* Suppress zcrcw request otherwise triggered by
* lastyunc==bytcnt
*/
Syslog('z', "got ZRPOS %d", Rxpos);
2004-11-08 12:24:36 +00:00
if (Rxpos > 0)
2004-11-20 15:34:07 +00:00
skipsize = Rxpos;
2004-11-08 12:24:36 +00:00
if (fseek(in, Rxpos, 0))
2004-11-20 15:34:07 +00:00
return TERROR;
2004-11-08 12:24:36 +00:00
Lastsync = (bytcnt = Txpos = Lrxpos = Rxpos) -1;
return zsendfdata();
}
2004-11-08 14:36:34 +00:00
}
2004-11-21 11:20:08 +00:00
fclose(in);
return TERROR;
2004-11-08 12:24:36 +00:00
}
/*
* Send the data in the file
*/
int zsendfdata(void)
{
2004-11-08 14:36:34 +00:00
int c = 0, e, n;
int newcnt;
int tcount = 0;
int junkcount; /* Counts garbage chars received by TX */
int maxblklen, goodblks = 0, goodneeded = 8;
2004-11-08 12:24:36 +00:00
2004-11-21 12:06:55 +00:00
if (use8k)
maxblklen = 8192;
else
maxblklen = 1024;
2004-11-08 14:36:34 +00:00
Syslog('z', "zsendfdata() maxblklen=%d", maxblklen);
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
junkcount = 0;
Beenhereb4 = 0;
2004-11-08 12:24:36 +00:00
somemore:
2004-11-08 14:36:34 +00:00
if (0) {
2004-11-08 12:24:36 +00:00
waitack:
2004-11-08 14:36:34 +00:00
junkcount = 0;
c = getinsync(0);
2004-11-08 12:24:36 +00:00
gotack:
2004-11-08 14:36:34 +00:00
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);
2004-11-08 12:24:36 +00:00
goto gotack;
2004-11-08 14:36:34 +00:00
case XOFF: /* Wait a while for an XON */
case XOFF|0200: GETCHAR(10);
}
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
2004-11-08 12:24:36 +00:00
to:
2004-11-08 14:36:34 +00:00
newcnt = Rxbuflen;
Txwcnt = 0;
stohdr(Txpos);
2004-11-20 13:30:13 +00:00
zsbhdr(ZDATA, Txhdr);
2004-11-08 14:36:34 +00:00
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;
Nopper();
2004-11-20 18:31:13 +00:00
alarm_on();
2004-11-08 14:36:34 +00:00
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);
}
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
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);
2004-11-08 12:24:36 +00:00
if (c == ZACK)
2004-11-08 14:36:34 +00:00
break;
2004-11-08 12:24:36 +00:00
/* zcrce - dinna wanna starta ping-pong game */
zsdata(txbuf, 0, ZCRCE);
goto gotack;
2004-11-08 14:36:34 +00:00
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;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
Syslog('z', "window = %ld", tcount);
}
} while (!Eofseen);
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
for (;;) {
stohdr(Txpos);
2004-11-20 13:30:13 +00:00
zsbhdr(ZEOF, Txhdr);
2004-11-08 12:24:36 +00:00
egotack:
2004-11-08 14:36:34 +00:00
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;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
2004-11-08 12:24:36 +00:00
}
/*
* Respond to receiver's complaint, get back in sync with receiver
*/
int getinsync(int flag)
{
2004-11-08 14:36:34 +00:00
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)) {
2004-11-08 12:24:36 +00:00
Syslog('+', "Zmodem: Bad Seek to %ld", Rxpos);
return TERROR;
2004-11-08 14:36:34 +00:00
}
Eofseen = 0;
bytcnt = Lrxpos = Txpos = Rxpos;
if (Lastsync == Rxpos) {
2004-11-08 12:24:36 +00:00
if (++Beenhereb4 > 12) {
2004-11-08 14:36:34 +00:00
Syslog('+', "Zmodem: Can't send block");
return TERROR;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
if (Beenhereb4 > 4) {
if (blklen > 32) {
blklen /= 2;
Syslog('z', "Zmodem: blocklen now %d", blklen);
}
}
} else {
2004-11-08 12:24:36 +00:00
Beenhereb4=0;
2004-11-08 14:36:34 +00:00
}
Lastsync = Rxpos;
return c;
case ZACK: Lrxpos = Rxpos;
if (flag || Txpos == Rxpos)
2004-11-08 12:24:36 +00:00
return ZACK;
2004-11-08 14:36:34 +00:00
continue;
case ZRINIT: return c;
case ZSKIP: Syslog('+', "Zmodem: File skipped by receiver request");
return c;
2004-11-20 13:30:13 +00:00
default: zsbhdr(ZNAK, Txhdr);
2004-11-08 14:36:34 +00:00
continue;
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
2004-11-08 12:24:36 +00:00
}
/*
* Set additional control chars to mask in Zsendmask
* according to bit array stored in char array at p
*/
void initzsendmsk(register char *p)
{
2004-11-08 14:36:34 +00:00
int c;
2004-11-08 12:24:36 +00:00
2004-11-08 14:36:34 +00:00
for (c = 0; c < 33; ++c) {
if (p[c>>3] & (1 << (c & 7))) {
Zsendmask[c] = 1;
Syslog('z', "Zmodem: Escaping %02o", c);
2004-11-08 12:24:36 +00:00
}
2004-11-08 14:36:34 +00:00
}
2004-11-08 12:24:36 +00:00
}