📄 ecurz.c
字号:
char *numeric_revision = "@(#)ecurz 3.20";/*+------------------------------------------------------------------------- ecurz.c - X/Y/ZMODEM receive program Derived from public domain source by Chuck Forsberg, Omen Technologies Adaptation for ecu 1989 wht@n4hgf.Mt-Park.GA.US Defined functions: SIGALRM_handler(sig) arg_token(parsestr,termchars) bye_bye(sig) cancel_transaction(can_code) close_and_report() flushline() fname_split(cmd,arg,arg_max_quan,narg_rtn) fname_too_long(fname) fname_truncated() getfree() isanylc(str) main(argc,argv,envp) make_dirs(pathname) mkdir(dpath,dmode) our_fopen(pathname,openmode) procheader(name) purgeline() readline(timeout) report_receive_progress(pos) rzfile() rzfiles() send_ZFIN() send_cancel(error) sendline(c) substr(str,token) sys2(shellcmd) tryz() uncaps(str) usage(fail_reason) wcgetsec(rxbuf,maxtime) wcreceive(argc,argp) wcrx() wcrxpn(rpn) write_sec_to_disk(buf,n) xsendline(c) Usage: ecurz -Z [-abeuy] (ZMODEM) ecurz -Y [-abuy] (YMODEM) ecurz -X [-abc] file (XMODEM or XMODEM-1k) -a ASCII transfer (strip CR) -b Binary transfer for all files -c Use 16 bit CRC (XMODEM) -e Escape control characters (ZMODEM) -p protect local files (ZMODEM) -t <tenths> rx timeout seconds -+ force append -u convert uppercase filenames to lower case -y Yes, clobber existing file if any -. line fd to use -, log protocol packets--------------------------------------------------------------------------*//*+:EDITS:*//*:09-10-1992-14:00-wht@n4hgf-ECU release 3.20 *//*:08-22-1992-15:39-wht@n4hgf-ECU release 3.20 BETA *//*:08-16-1992-03:08-wht@n4hgf-head off another POSIX plot *//*:08-10-1992-04:01-wht@n4hgf-use init_Nap *//*:07-30-1992-16:35-wht@n4hgf-our_fopen fixes 3.2v4 ENAMETOOLONG ambiguity *//*:07-20-1992-13:39-wht@n4hgf-need hzmsec for nap.c *//*:04-24-1992-15:28-wht@n4hgf-start thinking about M_UNIX with long filenames *//*:04-24-1992-15:23-wht@n4hgf-fix mkdir/make_dirs conditionals *//*:01-27-1992-23:43-wht@n4hgf-more efficient fopen processing *//*:01-20-1992-23:25-root@n4hgf-ZMAPND works now *//*:12-16-1991-12:59-wht@n4hgf-support ZCRESUM *//*:08-28-1991-14:08-wht@n4hgf2-SVR4 cleanup by aega84!lh *//*:07-25-1991-12:59-wht@n4hgf-ECU release 3.10 *//*:04-30-1991-18:33-wht@n4hgf-gcc version coredumping on putc(); use fputc() *//*:03-27-1991-21:21-wht@n4hgf-dont bump error count on send ZRPOS *//*:02-03-1991-17:27-wht@n4hgf-version number change - see zcurses.c *//*:12-18-1990-21:26-wht@n4hgf-better output control *//*:10-04-1990-14:01-wht@n4hgf-add file finish warning for me *//*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller *//*:08-23-1990-14:14-wht@n4hgf-sending ZACK was erroneously counted as error *//*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */#include <stdio.h>#include <signal.h>#include <setjmp.h>#include <ctype.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include "zmodem.h"#include <sys/param.h>#if defined(ENAMETOOLONG)char *fname_truncated();#endifextern unsigned short crctab[];extern int force_dumbtty;extern int errno;extern char *sys_errlist[];extern int sys_nerr;extern char Attn[]; /* Attention string rx sends to tx on err */extern int Crc32; /* Display flag indicating 32 bit CRC being received */extern int Rxcount; /* Count of data bytes received */extern char Rxhdr[]; /* Received header */extern char Txhdr[]; /* Transmitted header */extern int Rxtimeout; /* Tenths of seconds to wait for something */extern char s128[128];/* * Max value for VMIN_COUNT is 255. A larger value reduces system * overhead but may evoke kernel bugs. 133 corresponds to an XMODEM/CRC * sector.Paul Slootman said, though::PS: Something somewhere in the SVR4 kernel is a signed char, which causes:PS: VMIN values of more than 127 to return *immediately* without ever:PS: reading...:PS::PS: I had troubles running the regular rz, which was where I saw:PS: the bug the first time. I've also heard of this from someone:PS: else, running something else than the ICL SPARC port for SVR4::PS::PS: Date: Sat, 3 Aug 91 11:41:16 EDT:PS: From: tompkins@cat.syr.edu (Terry Tompkins):PS: Subject: Re: Zmodem:PS: :PS: Thanks for the info. I just returned from vacation - sorry for the delay.:PS: We are running AT&T 5.4 UNIX on an Osicom 25mhz 386. If you hear of a :PS: fix for the OS, let me know - I feel a little apprehensive about a kernel:PS: bug of this nature. (The machine is a network server that we are using:PS: for all kinds of things).*/#if !defined(VMIN_COUNT)# ifdef SVR4# define VMIN_COUNT 127# else# define VMIN_COUNT 133# endif#endifunsigned char vmin_count = VMIN_COUNT;int Readnum = VMIN_COUNT; /* num bytes to ask for in read() from modem */#define DEFBYTL 2000000000L /* default rx file size */#define RETRYMAX 5FILE *fout;long rxfilepos; /* received file seek position */long initial_filepos; /* initial file position */char Lzmanag; /* Local file management request */char Pathname[PATHLEN];char curr_dir[256];unsigned char linbuf[VMIN_COUNT];char secbuf[1025];char zconv; /* ZMODEM file conversion request */char zmanag; /* ZMODEM file management request */char ztrans; /* ZMODEM file transport request */int Batch;int Blklen; /* record length of received packets */int Crcflg;int Eofseen; /* indicates cpm eof (^Z) has been received */int Filcnt; /* count of number of files opened */int Filemode; /* Unix style mode for incoming file */int Firstsec;int Lastrx;int Lleft; /* number of characters in linbuf */int MakeLCPathname=1; /* make received pathname lower case */int Nozmodem; /* If invoked as "rb" */int Rxascii; /* receive files in ascii (translate) mode */int Rxbinary; /* receive all files in bin mode */int Rxclob; /* Clobber existing file */int Thisbinary; /* current file is to be received in bin mode */int Twostop; /* use two stop bits */int Zctlesc; /* Encode control characters */int Zmodem; /* ZMODEM protocol requested */int Zrwindow = 1400; /* RX window size (controls garbage count) */int ecusz_flag;int skip_count; /* skipped files */int errors;int expect_zrpos;int iofd;int force_dumbtty;int can_on_eof;int log_packets;int npats;int oldBlklen = -1; /* last block length */int this_file_errors;int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close */jmp_buf tohere; /* For the interrupt on RX timeout */long Bytesleft; /* number of bytes of incoming file left */long Modtime; /* Unix style mod time for incoming file */long TotalToReceive;long rx_char_count;long tx_char_count;struct stat fout_stat;time_t timep[2];unsigned Baudrate;unsigned long this_file_length;int required_type;char *bottom_label = (char *)0;char *got_garbage_txt = "got garbage (0x%02x)";char **gargv;int gargc;void purgeline();void send_cancel();/*+----------------------------------------------------------------------- arg_token(parsestr,termchars)Get next token from string parsestr ((char *)0 on 2nd, 3rd, etc.calls), where tokens are nonempty strings separated by runs of charsfrom termchars. Writes nulls into parsestr to end tokens.termchars need not remain constant from call to call.Treats multiple occurrences of a termchar as one delimiter (does notallow null fields).------------------------------------------------------------------------*/#if defined(ENAMETOOLONG)static char *arg_token_static = (char *)0;char *arg_token(parsestr,termchars)char *parsestr;char *termchars;{ register char *parseptr; char *token; if(parsestr == (char *)0 && arg_token_static == (char *)0) return((char *)0); if(parsestr) parseptr = parsestr; else parseptr = arg_token_static; while(*parseptr) { if(!strchr(termchars,*parseptr)) break; parseptr++; } if(!*parseptr) { arg_token_static = (char *)0; return((char *)0); } token = parseptr; if(*token == '\'') { token++; parseptr++; while(*parseptr) { if(*parseptr == '\'') { arg_token_static = parseptr + 1; *parseptr = 0; return(token); } parseptr++; } arg_token_static = (char *)0; return(token); } while(*parseptr) { if(strchr(termchars,*parseptr)) { *parseptr = 0; arg_token_static = parseptr + 1; while(*arg_token_static) { if(!strchr(termchars,*arg_token_static)) break; arg_token_static++; } return(token); } parseptr++; } arg_token_static = (char *)0; return(token);} /* end of arg_token */#endif/*+------------------------------------------------------------------------- fname_split(cmd,arg,arg_max_quan,&narg)--------------------------------------------------------------------------*/#if defined(ENAMETOOLONG)voidfname_split(cmd,arg,arg_max_quan,narg_rtn)char *cmd;char **arg;int arg_max_quan;int *narg_rtn;{ register itmp; register narg; for(itmp = 0; itmp < arg_max_quan; itmp++) arg[itmp] = (char *)0; arg[0] = arg_token(cmd,"/"); for(narg = 1; narg < arg_max_quan; ++narg) { if((arg[narg] = arg_token((char *)0,"/")) == (char *)0) break; } *narg_rtn = narg;} /* end of fname_split */#endif#if defined(ENAMETOOLONG)#define MAX_COMPONENT_LEN 14#define MAX_PATH_COMPONENTS 16static char trunc_fname[257];static char *trunc_components[MAX_PATH_COMPONENTS];static int trunc_components_quan;static int trunc_absolute_path;#endif/*+------------------------------------------------------------------------- fname_too_long(fname) - check for any pathname component too long--------------------------------------------------------------------------*/#if defined(ENAMETOOLONG)intfname_too_long(fname)register char *fname;{ register int itmp; register char **cpptr; if(trunc_absolute_path = (*fname == '/')) fname++; strncpy(trunc_fname,fname,sizeof(trunc_fname) - 1); fname_split(trunc_fname,trunc_components, MAX_PATH_COMPONENTS,&trunc_components_quan); itmp = trunc_components_quan; cpptr = trunc_components; while(itmp--) { if(strlen(*cpptr) > MAX_COMPONENT_LEN) return(1); cpptr++; } return(0);} /* end of fname_too_long */#endif/*+------------------------------------------------------------------------- fname_truncated() - build truncated path last checked by fname_too_long--------------------------------------------------------------------------*/#if defined(ENAMETOOLONG)char *fname_truncated(){ register int icomp; char new_fname[257]; register char *cptr = new_fname; if(trunc_absolute_path) { *cptr = '/'; *(cptr + 1) = 0; } else *cptr = 0; for(icomp = 0; icomp < trunc_components_quan; icomp++) { if(strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN) *(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0; strcat(cptr,trunc_components[icomp]); if(icomp < trunc_components_quan - 1) strcat(cptr,"/"); } strcpy(trunc_fname,cptr); return(trunc_fname);} /* end of fname_truncated */#endif/*+------------------------------------------------------------------------- our_fopen(pathname,openmode) - fopen for write considering ENAMETOOLONGThis can modify the pathname argument--------------------------------------------------------------------------*/FILE *our_fopen(pathname,openmode)char *pathname;char *openmode;{ FILE *fp; if(!(fp = fopen(pathname,openmode))) {#if defined(ENAMETOOLONG) if(errno == ENAMETOOLONG) { if(fname_too_long(pathname)) { strcpy(s128,"truncated: "); strncat(s128,pathname,sizeof(s128) - 12); ecu_log_event(getppid(),s128); report_str(s128,-1); strcpy(pathname,fname_truncated()); fp = fopen(pathname,openmode); } }#else ; /* dummy statement for anti new-fangled compiler warnings */#endif } return(fp);} /* end of our_fopen *//*+------------------------------------------------------------------------- substr(str,token) searches for token in string str returns pointer to token within string if found,NULL otherwise--------------------------------------------------------------------------*/char *substr(str,token)register char *str,*token;{ register char *ss; register char *tt; /* search for first char of token */ for(ss=str; *str; str++) if(*str == *token) /* compare token with substring */ for(ss=str,tt=token; ;) { if(!*tt) return(str); if(*ss++ != *tt++) break; } return(NULL);} /* end of substr *//*+------------------------------------------------------------------------- getfree() Routine to calculate the free bytes on the current file system ~0 means many free bytes (unknown)--------------------------------------------------------------------------*/longgetfree(){ return(~0L); /* many free bytes ... */} /* end of getfree *//*+------------------------------------------------------------------------- usage(fail_reason)--------------------------------------------------------------------------*/voidusage(fail_reason)char *fail_reason;{ fprintf(stderr,"%s\n",fail_reason); exit(255);} /* end of usage *//*+------------------------------------------------------------------------- SIGALRM_handler(sig)--------------------------------------------------------------------------*/voidSIGALRM_handler(sig)int sig;{ report_tx_ind(0); report_rx_ind(0); longjmp(tohere,-1);} /* end of SIGALRM_handler *//*+------------------------------------------------------------------------- bye_bye(sig)--------------------------------------------------------------------------*/voidbye_bye(sig)int sig;{ exit(sig+128);} /* end of bye_bye */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -