wht@tridom.uucp (Warren Tucker) (10/10/89)
---- Cut Here and unpack ---- #!/bin/sh # this is part 25 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file z/ecurz.c continued # CurArch=25 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file z/ecurz.c" sed 's/^X//' << 'SHAR_EOF' >> z/ecurz.c X{ X} /* end of flushline */ X X/*+------------------------------------------------------------------------- X purgeline() - purge the modem input queue of all characters X--------------------------------------------------------------------------*/ Xpurgeline() X{ X Lleft = 0; X#if defined(M_XENIX) X ioctl(iofd,TCFLSH,0); X#else X lseek(iofd,0L,2); X#endif X} /* end of purgeline */ X X/*+------------------------------------------------------------------------- X wcreceive(argc,argp) X--------------------------------------------------------------------------*/ Xwcreceive(argc,argp) Xint argc; Xchar **argp; X{ Xregister c; X X if(Batch || argc==0) X { X Crcflg=1; X c=tryz(); X if(Zmodem) X { X report_protocol_type("ZMODEM"); X report_protocol_crc_type((Crc32) ? "/CRC32" : "/CRC16"); X } X if(c) X { X if(c == ZCOMPL) X return(OK); X if(c == ERROR) X goto fubar; X c = rzfiles(); X if(c) X goto fubar; X } else X { X report_protocol_type("YMODEM"); X report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK"); X for(;;) X { X if(wcrxpn(secbuf)== ERROR) X goto fubar; X if(secbuf[0]==0) X return(OK); X if(procheader(secbuf) == ERROR) X goto fubar; X report_str("Receiving data",0); X if(wcrx()==ERROR) X goto fubar; X } X } X } X else X { X report_protocol_type("XMODEM"); X report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK"); X Bytesleft = DEFBYTL; X Filemode = 0; X Modtime = 0L; X procheader(""); X strcpy(Pathname,*argp); X if((fout=fopen(Pathname,"w")) == NULL) X return(ERROR); X report_file_rcv_started( Pathname,0L,Modtime,Filemode); X this_file_length = 0; X report_rxpos(0L); X report_str("Receiving data",0); X if(wcrx()==ERROR) X goto fubar; X } X return(OK); Xfubar: X send_cancel(); X if(fout) X { X fflush(fout); X fstat(fileno(fout),&fout_stat); X report_file_byte_io((long)fout_stat.st_size); X report_file_close(); X fclose(fout); X } X return(ERROR); X} /* end of wcreceive */ X X/*+------------------------------------------------------------------------- X wcgetsec(rxbuf,maxtime) X X Wcgetsec fetches a Ward Christensen type sector. Returns sector X number encountered or ERROR if valid sector not received, or CAN CAN X received or WCEOT if eot sector time is timeout for first char,set to X 4 seconds thereafter. NO ACK IS SENT IF SECTOR IS RECEIVED OK. Caller X must do that when he is good and ready to get next sector. X--------------------------------------------------------------------------*/ Xunsigned int Xwcgetsec(rxbuf,maxtime) Xchar *rxbuf; Xint maxtime; X{ Xregister unsigned int firstch; Xregister unsigned short oldcrc; Xregister unsigned char checksum; Xregister wcj; Xregister char *p; Xint sectcurr; X X for(Lastrx=errors=0; errors<RETRYMAX; errors++) X { X X firstch=readline(maxtime); X if((firstch == STX) || (firstch == SOH)) X { X oldBlklen = Blklen; X if(firstch == STX) X Blklen=1024; X else X Blklen=128; X if(oldBlklen != Blklen) X report_rxblklen(Blklen); X X sectcurr=readline(1); X if((sectcurr + (oldcrc=readline(1))) == 0xFF) X { X oldcrc=checksum=0; X for(p=rxbuf,wcj=Blklen; --wcj>=0; ) X { X if((firstch=readline(1)) < 0) X goto bilge; X oldcrc=updcrc(firstch,oldcrc); X checksum += (*p++ = firstch); X } X if((firstch=readline(1)) < 0) X goto bilge; X if(Crcflg) X { X oldcrc=updcrc(firstch,oldcrc); X if((firstch=readline(1)) < 0) X goto bilge; X oldcrc=updcrc(firstch,oldcrc); X if(oldcrc) X { X sprintf(s128,"CRC error = 0x%04x",oldcrc); X report_str(s128,1); X } X else X { X Firstsec=0; X return(sectcurr); X } X } X else if((checksum-firstch)==0) X { X Firstsec=0; X return(sectcurr); X } X else X report_str("checksum error",1); X } X else X { X report_last_txhdr("Noise",0); X sprintf(s128,"Sector garbled 0x%x 0x%x",sectcurr,oldcrc); X report_str(s128,1); X } X } X /* make sure eot really is eot and not just mixmash */ X#if defined(NFGVMIN) X else if(firstch==EOT && readline(1)==TIMEOUT) X return(WCEOT); X#else X else if(firstch==EOT && Lleft==0) X return(WCEOT); X#endif X else if(firstch==EOT) X { X report_str("Noisy EOT",2); X } X else if(firstch==CAN) X { X if(Lastrx==CAN) X { X report_str("Sender CANcelled",1); X report_last_rxhdr("CAN",1); X return(ERROR); X } else X { X Lastrx=CAN; X continue; X } X } X else if(firstch==TIMEOUT) X { X if(Firstsec) X goto humbug; Xbilge: X report_str("Timeout",1); X } X else X { X sprintf(s128,"Got 0x%02x sector header",firstch); X report_str(s128,1); X } X Xhumbug: X Lastrx=0; X while(readline(1)!=TIMEOUT) X ; X if(Firstsec) X { X sendline(Crcflg?WANTCRC:NAK); X report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0); X Lleft=0; /* Do read next time ... */ X } else X { X maxtime=40; X sendline(NAK); X report_last_txhdr("NAK",1); X Lleft=0; /* Do read next time ... */ X } X } X /* try to stop the bubble machine. */ X send_cancel(); X return(ERROR); X} /* end of wcgetsec */ X X/*+------------------------------------------------------------------------- X wcrxpn(rpn) X X Fetch a pathname from the other end. Length is indeterminate as long X as less than Blklen. During YMODEM xfers, a null string represents no X more files. X--------------------------------------------------------------------------*/ Xwcrxpn(rpn) Xchar *rpn; /* receive a pathname */ X{ Xregister c; X X#if defined(NFGVMIN) X readline(1); X#else X purgeline(); X#endif X Xet_tu: X Firstsec=1; X Eofseen=0; X sendline(Crcflg?WANTCRC:NAK); X report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0); X Lleft=0; /* Do read next time ... */ X while((c = wcgetsec(rpn,100)) != 0) X { X if(c == WCEOT) X { X sprintf(s128,"Pathname fetch returned %d",c); X report_str(s128,1); X sendline(ACK); X report_last_txhdr("ACK",0); X Lleft=0; /* Do read next time ... */ X readline(1); X goto et_tu; X } X return(ERROR); X } X sendline(ACK); X report_last_txhdr("ACK",0); X return(OK); X} /* end of wcrxpn */ X X/*+------------------------------------------------------------------------- X write_sec_to_disk(buf,n) X X Putsec writes the n characters of buf to receive file fout. If not in X binary mode, carriage returns, and all characters starting with CPMEOF X are discarded. X--------------------------------------------------------------------------*/ Xwrite_sec_to_disk(buf,n) Xchar *buf; Xregister n; X{ Xregister char *p; X X if(n == 0) X return(OK); X if(Thisbinary) X { X for(p=buf; --n>=0; ) X putc( *p++,fout); X } X else X { X if(Eofseen) X return(OK); X for(p=buf; --n>=0; ++p ) X { X if( *p == '\r') X continue; X if(*p == CPMEOF) X { X Eofseen=1; X fflush(fout); X fstat(fileno(fout),&fout_stat); X report_rxpos(fout_stat.st_size); X return(OK); X } X putc(*p ,fout); X } X } X fflush(fout); X fstat(fileno(fout),&fout_stat); X report_rxpos(fout_stat.st_size); X if(this_file_length != 0) X { X sprintf(s128,"Receiving data (%u%% complete)", X (unsigned int)( X ((unsigned long)fout_stat.st_size * (unsigned long)100) X / this_file_length)); X report_str(s128,0); X } X return(OK); X} /* end of write_sec_to_disk */ X X/*+------------------------------------------------------------------------- X wcrx() - receive an X/YMODEM sector X X Adapted from CMODEM13.C,written by Jack M. Wierda and Roderick W. Hart X--------------------------------------------------------------------------*/ Xint Xwcrx() X{ Xregister unsigned int sectnum,sectcurr; Xregister unsigned char sendchar; Xregister unsigned char *p; Xint cblklen; /* bytes to dump this block */ X X Firstsec=1; X sectnum=0; X Eofseen=0; X sendchar=Crcflg ? WANTCRC : NAK; X report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0); X X for(;;) X { X sendline(sendchar); /* send it now,we're ready! */ X if(sendchar == ACK) X report_last_txhdr("ACK",0); X Lleft=0; /* Do read next time ... */ X sectcurr=wcgetsec(secbuf,(sectnum&0177)?50:130); X sprintf(s128,"Block %d received",sectnum); X report_last_rxhdr(s128,0); X fstat(fileno(fout),&fout_stat); X report_rxpos(fout_stat.st_size); X if(sectcurr == (sectnum+1 & 0xFF)) X { X sectnum++; X cblklen = Bytesleft>Blklen ? Blklen : Bytesleft; X if(write_sec_to_disk(secbuf,cblklen) == ERROR) X return(ERROR); X if((Bytesleft-=cblklen) < 0) X Bytesleft = 0; X sendchar=ACK; X } X else if(sectcurr == sectnum) X { X report_str("Received duplicate Sector",-1); X sendchar = ACK; X } X else if(sectcurr == WCEOT) X { X if(close_and_report()) X return(ERROR); X sendline(ACK); X report_last_txhdr("ACK",0); X Lleft=0; /* Do read next time ... */ X return(OK); X } X else if(sectcurr==ERROR) X return(ERROR); X else X { X report_str( "Sync Error",1); X return(ERROR); X } X } X} /* end of wcrx */ X X/*+------------------------------------------------------------------------- X readline(timeout) X X read one or more characters timeout is in tenths of seconds X--------------------------------------------------------------------------*/ Xreadline(timeout) Xint timeout; X{ Xregister n; Xstatic unsigned char *cdq; /* pointer for removing chars from linbuf */ X X#ifndef bad_problem X if(--Lleft >= 0) X return(*cdq++); X X n = timeout/10; X if(n < 2) X n = 3; X if(setjmp(tohere)) X { X Lleft = 0; X return(TIMEOUT); X } X signal(SIGALRM,SIGALRM_handler); X alarm(n); X Lleft = read(iofd,cdq = linbuf,Readnum); X alarm(0); X rx_char_count += Lleft; X X if(Lleft < 1) X return(TIMEOUT); X X --Lleft; X return(*cdq++); X#else Xint rtnv; X X if(--Lleft >= 0) X { X rtnv = *cdq++; X goto LOG_AND_RETURN; X } X X n = timeout/10; X if(n < 2) X n = 3; X if(setjmp(tohere)) X { X Lleft = 0; X rtnv = *cdq++; X goto LOG_AND_RETURN; X } X signal(SIGALRM,SIGALRM_handler); X alarm(n); X Lleft = read(iofd,cdq = linbuf,Readnum); X alarm(0); X rx_char_count += Lleft; X X if(Lleft < 1) X { X rtnv = TIMEOUT; X goto LOG_AND_RETURN; X } X --Lleft; X rtnv = *cdq++; X XLOG_AND_RETURN: X if(log_packets) X { X sprintf(s128,"rl: l=%3d ch=%x\n",Lleft,rtnv); X write(log_packets,s128,strlen(s128)); X } X return(rtnv); X X#endif X X} /* end of readline */ X X/*+------------------------------------------------------------------------- X mkdir(dpath,dmode) X Directory-creating routines from Public Domain TAR by John Gilmore X Make a directory. Compatible with the mkdir() system call on 4.2BSD. X--------------------------------------------------------------------------*/ X#if defined(MD) X#if (MD != 2) X#define TERM_SIGNAL(status) ((status) & 0x7F) X#define TERM_COREDUMP(status) (((status) & 0x80) != 0) X#define TERM_VALUE(status) ((status) >> 8) Xmkdir(dpath,dmode) Xchar *dpath; Xint dmode; X{ X int cpid,status; X struct stat statbuf; X X if(stat(dpath,&statbuf) == 0) X { X errno = EEXIST; /* Stat worked,so it already exists */ X return(-1); X } X X /* If stat fails for a reason other than non-existence,return error */ X if(errno != ENOENT) X return(-1); X X switch(cpid = fork()) X { X X case -1: /* Error in fork() */ X return(-1); /* Errno is set already */ X X case 0: /* Child process */ X /* X * Cheap hack to set mode of new directory. Since this X * child process is going away anyway,we zap its umask. X * FIXME,this won't suffice to set SUID,SGID,etc. on this X * directory. Does anybody care? X */ X status = umask(0); /* Get current umask */ X status = umask(status | (0777 & ~dmode)); /* Set for mkdir */ X execl("/bin/mkdir","mkdir",dpath,(char *)0); X _exit(-1); /* Can't exec /bin/mkdir */ X X default: /* Parent process */ X while(cpid != wait(&status)) ; /* Wait for kid to finish */ X } X X if(TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) X { X errno = EIO; /* We don't know why,but */ X return(-1); /* /bin/mkdir failed */ X } X X return(0); X} /* end of mkdir */ X#endif /* MD != 2 */ X#endif /* if defined(MD) */ X X/*+------------------------------------------------------------------------- X make_dirs(pathname) X X Directory-creating routines from Public Domain TAR by John Gilmore X After a file/link/symlink/dir creation has failed, see if it's because X some required directory was not present, and if so, create all X required dirs. X--------------------------------------------------------------------------*/ X#if defined(MD) Xmake_dirs(pathname) Xregister char *pathname; X{ X register char *p; /* Points into path */ X int madeone = 0; /* Did we do anything yet? */ X int save_errno = errno; /* Remember caller's errno */ X X if(errno != ENOENT) X return(0); /* Not our problem */ X X for(p = strchr(pathname,'/'); p != NULL; p = strchr(p+1,'/')) X { X /* Avoid mkdir of empty string,if leading or double '/' */ X if(p == pathname || p[-1] == '/') X continue; X /* Avoid mkdir where last part of path is '.' */ X if(p[-1] == '.' && (p == pathname+1 || p[-2] == '/')) X continue; X *p = 0; /* Truncate the path there */ X if( !mkdir(pathname,0777)) X { /* Try to create it as a dir */ X sprintf(s128,"Made directory %s",pathname); X report_str(s128,-1); X madeone++; /* Remember if we made one */ X *p = '/'; X continue; X } X *p = '/'; X if(errno == EEXIST) /* Directory already exists */ X continue; X /* X * Some other error in the mkdir. We return to the caller. X */ X break; X } X errno = save_errno; /* Restore caller's errno */ X return(madeone); /* Tell them to retry if we made one */ X} /* end of make_dirs */ X#endif /* MD */ X X/*+------------------------------------------------------------------------- X uncaps(str) - make string str lower case X--------------------------------------------------------------------------*/ Xvoid Xuncaps(str) Xregister char *str; X{ Xregister int itmp; X X while(itmp = *str) X { X if(isupper(itmp)) X *str = tolower(itmp); X str++; X } X} /* end of uncaps */ X X/*+------------------------------------------------------------------------- X isanylc(str) - returns 1 if string str has any lower case letters X--------------------------------------------------------------------------*/ Xint Xisanylc(str) Xregister char *str; X{ X while(*str) X { X if(islower(*str)) X return(1); X str++; X } X return(0); X} /* end of isanylc */ X X/*+------------------------------------------------------------------------- X procheader(name) - process incoming file information header X--------------------------------------------------------------------------*/ Xint Xprocheader(name) Xchar *name; X{ Xregister char *openmode,*p,**pp; X X /* set default parameters and overrides */ X openmode = "w"; X Thisbinary = (!Rxascii) || Rxbinary; X if(Lzmanag) X zmanag = Lzmanag; X X /* X * Process ZMODEM remote file management requests X */ X if(!Rxbinary && zconv == ZCNL) /* Remote ASCII override */ X Thisbinary = 0; X if(zconv == ZCBIN) /* Remote Binary override */ X Thisbinary = 1; X else if(zmanag == ZMAPND) X openmode = "a"; X X report_xfer_mode(Thisbinary ? "BINARY" : "ASCII"); X this_file_errors = 0; X X Bytesleft = DEFBYTL; X Filemode = 0; X Modtime = 0L; X this_file_length = 0; X X if(strlen(name)) X p = name + 1 + strlen(name); X else X p = name; X if(*p) X { /* file coming from Unix or DOS system */ X int sscanf_count; X int SerialNumber; X int Filesleft; X long TotalLeft; X X sscanf_count = sscanf(p,"%ld%lo%o%d&d&ld", X &Bytesleft,&Modtime,&Filemode,&SerialNumber, X &Filesleft,&TotalLeft); X X switch(sscanf_count) X { X case 6: /* TotalLeft */ X if(!TotalToReceive) X TotalToReceive = TotalLeft; X case 5: /* Filesleft */ X if(!npats) X npats = Filesleft; X default: X break; X } X X if((zmanag & ZMMASK) == ZMNEW) X { X if(stat(name,&fout_stat) == 0) /* if file accessable ... */ X { X if(Modtime <= fout_stat.st_mtime) /* ... and not older */ X { X sprintf(s128,"RECEIVE skipped: %s (same or later date)", X name); X report_str(s128 + 8,-1); X#ifdef LOG_XFER X ecu_log_event(s128); X#endif X return(ERROR); X } X } X } X /* Check for existing file */ X else if(!Rxclob && ((zmanag & ZMMASK) != ZMCLOB) && X (fout=fopen(name,"r"))) X { X fclose(fout); X sprintf(s128,"RECEIVE skipped: %s (already exists)",name); X report_str(s128 + 8,-1); X#ifdef LOG_XFER X ecu_log_event(s128); X#endif X return(ERROR); X } X X if(Filemode & UNIXFILE) X ++Thisbinary; X ++Filcnt; X if(Bytesleft != DEFBYTL) X report_file_rcv_started( name,Bytesleft,Modtime,Filemode); X report_rxpos(0L); X report_str("",0); /* get rid of End of File */ X if(Bytesleft != DEFBYTL) X { X long min_100; X this_file_length = Bytesleft; X min_100 = 2L + (((Bytesleft * 11L)) * 10L) / (Baudrate * 6L); X sprintf(s128,"Receive time this file ~= %2lu:%02lu", X min_100 / 100,((min_100 % 100) * 60L) / 100L); X if(TotalToReceive) X { X min_100 = 2L + X (((TotalToReceive * 11L)) * 10L) / (Baudrate * 6L); X if(Baudrate > 4800) X { X min_100 *= 13; X min_100 /= 9; /* yech ... empirical */ X } X sprintf(&s128[strlen(s128)],", transaction ~= %2lu:%02lu", X min_100 / 100,((min_100 % 100) * 60L) / 100L); X } X report_transaction(s128); X sprintf(s128,"Receiving data (%d%% complete)",(int)0); X report_str(s128,0); X } X } X else X { /* File coming from CP/M system */ X for(p=name; *p; ++p) /* change / to _ */ X { X if( *p == '/') X *p = '_'; X } X X if( *--p == '.') /* zap trailing period */ X *p = 0; X } X X if(!Zmodem && MakeLCPathname && !isanylc(name) && !(Filemode&UNIXFILE)) X uncaps(name); X X strcpy(Pathname,name); X report_xfer_mode(Thisbinary?"BINARY":"ASCII"); X fout = fopen(name,openmode); X#if defined(MD) X if( !fout) X if(make_dirs(name)) X fout = fopen(name,openmode); X#endif X if( !fout) X return(ERROR); X this_file_errors = 0; X return(OK); X} /* end of procheader */ X X/*+------------------------------------------------------------------------- X send_cancel() - send cancel string X--------------------------------------------------------------------------*/ Xsend_cancel() X{ Xstatic char canistr[] = X{ X 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 X}; Xregister char *cptr = canistr; X X report_str("",0); X report_last_txhdr("^X CAN",1); X while(*cptr) X sendline(*cptr++); X Lleft=0; X} /* end of send_cancel */ X X/*+------------------------------------------------------------------------- X tryz() X X Initialize for Zmodem receive attempt, try to activate Zmodem sender X Handles ZSINIT frame X Return ZFILE if Zmodem filename received,-1 on error, X ZCOMPL if transaction finished, else 0 X--------------------------------------------------------------------------*/ Xint Xtryz() X{ Xregister c,n; X X if(Nozmodem) /* Check for "rb" program name */ X return(0); X X for(n=Zmodem?15:5; --n>=0; ) X { X /* Set buffer length (0) and capability flags */ X stohdr(0L); X#if defined(CANBREAK) X Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK; X#else X Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO; X#endif X if(Zctlesc) X Txhdr[ZF0] |= TESCCTL; X zshhdr(tryzhdrtype,Txhdr); X if(tryzhdrtype == ZSKIP) /* Don't skip too far */ X tryzhdrtype = ZRINIT; /* CAF 8-21-87 */ Xagain: X switch(zgethdr(Rxhdr,0)) X { X case ZRQINIT: X continue; X case ZEOF: X continue; X case TIMEOUT: X continue; X case ZFILE: X zconv = Rxhdr[ZF0]; X zmanag = Rxhdr[ZF1]; X ztrans = Rxhdr[ZF2]; X X strcpy(s128,"Transfer: "); X switch(zmanag & ZMMASK) X { X case 0: X strcat(s128,"if destination nonexistent"); X break; X case ZMAPND: /* Append contents to existing file (if any) */ X strcat(s128,"append to destination"); X break; X case ZMCLOB: /* Replace existing file */ X strcat(s128,"absolute (overwrite)"); X break; X case ZMNEW: X strcat(s128,"if source newer"); X break; X default: X sprintf(s128 + strlen(s128), X "absolute (%02x)",zmanag & ZMMASK); X break; X } X report_str(s128,2); X X tryzhdrtype = ZRINIT; X c = zrdata(secbuf,1024); X mode(3); X if(c == GOTCRCW) X return(ZFILE); X zshhdr(ZNAK,Txhdr); X goto again; X case ZSINIT: X Zctlesc = TESCCTL & Rxhdr[ZF0]; X if(zrdata(Attn,ZATTNLEN) == GOTCRCW) X { X stohdr(1L); X zshhdr(ZACK,Txhdr); X goto again; X } X zshhdr(ZNAK,Txhdr); X goto again; X case ZFREECNT: X stohdr(getfree()); X zshhdr(ZACK,Txhdr); X goto again; X case ZCOMMAND: X if(zrdata(secbuf,1024) == GOTCRCW) X { X stohdr(-1L); X purgeline(); /* dump impatient questions */ X while(errors < 20) X { X zshhdr(ZCOMPL,Txhdr); X if(zgethdr(Rxhdr,1) == ZFIN) X break; X } X send_ZFIN_and_exit(); X return(ZCOMPL); X } X zshhdr(ZNAK,Txhdr); X goto again; X case ZCOMPL: X goto again; X default: X continue; X case ZFIN: X send_ZFIN_and_exit(); X return(ZCOMPL); X case ZCAN: X return(ERROR); X } X } X return(0); X} /* end of tryz */ X X/*+------------------------------------------------------------------------- X rzfile() - receive a file with ZMODEM protocol X X assumes file name frame is in secbuf X--------------------------------------------------------------------------*/ Xrzfile() X{ Xregister c,n; Xlong rxbytes; X X Eofseen=0; X if(procheader(secbuf) == ERROR) X { X return(tryzhdrtype = ZSKIP); X } X X n = 20; X rxbytes = 0l; X X for(;;) X { X stohdr(rxbytes); X zshhdr(ZRPOS,Txhdr); X if(rxbytes) X report_str("Sending ZRPOS",1); Xnxthdr: X switch(c = zgethdr(Rxhdr,0)) X { X default: X sprintf(s128,"zgethdr returned %02x",c); X report_str(s128,1); X return(ERROR); X case ZNAK: X case TIMEOUT: X if( --n < 0) X { X sprintf(s128,"zgethdr returned %02x",c); X report_str(s128,1); X return(ERROR); X } X case ZFILE: X zrdata(secbuf,1024); X continue; X case ZEOF: X if(rclhdr(Rxhdr) != rxbytes) X { X /* X * Ignore eof if it's at wrong place - force X * a timeout because the eof might have gone X * out before we sent our zrpos. X */ X errors = 0; X goto nxthdr; X } X if(close_and_report()) X { X tryzhdrtype = ZFERR; X return(ERROR); X } X report_str("End of file",0); X return(c); X case ERROR: /* Too much garbage in header search error */ X if( --n < 0) X { X sprintf(s128,"zgethdr returned %02x",c); X report_str(s128,1); X return(ERROR); X } X zmputs(Attn); X continue; X case ZSKIP: X close_and_report(); X sprintf(s128,"rzfile: Sender SKIPPED file"); X report_str(s128,1); X return(c); X case ZDATA: X if(rclhdr(Rxhdr) != rxbytes) X { X if( --n < 0) X { X return(ERROR); X } X zmputs(Attn); X continue; X } Xmoredata: X switch(c = zrdata(secbuf,1024)) X { X case ZCAN: X sprintf(s128,"zgethdr returned %02x",c); X report_str(s128,1); X return(ERROR); X case ERROR: /* CRC error */ X if( --n < 0) X { X sprintf(s128,"zgethdr returned %02x",c); X report_str(s128,1); X return(ERROR); X } X zmputs(Attn); X continue; X case TIMEOUT: X if( --n < 0) X { X sprintf(s128,"zgethdr returned %02x",c); X report_str(s128,1); X return(ERROR); X } X continue; X case GOTCRCW: X n = 20; X write_sec_to_disk(secbuf,Rxcount); X rxbytes += Rxcount; X stohdr(rxbytes); X zshhdr(ZACK,Txhdr); X sendline(XON); X goto nxthdr; X case GOTCRCQ: X n = 20; X write_sec_to_disk(secbuf,Rxcount); X rxbytes += Rxcount; X stohdr(rxbytes); X zshhdr(ZACK,Txhdr); X goto moredata; X case GOTCRCG: X n = 20; X write_sec_to_disk(secbuf,Rxcount); X rxbytes += Rxcount; X goto moredata; X case GOTCRCE: X n = 20; X write_sec_to_disk(secbuf,Rxcount); X rxbytes += Rxcount; X goto nxthdr; X } X } X } X} /* end of rzfile */ X X/*+------------------------------------------------------------------------- X rzfiles() - receive file(s) with ZMODEM protocol X--------------------------------------------------------------------------*/ Xrzfiles() X{ Xregister c; X X for(;;) X { X switch(c = rzfile()) X { X case ZEOF: X case ZSKIP: X switch(tryz()) X { X case ZCOMPL: X return(OK); X default: X return(ERROR); X case ZFILE: X break; X } X continue; X default: X return(c); X case ERROR: X return(ERROR); X } X } X} /* end of rzfiles */ X X/*+------------------------------------------------------------------------- X close_and_report() - close the received file, set mod time and chmod X(specifically exclude set uid and gid from chmod) X--------------------------------------------------------------------------*/ Xclose_and_report() X{ X fflush(fout); X fstat(fileno(fout),&fout_stat); X report_file_byte_io((long)fout_stat.st_size); X report_file_close(); X X if(fclose(fout)==ERROR) X return(ERROR); X X#if defined(LOG_XFER) X sprintf(s256,"RECEIVE success: %s",Pathname); X ecu_log_event(s256); X#endif X X if(Modtime) X { X timep[0] = time(NULL); X timep[1] = Modtime; X utime(Pathname,timep); X } X X if((Filemode & S_IFMT) == S_IFREG) X { X Filemode &= ~(S_ISUID | S_ISGID); X chmod(Pathname,(07777 & Filemode)); X } X X return(OK); X X} /* end of close_and_report */ X X/*+------------------------------------------------------------------------- X send_ZFIN_and_exit() - send ZFIN packet and wait for "OO" ack X--------------------------------------------------------------------------*/ Xsend_ZFIN_and_exit() X{ Xregister n; X X Readnum = 1; X stohdr(0L); X for(n = 0; n < 4; n++) X { X purgeline(); X zshhdr(ZFIN,Txhdr); X switch(readline(100)) X { X case 'O': X readline(1); /* Discard 2nd 'O' */ X return; X case RCDO: X return; X case TIMEOUT: X default: X break; X } X } X} /* end of send_ZFIN_and_exit */ X X/*+------------------------------------------------------------------------- X sys2(shellcmd) - execute shell command X X Strip leading ! if present X--------------------------------------------------------------------------*/ Xsys2(shellcmd) Xregister char *shellcmd; X{ X if(*shellcmd == '!') X ++shellcmd; X return(system(shellcmd)); X} /* end of sys2 */ X X/*+------------------------------------------------------------------------- X main(argc,argv,envp) X--------------------------------------------------------------------------*/ Xmain(argc,argv,envp) Xint argc; Xchar **argv; Xchar **envp; X{ Xregister char *cp; Xchar **patts; Xchar *getenv(); Xint exitcode; Xchar **gargv = argv; Xint gargc = argc; X X signal(SIGINT,bye_bye); X signal(SIGTERM,bye_bye); X X get_curr_dir(curr_dir,sizeof(curr_dir)); X X Rxtimeout = 100; X X npats = 0; X while(--argc) X { X cp = *++argv; X if(*cp == '-') X { X while( *++cp) X { X switch(*cp) X { X case 'X': X required_type = 1; X Batch = 0; X break; X case 'Y': X required_type = 1; X Nozmodem = 1; X Batch = 1; X break; X case 'Z': X required_type = 1; X Nozmodem = 0; X Batch = 1; X break; X case '+': X Lzmanag = ZMAPND; X break; X case 'a': X Rxascii=1; X break; X case 'b': X Rxbinary=1; X break; X case 'c': X Crcflg=1; X break; X case 'e': X Zctlesc = 1; X break; X case 'p': X Lzmanag = ZMPROT; X break; X case ',': X log_packets = 1; X break; X case '.': X if(--argc < 1) X { X usage("no iofd after -."); X } X iofd = atoi(*++argv); X break; X case 't': X if(--argc < 1) X { X usage("no rcvr timeout after -t"); X } X Rxtimeout = atoi(*++argv); X if(Rxtimeout<10 || Rxtimeout>1000) X usage("illegal timeout: must be 10 <= t <= 1000"); X break; X case 'w': X if(--argc < 1) X { X usage("no Zrwindow after -w"); X } X Zrwindow = atoi(*++argv); X break; X case 'C': X if(--argc < 1) X usage("no label after -C"); X bottom_label = *++argv; X break; X case 'u': X MakeLCPathname=0; X break; X case 'y': X Rxclob=1; X break; X default: X sprintf(s128,"Unknown switch -%c",*cp); X usage(s128); X } X } X } X else if( !npats && argc>0) X { X if(argv[0][0]) X { X npats=argc; X patts=argv; X } X } X } X X if(!required_type || !iofd) X { SHAR_EOF echo "End of part 25" echo "File z/ecurz.c is continued in part 26" echo "26" > s2_seq_.tmp exit 0 -- ------------------------------------------------------------------- Warren Tucker, Tridom Corporation ...!gatech!emory!tridom!wht Ker-au'-lo-phon. An 8-foot partial flue-stop, having metal pipes surmounted by adjustable rings, and with a hole bored near the top of each pipe, producing a soft and "reedy" tone.