home *** CD-ROM | disk | FTP | other *** search
- Subject: v12i023: Zmodem file transfer programs, Part03/03
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: omen!caf
- Posting-number: Volume 12, Issue 23
- Archive-name: zmodem/part03
-
- Source code for Unix ZMODEM programs rz.c and sz.c and related files follows.
- ZMODEM is the ideal protocol for file transfer to and from Unix systems
- using a serial port. The source code has also been used for numerous ZMODEM
- versions, including the Opus bulletin board (Fido replacemet). ZMODEM's
- pleasant user interface with automatic file and command download allows a
- Makefile to control a DOS machine running Pro-YAM, dor example.
-
- #!/bin/sh
- # to extract, remove the header and type "sh filename"
- if `test ! -s ./sz.c`
- then
- echo "Writing ./sz.c"
- cat > ./sz.c << '\Rogue\Monster\'
- #define VERSION "sz 1.36 08-31-87"
- #define PUBDIR "/usr/spool/uucppublic"
-
- /*% cc -M0 -Ox -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
- *
- * sz.c By Chuck Forsberg
- *
- * cc -O sz.c -o sz USG (SYS III/V) Unix
- * cc -O -DSVR2 sz.c -o sz Sys V Release 2 with non-blocking input
- * Define to allow reverse channel checking
- * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
- *
- * cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Xenix
- *
- * ln sz sb **** All versions ****
- * ln sz sx **** All versions ****
- *
- *
- * ******* Some systems (Venix, Coherent, Regulus) do not *******
- * ******* support tty raw mode read(2) identically to *******
- * ******* Unix. ONEREAD must be defined to force one *******
- * ******* character reads for these systems. *******
- *
- * A program for Unix to send files and commands to computers running
- * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
- *
- * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
- *
- * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
- *
- * 1.34 implements tx backchannel garbage count and ZCRCW after ZRPOS
- * in accordance with the 7-31-87 ZMODEM Protocol Description
- */
-
-
- char *substr(), *getenv();
-
- #define LOGFILE "/tmp/szlog"
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
-
- #define PATHLEN 256
- #define OK 0
- #define FALSE 0
- #define TRUE 1
- #define ERROR (-1)
-
- #define HOWMANY 2
- int Zmodem=0; /* ZMODEM protocol requested */
- unsigned Baudrate;
- unsigned Txwindow; /* Control the size of the transmitted window */
- unsigned Txwspac; /* Spacing between zcrcq requests */
- unsigned Txwcnt; /* Counter used to space ack requests */
- long Lrxpos; /* Receiver's last reported offset */
- int Fromcu = 0; /* Were called from cu or yam */
- int errors;
- #include "rbsb.c" /* most of the system dependent stuff here */
-
- /*
- * Attention string to be executed by receiver to interrupt streaming data
- * when an error is detected. A pause (0336) may be needed before the
- * ^C (03) or after it.
- */
- #ifdef READCHECK
- char Myattn[] = { 0 };
- #else
- #ifdef USG
- char Myattn[] = { 03, 0336, 0 };
- #else
- char Myattn[] = { 0 };
- #endif
- #endif
-
- FILE *in;
-
- /* Ward Christensen / CP/M parameters - Don't change these! */
- #define ENQ 005
- #define CAN ('X'&037)
- #define XOFF ('s'&037)
- #define XON ('q'&037)
- #define SOH 1
- #define STX 2
- #define EOT 4
- #define ACK 6
- #define NAK 025
- #define CPMEOF 032
- #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
- #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */
- #define TIMEOUT (-2)
- #define RCDO (-3)
- #define RETRYMAX 10
- #define SECSIZ 128 /* cp/m's Magic Number record size */
- #define KSIZE 1024
-
- char Lastrx;
- char Crcflg;
- int Wcsmask=0377;
- int Verbose=0;
- int Modem2=0; /* XMODEM Protocol - don't send pathnames */
- int Restricted=0; /* restricted; no /.. or ../ in filenames */
- int Quiet=0; /* overrides logic that would otherwise set verbose */
- int Ascii=0; /* Add CR's for brain damaged programs */
- int Fullname=0; /* transmit full pathname */
- int Unlinkafter=0; /* Unlink file after it is sent */
- int Dottoslash=0; /* Change foo.bar.baz to foo/bar/baz */
- int firstsec;
- int errcnt=0; /* number of files unreadable */
- int blklen=SECSIZ; /* length of transmitted records */
- int Optiong; /* Let it rip no wait for sector ACK's */
- int Noeofseen;
- int Totsecs; /* total number of sectors this file */
- char txbuf[KSIZE];
- int Filcnt=0; /* count of number of files opened */
- int Lfseen=0;
- unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
- int Tframlen = 0; /* Override for tx frame length */
- int blkopt=0; /* Override value for zmodem blklen */
- int Rxflags = 0;
- long bytcnt;
- int Wantfcs32 = TRUE; /* want to send 32 bit FCS */
- char Lzconv; /* Local ZMODEM file conversion request */
- char Lzmanag; /* Local ZMODEM file management request */
- int Lskipnocor;
- char Lztrans;
- char zconv; /* ZMODEM file conversion request */
- char zmanag; /* ZMODEM file management request */
- char ztrans; /* ZMODEM file transport request */
- int Command; /* Send a command, then exit. */
- char *Cmdstr; /* Pointer to the command string */
- int Cmdtries = 11;
- int Cmdack1; /* Rx ACKs command, then do it */
- int Exitcode;
- int Testattn; /* Force receiver to send Attn, etc with qbf. */
- char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
- long Lastread; /* Beginning offset of last buffer read */
- int Lastn; /* Count of last buffer read or -1 */
- int Dontread; /* Don't read the buffer, it's still there */
- long Lastsync; /* Last offset to which we got a ZRPOS */
- int Beenhereb4; /* How many times we've been ZRPOS'd same place */
-
- jmp_buf tohere; /* For the interrupt on RX timeout */
- jmp_buf intrjmp; /* For the interrupt on RX CAN */
-
- /* called by signal interrupt or terminate to clean things up */
- bibi(n)
- {
- canit(); fflush(stdout); mode(0);
- fprintf(stderr, "sz: caught signal %d; exiting\n", n);
- if (n == SIGQUIT)
- abort();
- exit(128+n);
- }
- /* Called when Zmodem gets an interrupt (^X) */
- onintr()
- {
- signal(SIGINT, SIG_IGN);
- longjmp(intrjmp, -1);
- }
-
-
- #define sendline(c) putchar(c & Wcsmask)
-
- #define xsendline(c) putchar(c)
-
- flushmo()
- {
- fflush(stdout);
- }
-
- int Zctlesc; /* Encode control characters */
- int Nozmodem = 0; /* If invoked as "sb" */
- char *Progname = "sz";
- int Zrwindow = 1400; /* RX window size (controls garbage count) */
- #include "zm.c"
-
-
- main(argc, argv)
- char *argv[];
- {
- register char *cp;
- register npats;
- int agcnt; char **agcv;
- char **patts;
- static char xXbuf[BUFSIZ];
-
- if ((cp = getenv("ZNULLS")) && *cp)
- Znulls = atoi(cp);
- if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
- Restricted=TRUE;
- chkinvok(argv[0]);
-
- Rxtimeout = 600;
- npats=0;
- if (argc<2)
- usage();
- setbuf(stdout, xXbuf);
- while (--argc) {
- cp = *++argv;
- if (*cp++ == '-' && *cp) {
- while ( *cp) {
- switch(*cp++) {
- case '+':
- Lzmanag = ZMAPND; break;
- case '1':
- iofd = 1; break;
- #ifdef CSTOPB
- case '2':
- Twostop = TRUE; break;
- #endif
- case '7':
- Wcsmask=0177; break;
- case 'a':
- Lzconv = ZCNL;
- Ascii = TRUE; break;
- case 'b':
- Lzconv = ZCBIN; break;
- case 'C':
- if (--argc < 1) {
- usage();
- }
- Cmdtries = atoi(*++argv);
- break;
- case 'i':
- Cmdack1 = ZCACK1;
- /* **** FALL THROUGH TO **** */
- case 'c':
- if (--argc != 1) {
- usage();
- }
- Command = TRUE;
- Cmdstr = *++argv;
- break;
- case 'd':
- ++Dottoslash;
- /* **** FALL THROUGH TO **** */
- case 'f':
- Fullname=TRUE; break;
- case 'e':
- Zctlesc = 1; break;
- case 'k':
- blklen=KSIZE; break;
- case 'L':
- if (--argc < 1) {
- usage();
- }
- blkopt = atoi(*++argv);
- if (blkopt<24 || blkopt>1024)
- usage();
- break;
- case 'l':
- if (--argc < 1) {
- usage();
- }
- Tframlen = atoi(*++argv);
- if (Tframlen<32 || Tframlen>1024)
- usage();
- break;
- case 'N':
- Lzmanag = ZMNEWL; break;
- case 'n':
- Lzmanag = ZMNEW; break;
- case 'o':
- Wantfcs32 = FALSE; break;
- case 'p':
- Lzmanag = ZMPROT; break;
- case 'r':
- Lzconv = ZCRESUM;
- case 'q':
- Quiet=TRUE; Verbose=0; break;
- case 't':
- if (--argc < 1) {
- usage();
- }
- Rxtimeout = atoi(*++argv);
- if (Rxtimeout<10 || Rxtimeout>1000)
- usage();
- break;
- case 'T':
- Testattn = TRUE; break;
- case 'u':
- ++Unlinkafter; break;
- case 'v':
- ++Verbose; break;
- case 'w':
- if (--argc < 1) {
- usage();
- }
- Txwindow = atoi(*++argv);
- if (Txwindow < 256)
- Txwindow = 256;
- Txwindow = (Txwindow/64) * 64;
- Txwspac = Txwindow/4;
- if (blkopt > Txwspac
- || (!blkopt && Txwspac < 1024))
- blkopt = Txwspac;
- break;
- case 'X':
- ++Modem2; break;
- case 'Y':
- Lskipnocor = TRUE;
- /* **** FALLL THROUGH TO **** */
- case 'y':
- Lzmanag = ZMCLOB; break;
- default:
- usage();
- }
- }
- }
- else if ( !npats && argc>0) {
- if (argv[0][0]) {
- npats=argc;
- patts=argv;
- if ( !strcmp(*patts, "-"))
- iofd = 1;
- }
- }
- }
- if (npats < 1 && !Command)
- usage();
- if (Verbose) {
- if (freopen(LOGFILE, "a", stderr)==NULL) {
- printf("Can't open log file %s\n",LOGFILE);
- exit(0200);
- }
- setbuf(stderr, NULL);
- }
- if ((Fromcu=from_cu()) && !Quiet) {
- if (Verbose == 0)
- Verbose = 2;
- }
-
- mode(1);
-
- if (signal(SIGINT, bibi) == SIG_IGN) {
- signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
- } else {
- signal(SIGINT, bibi); signal(SIGKILL, bibi);
- }
- if ( !Fromcu)
- signal(SIGQUIT, SIG_IGN);
- signal(SIGTERM, bibi);
-
- if ( !Modem2) {
- if (!Nozmodem) {
- printf("rz\r"); fflush(stdout);
- }
- if (!Command && !Quiet && Verbose != 1) {
- fprintf(stderr, "%s: %d file%s requested:\r\n",
- Progname, npats, npats>1?"s":"");
- for ( agcnt=npats, agcv=patts; --agcnt>=0; ) {
- fprintf(stderr, "%s ", *agcv++);
- }
- fprintf(stderr, "\r\n");
- printf("\r\n\bSending in Batch Mode\r\n");
- }
- if (!Nozmodem) {
- stohdr(0L);
- if (Command)
- Txhdr[ZF0] = ZCOMMAND;
- zshhdr(ZRQINIT, Txhdr);
- }
- }
- fflush(stdout);
-
- if (Command) {
- if (getzrxinit()) {
- Exitcode=0200; canit();
- }
- else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
- Exitcode=0200; canit();
- }
- } else if (wcsend(npats, patts)==ERROR) {
- Exitcode=0200;
- canit();
- }
- fflush(stdout);
- mode(0);
- exit((errcnt != 0) | Exitcode);
- /*NOTREACHED*/
- }
-
- wcsend(argc, argp)
- char *argp[];
- {
- register n;
-
- Crcflg=FALSE;
- firstsec=TRUE;
- bytcnt = -1;
- for (n=0; n<argc; ++n) {
- Totsecs = 0;
- if (wcs(argp[n])==ERROR)
- return ERROR;
- }
- Totsecs = 0;
- if (Filcnt==0) { /* bitch if we couldn't open ANY files */
- if (1) {
- Command = TRUE;
- Cmdstr = "echo \"sz: Can't open any requested files\"";
- if (getnak()) {
- Exitcode=0200; canit();
- }
- if (!Zmodem)
- canit();
- else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
- Exitcode=0200; canit();
- }
- Exitcode = 1; return OK;
- }
- canit();
- fprintf(stderr,"\r\nCan't open any requested files.\r\n");
- return ERROR;
- }
- if (Zmodem)
- saybibi();
- else if ( !Modem2)
- wctxpn("");
- return OK;
- }
-
- wcs(oname)
- char *oname;
- {
- register c;
- register char *p;
- struct stat f;
- char name[PATHLEN];
-
- strcpy(name, oname);
-
- if (Restricted) {
- /* restrict pathnames to current tree or uucppublic */
- if ( substr(name, "../")
- || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
- canit();
- fprintf(stderr,"\r\nsz:\tSecurity Violation\r\n");
- return ERROR;
- }
- }
-
- if ( !strcmp(oname, "-")) {
- if ((p = getenv("ONAME")) && *p)
- strcpy(name, p);
- else
- sprintf(name, "s%d.sz", getpid());
- in = stdin;
- }
- else if ((in=fopen(oname, "r"))==NULL) {
- ++errcnt;
- return OK; /* pass over it, there may be others */
- }
- ++Noeofseen; Lastread = 0; Lastn = -1; Dontread = FALSE;
- /* Check for directory or block special files */
- fstat(fileno(in), &f);
- c = f.st_mode & S_IFMT;
- 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, f.st_size>>7);
- }
- fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
- return OK;
- }
- zperr("Awaiting pathname nak for %s", *name?name:"<END>");
- 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 + KSIZE))
- *q++ = 0;
- if (!Ascii && (in!=stdin) && *name && fstat(fileno(in), &f)!= -1)
- sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
- /* force 1k blocks if name won't fit in 128 byte block */
- if (txbuf[125])
- blklen=KSIZE;
- else { /* A little goodie for IMP/KMD */
- if (Zmodem)
- blklen = SECSIZ;
- 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, SECSIZ)==ERROR)
- return ERROR;
- return OK;
- }
-
- getnak()
- {
- register firstch;
-
- Lastrx = 0;
- for (;;) {
- switch (firstch = readock(800,1)) {
- case ZPAD:
- if (getzrxinit())
- return ERROR;
- Ascii = 0;
- return FALSE;
- case TIMEOUT:
- zperr("Timeout on pathname");
- return TRUE;
- case WANTG:
- #ifdef USG
- mode(2); /* Set cbreak, XON/XOFF, etc. */
- #endif
- Optiong = TRUE;
- blklen=KSIZE;
- case WANTCRC:
- Crcflg = TRUE;
- case NAK:
- return FALSE;
- case CAN:
- if ((firstch = readock(20,1)) == CAN && Lastrx == CAN)
- return TRUE;
- default:
- break;
- }
- Lastrx = firstch;
- }
- }
-
-
- wctx(flen)
- long flen;
- {
- register int thisblklen;
- register int sectnum, attempts, firstch;
- long charssent;
-
- charssent = 0; firstsec=TRUE; thisblklen = blklen;
- vfile("wctx:file length=%ld", flen);
-
- while ((firstch=readock(Rxtimeout, 2))!=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=(readock(Rxtimeout, 1)) != 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>2)
- fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs/8 );
- else if (Verbose>1)
- fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
- for (attempts=0; attempts <= RETRYMAX; attempts++) {
- Lastrx= firstch;
- sendline(cseclen==KSIZE?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 = readock(Rxtimeout, (Noeofseen&§num) ? 2:1);
- 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 = readock(Rxtimeout, 2)) == 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 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 > 2) {
- 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)) {
- zperr("TIMEOUT");
- return TIMEOUT;
- }
- c = timeout/10;
- if (c<2)
- c=2;
- if (Verbose>5) {
- 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
- }
-
-
- /* 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");
- }
-
- /*
- * return 1 iff stdout and stderr are different devices
- * indicating this program operating with a modem on a
- * different line
- */
- from_cu()
- {
- 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;
- }
-
- char *babble[] = {
- "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
- " (Y) = Option applies to YMODEM only",
- " (Z) = Option applies to ZMODEM only",
- "Usage: sz [-12+abdefkLlNnquvwYy] [-] file ...",
- " sz [-12Ceqv] -c COMMAND",
- " sb [-12adfkquv] [-] file ...",
- " sx [-12akquv] [-] file",
- " 1 Use stdout for modem input",
- #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)",
- " 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 as sPID.sz or environment ONAME",
- ""
- };
-
- usage()
- {
- char **pp;
-
- for (pp=babble; **pp; ++pp)
- fprintf(stderr, "%s\n", *pp);
- fprintf(stderr, "%s for %s by Chuck Forsberg ", VERSION, OS);
- 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 = 0377 & Rxhdr[ZF0];
- Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
- Zctlesc |= Rxflags & TESCCTL;
- Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
- vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
- if ( !Fromcu)
- signal(SIGINT, SIG_IGN);
- #ifdef USG
- mode(2); /* Set cbreak, XON/XOFF, etc. */
- #endif
- #ifndef READCHECK
- #ifndef USG
- /* Use 1024 byte frames if no sample/interrupt */
- if (Rxbuflen < 32 || Rxbuflen > 1024) {
- Rxbuflen = 1024;
- vfile("Rxbuflen=%d", Rxbuflen);
- }
- #endif
- #endif
- /* Override to force shorter frame length */
- if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
- Rxbuflen = Tframlen;
- if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
- 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 == 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;
- vfile("Rxbuflen=%d", Rxbuflen);
-
- 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;
-
- 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 ZSKIP:
- fclose(in); return c;
- case ZRPOS:
- /*
- * Suppress zcrcw request otherwise triggered by
- * lastyunc==bytcnt
- */
- Lastsync = (bytcnt = Txpos = Rxpos) -1;
- fseek(in, Rxpos, 0);
- Dontread = FALSE;
- 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 */
-
- if (Baudrate > 300)
- blklen = 256;
- if (Baudrate > 1200)
- blklen = 512;
- if (Baudrate > 2400)
- blklen = KSIZE;
- 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);
- Lrxpos = 0;
- junkcount = 0;
- Beenhereb4 = FALSE;
- somemore:
- if (setjmp(intrjmp)) {
- waitack:
- junkcount = 0;
- c = getinsync(0);
- gotack:
- switch (c) {
- default:
- case ZCAN:
- fclose(in);
- return ERROR;
- case ZSKIP:
- 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 SVR2
- switch (checked)
- #else
- switch (readline(1))
- #endif
- {
- case CAN:
- case ZPAD:
- c = getinsync(1);
- goto gotack;
- case XOFF: /* Wait a while for an XON */
- case XOFF|0200:
- readline(100);
- }
- }
- #endif
- }
-
- if ( !Fromcu)
- signal(SIGINT, onintr);
- 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 (Testattn) {
- if ( --tleft)
- while (tcount < 20000) {
- printf(qbf); fflush(stdout);
- tcount += strlen(qbf);
- #ifdef READCHECK
- while (rdchk(iofd)) {
- #ifdef SVR2
- 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 */
- case XOFF|0200:
- readline(100);
- }
- }
- #endif
- }
- 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 {
- if (Dontread) {
- n = Lastn;
- } else {
- n = zfilbuf(txbuf, blklen);
- Lastread = Txpos; Lastn = n;
- }
- Dontread = FALSE;
- if (n < blklen)
- 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)
- fprintf(stderr, "\r%7ld ZMODEM%s ",
- Txpos, Crc32t?" CRC-32":"");
- 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 SVR2
- 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 */
- case XOFF|0200:
- 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 (n == blklen);
- 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:
- fclose(in);
- return c;
- default:
- fclose(in);
- return ERROR;
- }
- }
- }
-
- /*
- * Respond to receiver's complaint, get back in sync with receiver
- */
- getinsync(flag)
- {
- 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:
- /* ************************************* */
- /* If sending to a modem beuufer, you */
- /* might send a break at this point to */
- /* dump the modem's buffer. */
- if (Lastn >= 0 && Lastread == Rxpos) {
- Dontread = TRUE;
- } else {
- clearerr(in); /* In case file EOF seen */
- fseek(in, Rxpos, 0);
- }
- bytcnt = Lrxpos = Txpos = Rxpos;
- if (Lastsync == Rxpos) {
- if (++Beenhereb4 > 4)
- if (blklen > 256)
- blklen /= 2;
- }
- Lastsync = Rxpos;
- return c;
- case ZACK:
- Lrxpos = Rxpos;
- if (flag || Txpos == Rxpos)
- return ZACK;
- continue;
- 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); /* 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 sb 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') {
- Nozmodem = TRUE; blklen=KSIZE;
- }
- if (s[0]=='s' && s[1]=='x') {
- Modem2 = TRUE;
- }
- }
- /* End of sz.c */
- \Rogue\Monster\
- else
- echo "will not over write ./sz.c"
- fi
- if [ `wc -c ./sz.c | awk '{printf $1}'` -ne 31161 ]
- then
- echo `wc -c ./sz.c | awk '{print "Got " $1 ", Expected " 31161}'`
- fi
- if `test ! -s ./rz.c`
- then
- echo "Writing ./rz.c"
- cat > ./rz.c << '\Rogue\Monster\'
- #define VERSION "1.26 08-21-87"
- #define PUBDIR "/usr/spool/uucppublic"
-
- /*% cc -M0 -Ox -K -i % -o rz; size rz;
- <-xtx-*> cc386 -Ox rz.c -o $B/rz; size $B/rz
- *
- * rz.c By Chuck Forsberg
- *
- * cc -O rz.c -o rz USG (3.0) Unix
- * cc -O -DV7 rz.c -o rz Unix V7, BSD 2.8 - 4.3
- *
- * ln rz rb; ln rz rx For either system
- *
- * ln rz /usr/bin/rzrmail For remote mail. Make this the
- * login shell. rzrmail then calls
- * rmail(1) to deliver mail.
- *
- *
- * Unix is a trademark of Western Electric Company
- *
- * A program for Unix to receive files and commands from computers running
- * Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
- * rz uses Unix buffered input to reduce wasted CPU time.
- *
- * Iff the program is invoked by rzCOMMAND, output is piped to
- * "COMMAND filename"
- *
- * Some systems (Venix, Coherent, Regulus) may not support tty raw mode
- * read(2) the same way as Unix. ONEREAD must be defined to force one
- * character reads for these systems. Added 7-01-84 CAF
- *
- * Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
- *
- * BIX added 6-30-87 to support BIX(TM) upload protocol used by the
- * Byte Information Exchange.
- *
- * NFGVMIN Updated 2-18-87 CAF for Xenix systems where c_cc[VMIN]
- * doesn't work properly (even though it compiles without error!),
- *
- * HOWMANY may be tuned for best performance
- *
- * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
- */
- #define LOGFILE "/tmp/rzlog"
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
- FILE *popen();
-
- #define OK 0
- #define FALSE 0
- #define TRUE 1
- #define ERROR (-1)
-
- /*
- * Max value for HOWMANY is 255.
- * A larger value reduces system overhead but may evoke kernel bugs.
- * 133 corresponds to an XMODEM/CRC sector
- */
- #ifndef HOWMANY
- #define HOWMANY 133
- #endif
-
- int Zmodem=0; /* ZMODEM protocol requested */
- int Nozmodem = 0; /* If invoked as "rb" */
- unsigned Baudrate;
- #include "rbsb.c" /* most of the system dependent stuff here */
-
- char *substr();
- FILE *fout;
-
- /*
- * Routine to calculate the free bytes on the current file system
- * ~0 means many free bytes (unknown)
- */
- long getfree()
- {
- return(~0L); /* many free bytes ... */
- }
-
- /* Ward Christensen / CP/M parameters - Don't change these! */
- #define ENQ 005
- #define CAN ('X'&037)
- #define XOFF ('s'&037)
- #define XON ('q'&037)
- #define SOH 1
- #define STX 2
- #define EOT 4
- #define ACK 6
- #define NAK 025
- #define CPMEOF 032
- #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
- #define TIMEOUT (-2)
- #define RCDO (-3)
- #define ERRORMAX 5
- #define RETRYMAX 5
- #define WCEOT (-10)
- #define SECSIZ 128 /* cp/m's Magic Number record size */
- #define PATHLEN 257 /* ready for 4.2 bsd ? */
- #define KSIZE 1024 /* record size with k option */
- #define UNIXFILE 0x8000 /* happens to the the S_IFREG file mask bit for stat */
-
- int Lastrx;
- int Crcflg;
- int Firstsec;
- int Eofseen; /* indicates cpm eof (^Z) has been received */
- int errors;
- int Restricted=0; /* restricted; no /.. or ../ in filenames */
- #ifdef ONEREAD
- /* Sorry, Regulus and some others don't work right in raw mode! */
- int Readnum = 1; /* Number of bytes to ask for in read() from modem */
- #else
- int Readnum = HOWMANY; /* Number of bytes to ask for in read() from modem */
- #endif
-
- #define DEFBYTL 2000000000L /* default rx file size */
- long Bytesleft; /* number of bytes of incoming file left */
- long Modtime; /* Unix style mod time for incoming file */
- short Filemode; /* Unix style mode for incoming file */
- char Pathname[PATHLEN];
- char *Progname; /* the name by which we were called */
-
- int Batch=0;
- int Wcsmask=0377;
- int Topipe=0;
- int MakeLCPathname=TRUE; /* make received pathname lower case */
- int Verbose=0;
- int Quiet=0; /* overrides logic that would otherwise set verbose */
- int Nflag = 0; /* Don't really transfer files */
- int Rxbinary=FALSE; /* receive all files in bin mode */
- int Rxascii=FALSE; /* receive files in ascii (translate) mode */
- int Thisbinary; /* current file is to be received in bin mode */
- int Blklen; /* record length of received packets */
- char secbuf[KSIZE+1];
- char linbuf[HOWMANY];
- int Lleft=0; /* number of characters in linbuf */
- time_t timep[2];
- char Lzmanag; /* Local file management request */
- char zconv; /* ZMODEM file conversion request */
- char zmanag; /* ZMODEM file management request */
- char ztrans; /* ZMODEM file transport request */
- int Zctlesc; /* Encode control characters */
- int Zrwindow = 1400; /* RX window size (controls garbage count) */
-
- jmp_buf tohere; /* For the interrupt on RX timeout */
-
- #include "zm.c"
-
- int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close */
-
- alrm()
- {
- longjmp(tohere, -1);
- }
-
- /* called by signal interrupt or terminate to clean things up */
- bibi(n)
- {
- if (Zmodem)
- zmputs(Attn);
- canit(); mode(0);
- fprintf(stderr, "rz: caught signal %d; exiting", n);
- exit(128+n);
- }
-
- main(argc, argv)
- char *argv[];
- {
- register char *cp;
- register npats;
- char *virgin, **patts;
- char *getenv();
- int exitcode;
-
- Rxtimeout = 100;
- setbuf(stderr, NULL);
- if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
- Restricted=TRUE;
-
- chkinvok(virgin=argv[0]); /* if called as [-]rzCOMMAND set flag */
- npats = 0;
- while (--argc) {
- cp = *++argv;
- if (*cp == '-') {
- while( *++cp) {
- switch(*cp) {
- case '+':
- Lzmanag = ZMAPND; break;
- case '1':
- iofd = 1; break;
- case '7':
- Wcsmask = 0177;
- case 'a':
- Rxascii=TRUE; break;
- case 'b':
- Rxbinary=TRUE; break;
- case 'c':
- Crcflg=TRUE; break;
- case 'D':
- Nflag = TRUE; break;
- case 'e':
- Zctlesc = 1; break;
- case 'p':
- Lzmanag = ZMPROT; break;
- case 'q':
- Quiet=TRUE; Verbose=0; break;
- case 't':
- if (--argc < 1) {
- usage();
- }
- Rxtimeout = atoi(*++argv);
- if (Rxtimeout<10 || Rxtimeout>1000)
- usage();
- break;
- case 'w':
- if (--argc < 1) {
- usage();
- }
- Zrwindow = atoi(*++argv);
- break;
- case 'u':
- MakeLCPathname=FALSE; break;
- case 'v':
- ++Verbose; break;
- default:
- usage();
- }
- }
- }
- else if ( !npats && argc>0) {
- if (argv[0][0]) {
- npats=argc;
- patts=argv;
- }
- }
- }
- if (npats > 1)
- usage();
- if (Verbose) {
- if (freopen(LOGFILE, "a", stderr)==NULL) {
- printf("Can't open log file %s\n",LOGFILE);
- exit(0200);
- }
- setbuf(stderr, NULL);
- fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
- }
- if (fromcu() && !Quiet) {
- if (Verbose == 0)
- Verbose = 2;
- }
- mode(1);
- if (signal(SIGINT, bibi) == SIG_IGN) {
- signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
- }
- else {
- signal(SIGINT, bibi); signal(SIGKILL, bibi);
- }
- signal(SIGTERM, bibi);
- if (wcreceive(npats, patts)==ERROR) {
- exitcode=0200;
- canit();
- }
- mode(0);
- if (exitcode && !Zmodem) /* bellow again with all thy might. */
- canit();
- exit(exitcode);
- }
-
-
- usage()
- {
- fprintf(stderr,"%s %s for %s by Chuck Forsberg\n",
- Progname, VERSION, OS);
- fprintf(stderr,"Usage: rz [-1abeuv] (ZMODEM Batch)\n");
- fprintf(stderr,"or rb [-1abuv] (YMODEM Batch)\n");
- fprintf(stderr,"or rx [-1abcv] file (XMODEM or XMODEM-1k)\n");
- fprintf(stderr," -1 For cu(1): Use fd 1 for input\n");
- fprintf(stderr," -a ASCII transfer (strip CR)\n");
- fprintf(stderr," -b Binary transfer for all files\n");
- fprintf(stderr," -c Use 16 bit CRC (XMODEM)\n");
- fprintf(stderr," -e Ignore control characters (ZMODEM)\n");
- fprintf(stderr," -v Verbose more v's give more info\n");
- exit(1);
- }
- /*
- * Debugging information output interface routine
- */
- /* VARARGS1 */
- vfile(f, a, b, c)
- register char *f;
- {
- if (Verbose > 2) {
- fprintf(stderr, f, a, b, c);
- fprintf(stderr, "\n");
- }
- }
-
- /*
- * Let's receive something already.
- */
-
- char *rbmsg =
- "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n";
-
- wcreceive(argc, argp)
- char **argp;
- {
- register c;
-
- if (Batch || argc==0) {
- Crcflg=(Wcsmask==0377);
- if ( !Quiet)
- fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
- if (c=tryz()) {
- if (c == ZCOMPL)
- return OK;
- if (c == ERROR)
- goto fubar;
- c = rzfiles();
- if (c)
- goto fubar;
- } else {
- for (;;) {
- if (wcrxpn(secbuf)== ERROR)
- goto fubar;
- if (secbuf[0]==0)
- return OK;
- if (procheader(secbuf) == ERROR)
- goto fubar;
- if (wcrx()==ERROR)
- goto fubar;
- }
- }
- } else {
- Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
-
- procheader(""); strcpy(Pathname, *argp); checkpath(Pathname);
- fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
- if ((fout=fopen(Pathname, "w")) == NULL)
- return ERROR;
- if (wcrx()==ERROR)
- goto fubar;
- }
- return OK;
- fubar:
- canit();
- if (Topipe && fout) {
- pclose(fout); return ERROR;
- }
- if (fout)
- fclose(fout);
- if (Restricted) {
- unlink(Pathname);
- fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
- }
- return ERROR;
- }
-
-
- /*
- * Fetch a pathname from the other end as a C ctyle ASCIZ string.
- * Length is indeterminate as long as less than Blklen
- * A null string represents no more files (YMODEM)
- */
- wcrxpn(rpn)
- char *rpn; /* receive a pathname */
- {
- register c;
-
- #ifdef NFGVMIN
- readline(1);
- #else
- purgeline();
- #endif
-
- et_tu:
- Firstsec=TRUE; Eofseen=FALSE;
- sendline(Crcflg?WANTCRC:NAK);
- Lleft=0; /* Do read next time ... */
- while ((c = wcgetsec(rpn, 100)) != 0) {
- if (c == WCEOT) {
- zperr( "Pathname fetch returned %d", c);
- sendline(ACK);
- Lleft=0; /* Do read next time ... */
- readline(1);
- goto et_tu;
- }
- return ERROR;
- }
- sendline(ACK);
- return OK;
- }
-
- /*
- * Adapted from CMODEM13.C, written by
- * Jack M. Wierda and Roderick W. Hart
- */
-
- wcrx()
- {
- register int sectnum, sectcurr;
- register char sendchar;
- register char *p;
- int cblklen; /* bytes to dump this block */
-
- Firstsec=TRUE;sectnum=0; Eofseen=FALSE;
- sendchar=Crcflg?WANTCRC:NAK;
-
- for (;;) {
- sendline(sendchar); /* send it now, we're ready! */
- Lleft=0; /* Do read next time ... */
- sectcurr=wcgetsec(secbuf, (sectnum&0177)?50:130);
- report(sectcurr);
- if (sectcurr==(sectnum+1 &Wcsmask)) {
- sectnum++;
- cblklen = Bytesleft>Blklen ? Blklen:Bytesleft;
- if (putsec(secbuf, cblklen)==ERROR)
- return ERROR;
- if ((Bytesleft-=cblklen) < 0)
- Bytesleft = 0;
- sendchar=ACK;
- }
- else if (sectcurr==(sectnum&Wcsmask)) {
- zperr( "Received dup Sector");
- sendchar=ACK;
- }
- else if (sectcurr==WCEOT) {
- if (closeit())
- return ERROR;
- sendline(ACK);
- Lleft=0; /* Do read next time ... */
- return OK;
- }
- else if (sectcurr==ERROR)
- return ERROR;
- else {
- zperr( "Sync Error");
- return ERROR;
- }
- }
- }
-
- /*
- * Wcgetsec fetches a Ward Christensen type sector.
- * Returns sector number encountered or ERROR if valid sector not received,
- * or CAN CAN received
- * or WCEOT if eot sector
- * time is timeout for first char, set to 4 seconds thereafter
- ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
- * (Caller must do that when he is good and ready to get next sector)
- */
-
- wcgetsec(rxbuf, maxtime)
- char *rxbuf;
- int maxtime;
- {
- register checksum, wcj, firstch;
- register unsigned short oldcrc;
- register char *p;
- int sectcurr;
-
- for (Lastrx=errors=0; errors<RETRYMAX; errors++) {
-
- if ((firstch=readline(maxtime))==STX) {
- Blklen=KSIZE; goto get2;
- }
- if (firstch==SOH) {
- Blklen=SECSIZ;
- get2:
- sectcurr=readline(1);
- if ((sectcurr+(oldcrc=readline(1)))==Wcsmask) {
- oldcrc=checksum=0;
- for (p=rxbuf,wcj=Blklen; --wcj>=0; ) {
- if ((firstch=readline(1)) < 0)
- goto bilge;
- oldcrc=updcrc(firstch, oldcrc);
- checksum += (*p++ = firstch);
- }
- if ((firstch=readline(1)) < 0)
- goto bilge;
- if (Crcflg) {
- oldcrc=updcrc(firstch, oldcrc);
- if ((firstch=readline(1)) < 0)
- goto bilge;
- oldcrc=updcrc(firstch, oldcrc);
- if (oldcrc & 0xFFFF)
- zperr( "CRC");
- else {
- Firstsec=FALSE;
- return sectcurr;
- }
- }
- else if (((checksum-firstch)&Wcsmask)==0) {
- Firstsec=FALSE;
- return sectcurr;
- }
- else
- zperr( "Checksum");
- }
- else
- zperr("Sector number garbled");
- }
- /* make sure eot really is eot and not just mixmash */
- #ifdef NFGVMIN
- else if (firstch==EOT && readline(1)==TIMEOUT)
- return WCEOT;
- #else
- else if (firstch==EOT && Lleft==0)
- return WCEOT;
- #endif
- else if (firstch==CAN) {
- if (Lastrx==CAN) {
- zperr( "Sender CANcelled");
- return ERROR;
- } else {
- Lastrx=CAN;
- continue;
- }
- }
- else if (firstch==TIMEOUT) {
- if (Firstsec)
- goto humbug;
- bilge:
- zperr( "TIMEOUT");
- }
- else
- zperr( "Got 0%o sector header", firstch);
-
- humbug:
- Lastrx=0;
- while(readline(1)!=TIMEOUT)
- ;
- if (Firstsec) {
- sendline(Crcflg?WANTCRC:NAK);
- Lleft=0; /* Do read next time ... */
- } else {
- maxtime=40; sendline(NAK);
- Lleft=0; /* Do read next time ... */
- }
- }
- /* try to stop the bubble machine. */
- canit();
- return ERROR;
- }
-
- /*
- * This version of readline is reasoably well suited for
- * reading many characters.
- * (except, currently, for the Regulus version!)
- *
- * timeout is in tenths of seconds
- */
- readline(timeout)
- int timeout;
- {
- register n;
- static char *cdq; /* pointer for removing chars from linbuf */
-
- if (--Lleft >= 0) {
- if (Verbose > 8) {
- fprintf(stderr, "%02x ", *cdq&0377);
- }
- return (*cdq++ & Wcsmask);
- }
- n = timeout/10;
- if (n < 2)
- n = 3;
- if (Verbose > 5)
- fprintf(stderr, "Calling read: alarm=%d Readnum=%d ",
- n, Readnum);
- if (setjmp(tohere)) {
- #ifdef TIOCFLUSH
- /* ioctl(iofd, TIOCFLUSH, 0); */
- #endif
- Lleft = 0;
- if (Verbose>1)
- fprintf(stderr, "Readline:TIMEOUT\n");
- return TIMEOUT;
- }
- signal(SIGALRM, alrm); alarm(n);
- Lleft=read(iofd, cdq=linbuf, Readnum);
- alarm(0);
- if (Verbose > 5) {
- fprintf(stderr, "Read returned %d bytes\n", Lleft);
- }
- if (Lleft < 1)
- return TIMEOUT;
- --Lleft;
- if (Verbose > 8) {
- fprintf(stderr, "%02x ", *cdq&0377);
- }
- return (*cdq++ & Wcsmask);
- }
-
-
-
- /*
- * Purge the modem input queue of all characters
- */
- purgeline()
- {
- Lleft = 0;
- #ifdef USG
- ioctl(iofd, TCFLSH, 0);
- #else
- lseek(iofd, 0L, 2);
- #endif
- }
-
-
- /*
- * Process incoming file information header
- */
- procheader(name)
- char *name;
- {
- register char *openmode, *p, **pp;
-
- /* set default parameters and overrides */
- openmode = "w";
- Thisbinary = (!Rxascii) || Rxbinary;
- if (Lzmanag)
- zmanag = Lzmanag;
-
- /*
- * Process ZMODEM remote file management requests
- */
- if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
- Thisbinary = 0;
- if (zconv == ZCBIN) /* Remote Binary override */
- Thisbinary = TRUE;
- else if (zmanag == ZMAPND)
- openmode = "a";
-
- #ifndef BIX
- /* ZMPROT check for existing file */
- if (zmanag == ZMPROT && (fout=fopen(name, "r"))) {
- fclose(fout); return ERROR;
- }
- #endif
-
- Bytesleft = DEFBYTL; Filemode = 0; Modtime = 0L;
-
- p = name + 1 + strlen(name);
- if (*p) { /* file coming from Unix or DOS system */
- sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
- if (Filemode & UNIXFILE)
- ++Thisbinary;
- if (Verbose) {
- fprintf(stderr, "Incoming: %s %ld %lo %o\n",
- name, Bytesleft, Modtime, Filemode);
- }
- }
-
- #ifdef BIX
- if ((fout=fopen("scratchpad", openmode)) == NULL)
- return ERROR;
- return OK;
- #else
-
- else { /* File coming from CP/M system */
- for (p=name; *p; ++p) /* change / to _ */
- if ( *p == '/')
- *p = '_';
-
- if ( *--p == '.') /* zap trailing period */
- *p = 0;
- }
-
- if (!Zmodem && MakeLCPathname && !IsAnyLower(name))
- uncaps(name);
- if (Topipe) {
- sprintf(Pathname, "%s %s", Progname+2, name);
- if (Verbose)
- fprintf(stderr, "Topipe: %s %s\n",
- Pathname, Thisbinary?"BIN":"ASCII");
- if ((fout=popen(Pathname, "w")) == NULL)
- return ERROR;
- } else {
- strcpy(Pathname, name);
- if (Verbose) {
- fprintf(stderr, "Receiving %s %s %s\n",
- name, Thisbinary?"BIN":"ASCII", openmode);
- }
- checkpath(name);
- if (Nflag)
- name = "/dev/null";
- if ((fout=fopen(name, openmode)) == NULL)
- return ERROR;
- }
- return OK;
- #endif /* BIX */
- }
-
- /*
- * 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.
- */
- putsec(buf, n)
- char *buf;
- register n;
- {
- register char *p;
-
- 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 == CPMEOF) {
- Eofseen=TRUE; return OK;
- }
- putc(*p ,fout);
- }
- }
- return OK;
- }
-
- /*
- * Send a character to modem. Small is beautiful.
- */
- sendline(c)
- {
- char d;
-
- d = c;
- if (Verbose>6)
- fprintf(stderr, "Sendline: %x\n", c);
- write(1, &d, 1);
- }
-
- xsendline(c)
- {
- sendline(c);
- }
-
- flushmo() {}
-
-
-
-
- /* make string s lower case */
- uncaps(s)
- register char *s;
- {
- for ( ; *s; ++s)
- if (isupper(*s))
- *s = tolower(*s);
- }
- /*
- * IsAnyLower returns TRUE if string s has lower case letters.
- */
- IsAnyLower(s)
- register char *s;
- {
- for ( ; *s; ++s)
- if (islower(*s))
- return TRUE;
- return FALSE;
- }
-
- /*
- * 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;
- }
-
- /*
- * 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");
- }
-
- /* 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);
- Lleft=0; /* Do read next time ... */
- fflush(stdout);
- }
-
-
- /*
- * 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);
- }
-
- report(sct)
- int sct;
- {
- if (Verbose>1)
- fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
- }
-
- /*
- * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
- * If called as [-][dir/../]rzCOMMAND set the pipe flag
- * If called as rb 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]=='r' && s[1]=='b')
- Nozmodem = TRUE;
- if (s[2] && s[0]=='r' && s[1]=='b')
- Topipe=TRUE;
- if (s[2] && s[0]=='r' && s[1]=='z')
- Topipe=TRUE;
- }
-
- /*
- * Totalitarian Communist pathname processing
- */
- checkpath(name)
- char *name;
- {
- if (Restricted) {
- if (fopen(name, "r") != NULL) {
- canit();
- fprintf(stderr, "\r\nrz: %s exists\n", name);
- bibi(-1);
- }
- /* restrict pathnames to current tree or uucppublic */
- if ( substr(name, "../")
- || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
- canit();
- fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
- bibi(-1);
- }
- }
- }
-
- /*
- * 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
- */
- tryz()
- {
- register c, n;
- register cmdzack1flg;
-
- if (Nozmodem) /* Check for "rb" program name */
- return 0;
-
-
- for (n=Zmodem?15:5; --n>=0; ) {
- /* Set buffer length (0) and capability flags */
- stohdr(0L);
- #ifdef CANBREAK
- Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
- #else
- Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
- #endif
- if (Zctlesc)
- Txhdr[ZF0] |= TESCCTL;
- zshhdr(tryzhdrtype, Txhdr);
- if (tryzhdrtype == ZSKIP) /* Don't skip too far */
- tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
- again:
- switch (zgethdr(Rxhdr, 0)) {
- case ZRQINIT:
- continue;
- case ZEOF:
- continue;
- case TIMEOUT:
- continue;
- case ZFILE:
- zconv = Rxhdr[ZF0];
- zmanag = Rxhdr[ZF1];
- ztrans = Rxhdr[ZF2];
- tryzhdrtype = ZRINIT;
- c = zrdata(secbuf, KSIZE);
- mode(3);
- if (c == GOTCRCW)
- return ZFILE;
- zshhdr(ZNAK, Txhdr);
- goto again;
- case ZSINIT:
- Zctlesc = TESCCTL & Rxhdr[ZF0];
- if (zrdata(Attn, ZATTNLEN) == GOTCRCW) {
- zshhdr(ZACK, Txhdr);
- goto again;
- }
- zshhdr(ZNAK, Txhdr);
- goto again;
- case ZFREECNT:
- stohdr(getfree());
- zshhdr(ZACK, Txhdr);
- goto again;
- case ZCOMMAND:
- cmdzack1flg = Rxhdr[ZF0];
- if (zrdata(secbuf, KSIZE) == GOTCRCW) {
- if (cmdzack1flg & ZCACK1)
- stohdr(0L);
- else
- stohdr((long)sys2(secbuf));
- purgeline(); /* dump impatient questions */
- do {
- zshhdr(ZCOMPL, Txhdr);
- }
- while (++errors<20 && zgethdr(Rxhdr,1) != ZFIN);
- ackbibi();
- if (cmdzack1flg & ZCACK1)
- exec2(secbuf);
- return ZCOMPL;
- }
- zshhdr(ZNAK, Txhdr); goto again;
- case ZCOMPL:
- goto again;
- default:
- continue;
- case ZFIN:
- ackbibi(); return ZCOMPL;
- case ZCAN:
- return ERROR;
- }
- }
- return 0;
- }
-
- /*
- * Receive 1 or more files with ZMODEM protocol
- */
- rzfiles()
- {
- register c;
-
- for (;;) {
- switch (c = rzfile()) {
- case ZEOF:
- case ZSKIP:
- switch (tryz()) {
- case ZCOMPL:
- return OK;
- default:
- return ERROR;
- case ZFILE:
- break;
- }
- continue;
- default:
- return c;
- case ERROR:
- return ERROR;
- }
- }
- }
-
- /*
- * Receive a file with ZMODEM protocol
- * Assumes file name frame is in secbuf
- */
- rzfile()
- {
- register c, n;
- long rxbytes;
-
- Eofseen=FALSE;
- if (procheader(secbuf) == ERROR) {
- return (tryzhdrtype = ZSKIP);
- }
-
- n = 20; rxbytes = 0l;
-
- for (;;) {
- stohdr(rxbytes);
- zshhdr(ZRPOS, Txhdr);
- nxthdr:
- switch (c = zgethdr(Rxhdr, 0)) {
- default:
- vfile("rzfile: zgethdr returned %d", c);
- return ERROR;
- case ZNAK:
- case TIMEOUT:
- if ( --n < 0) {
- vfile("rzfile: zgethdr returned %d", c);
- return ERROR;
- }
- case ZFILE:
- zrdata(secbuf, KSIZE);
- 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()) {
- tryzhdrtype = ZFERR;
- vfile("rzfile: closeit returned <> 0");
- return ERROR;
- }
- vfile("rzfile: normal EOF");
- return c;
- case ERROR: /* Too much garbage in header search error */
- if ( --n < 0) {
- vfile("rzfile: zgethdr returned %d", c);
- return ERROR;
- }
- zmputs(Attn);
- continue;
- case ZDATA:
- if (rclhdr(Rxhdr) != rxbytes) {
- if ( --n < 0) {
- return ERROR;
- }
- zmputs(Attn); continue;
- }
- moredata:
- if (Verbose>1)
- fprintf(stderr, "\r%7ld ZMODEM%s ",
- rxbytes, Crc32?" CRC-32":"");
- switch (c = zrdata(secbuf, KSIZE)) {
- case ZCAN:
- vfile("rzfile: zgethdr returned %d", c);
- return ERROR;
- case ERROR: /* CRC error */
- if ( --n < 0) {
- vfile("rzfile: zgethdr returned %d", c);
- return ERROR;
- }
- zmputs(Attn);
- continue;
- case TIMEOUT:
- if ( --n < 0) {
- vfile("rzfile: zgethdr returned %d", c);
- return ERROR;
- }
- continue;
- case GOTCRCW:
- n = 20;
- putsec(secbuf, Rxcount);
- rxbytes += Rxcount;
- stohdr(rxbytes);
- zshhdr(ZACK, Txhdr);
- sendline(XON);
- goto nxthdr;
- case GOTCRCQ:
- n = 20;
- putsec(secbuf, Rxcount);
- rxbytes += Rxcount;
- stohdr(rxbytes);
- zshhdr(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)
- */
- zmputs(s)
- char *s;
- {
- register c;
-
- while (*s) {
- switch (c = *s++) {
- case '\336':
- sleep(1); continue;
- case '\335':
- sendbrk(); continue;
- default:
- sendline(c);
- }
- }
- }
-
- /*
- * Close the receive dataset, return OK or ERROR
- */
- closeit()
- {
- if (Topipe) {
- if (pclose(fout)) {
- return ERROR;
- }
- return OK;
- }
- if (fclose(fout)==ERROR) {
- fprintf(stderr, "file close ERROR\n");
- return ERROR;
- }
- if (Modtime) {
- timep[0] = time(NULL);
- timep[1] = Modtime;
- utime(Pathname, timep);
- }
- if (Filemode)
- chmod(Pathname, (07777 & Filemode));
- return OK;
- }
-
- /*
- * Ack a ZFIN packet, let byegones be byegones
- */
- ackbibi()
- {
- register n;
-
- vfile("ackbibi:");
- Readnum = 1;
- stohdr(0L);
- for (n=3; --n>=0; ) {
- purgeline();
- zshhdr(ZFIN, Txhdr);
- switch (readline(100)) {
- case 'O':
- readline(1); /* Discard 2nd 'O' */
- vfile("ackbibi complete");
- return;
- case RCDO:
- return;
- case TIMEOUT:
- default:
- break;
- }
- }
- }
-
-
-
- /*
- * Local console output simulation
- */
- bttyout(c)
- {
- if (Verbose || fromcu())
- putc(c, stderr);
- }
-
- /*
- * Strip leading ! if present, do shell escape.
- */
- sys2(s)
- register char *s;
- {
- if (*s == '!')
- ++s;
- return system(s);
- }
- /*
- * Strip leading ! if present, do exec.
- */
- exec2(s)
- register char *s;
- {
- if (*s == '!')
- ++s;
- mode(0);
- execl("/bin/sh", "sh", "-c", s);
- }
- /* End of rz.c */
- \Rogue\Monster\
- else
- echo "will not over write ./rz.c"
- fi
- if [ `wc -c ./rz.c | awk '{printf $1}'` -ne 25038 ]
- then
- echo `wc -c ./rz.c | awk '{print "Got " $1 ", Expected " 25038}'`
- fi
- echo "Finished archive 2 of 3"
- exit
-
-