📄 lsz.c
字号:
case ZRPOS: /* * Suppress zcrcw request otherwise triggered by * lastyunc==bytcnt */#ifdef HAVE_MMAP if (!mm_addr)#endif if (Rxpos && fseek(in, Rxpos, 0)) return ERROR; bytcnt = Txpos = Rxpos; Lastsync = Rxpos -1; return zsendfdata(); } }}/* Send the data in the file */zsendfdata(){ register c, e, n; register newcnt; register long tcount = 0; int junkcount; /* Counts garbage chars received by TX */ static int tleft = 6; /* Counter for test mode */ long last_txpos=0; long last_bps=0; long not_printed=0; static long total_sent=0;#ifdef HAVE_MMAP { struct stat st; if (fstat(fileno(in),&st)==0) { mm_size=st.st_size; mm_addr = mmap (0, mm_size, PROT_READ, MAP_SHARED, fileno(in), 0); if ((caddr_t) mm_addr==(caddr_t) -1) mm_addr=NULL; else { fclose(in); in=NULL; } } }#endif Lrxpos = 0; junkcount = 0; Beenhereb4 = 0;somemore: if (setjmp(intrjmp)) {waitack: junkcount = 0; c = getinsync(0);gotack: switch (c) { default: case ZCAN: if (in) fclose(in); return ERROR; case ZSKIP: if (in) fclose(in); return c; case ZACK: case ZRPOS: break; case ZRINIT: return OK; }#ifdef READCHECK /* * 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(fdes) returns non 0 if a character is available */ while (rdchk(iofd)) {#ifdef READCHECK_READS switch (checked)#else switch (readline(1))#endif { case CAN: case ZPAD: c = getinsync(1); goto gotack; case XOFF: /* Wait a while for an XON */#ifndef linux case XOFF|0200:#endif readline(100); } }#endif }#ifndef linux if ( !Fromcu) signal(SIGINT, onintr);#endif newcnt = Rxbuflen; Txwcnt = 0; stohdr(Txpos); zsbhdr(ZDATA, Txhdr); /* * Special testing mode. This should force receiver to Attn,ZRPOS * many times. Each time the signal should be caught, causing the * file to be started over from the beginning. */ if (Test) { if ( --tleft) while (tcount < 20000) { printf(qbf); fflush(stdout); tcount += strlen(qbf);#ifdef READCHECK while (rdchk(iofd)) {#ifdef READCHECK_READS switch (checked)#else switch (readline(1))#endif { case CAN: case ZPAD:#ifdef TCFLSH ioctl(iofd, TCFLSH, 1);#endif goto waitack; case XOFF: /* Wait for XON */#ifndef linux case XOFF|0200:#endif readline(100); } }#endif } signal(SIGINT, SIG_IGN); canit(); sleep(3); purgeline(); mode(0); printf("\nlsz: Tcount = %ld\n", tcount); if (tleft) { printf("ERROR: Interrupts Not Caught\n"); exit(1); } exit(SS_NORMAL); } do {#ifdef NEW_ERROR int old=blklen; blklen=calc_blklen(total_sent); total_sent+=blklen+OVERHEAD; if (Verbose >2 && blklen!=old) fprintf(stderr,"blklen now %ld\n",blklen);#endif#ifdef HAVE_MMAP if (mm_addr) { if (Txpos+blklen<mm_size) n=blklen; else { n=mm_size-Txpos; Eofseen=1; } } else #endif 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; if (Verbose>1 && (not_printed > 5 || Txpos > last_bps / 2 + last_txpos)) { int minleft = 0; int secleft = 0; last_bps=(Txpos/timing(0)); if (last_bps > 0) { minleft = (Filesize-Txpos)/last_bps/60; secleft = ((Filesize-Txpos)/last_bps)%60; } fprintf(stderr, "\rBytes Sent:%7ld/%7ld BPS:%-6d ETA %02d:%02d ", Txpos, Filesize, last_bps, minleft, secleft); last_txpos=Txpos; } else if (Verbose) not_printed++;#ifdef HAVE_MMAP if (mm_addr) zsdata(mm_addr+Txpos,n,e); else#endif zsdata(txbuf, n, e); bytcnt = Txpos += n; if (e == ZCRCW) goto waitack;#ifdef READCHECK /* * 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(fdes) returns non 0 if a character is available */ fflush(stdout); while (rdchk(iofd)) {#ifdef READCHECK_READS switch (checked)#else switch (readline(1))#endif { case CAN: case ZPAD: c = getinsync(1); if (c == ZACK) break;#ifdef TCFLSH ioctl(iofd, TCFLSH, 1);#endif /* zcrce - dinna wanna starta ping-pong game */ zsdata(txbuf, 0, ZCRCE); goto gotack; case XOFF: /* Wait a while for an XON */#ifndef linux case XOFF|0200:#endif readline(100); default: ++junkcount; } }#endif /* READCHECK */ if (Txwindow) { while ((tcount = Txpos - Lrxpos) >= Txwindow) { vfile("%ld window >= %u", tcount, Txwindow); if (e != ZCRCQ) zsdata(txbuf, 0, e = ZCRCQ); c = getinsync(1); if (c != ZACK) {#ifdef TCFLSH ioctl(iofd, TCFLSH, 1);#endif zsdata(txbuf, 0, ZCRCE); goto gotack; } } vfile("window = %ld", tcount); } } while (!Eofseen); if (Verbose > 1) fprintf(stderr, "\rBytes Sent:%7ld BPS:%-6d \n", Filesize,last_bps); if ( !Fromcu) signal(SIGINT, SIG_IGN); for (;;) { stohdr(Txpos); zsbhdr(ZEOF, Txhdr); switch (getinsync(0)) { case ZACK: continue; case ZRPOS: goto somemore; case ZRINIT: return OK; case ZSKIP: if (in) fclose(in); return c; default: if (in) fclose(in); return ERROR; } }}#ifdef NEW_ERRORintcalc_blklen(long total_sent){ static long total_bytes=0; static int calcs_done=0; static long last_error_count=0; static int last_blklen=0; static long last_bytes_per_error=0; long best_bytes=0; long best_size=0; long bytes_per_error; long d; int i; if (total_bytes==0) { /* called from countem */ total_bytes=total_sent; return 0; } /* it's not good to calc blklen too early */ if (calcs_done++ < 5) { if (error_count && start_blklen >1024) return last_blklen=1024; else last_blklen/=2; return last_blklen=start_blklen; } if (!error_count) { /* that's fine */ if (start_blklen==max_blklen) return start_blklen; bytes_per_error=LONG_MAX; goto calcit; } if (error_count!=last_error_count) { /* the last block was bad. shorten blocks until one block is * ok. this is because very often many errors come in an * short period */ if (error_count & 2) { last_blklen/=2; if (last_blklen < 32) last_blklen = 32; else if (last_blklen > 512) last_blklen=512; if (Verbose > 3) fprintf(stderr,"calc_blklen: reduced to %d due to error\n", last_blklen); last_error_count=error_count; last_bytes_per_error=0; /* force recalc */ } return last_blklen; } bytes_per_error=total_sent / error_count; /* we do not get told about every error! * from my experience the value is ok */ bytes_per_error/=2; /* there has to be a margin */ if (bytes_per_error<100) bytes_per_error=100; /* be nice to the poor machine and do the complicated things not * too often */ if (last_bytes_per_error>bytes_per_error) d=last_bytes_per_error-bytes_per_error; else d=bytes_per_error-last_bytes_per_error; if (d<4) { if (Verbose > 3) { fprintf(stderr,"calc_blklen: returned old value %d due to low bpe diff\n", last_blklen); fprintf(stderr,"calc_blklen: old %ld, new %ld, d %ld\n", last_bytes_per_error,bytes_per_error,d ); } return last_blklen; } last_bytes_per_error=bytes_per_error;calcit: if (Verbose > 3) fprintf(stderr,"calc_blklen: calc total_bytes=%ld, bpe=%ld\n", total_bytes,bytes_per_error); for (i=32;i<=max_blklen;i*=2) { long ok; /* some many ok blocks do we need */ long failed; /* and that's the number of blocks not transmitted ok */ long transmitted; ok=total_bytes / i + 1; failed=((long) i + OVERHEAD) * ok / bytes_per_error; transmitted=ok * ((long) i+OVERHEAD) + failed * ((long) i+OVERHEAD+OVER_ERR); if (Verbose > 4) fprintf(stderr,"calc_blklen: blklen %d, ok %ld, failed %ld -> %ld\n", i,ok,failed,transmitted); if (transmitted < best_bytes || !best_bytes) { best_bytes=transmitted; best_size=i; } } if (best_size > 2*last_blklen) best_size=2*last_blklen; last_blklen=best_size; if (Verbose > 3) fprintf(stderr,"calc_blklen: returned %d as best\n", last_blklen); return last_blklen;}#endif/* * Respond to receiver's complaint, get back in sync with receiver */getinsync(flag){ register c; for (;;) { if (Test) { printf("\r\n\n\n***** Signal Caught *****\r\n"); Rxpos = 0; c = ZRPOS; } else c = zgethdr(Rxhdr, 0); switch (c) { case ZCAN: case ZABORT: case ZFIN: case TIMEOUT: return ERROR; 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 */#ifdef HAVE_MMAP if (!mm_addr)#endif if (fseek(in, Rxpos, 0)) return ERROR; Eofseen = 0; bytcnt = Lrxpos = Txpos = Rxpos; if (Lastsync == Rxpos) {#ifndef NEW_ERROR if (++Beenhereb4 > 4) if (blklen > 32) { blklen /= 2; if (Verbose > 1) { fprintf(stderr,"\rFalldown to %ld blklen\r\n", blklen); } }#else error_count++;#endif } Lastsync = Rxpos-1; return c; case ZACK: Lrxpos = Rxpos; if (flag || Txpos == Rxpos) return ZACK; continue; case ZRINIT: case ZSKIP: if (in) fclose(in); return c; case ERROR: default:#ifdef NEW_ERROR error_count++;#endif zsbhdr(ZNAK, Txhdr); continue; } }}/* Say "bibi" to the receiver, try to do it cleanly */saybibi(){ for (;;) { stohdr(0L); /* CAF Was zsbhdr - minor change */ zshhdr(ZFIN, Txhdr); /* to make debugging easier */ switch (zgethdr(Rxhdr, 0)) { case ZFIN: sendline('O'); sendline('O'); flushmo(); case ZCAN: case TIMEOUT: return; } }}/* Local screen character display function */bttyout(c){ if (Verbose) putc(c, stderr);}/* Send command and related info */zsendcmd(buf, blen)char *buf;{ register c; long cmdnum; cmdnum = getpid(); errors = 0; for (;;) { stohdr(cmdnum); Txhdr[ZF0] = Cmdack1; zsbhdr(ZCOMMAND, Txhdr); zsdata(buf, blen, ZCRCW);listen: Rxtimeout = 100; /* Ten second wait for resp. */ c = zgethdr(Rxhdr, 1); switch (c) { case ZRINIT: goto listen; /* CAF 8-21-87 */ case ERROR: case TIMEOUT: if (++errors > Cmdtries) return ERROR; continue; case ZCAN: case ZABORT: case ZFIN: case ZSKIP: case ZRPOS: return ERROR; default: if (++errors > 20) return ERROR; continue; case ZCOMPL: Exitcode = Rxpos; saybibi(); return OK; case ZRQINIT: vfile("******** RZ *******"); system("rz"); vfile("******** SZ *******"); goto listen; } }}/* * If called as lsb use YMODEM protocol */chkinvok(s)char *s;{ register char *p; p = s; while (*p == '-') s = ++p; while (*p) if (*p++ == '/') s = p; if (*s == 'v') { Verbose=1; ++s; } Progname = s; if ((s[0]=='s' && s[1]=='b') || (s[0]=='l' && s[1]=='s' && s[2]=='b')) { Nozmodem = TRUE; blklen=1024; } if ((s[0]=='s' && s[1]=='x') || (s[0]=='l' && s[1]=='s' && s[2]=='x')) { Modem2 = TRUE; }}countem(argc, argv)register char **argv;{ register c; struct stat f; for (Totalleft = 0, Filesleft = 0; --argc >=0; ++argv) { f.st_size = -1; if (Verbose>2) { fprintf(stderr, "\nCountem: %03d %s ", argc, *argv); fflush(stderr); } if (access(*argv, 04) >= 0 && stat(*argv, &f) >= 0) { c = f.st_mode & S_IFMT; if (c != S_IFDIR && c != S_IFBLK) { ++Filesleft; Totalleft += f.st_size; } } if (Verbose>2) fprintf(stderr, " %ld", (long) f.st_size); } if (Verbose>2) fprintf(stderr, "\ncountem: Total %d %ld\n", Filesleft, Totalleft);#ifdef NEW_ERROR calc_blklen(Totalleft);#endif}chartest(m){ register n; mode(m); printf("\r\n\nCharacter Transparency Test Mode %d\r\n", m); printf("If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n"); printf("Hit Enter.\021"); fflush(stdout); readline(500); for (n = 0; n < 256; ++n) { if (!(n%8)) printf("\r\n"); printf("%02x ", n); fflush(stdout); sendline(n); flushmo(); printf(" "); fflush(stdout); if (n == 127) { printf("Hit Enter.\021"); fflush(stdout); readline(500); printf("\r\n"); fflush(stdout); } } printf("\021\r\nEnter Characters, echo is in hex.\r\n"); printf("Hit SPACE or pause 40 seconds for exit.\r\n"); while (n != TIMEOUT && n != ' ') { n = readline(400); printf("%02x\r\n", n); fflush(stdout); } printf("\r\nMode %d character transparency test ends.\r\n", m); fflush(stdout);}/* End of lsz.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -