📄 gkermit.c
字号:
/* G K E R M I T -- GNU Kermit *//* A free implementation of the Kermit file transfer protocol for UNIX. If you change this software, please either (a) send changes back to the Kermit Project to be considered for the base version; or (b) change the strings below to show a new version number and date and to reflect the person or organization responsible for the new version. Sat Dec 25 19:22:54 1999*/char *versio = "G-Kermit CU-1.00, Columbia University, 1999-12-25";char *url = "http://www.columbia.edu/kermit/";char *email = "kermit@columbia.edu";/* Author: Frank da Cruz The Kermit Project Columbia University 612 West 115th Street New York NY 10025-7799 USA http://www.columbia.edu/kermit/ kermit@columbia.edu Copyright (C) 1999, The Trustees of Columbia University in the City of New York. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifdef POSIXchar *build = "POSIX"; /* Identify which build */#else#ifdef SYSVchar *build = "SYSV";#else#ifdef BSDchar *build = "BSD";#elsechar *build = "stty";#endif /* BSD */#endif /* SYSV */#endif /* POSIX */#define _GKERMIT_C#include <stdio.h>#include "gkermit.h"/* Forward declarations of functions used within this module... */_MYPROTOTYPE( int cmdlin, (void) ); /* Command-line parser */_MYPROTOTYPE( int spacket, (char,int,int,char *) ); /* Make & send a packet */_MYPROTOTYPE( int rpacket, (void) ); /* Read a packet */_MYPROTOTYPE( unsigned int chk1, (char *,int) ); /* 1-byte block check */_MYPROTOTYPE( unsigned int chk3, (char *,int) ); /* 3-byte CRC */_MYPROTOTYPE( unsigned int chksum, (char *,int) ); /* Checksum */_MYPROTOTYPE( int getpkt, (int) ); /* Fill packet data field */_MYPROTOTYPE( VOID encode, (int,int) ); /* Encode a character */_MYPROTOTYPE( VOID decstr, (char *) ); /* Decode a memory string *//* Externs */extern int zincnt; /* For buffered file i/o */extern char * zinptr;extern FILE * ofp; /* Output file pointer *//* Global variables declared here */char *cmarg, *cmarg2 = NULL; /* Send filename pointers */char **cmlist = NULL; /* Pointer to file list in argv */FILE * db = NULL; /* Debug log file pointer */int debug = 0; /* Debugging on */int failure = 0; /* Return status */int retries = 0; /* Packet retry counter */int sendtype = 0; /* Type of last packet sent */int recvtype = 0; /* Type of last packet received */int datalen = 0; /* Length of received data field *//* Protocol parameters */int spsiz = 90, /* Default send-packet size */ rpsiz = 94, /* Default short receive-packet size */ urpsiz = DEFRP, /* Default long receive-packet size */ maxrp = MAXRP, /* Maximum long receive-packet size */ timint = 9, /* Timeout interval I use */ rtimo = 7, /* Timeout I want you to use */ rpadn = 0, /* How much padding to send */ spadn = 0, /* How much padding to ask for */ bctr = 3, /* Block check type requested */ bctu = 1, /* Block check type used */ ebq = '&', /* 8th bit prefix */ ebqflg = 0, /* 8th-bit quoting flag */ rqf = -1, /* Flag used in 8bq negotiation */ rq = 0, /* Received 8bq bid */ sq = 'Y', /* Sent 8bq bid */ rpt = 0, /* Repeat count */ rptq = '~', /* Repeat prefix */ rptflg = 0, /* Repeat processing flag */ backup = 1, /* Back up existing files */ seq = 0, /* Current packet number */ size, /* Current size of output pkt data */ osize, /* Previous output packet data size */ maxsiz, /* Max size for building data field */ rln, /* Received packet length */ rsn, /* Received packet sequence number */ sndpkl; /* Length of packet being sent */char spadc = 0, /* Padding character to send */ rpadc = 0, /* Padding character to ask for */ seol = CR, /* End-Of-Line character to send */ reol = CR, /* End-Of-Line character to look for */ rctlq = '#', /* Control prefix in incoming data */ sctlq = '#', /* Outbound control character prefix */ sndpkt[MAXSP+16], /* Entire packet being sent */ rcvpkt[MAXRP+16], /* Packet most recently received */ *rdatap, /* Pointer to data field of rcvpkt */ xxdata[MAXRP+16], /* Packet data buffer */ *isp = NUL, /* Input string pointer */ *osp = NUL, /* Output string pointer */ smark = '\1', /* Outbound packet-start character */ rmark = '\1'; /* Incoming packet-start character */char * xdata = xxdata; /* Packet data field pointer *//* File-related variables */char filnam[MAXPATHLEN+1]; /* Name of current file. */char ttname[DEVNAMLEN+1]; /* Name of communication device. */int nfils; /* Number of files to send */int cx = 0, cz = 0; /* File and batch interruption flags */int quiet = 0; /* Suppress messages */int keep = 0; /* Keep incompletely received files */int streamok = 0; /* Streaming protocol negotiated */int streaming = 0; /* Streaming active now */int nomodes = 0; /* Don't mess with tty modes */int xonxoff = 0; /* Force Xon/Xoff */int noxonxoff = 0; /* Don't force Xon/Xoff */int manual = 0; /* Transfer mode manual, not auto */int parity = 0; /* Parity specified, 0,'e','o',etc */int delay = 1; /* Initial delay before sending */int text = 0; /* Flag for text/binary mode */int first = 0; /* Flag for first input from file */int longpackets = 0; /* Long packets negotiated */int attributes = 0; /* Attribute packets negotiated */int literal = 0; /* Literal filenames */char start = 0; /* Starting state for automaton */char **xargv; /* Global copies of argv */int xargc; /* and argc */char *dftty = CTTNAM; /* Default controlling terminal name */char *#ifdef __STDC__mystrchr(char * s, char c)#elsemystrchr(s,c) char *s, c;#endif /* __STDC__ */{ if (!s) /* strchr() replacement */ return(NULL); /* because strchr not portable */ while (*s && *s != c) s++; return((*s == c) ? s : NULL);}int /* Main Program */main(argc,argv) int argc; char **argv; { xargc = argc; /* Make global copies of argc */ xargv = argv; /* ...and argv. */ start = 0; /* No default start state. */ seq = 0; /* Packet sequence number. */ parity = 0; /* Initial parity. */ strncpy(ttname,dftty,DEVNAMLEN); /* Default device name. */ if (argc < 2) { /* If no args */ usage(); /* give usage message */ doexit(1); /* and quit. */ } sysinit(); /* Set up interrupt handlers, etc */ if (urpsiz > MAXRP) /* In case MAXRP < DEFRP... */ urpsiz = MAXRP; if (maxrp > 9020) maxrp = 9020; start = cmdlin(); /* Parse args */ if (start == 0 && !debug) { /* Nothing to do? */ fprintf(stderr,"No start state\n"); doexit(1); } if (ttopen(ttname) < 0) { /* "Open" the communication device */ fprintf(stderr,"Can't open terminal\n"); doexit(1); } if (ttpkt(parity) < 0) { /* Open OK, put it in packet mode */ printf("Can't set packet mode\n"); doexit(1); } /* OK, do requested actions. */ if (start) { /* Start state */ if (start == 's' || start == 'r') /* If sending or getting*/ ttflui(); /* flush comm line input buffer */ gwart(); /* Do the protocol */ } doexit(failure); /* Done, exit. */ return(failure); /* To shut up picky compilers. */}/* Functions */int /* Called implicitly by protocol */input() { /* to get the next packet. */ int x, type; if (start != 0) { /* Start state in effect? */ type = start; /* Yes, call it a packet type, */ start = 0; /* nullify the start state, */ if (debug) fprintf(db,"input[%c]\n",(char)type); return(type); /* and return the type. */ } if (streaming && (sendtype == 'D')) { /* If streaming and sending data */ x = ttchk(); /* Look for return traffic */ if (debug) fprintf(db,"input streaming ttchk %d\n",x); if (x < 0) errpkt("Fatal i/o error"); else if (x < 5) return('Y'); /* If none, pretend we got an ACK */ timint = 4; type = rpacket(); /* Something came in, read it */ timint = 0; if (mystrchr("TQN",type)) errpkt("Transmission error while streaming"); } else { type = rpacket(); /* No start state, read a packet. */ while (rsn != seq || /* Sequence number doesn't match, or */ mystrchr("TQN",type) /* Timeout, Checksum error, or NAK */ ) { if (streaming) errpkt("Transmission error while streaming"); resend(); /* Resend previous packet. */ type = rpacket(); /* Try to read response. */ } } if (!streaming) /* Got a good packet */ ttflui(); /* Flush buffer if not streaming */ if (debug) fprintf(db,"input[%c]\n",(char)type); return(type); /* Return its type */}VOIDnxtpkt() { /* Next packet */ retries = 0; /* Reset per-packet retry count */ seq = (seq + 1) & 63; /* Next packet number, mod 64 */}intack() { /* Acknowledge */ int x = 0; /* Empty acknowledgement */ if (!streaming || recvtype != 'D') x = spacket('Y',seq,0,""); /* Send the packet */ nxtpkt(); /* Increment packet number */ return(x);}intack1(s) char *s; { /* Acknowledgement with data */ int x; x = spacket('Y',seq,strlen(s),s); /* Send the packet */ nxtpkt(); /* Increment packet number */ return(x);}intnak() { /* Negative acknowledgement */ int x; retries++; if (debug) fprintf(db,"nak #%d (%d/%d)\n",seq,retries,MAXTRY); if (retries > MAXTRY) { /* Check retry limit */ errpkt("Too many retries"); doexit(1); } x = spacket('N',seq,0,""); /* A NAK never has data */ return(x);}VOIDtinit() { /* Transaction Initialization */ osp = NULL; /* Reset output string pointer */ cx = cz = 0; /* File interruption flags off */ bctu = 1; /* Block check back to 1 */ ebqflg = rptflg = 0; /* 8th bit & repeat quoting off */ sq = 'Y'; /* Normal 8th bit quote bid */ rqf = -1; /* Flag that no 8-b-q bid seen yet */ seq = 0; /* Start off with packet zero */ *filnam = *sndpkt = *rcvpkt = NUL; /* Clear out string buffers */}VOIDerrpkt(s) char *s; { /* Fatal error */ if (start == 'v' || start == 'r') /* Receiving a file? */ sleep(1); /* Time to soak up incoming junk. */ spacket('E',seq,(int)strlen(s),s); /* Send Error packet. */ doexit(1); /* Exit with failure status. */}int#ifdef __STDC__sinit(char c)#elsesinit(c) char c;#endif /* __STDC__ */{ /* Begin send */ char *s; s = rpar(); /* Get our protocol parameters */ if (c == 'S') { /* Sending a file... */ tmsgl(versio); tmsgl("Escape back to your local Kermit and give a RECEIVE command."); tmsgl(""); tmsgl("KERMIT READY TO SEND..."); sleep(delay); } return(spacket(c,seq,strlen(s),s)); /* Send S or I packet */}intsfile() { /* Send file header packet */ int x; char pktnam[MAXPATHLEN]; if (debug) fprintf(db,"sfile filnam [%s] max = %d\n",filnam,MAXPATHLEN); if (zopeni(filnam) < 0) { /* Open the input file */ if (debug) fprintf(db,"sfile error %d",errno); errpkt("Failure to open file"); } if (cmarg2) /* User-supplied name - use as-is */ strncpy(pktnam,cmarg2,MAXPATHLEN); else /* Actual filename - convert */ zltor(filnam,pktnam,MAXPATHLEN); cmarg2 = NULL; /* Only works for one file */ if (debug) fprintf(db,"sfile pktnam %s\n",pktnam); x = encstr(pktnam); /* Encode name */ if (debug) fprintf(db,"sfile encstr[%s] x=%d\n",xdata,x); first = 1; /* Starting condition for file */ maxsiz = spsiz - (bctr + 3); /* Maximum packet data field length */ if (spsiz > 94) maxsiz -= 4; /* Long packet has more fields */ nxtpkt(); /* Get next packet number */ return(spacket('F',seq,x,xdata)); /* Send filename */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -