📄 sz.c
字号:
goto gotnak; if (firstch == CAN && Lastrx == CAN) goto cancan; } } logent("Retry Count Exceeded\n"); 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 buf with count chars */zfilbuf(buf, count)register char *buf;{ register c, m; m=count; while ((c=getc(in))!=EOF) { *buf++ =c; if (--m == 0) break; } return (count - m);}/* VARARGS1 */vfile(f, a, b, c)register char *f;{ if (Verbose > 1) { fprintf(stderr, f, a, b, c); fprintf(stderr, "\n"); }}alrm(){ longjmp(tohere, -1);}/* * readock(timeout, count) reads character(s) from file descriptor 0 * (1 <= count <= 3) * it attempts to read count characters. If it gets more than one, * it is an error unless all are CAN * (otherwise, only normal response is ACK, CAN, or C) * Only looks for one if Optiong, which signifies cbreak, not raw input * * timeout is in tenths of seconds */readock(timeout, count){ register int c; static char byt[5]; if (Optiong) count = 1; /* Special hack for cbreak */ fflush(stdout); if (setjmp(tohere)) { logent("TIMEOUT\n"); return TIMEOUT; } c = timeout/10; if (c<2) c=2; if (Verbose>3) { fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, c); byt[1] = 0; } signal(SIGALRM, alrm); alarm(c);#ifdef ONEREAD c=read(iofd, byt, 1); /* regulus raw read is unique */#else c=read(iofd, byt, count);#endif alarm(0); if (Verbose>5) fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]); if (c<1) return TIMEOUT; if (c==1) return (byt[0]&0377); else while (c) if (byt[--c] != CAN) return ERROR; return CAN;}readline(n){ return (readock(n, 1));}purgeline(){#ifdef USG ioctl(iofd, TCFLSH, 0);#else lseek(iofd, 0L, 2);#endif}/* update CRC */unsignedupdcrc(c, crc)register c;register unsigned crc;{ register count; for (count=8; --count>=0;) { if (crc & 0x8000) { crc <<= 1; crc += (((c<<=1) & 0400) != 0); crc ^= 0x1021; } else { crc <<= 1; crc += (((c<<=1) & 0400) != 0); } } return crc; }/* send cancel string to get the other end to shut up */canit(){ static char canistr[] = { ZPAD,ZPAD,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 }; printf(canistr); fflush(stdout);}/*VARARGS1*/logent(a, b, c)char *a, *b, *c;{ if(Verbose) fprintf(stderr, a, b, c);}/* * return 1 iff stdout and stderr are different devices * indicating this program operating with a modem on a * different line */fromcu(){ struct stat a, b; fstat(1, &a); fstat(2, &b); return (a.st_rdev != b.st_rdev);}/* * substr(string, token) searches for token in string s * returns pointer to token within string if found, NULL otherwise */char *substr(s, t)register char *s,*t;{ register char *ss,*tt; /* search for first char of token */ for (ss=s; *s; s++) if (*s == *t) /* compare token with substring */ for (ss=s,tt=t; ;) { if (*tt == 0) return s; if (*ss++ != *tt++) break; } return NULL;}usage(){ fprintf(stderr,"\nSend file(s) with ZMODEM/YMODEM/XMODEM Protocol\n"); fprintf(stderr,"%s for %s by Chuck Forsberg\n", VERSION, OS); fprintf(stderr,"Usage: sz [-1+adfknquvXy] [-] file ...\n"); fprintf(stderr," (Y) = Option applies to YMODEM only\n"); fprintf(stderr," (Z) = Option applies to ZMODEM only\n"); fprintf(stderr," sz [-1qv] -c COMMAND\n"); fprintf(stderr," 1 Use stdout for modem input\n"); fprintf(stderr," + Append to existing destination file (Z)\n"); fprintf(stderr," a (ASCII) change NL to CR/LF\n"); fprintf(stderr," c send COMMAND (Z)\n"); fprintf(stderr,"\tC N (set command retries to N default=%d) (Z)\n", Cmdtries); fprintf(stderr," d Change '.' to '/' in pathnames (Y/Z)\n"); fprintf(stderr," f send Full pathname (Y/Z)\n"); fprintf(stderr," i send COMMAND, ack Immediately (Z)\n"); fprintf(stderr," k Send 1024 byte packets (Y)\n"); fprintf(stderr," n send file if Newer|different length (Z)\n"); fprintf(stderr," N send file if different length|CRC (Z)\n"); fprintf(stderr," r Resume interrupted file transfer (Z)\n"); fprintf(stderr," q Quiet (no progress reports)\n"); fprintf(stderr," u Unlink file after transmission\n"); fprintf(stderr," v Verbose - debugging information\n"); fprintf(stderr," X XMODEM protocol - no pathnames\n"); fprintf(stderr," y Yes, overwrite existing file (Z)\n"); fprintf(stderr,"- as pathname sends standard input as sPID.sz or environment ONAME\n"); exit(1);}/* * 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 = Rxhdr[ZF0]; Rxbuflen = Rxhdr[ZP0] + (Rxhdr[ZP1]<<8); signal(SIGINT, SIG_IGN); mode(2); /* Set cbreak, XON/XOFF, etc. */ /* If using a pipe for testing set lower buf len */ fstat(iofd, &f); if ((f.st_mode & S_IFMT) != S_IFCHR && (Rxbuflen == 0 || Rxbuflen > 4096)) Rxbuflen = 4096; /* * If input is not a regular file, force ACK's each 1024 * (A smarter strategey could be used here ...) */ fstat(fileno(in), &f); if (((f.st_mode & S_IFMT) != S_IFREG) && (Rxbuflen == 0 || Rxbuflen > 1024)) Rxbuflen = 1024; 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; register errors; errors = 0; for (;;) { stohdr(0L); zsbhdr(ZSINIT, Txhdr); zsbdata(Myattn, 1+strlen(Myattn), ZCRCW); c = zgethdr(Rxhdr, 1); switch (c) { case ZCAN: return ERROR; case ZACK: return OK; default: if (++errors > 9) return ERROR; continue; } }}/* Send file name and related info */zsendfile(buf, blen)char *buf;{ register c; for (;;) { Txhdr[ZF0] = Lzconv; /* file conversion request */ Txhdr[ZF1] = Lzmanag; /* file management request */ Txhdr[ZF2] = Lztrans; /* file transport request */ Txhdr[ZF3] = 0; zsbhdr(ZFILE, Txhdr); zsbdata(buf, blen, ZCRCW);again: c = zgethdr(Rxhdr, 1); switch (c) { case ZRINIT: goto again; case ZCAN: case TIMEOUT: case ZABORT: case ZFIN: return ERROR; case ZSKIP: fclose(in); return c; case ZRPOS: fseek(in, Rxpos, 0); Txpos = Rxpos; return zsendfdata(); case ERROR: default: continue; } }}/* Send the data in the file */zsendfdata(){ register c, e; register newcnt; register long tcount = 0; static int tleft = 6; /* Counter for test mode */ if (Baudrate > 300) blklen = 256; if (Baudrate > 2400) blklen = KSIZE; if (Rxbuflen && blklen>Rxbuflen) blklen = Rxbuflen;somemore: if (setjmp(intrjmp)) {waitack: switch (c = getinsync()) { default: case ZCAN: fclose(in); return ERROR; case ZSKIP: fclose(in); return c; case ZACK: case ZRPOS: break; } } signal(SIGINT, onintr); newcnt = Rxbuflen; 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 (Testattn) { if ( --tleft) while (tcount < 20000) { printf(qbf); fflush(stdout); tcount += strlen(qbf); } signal(SIGINT, SIG_IGN); canit(); sleep(3); purgeline(); mode(0); printf("\nsz: Tcount = %ld\n", tcount); if (tleft) { printf("ERROR: Interrupts Not Caught\n"); exit(1); } exit(0); } do { c = zfilbuf(txbuf, blklen); if (c < blklen) e = ZCRCE; else if (Rxbuflen && (newcnt -= c) <= 0) e = ZCRCW; else e = ZCRCG; zsbdata(txbuf, c, e); Txpos += c; if (e == ZCRCW) goto waitack;#ifdef NOTDEF_DOS if ( !carrier()) { return ERROR; } /* * 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 * miready() returns non 0 if a character is available */ while (miready()) { if (readline(1) == ZPAD) { zsbdata(U.ubuf, 0, ZCRCW); goto somemore; } }#endif } while (c == blklen); signal(SIGINT, SIG_IGN); for (;;) { stohdr(Txpos); zsbhdr(ZEOF, Txhdr); switch (getinsync()) { case ZRPOS: goto somemore; case ZRINIT: fclose(in); return OK; case ZSKIP: fclose(in); return c; default: fclose(in); return ERROR; } }}/* * Respond to receiver's complaint, get back in sync with receiver */getinsync(){ register c; for (;;) { if (Testattn) { 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: clearerr(in); /* In case file EOF seen */ fseek(in, Rxpos, 0); Txpos = Rxpos; return c; case ZACK: return c; case ZRINIT: case ZSKIP: fclose(in); return c; case ERROR: default: zsbhdr(ZNAK, Txhdr); continue; } }}/* Say "bibi" to the receiver, try to do it cleanly */saybibi(){ for (;;) { stohdr(0L); zsbhdr(ZFIN, Txhdr); 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, errors; long cmdnum; cmdnum = getpid(); errors = 0; for (;;) { stohdr(cmdnum); Txhdr[ZF0] = Cmdack1; zsbhdr(ZCOMMAND, Txhdr); zsbdata(buf, blen, ZCRCW);listen: Rxtimeout = 100; /* Ten second wait for resp. */ c = zgethdr(Rxhdr, 1); switch (c) { case ZRINIT: continue; 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 > 10) return ERROR; continue; case ZCOMPL: Exitcode = Rxpos; saybibi(); return OK; case ZRQINIT: vfile("******** RZ *******"); system("rz"); vfile("******** SZ *******"); goto listen; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -