📄 lsz.c
字号:
if (c == S_IFDIR || c == S_IFBLK) { fclose(in); return OK; } ++Filcnt; switch (wctxpn(name)) { case ERROR: return ERROR; case ZSKIP: return OK; } if (!Zmodem && wctx(f.st_size)==ERROR) return ERROR; if (Unlinkafter) unlink(oname); return 0;}/* * generate and transmit pathname block consisting of * pathname (null terminated), * file length, mode time and file mode in octal * as provided by the Unix fstat call. * N.B.: modifies the passed name, may extend it! */wctxpn(name)char *name;{ register char *p, *q; char name2[PATHLEN]; struct stat f; if (Modem2) { if ((in!=stdin) && *name && fstat(fileno(in), &f)!= -1) { fprintf(stderr, "Sending %s, %ld blocks: ", name, (long) (f.st_size>>7)); } fprintf(stderr, "Give your local XMODEM receive command now.\r\n"); return OK; } if ( !Zmodem) if (getnak()) return ERROR; q = (char *) 0; if (Dottoslash) { /* change . to . */ for (p=name; *p; ++p) { if (*p == '/') q = p; else if (*p == '.') *(q=p) = '/'; } if (q && strlen(++q) > 8) { /* If name>8 chars */ q += 8; /* make it .ext */ strcpy(name2, q); /* save excess of name */ *q = '.'; strcpy(++q, name2); /* add it back */ } } for (p=name, q=txbuf ; *p; ) if ((*q++ = *p++) == '/' && !Fullname) q = txbuf; *q++ = 0; p=q; while (q < (txbuf + MAX_BLOCK)) *q++ = 0; if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1) sprintf(p, "%lu %lo %o 0 %d %ld", (long) f.st_size, f.st_mtime, f.st_mode, Filesleft, Totalleft); fprintf(stderr, "Sending: %s\n",name); Totalleft -= f.st_size; Filesize = f.st_size; if (--Filesleft <= 0) Totalleft = 0; 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) return zsendfile(txbuf, 1+strlen(p)+(p-txbuf)); if (wcputsec(txbuf, 0, 128)==ERROR) return ERROR; return OK;}getnak(){ register firstch; Lastrx = 0; for (;;) { switch (firstch = readline(800)) { case ZPAD: if (getzrxinit()) return ERROR; Ascii = 0; /* Receiver does the conversion */ return FALSE; case TIMEOUT: zperr("Timeout on pathname"); return TRUE; case WANTG:#ifdef MODE2OK mode(2); /* Set cbreak, XON/XOFF, etc. */#endif Optiong = TRUE; blklen=1024; case WANTCRC: Crcflg = TRUE; case NAK: return FALSE; case CAN: if ((firstch = readline(20)) == CAN && Lastrx == CAN) return TRUE; default: break; } Lastrx = firstch; }}static int wctx(off_t flen){ register int thisblklen; register int sectnum, attempts, firstch; long charssent; charssent = 0; firstsec=TRUE; thisblklen = blklen; vfile("wctx:file length=%ld", (long) flen); while ((firstch=readline(Rxtimeout))!=NAK && firstch != WANTCRC && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN) ; if (firstch==CAN) { zperr("Receiver Cancelled"); return ERROR; } if (firstch==WANTCRC) Crcflg=TRUE; if (firstch==WANTG) Crcflg=TRUE; sectnum=0; for (;;) { if (flen <= (charssent + 896L)) thisblklen = 128; if ( !filbuf(txbuf, thisblklen)) break; if (wcputsec(txbuf, ++sectnum, thisblklen)==ERROR) return ERROR; charssent += thisblklen; } fclose(in); attempts=0; do { purgeline(); sendline(EOT); fflush(stdout); ++attempts; } while ((firstch=(readline(Rxtimeout)) != ACK) && attempts < RETRYMAX); if (attempts == RETRYMAX) { zperr("No ACK on EOT"); return ERROR; } else return OK;}wcputsec(buf, sectnum, cseclen)char *buf;int sectnum;int cseclen; /* data length of this sector to send */{ register checksum, wcj; register char *cp; unsigned oldcrc; int firstch; int attempts; firstch=0; /* part of logic to detect CAN CAN */ if (Verbose>1) fprintf(stderr, "\rYmodem sectors/kbytes sent: %3d/%2dk", Totsecs, Totsecs/8 ); for (attempts=0; attempts <= RETRYMAX; attempts++) { Lastrx= firstch; sendline(cseclen==1024?STX:SOH); sendline(sectnum); sendline(-sectnum -1); oldcrc=checksum=0; for (wcj=cseclen,cp=buf; --wcj>=0; ) { sendline(*cp); oldcrc=updcrc((0377& *cp), oldcrc); checksum += *cp++; } if (Crcflg) { oldcrc=updcrc(0,updcrc(0,oldcrc)); sendline((int)oldcrc>>8); sendline((int)oldcrc); } else sendline(checksum); if (Optiong) { firstsec = FALSE; return OK; } firstch = readline(Rxtimeout);gotnak: switch (firstch) { case CAN: if(Lastrx == CAN) {cancan: zperr("Cancelled"); return ERROR; } break; case TIMEOUT: zperr("Timeout on sector ACK"); continue; case WANTCRC: if (firstsec) Crcflg = TRUE; case NAK: zperr("NAK on sector"); continue; case ACK: firstsec=FALSE; Totsecs += (cseclen>>7); return OK; case ERROR: zperr("Got burst for sector ACK"); break; default: zperr("Got %02x for sector ACK", firstch); break; } for (;;) { Lastrx = firstch; if ((firstch = readline(Rxtimeout)) == TIMEOUT) break; if (firstch == NAK || firstch == WANTCRC) goto gotnak; if (firstch == CAN && Lastrx == CAN) goto cancan; } } zperr("Retry Count Exceeded"); return ERROR;}/* fill buf with count chars padding with ^Z for CPM */filbuf(buf, count)register char *buf;{ register c, m; if ( !Ascii) { m = read(fileno(in), buf, count); if (m <= 0) return 0; while (m < count) buf[m++] = 032; return count; } m=count; if (Lfseen) { *buf++ = 012; --m; Lfseen = 0; } while ((c=getc(in))!=EOF) { if (c == 012) { *buf++ = 015; if (--m == 0) { Lfseen = TRUE; break; } } *buf++ =c; if (--m == 0) break; } if (m==count) return 0; else while (--m>=0) *buf++ = CPMEOF; return count;}/* Fill buffer with blklen chars */zfilbuf(){ int n; n = fread(txbuf, 1, blklen, in); if (n < blklen) Eofseen = 1; return n;}/* VARARGS1 */vfile(f, a, b, c)register char *f;{ if (Verbose > 2) { fprintf(stderr, f, a, b, c); fprintf(stderr, "\n"); }}RETSIGTYPEalrm(int dummy){ /* this doesn't need to do anything - it interrupts read(), and * that's enough. */}/* * readline(timeout) reads character(s) from file descriptor 0 * timeout is in tenths of seconds */readline(timeout){ register int c; static char buf[64]; static char *bufptr=buf; static int bufleft=0; if (timeout==-1) { bufleft=0; return 0; } if (bufleft) { c=*bufptr & 0377; bufptr++; bufleft--; if (Verbose>5) fprintf(stderr, "ret %x\n", c); return c; } fflush(stdout); if (!no_timeout) { c = timeout/10; if (c<2) c=2; if (Verbose>5) { fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); } signal(SIGALRM, alrm); alarm(c); } else if (Verbose>5) fprintf(stderr, "Calling read "); bufleft=read(iofd, buf, sizeof(buf)); if (!no_timeout) alarm(0); if (Verbose>5) fprintf(stderr, "ret %x\n", buf[0]); if (bufleft<1) return TIMEOUT; bufptr=buf+1; bufleft--; return (buf[0]&0377);}flushmo(){ fflush(stdout);}purgeline(){ readline(-1);#ifdef TCFLSH ioctl(iofd, TCFLSH, 0);#else lseek(iofd, 0L, 2);#endif}/* send cancel string to get the other end to shut up */canit(){ static char canistr[] = { 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 }; printf(canistr); fflush(stdout);}/* * Log an error *//*VARARGS1*/zperr(s,p,u)char *s, *p, *u;{ if (Verbose <= 0) return; fprintf(stderr, "Retry %d: ", errors); fprintf(stderr, s, p, u); fprintf(stderr, "\n");}char *babble[] = { "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol", " (Y) = Option applies to YMODEM only", " (Z) = Option applies to ZMODEM only", "Usage: lsz [-2+abdefkLlNnquvwYy] [-] file ...", " lsz [-2Ceqv] -c COMMAND", " lsb [-2adfkquv] [-] file ...", " lsx [-2akquv] [-] file",#ifdef CSTOPB " 2 Use 2 stop bits",#endif " + Append to existing destination file (Z)", " a (ASCII) change NL to CR/LF", " b Binary file transfer override", " c send COMMAND (Z)", " d Change '.' to '/' in pathnames (Y/Z)", " e Escape all control characters (Z)", " f send Full pathname (Y/Z)", " i send COMMAND, ack Immediately (Z)", " h Print this usage message", " k Send 1024 byte packets (Y)", " L N Limit subpacket length to N bytes (Z)", " l N Limit frame length to N bytes (l>=L) (Z)", " n send file if source newer (Z)", " N send file if source newer or longer (Z)", " o Use 16 bit CRC instead of 32 bit CRC (Z)", " p Protect existing destination file (Z)", " r Resume/Recover interrupted file transfer (Z)", " q Quiet (no progress reports)", " u Unlink file after transmission", " v Verbose - provide debugging information", " w N Window is N bytes (Z)", " Y Yes, overwrite existing file, skip if not present at rx (Z)", " y Yes, overwrite existing file (Z)", " - as pathname sends standard input", ""};usage(){ char **pp; for (pp=babble; **pp; ++pp) fprintf(stderr, "%s\n", *pp); fprintf(stderr, "\t%s version %s for %s %s\n", Progname, VERSION, CPU, OS); cucheck(); exit(SS_NORMAL);}/* * Get the receiver's init parameters */getzrxinit(){ register n; struct stat f; for (n=10; --n>=0; ) { switch (zgethdr(Rxhdr, 1)) { case ZCHALLENGE: /* Echo receiver's challenge numbr */ stohdr(Rxpos); zshhdr(ZACK, Txhdr); continue; case ZCOMMAND: /* They didn't see out ZRQINIT */ stohdr(0L); zshhdr(ZRQINIT, Txhdr); continue; case ZRINIT: Rxflags = 0377 & Rxhdr[ZF0]; Rxflags2 = 0377 & Rxhdr[ZF1]; Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32)); Zctlesc |= Rxflags & TESCCTL; Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8); if ( !(Rxflags & CANFDX)) Txwindow = 0; vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen); if ( !Fromcu) signal(SIGINT, SIG_IGN);#ifdef MODE2OK mode(2); /* Set cbreak, XON/XOFF, etc. */#endif#ifndef READCHECK /* Use MAX_BLOCK byte frames if no sample/interrupt */ if (Rxbuflen < 32 || Rxbuflen > MAX_BLOCK) { Rxbuflen = MAX_BLOCK; vfile("Rxbuflen=%d", Rxbuflen); }#endif /* Override to force shorter frame length */ if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32)) Rxbuflen = Tframlen; if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=MAX_BLOCK)) Rxbuflen = Tframlen; vfile("Rxbuflen=%d", Rxbuflen); /* If using a pipe for testing set lower buf len */ fstat(iofd, &f); if ((f.st_mode & S_IFMT) != S_IFCHR) { Rxbuflen = MAX_BLOCK; } /* * If input is not a regular file, force ACK's to * prevent running beyond the buffer limits */ if ( !Command) { fstat(fileno(in), &f); if ((f.st_mode & S_IFMT) != S_IFREG) { Canseek = -1; return ERROR; } } /* Set initial subpacket length */ if (blklen < 1024) { /* Command line override? */ if (Baudrate > 300) blklen = 256; if (Baudrate > 1200) blklen = 512; if (Baudrate > 2400) blklen = 1024; } if (Rxbuflen && blklen>Rxbuflen) blklen = Rxbuflen; if (blkopt && blklen > blkopt) blklen = blkopt; vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen); vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac); return (sendzsinit()); case ZCAN: case TIMEOUT: return ERROR; case ZRQINIT: if (Rxhdr[ZF0] == ZCOMMAND) continue; default: zshhdr(ZNAK, Txhdr); continue; } } return ERROR;}/* Send send-init information */sendzsinit(){ register c; if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL))) return OK; errors = 0; for (;;) { stohdr(0L); if (Zctlesc) { Txhdr[ZF0] |= TESCCTL; zshhdr(ZSINIT, Txhdr); } else zsbhdr(ZSINIT, Txhdr); zsdata(Myattn, 1+strlen(Myattn), ZCRCW); c = zgethdr(Rxhdr, 1); switch (c) { case ZCAN: return ERROR; case ZACK: return OK; default: if (++errors > 19) return ERROR; continue; } }}/* Send file name and related info */zsendfile(buf, blen)char *buf;{ register c; register unsigned long crc; for (;;) { 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(ZFILE, Txhdr); zsdata(buf, blen, ZCRCW);again: c = zgethdr(Rxhdr, 1); switch (c) { case ZRINIT: while ((c = readline(50)) > 0) if (c == ZPAD) { goto again; } /* **** FALL THRU TO **** */ default: continue; case ZCAN: case TIMEOUT: case ZABORT: case ZFIN: return ERROR; case ZCRC: crc = 0xFFFFFFFFL;#ifdef HAVE_MMAP if (mm_addr) { size_t i; char *p=mm_addr; for (i=0;i<Rxpos && i<mm_size;i++,p++) { crc = UPDC32(*p, crc); } crc = ~crc; } else#endif if (Canseek >= 0) { while (((c = getc(in)) != EOF) && --Rxpos) crc = UPDC32(c, crc); crc = ~crc; clearerr(in); /* Clear EOF */ fseek(in, 0L, 0); } stohdr(crc); zsbhdr(ZCRC, Txhdr); goto again; case ZSKIP: if (in) fclose(in); return c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -