KERMIT PROTOCOL MANUAL KERMIT PROTOCOL MANUAL KERMIT PROTOCOL MANUAL ______ _______ Fourth Edition 1 Frank da Cruz, Bill Catchings Columbia University Center for Computing Activities New York, New York 10027 20 October 1983 Copyright (C) 1981,1982,1983 Trustees of Columbia University in the City of New York __________ __ _______ __ ___ __________ __ ___________ __ ____ __ Permission is granted to any individual or institution to copy or ___ ____ ________ ___ ___ ________ _________ __ __ ______ ___ use this document and the programs described in it, except for __________ __________ ________ explicitly commercial purposes. _______________ 1 Present address: Lehman Bros Kuhn Loeb, NYC 1 - 2 - Preface to the Fourth Edition Preface to the Fourth Edition Preface to the Fourth Edition The fourth edition of the KERMIT Protocol Manual incorporates some new ideas that grew from our experience in attempting to implement some of the features described in earlier editions, particularly user/server functions. These in- clude a mechanism to allow batch transfers to be interrupted gracefully for ei- ther the current file or the entire batch of files; a "capability mask"; a protocol extension for passing file attributes. In addition, numbers are now written in decimal notation, rather than octal, which was confusing to many readers. Also, several incompatible changes were made in minor areas where no attempts at an implementation had yet been made; these include: - The format and interpretation of the operands to the server commands. - Usurpation of the reserved fields 10-11 of the Send-Init packet, and addition of new reserved fields. Most of the remaining material has been rewritten and reorganized, and much new material added, including a section on the recommonded vocabulary for documen- tation and commands. The previous edition of the Protocol Manual attempted to define "protocol ver- sion 3"; this edition abandons that concept. Since KERMIT development is an unorganized, disorderly, distributed enterprise, no requirement can be imposed on KERMIT implementors to include a certain set of capabilities in their im- plementations. Rather, in this edition we attempt to define the basic functionality of KERMIT, and then describe various optional functions. The key principle is that any implementation of KERMIT should work with any other, no matter how advanced the one or how primitive the other. The capabily mask and other Send-Init fields attempt to promote this principle. ______ __________ __ _____ _ ___ ______ _______ __ ____ __ _____ ____ ___ __ Before attempting to write a new Kermit program, be sure to check with the au- _____ __ ____ ____ ____ __ ___ ____ __ _______ __ ___ ____ _____ ___ ____ ___ thors to make sure that no one else is working on the same thing, and that you ____ ___ ______ ___________ have the latest information. The Columbia University DEC-20 implementation of KERMIT should be considered the definitive implementation of the protocol. The true test of any new Kermit is whether it can talk to Columbia DEC-20 Kermit. KERMIT is distributed from Columbia University on magnetic tape. Complete or- ______ _____ _____ dering instructions are in the Kermit Users Guide. KERMIT Distribution Columbia University Center for Computing Activities 7th Floor, Watson Laboratory 612 West 115th Street New York, NY 10025 - 3 - No warranty of the software nor of the accuracy of the documentation surround- ing it is expressed or implied, and neither the authors nor Columbia University acknowledge any liability resulting from program or documentation errors. - 4 - CHAPTER 1 CHAPTER 1 CHAPTER 1 INTRODUCTION INTRODUCTION INTRODUCTION This manual describes the KERMIT protocol. It is assumed that you understand the purpose and operation of the Kermit file transfer facility, described in ______ _____ _____ the Kermit Users Guide, and basic terminology of data communications and com- puter programming. 1.1. Background 1.1. Background 1.1. Background The KERMIT file transfer protocol is intended for use in an environment where there may be a diverse mixture of computers -- micros, personal computers, workstations, laboratory computers, timesharing systems -- from a variety of manufacturers. All these systems need have in common is the ability to com- municate in ASCII over ordinary serial telecommunication lines. KERMIT was originally designed at Columbia to meet the need for file transfer between our DECSYSTEM-20 and IBM 370-series mainframes and various microcom- puters. It turned out that the diverse characteristics of these three kinds of systems resulted in a design that was general enough to fit almost any system. The IBM mainframe, in particular, strains most common assumptions about how computers communicate. 1.2. Overview 1.2. Overview 1.2. Overview The KERMIT protocol is specifically designed for character-oriented transmis- sion over serial telecommunication lines. The design allows for the restric- tions and peculiarities of the medium and the requirements of diverse operating environments -- buffering, duplex, parity, character set, file organization, etc. The protocol is carried out by KERMIT programs on each end of the serial connection sending "packets" back and forth; the sender sends file names, file contents, and control information; the receiver acknowledges (positively or negatively) each packet. The packets have a layered design, in keeping with the ANSI and ISO philosophies, with the outermost fields used by the data link layer to verify data integrity, the next by the session layer to verify continuity, and the data itself at the application level. Connections between systems are established by the ordinary user. In a typical case, the user runs KERMIT on a microcomputer, enters terminal emulation, con- nects to a remote host computer (perhaps by dialing up), logs in, runs KERMIT on the remote host, and then issues commands to that KERMIT to start a file transfer, "escapes" back to the micro, and issues commands to that KERMIT to start its side of the file transfer. Files may be transferred singly or in groups. __________ Basic KERMIT provides only file transfer, and that is provided for sequential _____ ____ files only, though the protocol attempts to allow for various types of sequen- tial files. Microcomputer implementations of KERMIT are also expected to - 5 - provide terminal emulation, to facilitate the initial connection. More advanced implementations simplify the "user interface" somewhat by allow- ing the KERMIT on the remote host to run as a "server", which can transfer files in either direction upon command from the local "user" Kermit. The serv- er can also provide additional functionality, such as file management, mes- sages, mail, and so forth. Other optional features also exist, including a variety of block check types, a mechanism for passing 8-bit data through a 7-bit communication link, a way to compressing a repeated sequence of charac- ters, and so forth. As local area networks become more popular, inexpensive, and standardized, the demand for KERMIT and similar protocols may dwindle, but will never wither away entirely. Unlike hardwired networks, KERMIT gives the ordinary user the power ___ ___ to establish reliable error-free connections between any two computers; this may always be necessary for one-shot or long-haul connections. - 6 - CHAPTER 2 CHAPTER 2 CHAPTER 2 DEFINITIONS DEFINITIONS DEFINITIONS 2.1. General Terminology 2.1. General Terminology 2.1. General Terminology ___ TTY: This is the term commonly used for a device which is connected to a com- puter over an EIA RS-232 serial telecommunication line. This device is most commonly an ASCII terminal, but it may be a microcomputer or even a large multi-user computer emulating an ASCII terminal. Most computers provide hardware (RS-232 connectors and UARTs) and software (device drivers) to support TTY connections; this is what allows TTY-oriented file transfer protocols like KERMIT possible on almost any system at little or no cost. _____ LOCAL: When two machines are connected, the LOCAL machine is the one which you interact with directly, and which is in control of the terminal. The "local Kermit" is the one that runs on the local machine. A local Kermit always com- municates over an external device (the micro's communication port, an assigned TTY line, etc). ______ REMOTE: The REMOTE machine is the one on the far side of the connection, which you must interact with "through" the local machine. The "remote Kermit" runs on the remote machine. A remote Kermit usually communicates over its own "console", "controlling terminal", or "standard i/o" device. ____ HOST: Another word for "computer", usually meaning a computer that can provide a home for multiple users or applications. This term should be avoided in KER- MIT lore, unless preceded immediately by LOCAL or REMOTE. ______ SERVER: An implementation of remote Kermit that can accept commands from a local Kermit program, instead of directly from the user. ____ USER: In addition to its usual use to denote the person using a system or program, "user" will also be used refer to the local Kermit program, when the remote Kermit is a server. 2.2. Numbers 2.2. Numbers 2.2. Numbers _______ All numbers in the following text are expressed in decimal (base 10) notation unless otherwise specified. Numbers are also referred to in terms of their bit positions in a computer word. Since KERMIT may be implemented on computers with various word sizes, we start numbering the bits from the "right" -- bit 0 is the least significant. Bits 0-5 are the 6 least significant bits; if they were all set to one, the value would be 63. A special quirk in terminology, however, refers to the high order bit of a character as it is transmitted on the communication line, as the "8th bit". More properly, it is bit 7. References to the "8th bit" generally are with regard to that bit which ASCII transmission sets aside for use as a parity bit. - 7 - KERMIT concerns itself with whether this bit can be usurped for the transmis- sion of data, and if not, it may resort to "8th-bit prefixing". 2.3. Character Set 2.3. Character Set 2.3. Character Set __________ All characters are in ASCII (American national Standard Code for Information Interchange) representation, ANSI standard X3.4-1968. All implementations of KERMIT transmit and receive characters only in ASCII. _____ _________ __________ ASCII_character_mnemonics: NUL Null, idle, ASCII character 0. SOH Start-of-header, ASCII character 1 (Control-A). SP Space, blank, ASCII 32. CR Carriage return, ASCII 13 (Control-M). LF Linefeed, ASCII 10 (Control-J). CRLF A carriage-return linefeed sequence. DEL Delete, rubout, ASCII 127. _______ _________ A control_character is considered to be any ASCII character in the range 0 through 31, or the DEL character (127). In this document, control characters are written in several ways: Control-A This denotes ASCII character 1, commonly referred to as "Control-A". Control-B is ASCII character 2, and so forth. CTRL-A This is a common abbreviation for "Control-A". A control character is generally typed at a computer terminal by holding down the key marked CTRL and pressing the corresponding alphabetic character, in this case "A". ^A "Upparow" notation for CTRL-A. Many computer systems "echo" control characters in this fashion. _________ _____ _________ A printable__ASCII_character is considered to be any character in the range 32 (SP) through 126 (tilde). 2.4. Conversion Functions 2.4. Conversion Functions 2.4. Conversion Functions Several conversion functions are useful in the description of the protocol and in the program example. The machine that Kermit runs on need operate only on integer data; these are functions that operate upon the numeric value of single ASCII characters. _ char(x) = x+32 Transforms the integer x, which is assumed to lie in the range 0 to 94, into a printable ASCII character; 0 becomes SP, 1 be- comes "!", etc. unchar(x) = x-32 - 8 - _ Transforms the character x, which is assumed to be in the printable range (SP through tilde), into an integer in the range 0 to 94. ctl(x) = x XOR 64 Maps between control characters and their printable represen- 2 _ tations, preserving the high-order bit . If x is a control character, then x = ctl(ctl(x)) that is, the same function is used to controllify and uncon- trollify. The argument is assumed to be a true control charac- ter (0 to 31, or 127), or the result of applying CTL to a true control character (i.e. 63 to 95). The transformation is a mnemonic one -- ^A becomes A and vice versa. 2.5. Protocol Jargon 2.5. Protocol Jargon 2.5. Protocol Jargon ______ A Packet is a clearly delimited string of characters, comprised "control fields" nested around data; the control fields allow a KERMIT program to deter- mine whether the data has been transmitted correctly and completely. A packet is the smallest unit of transmission in the KERMIT protocol. ___ ACK stands for "Acknowledge". An ACK is a packet that is sent to acknowledge receipt of another packet. Not to be confused with the ASCII character ACK. ___ NAK stands for "Negative Acknowledge". A NAK is a packet sent to say that a corrupted or incomplete packet was received, the wrong packet was received, or an expected packet was not received. Not to be confused with the ASCII charac- ter NAK. _______________ 2 The high order bit is normally the parity bit, but Kermit uses this bit as data in order to do 8-bit transmission for binary files when the systems permit. - 9 - CHAPTER 3 CHAPTER 3 CHAPTER 3 SYSTEM REQUIREMENTS SYSTEM REQUIREMENTS SYSTEM REQUIREMENTS The KERMIT protocol requires that: - The host can send and receive characters using 7- or 8-bit ASCII en- coding over a EIA RS-232 physical connection, either hardwired or dialup. - All printable ASCII characters are acceptable as input to the host 3 and will not be transformed in any way . Similarly, any intervening network or communications equipment (TELENET, terminal concentrators, port selectors, etc) must not transform or swallow any printable AS- CII characters. - A single ASCII control character can pass from one system to the other without transformation. This character is used for packet synchronization. The character is normally Control-A (SOH, ASCII 1), but can be redefined. - If a host requires a line terminator for terminal input, that ter- minator must be a single ASCII control character, such as CR or LF, distinct from the packet synchronization character. - When using a job's controlling terminal for file transfer, the system must allow the KERMIT program to set the terminal to half duplex, in- finite width (no "wraparound" or CRLF insertion by the operating system), and no "formatting" of incoming or outgoing characters (for instance, raising lowercase letters to uppercase, transforming con- trol characters to printable sequences, etc). In short, the terminal must be put in "binary" or "raw" mode, and, hopefully, restored af- terwards to normal operation. - The host's terminal input processor should be capable of receiving a single burst of 40 to 100 characters at normal transmission speeds. This is the typical size of packet. - If a host requires padding, the padding character must be a control character (including DEL). ___ KERMIT does not require: _______________ 3 If they are translated to another character set, like EBCDIC, the KERMIT program must be able to reconstruct the packet as it appeared on the communication line, before transformation. - 10 - - That the connection run at any particular baud rate. - That the system can do XON/XOFF or any other kind of flow control. System- or hardware-level flow control can help, but it's not neces- sary. See section 7.6. - That the system is capable of full duplex operation. Any mixture of half and full duplex systems is supported. - That the system can transmit or receive 8-bit bytes. KERMIT will take advantage of 8-bit connections to send binary files; if an 8-bit connection is not possible, then binary files may be sent using an optional prefix encoding. - 11 - CHAPTER 4 CHAPTER 4 CHAPTER 4 PRINTABLE TEXT VERSUS BINARY DATA PRINTABLE TEXT VERSUS BINARY DATA PRINTABLE TEXT VERSUS BINARY DATA For transmission between unlike systems, files must be assigned to either of _________ ____ ______ two catagories: printable text or binary. A printable text file is one that can make sense on an unlike system -- a docu- ment, program source, textual data, etc. A binary file is one that will not (and probably can not) make sense on an unlike system -- an executable program, numbers stored in internal format, etc. On systems with 8-bit bytes, printable 4 ASCII files will have the high order bit of each byte set to zero (since ASCII is a 7-bit code) whereas binary files will use the high order bit of each byte for data, in which case its value can vary from byte to byte. Since computers can't be expected to distinguish a printable file from a binary file -- especially one originating from an unlike system -- the user may have to give an explicit command to Kermit to tell it whether to perform these con- versions. 4.1. Printable Text Files 4.1. Printable Text Files 4.1. Printable Text Files For printable text files to be transferred in a useful fashion, there must be a standard way to represent them during transmission. KERMIT's standard is simple: ASCII characters, with "logical records" (lines) delimited by CRLFs. It is the responsibility of systems that do not store printable files in this fashion to perform the necessary conversions upon input and output. For in- stance, IBM mainframes might strip trailing blanks on output and add them back on input; UNIX would prepend a CR to its normal record terminator, LF, upon output and discard it upon input. 4.2. Binary Files 4.2. Binary Files 4.2. Binary Files Binary files are transmitted as though they were a sequence of characters. The difference from printable files is that the status of the "8th bit" must be preserved. When binary files are transmitted to an unlike system, the main ob- jective is that they can be brought back to the original system (or one like it) intact; no special conversions are necessary during transmission, except to make the data fit the transmission medium. For binary files, eight bit character transmission is permissible as long as the two Kermit programs involved can control the value of the parity bit, and _______________ 4 There are some exceptions, such as systems that store text files in so- called "negative ASCII", or text files produced by word processors that use the high order bit to indicate underline or boldface attributes. - 12 - no intervening communications equipment will change its value. In that case, the 8th bit of a transmitted character will match that of the original data byte, after control-quoting has been done. When one or both sides cannot con- trol the parity bit, a special prefix character may be prepended, as described below. Systems that do not store binary data in 8-bit bytes, or whose word size is not a multiple of 8, may make special provisions for "image mode" transfer of bi- nary files. This may be done within the basic protocol by having the two sides implicitly agree upon a scheme for packing the data into 7- or 8-bit ASCII characters, or else the more flexible (but optional) file attributes feature may be used. - 13 - CHAPTER 5 CHAPTER 5 CHAPTER 5 PACKET FORMAT PACKET FORMAT PACKET FORMAT The KERMIT protocol is built around exchange of packets of the following for- mat: +------+-----------+-----------+------+------------+-------+ | MARK | char(LEN) | char(SEQ) | TYPE | DATA | CHECK | +------+-----------+-----------+------+------------+-------+ where all fields consist of ASCII characters. The fields are: ____ MARK The synchronization character that marks the beginning of the packet. This should normally be CTRL-A, but may be redefined. ___ LEN The number of ASCII characters within the packet that follow this field, in other words the packet length minus two. Since this number is transformed to a single character via the char function, packet character counts of 0 to 94 (decimal) are permitted, and 96 (decimal) is the maximum total packet length. The length does not include end- of-line or padding characters, which are outside the packet and are strictly for the benefit of the operating system, but it does include the block check characters. ___ SEQ The packet sequence number, modulo 64, ranging from 0 to 63. Sequence numbers "wrap around" to 0 after each group of 64 packets. ____ TYPE The packet type, a single ASCII character. The following packet types are required: D Data packet Y Acknowledge (ACK) N Negative acknowledge (NAK) S Send initiate (exchange parameters) B Break transmission (EOT) F File header Z End of file (EOF) E Error ____ DATA The "contents" of the packet, if any contents are required in the given type of packet, interpreted according to the packet type. Control characters are preceded by a special prefix character, normally "#", and "uncontrollified" via ctl(). A prefixed sequence may not be broken across packets. Logical records in printable files are delimited with CRLFs, suitably prefixed (e.g. "#M#J"). Any prefix characters are in- cluded in the count. Optional encoding for 8-bit data and repeated characters is described later. _____ CHECK A block check on the characters in the packet between, but not includ- ing, the mark and the block check itself. The check for each packet is computed by both hosts, and must agree if a packet is to be accepted. A single-character arithmetic checksum is the normal and required block - 14 - check. Only six bits of the arithmetic sum are included. In order that all the bits of each data character contribute to this quantity, bits 6 and 7 of the final value are added to the quantity formed by _ bits 0-5. Thus if s is the arithmetic sum of the ASCII characters, then _____ _ _ check = char((s + ((s AND 300)/100)) AND 77) This is the default block check, and all Kermits must be capable of performing it. Other optional block check types are described later. The block check is based on the ASCII values of the characters in the packet. Non-ASCII systems must translate to ASCII before performing the block check calculation. Any line terminator that is required by the system may be appended to the packet; this is carriage return (ASCII 15) by default. Line terminators are not considered part of the packet, and are not accounted for in the count or checksum. Terminators are not necessary to the protocol, and are invisible to it, as are any characters that may appear between packets. If a host cannot do single character input from a TTY line, then a terminator will be required for that host. The terminator can be specified in the initial connection protocol. - 15 - CHAPTER 6 CHAPTER 6 CHAPTER 6 INITIAL CONNECTION INITIAL CONNECTION INITIAL CONNECTION Initial connection occurs when the user has started up a Kermit program on both ends of the physical connection. One Kermit has been directed (in one way or another) to send a file, and the other to receive it. The receiving Kermit waits for a "Send-Init" packet from the sending Kermit. It doesn't matter whether the sending Kermit is started before or after the receiving Kermit (if before, the Send-Init packet should be retransmitted periodically until the receiving Kermit acknowledges it). The data field of the Send-Init packet is optional; trailing fields can be omitted (or left blank, i.e. contain a space) to accept or specify default values. It is important to note that newly invented fields are added at the right, so that old KERMIT programs that do not have code to handle the new fields will act as if they were not there. For this reason, the default value for any field, indicated by blank, should result in the behavior that occurred before the field was added. 1 2 3 4 5 6 7 8 9 10... +------+------+------+------+------+------+------+------+------+--------- | MAXL | TIME | NPAD | PADC | EOL | QCTL | QBIN | CHKT | REPT | Capabili +------+------+------+------+------+------+------+------+------+--------- The fields are as follows (the first and second person "I" and "you" are used to distinguish the two sides). Fields are encoded printably using the char() function unless indicated otherwise. ____ 1. MAXL The maximum length packet I want to receive, a number up to 94 (decimal). You respond with the maximum you want me to send. This allows systems to adjust to each other's buffer sizes, or to the con- dition of the transmission medium. ____ 2. TIME The number of seconds after which I want you to time me out while waiting for a packet from me. You respond with the amount of time I should wait for packets from you. This allows the two sides to ac- commodate to different line speeds or other factors that could cause timing problems. ____ 3. NPAD The number of padding characters I want to precede each incoming packet; you respond in kind. Padding may be necessary for a half duplex system that requires some time to change the direction of transmission, although in practice this situation is more commonly handled by a "handshake" mechanism. ____ 4. PADC The control character I need for padding, if any, transformed by ___ ctl() (not char()) to make it printable. You respond in kind. Nor- mally NUL (ASCII 0), some systems use DEL (ASCII 127). This field is ignored if the value NPAD is zero. ___ 5. EOL The character I need to terminate an incoming packet, if any. You - 16 - respond in kind. Most systems that require a line terminator for terminal input accept carriage return for this purpose. ____ 6. QCTL (verbatim) The printable ASCII character I will use to quote control characters, normally "#". You respond with the one you will use. ____ 7. QBIN (verbatim) The printable ASCII character I want to use to quote characters which have the 8th bit set, for transmitting binary files when the parity bit cannot be used for data. Since this kind of quoting increases both processor and transmission overhead, it is normally to be avoided. If used, the quote character must be in the range 33-62 ("!" through ">") or 96-126 ("`" through "~"), but dif- ferent from the control-quoting character. This field is interpreted as follows: Y I agree to 8-bit quoting if you request it. N I will not do 8-bit quoting. & (or any other character in the range 33-62 or 96-126 besides Y and N) I want to do 8-bit quoting using this character (it will be done if the other Kermit puts a Y in this field). The recom- mended 8th-bit quoting prefix character is "&". ________ ____ Anything Else: 8-bit quoting will not be done. ____ 8. CHKT Check Type, the method for detecting errors. "1" for single-charac- ter checksum (the normal and required method), "2" for two-character checksum (optional), "3" for three-character CRC-CCITT (optional). If your response agrees, the designated method will be used; other- wise the single-character checksum will be used. ____ 9. REPT The prefix character I will use to indicate a repeated character. This can be any printable character in the range 33-62 or 96-126, but different from the control and 8th-bit prefixes. SP (32) denotes no repeat count processing is to be done. Tilde ("~") is the recom- mended and normal repeat prefix. If you don't respond identically, repeat counts will not be done. Groups of at least 3 or 4 identical characters may be transmitted more efficiently using a repeat count, though an individual implementation may wish to set a different threshhold. ____________ 10-?. Capabilities A bit mask, in which each bit position corresponds to a capability of KERMIT, and is set to 1 if that capability is present, or 0 if it is not. Each character contains a 6-bit field (transformed by CHAR()), whose low order bit is set to 1 if another capability byte follows, and to 0 in the last capability byte. The capabilities defined so far are: #1 Ability to time out. #2 Ability to accept server commands. #3 Ability to accept "A" packets (file attributes) The capability byte as defined so far would then look like: - 17 - bit5 bit4 bit3 bit2 bit1 bit0 +----+----+----+----+----+----+ | #1 | #2 | #3 | -- | -- | 0 | +----+----+----+----+----+----+ If all these capabilities were "on", the value of the byte would be 70 (octal). When capabilities 5 and 6 are added, the capability mask will look like this: bit5 bit4 bit3 bit2 bit1 bit0 bit5 bit4 bit3 bit2 bit1 bit +----+----+----+----+----+----+ +----+----+----+----+----+-- | #1 | #2 | #3 | #4 | #5 | 1 | | #6 | -- | -- | -- | -- | +----+----+----+----+----+----+ +----+----+----+----+----+-- ____ _ ________ ______ Next 4: Reserved_Fields Sites that wish to add their own parameters to the initial connection negotiation must start at the 5th field after the last capability byte. Any intervening fields may be left blank (that is, they may contain the space character). These fields are reserved for future use by the standard KERMIT protocol. ___ _______ ___ ___ ___ ______ ________ ____ __ ________ The control, 8th-bit, and repeat prefixes must be distinct. The receiving Kermit responds with an ACK ("Y") packet in the same format to indicate its own preferences, options, and parameters. The ACK need not con- tain the same number of fields as the the Send-Init. From that point, the two KERMIT programs are "configured" to communicate with each other for the remainder of the transaction. In the case of 8th-bit quoting, one side must specify the character to be used, and the other must agree with a "Y" in the same field, but the order in which this occurs does not matter. Similarly for checksums -- if one side requests 2 character checksums and the other side responds with a "1" or with nothing at all, then single-character checksums will be done, since not all implementations can be expected to do 2-character checksums or CRCs. And for repeat counts; if the repeat field of the send-init and the ACK do not agree, repeat processing will not be done. All Send-Init fields are optional. The data field may be left totally empty. Similarly, intervening fields may be defaulted by setting them to blank. Ker- mit implementations should know what to do in these cases, namely apply ap- propriate defaults. The defaults should be: MAXL: 80 NPAD: 0, no padding PADC: 0 (NUL) EOL: CR (carriage return) QCTL: the character "#" QBIN: none, don't do 8-bit quoting CHKT: "1", single-character checksum REPT: No repeat count processing MASK: All zeros (no special capabilities) Note that there are no prolonged negotiations in the initial connection se- - 18 - quence -- there is one Send-Init and one ACK in reply. Everything must be settled in this exchange. The very first Send-Init may not get through if the sending Kermit makes wrong assumptions about the receiving host. For instance, the receiving host may re- quire certain parity, some padding, or a special end of line character in order to read the Send-Init packet. For this reason, there should be a way for the user the user to specify whatever may be necessary to get the first packet through. A parity field is not provided in the Send-Init packet because it could not be of use. If the sender requires a certain kind of parity, it will also be send- ______ ing it. If the receiver does not know this in advance, i.e. before getting the Send-Init, it will not be able to read the Send-Init packet. - 19 - CHAPTER 7 CHAPTER 7 CHAPTER 7 FILE TRANSFER FILE TRANSFER FILE TRANSFER ___________ The file transfer protocol is defined over a transaction. A transaction is defined as an exchange of packets beginning with a Send-Init (S) packet, and 5 ending with a Break Transmission (B) or Error (E) packet , and may include the transfer of one or more files, all in the same direction. The following se- ______ quence characterizes basic Kermit operation; the sender is the machine that is ________ sending files; the receiver is the machine receiving the files. 1. The sender transmits a Send-Initiate (S) packet to specify its parameters (packet length, timeout, etc). 2. The receiver sends an ACK (Y) packet, with its own parameters in the data field. 3. The sender transmits a File-Header (F) packet, which contains the file's name in the data field. The receiver ACKs the F packet, with no data in the data field of the ACK (optionally, it may contain the name under which the receiver will store the file under). 4. The sender sends the contents of the file, in Data (D) packets. Each D packet must be acknowledged before the next one is sent. 5. When all the file data has been sent, the sender sends an End-Of- File (Z) packet. The receiver ACKs it. 6. If there is another file to be sent, the process is repeated, begin- ning at step 3. 7. When no more files remain to be sent, the sender transmits an End- Of-Transmission (B) packet. The receiver ACKs it. This ends the transaction, and closes the logical connection (the physical connec- tion remains open). Each packet has a sequence number, starting with 0. The acknowledgment (ACK or NAK) for a packet has the same packet number as the packet it is acknowledging. Once an acknowledgment is successfully received, the sender increments the packet number by one, modulo 64. If the sender is remote, it waits for a certain amount of time (somewhere in the 5-30 second range) before transmitting the Send-Init, to give the user time to escape back to the local KERMIT and tell it to receive files. _______________ 5 A transaction should also be considered terminated when one side or the other has stopped without sending an Error packet. - 20 - 7.1. Timeouts, NAKs, and Retries 7.1. Timeouts, NAKs, and Retries 7.1. Timeouts, NAKs, and Retries If a KERMIT program is capable of setting a timer interrupt, or setting a time limit on an input request, it should do so whenever attempting to read a packet from the communication line, whether sending or receiving files. Having read a packet, it should turn off the timer. If the sender times out waiting for an acknowledgement, it should send the same packet again, repeating the process a certain number of times up to a retry limit, or until an acknowledgement is received. If the receiver times out waiting for a packet, it can send either a NAK packet for the expected packet or another ACK for the last packet it got. If a packet from the sender is garbled or lost in transmission (the latter is detected when the sequence number increases by more than 1, modulo 64, the former by a bad checksum), the receiver sends a NAK for the garbled or missing packet. If an ACK or a NAK from the receiver is garbled or lost, the sender ignores it; in that case, one side or the other will time out and retransmit. A retry count is maintained, and there is a retry threshold, normally set at about 5. Whenever a packet is resent -- because of a timeout, or because it was NAK'd -- the counter is incremented. When it reaches the threshold, the transaction is terminated. If neither side is capable of timing out, a facility for manual intervention must be available on the local KERMIT. Typically, this will work by sampling the keyboard (console) periodically; if input, such as a CR, appears, then the same action is taken as if a timeout had occurred. The local KERMIT keeps a running display of the packet number or byte count on the screen to allow the user to detect when traffic has stopped. At this point, manual intervention should break the deadlock. Shared systems which can become sluggish when heavily used should adjust their own timeout intervals on a per-packet basis, based on the system load, so that file transfers won't fail simply because the system was too slow. 7.2. Errors 7.2. Errors 7.2. Errors During file transfer, the sender may encounter an i/o error on the disk, or the receiver may attempt to write to a full or write-protected device. Any con- dition that will prevent successful transmission of the file is called a "fatal error". Fatal errors should be detected, and the transfer shut down grace- fully, with the pertinent information provided to the user. Error packets provide a mechanism to do this. If a fatal error takes place on either the sending or receiving side, the side which encountered the error should send an Error (E) packet. The E packet con- tains a brief English error message in the data field. Both the sender and receiver should be prepared to receive an Error packet at any time during the transaction. Both the sender and receiver of the Error packet should halt, or go back into into user command mode. The side that is local should print the - 21 - error message on the screen. 7.3. Heuristics 7.3. Heuristics 7.3. Heuristics A few heuristics are useful: 1. A NAK for the current packet is equivalent to an ACK for the pre- vious packet. This covers the common situation in which a packet is successfully received, and then ACK'd, but the ACK is lost. The ACKing side then times out waiting for the next packet and NAKs it. _ _ The side that receives a NAK for packet n+1 while waiting for an ACK _ _ _ for packet n simply sends packet n+1. _ 2. If packet n arrives more than once, simply ACK it and discard it. This can happen when the first ACK was lost. Resending the ACK is ___ necessary and sufficient -- don't write the packet out to the file again! 3. When opening a connection, discard the contents of the line's input buffer before reading or sending the first packet. This is espe- cially important if the other side is in receive mode (or acting as a server), in which case it may have been sending out periodic NAKs for your expected SEND-INIT or command packet. If you don't do this, you may find that there are sufficient NAKs to prevent the transfer -- you send a Send-Init, read the response, which is an old NAK, so you send another Send-Init, read the next old NAK, and so forth, up to the retransmission limit, and give up before getting to the ACKs that are waiting in line behind all the old NAKs. If the number of NAKs is below the cutoff, then each packet may be trans- mitted multiply. 4. Similarly, after reading a packet (successfully or not), you should clear the input buffer. There should be nothing there for you anyway, since the other side must normally wait for you to send your packet in response. Failure to clear the buffer could result in propogation of the repetition of a packet caused by stacked-up NAKs. 7.4. File Names 7.4. File Names 7.4. File Names The syntax for file names can vary widely from system to system. To avoid problems, it is suggested that filenames be represented in the File Header (F) packet in a "normal form", by default (that is, there should be an option to override such conversions). 1. Delete all pathnames and attributes from the file specification. The file header packet should not contain directory or device names; if it does, it may cause the recipient to try to store the file in an inaccessible or nonexistent area, or it may result in a very strange filename. - 22 - 2. After stripping any pathname, convert the remainder of the file ____ ____ specification to the form "name.type", with no restriction on length (except that it fit in the data field of the F packet), and: a. Include no more than one dot. ____ ____ b. Use digits, uppercase letters only in name and type. Special characters like "$", "_", "-", "&", and so forth should be disallowed, since they're sure to cause problems on one system or another. The recipient, of course, cannot depend upon the sender to follow this conven- tion, and should still take precautions. However, since most file systems em- body the notion of a file name and a file type, this convention will allow these items to be expressed in a way that an unlike system can understand. The particular notation is chosen simply because it is the most common. The recipient must worry about the length of the name and type fields of the file name. If either is too long, they must be truncated. If the result (whether truncated or not) is the same as the name of a file that already ex- ists in the same area, the recipient should have the ability to take some spe- cial action to avoid writing over the original file. KERMIT implementations that convert file specifications to normal form by default should have an option to override this feature. This would be most useful when transferring files between like systems, perhaps used in conjunc- tion with "image mode" file transfer. This could allow, for instance, one UNIX system to send an entire directory tree to another UNIX system. 7.5. Robustness 7.5. Robustness 7.5. Robustness A major feature of the KERMIT protocol is the ability to transfer multiple files. Whether a particular KERMIT program can actually send multiple files depends on the capabilities of the program and the host operating system (any KERMIT program can receive multiple files). If a KERMIT program can send multiple files, it should make every attempt to send the entire group specified. If it fails to send a particular file, it should terminate the entire batch, but should go on the the next one, and proceed until an attempt has been made to send each file in the group. Operating in this robust manner, however, gives rise to a problem: the user must be notified of a failure to send any particular file. Unfortunately, it is not sufficient to print a message to the screen; users who initiate long batch transfers may have gone out to lunch and such messages may be long gone by the time they return. Furthermore, there is no way for a remote sender to inform the local receiver of such an error without killing the whole batch transfer, since Error (E) packets always cause the transaction to terminate. One solution might be to invent a non-fatal warning or general purpose display message packet, but this would still not help the user who was not there to see it. A better solution would be to have the sender optionally keep a log of the - 23 - transaction, giving the name of each file for which an attempt was made, and stating whether the attempt was successful, and if not, the reason. 7.6. Flow Control 7.6. Flow Control 7.6. Flow Control On full duplex connections, XON/XOFF flow control can generally be used in con- junction with KERMIT file transfer with no ill effects. This is because XOFFs are sent in the opposite direction of packet flow, so they will not interfere with the packets themselves. XON/XOFF, therefore, need not be implemented by the KERMIT program, but can done by the host system. If the host system provides this capability, it should be used -- if both sides can respond XON/XOFF signals, then buffer overruns and the resulting costly packet retransmissions can be avoided. Flow control via modem signals can also be used when available. - 24 - CHAPTER 8 CHAPTER 8 CHAPTER 8 BASIC KERMIT PROTOCOL STATE TABLE BASIC KERMIT PROTOCOL STATE TABLE BASIC KERMIT PROTOCOL STATE TABLE The KERMIT protocol can be described as a set of states and transitions, and rules for what to do when changing from one state to another. State changes occur based on the type of packets that are sent or received, or errors that may occur. Packets always go back and forth; the sender of a file always sends data packets of some kind (init, header, data) and the receiver always returns ACK or NAK packets. Timeouts and error conditions have been omitted from the following state table for simplicity, but the action is as described above. Upon entering a given state, a certain kind of packet is either being sent or is expected to arrive -- this is shown on top of the description of that state. As a result of the action, various events may take place; these are shown in the EVENT column. For each event, an appropriate ACTION is taken, and the protocol enters a NEW STATE. - 25 - KERMIT PROTOCOL STATE TABLE KERMIT PROTOCOL STATE TABLE KERMIT PROTOCOL STATE TABLE _____ _____ ______ ___ _____ STATE EVENT ACTION NEW_STATE ____ ______ -- SEND STATES -- ____ ____ ____ ______ ____ _________ ______ Send_Send-Init_Packet_____________________________________ S Get NAK,bad ACK (None) S Get good ACK Set remote's params, open file SF (Other) (None) A ____ ____ ______ ______ ____ ___________ ______ Send_File-Header_Packet___________________________________ SF Get NAK,bad ACK (None) SF Get good ACK Get bufferful of file data SD (Other) (None) A ____ ____ ____ ______ ____ _________ ______ Send_File-Data_Packet_____________________________________ SD Get NAK,bad ACK (None) SD Get good ACK Get bufferful of file data SD (End of file) (None) SZ (Other) (None) A ____ ___ ______ ____ ___ ______ Send_EOF_Packet___________________________________________ SZ Get NAK,bad ACK (None) SZ Get good ACK Get next file to send SF (No more files) (None) SB (Other) (None) A ____ _____ ___ ______ ____ _____ _____ ______ Send_Break_(EOT)_Packet___________________________________ SB Get NAK,bad ACK (None) SB Get good ACK (None) C (Other) (None) A _______ ______ -- RECEIVE STATES -- ____ ___ ____ ____ ______ ____ ___ _________ ______ Wait_for_Send-Init_Packet_________________________________ R Get Send-Init ACK w/local params RF (Other) (None) A ____ ___ ____ ______ ______ ____ ___ ___________ ______ Wait_for_File-Header_Packet_______________________________ RF Get Send-Init ACK w/local params (previous ACK was lost) RF Get Send-EOF ACK (prev ACK lost) RF Get Break ACK C Get File-Header Open file, ACK RD (Other) (None) A - 26 - ____ ___ ____ ____ ______ ____ ___ _________ ______ Wait_for_File-Data_Packet_________________________________ RD Get previous packet(D,F) ACK it again RD Get EOF ACK it, close the file RF Get good data Write to file, ACK RD (Other) (None) A ______ ______ __ _______ ___ _________ -- STATES COMMON TO SENDING AND RECEIVING -- C (Send Complete) start A ("Abort") start - 27 - CHAPTER 9 CHAPTER 9 CHAPTER 9 OPTIONAL FEATURES OPTIONAL FEATURES OPTIONAL FEATURES The foregoing sections have discussed basic, required operations for any KERMIT implementation. The following sections discuss optional features. 9.1. 8th-Bit and Repeat Count Prefixing 9.1. 8th-Bit and Repeat Count Prefixing 9.1. 8th-Bit and Repeat Count Prefixing Prefix quoting of control characters is mandatory. In addition, prefixing may also be used for 8-bit quantities or repeat counts, when both KERMIT programs agree to do so. 8th-bit prefixing can allow 8-bit binary data pass through 7-bit physical links. Repeat count prefixing can improve the throughput of certain kinds of files dramatically; binary files (particularly executable programs) and structured text (highly indented or columnar text) tend to be the major beneficiaries. When more than one type of prefixing is in effect, a single data character can be preceded by more than one prefix character. A receiver will never do any kind of prefixing, since prefixing can only occur in the data field, and the receiver only responds with ACKs and NAKs with empty or special data fields. Repeat count processing can only be requested by the sender, and will only be used by the sender if the receiver agrees. 8th-bit prefixing is a special case because it is normally not desirable to use it, since it increases both processing and transmission overhead. However, since it is the only straightforward mechanism for binary file transfer available to those systems that usurp the parity bit, a receiver must be able to request the sender to do 8th-bit quoting, since most senders will not normally do it by default. The repeat prefix is followed immediately by a single-character repeat count, encoded printably via char(), followed by the character itself (perhaps prefixed by control or 8th bit quotes, as explained below). The repeat count may express values from 0 to 94. If a character appears more than 94 times in a row, it must be "cut off" at 94, emitted with all appropriate prefixes, and "restarted". The following table should clarify Kermit's quoting mechanism (the final line shows how a sequence of 120 consecutive NULs would be encoded): Quoted With _________ ______________ ______ _____ ___ _ Character Representation Repeat_Count_for_6 A A ~(A ["(" is ASCII 40 - 32 = 6] ^A #A ~(#A 'A &A ~(&A '^A &#A ~(&#A # ## ~(## '# &## ~(&## & #& ~(#& '& &#& ~(&#& ~ #~ ~(#~ '~ &#~ ~(&#~ NUL #@ ~~#@~:#@ [120 NULs] A represents any printable character, ^A represents any control character, 'x - 28 - represents any character with the 8th bit set. The # character is used for control-character quoting, and the & character for 8-bit quoting. The repeat count must always precede any other prefix character. The repeat count is taken literally (after transformation by unchar(); for instance "#" and "&" im- mediately following a "~" denote repeat counts, not control characters or 8-bit characters. The control quote character "#" is most closely bound to the data character, then the 8-bit prefix, then the repeat count; in other words, the order should be: repeat prefix and count, 8-bit quote, control quote, and the ___ data character itself. To illustrate, note that &#A is not equivalent to #&A. And finally, remember: ________ _________ ____ ___ __ ______ ______ _______ - Prefixed sequences must not be broken across packets. _______ ___ ___ ___ ______ _____ ________ ____ __ ________ - Control, 8th-bit, and repeat count prefixes must be distinct. 9.2. Server Operation 9.2. Server Operation 9.2. Server Operation A KERMIT server is a KERMIT program running remotely with no "user interface". All commands to the server arrive in packets from the local KERMIT. SERVER operation is much more convenient than basic operation, since the user need never again interact directly with the remote KERMIT program after starting it up in server mode, and therefore need not issue complementary SEND and RECEIVE commands on the two sides to get a file transfer started; rather, a single com- mand (SEND or GET) to the local KERMIT suffices. KERMIT servers can also provide services beyond file transfer. Between transactions, a Kermit server waits for packets containing server com- mands. The packet sequence number is always set back to 0 after a transaction. A Kermit server in command wait should be looking for packet 0, and command packets sent to servers should also be packet 0. Certain server commands will result in the exchange of multiple packets. Those operations proceed exactly like file transfer. Server operation must be implemented in two places: in the server itself, and in any KERMIT program that will be communicating with a server. The server must have code to read the server commands from packets and respond to them. The user KERMIT must have code to parse commands to send requests to servers, to form the server command packets, and to handle the responses to those server commands. Server commands are listed below. Not all of them have been implemented, and some may never be, but their use should be reserved. Although server-mode operation is optional, certain commands should be implemented in every server. These include Send-Init (S), Receive-Init (R), and the Generic Logout (GL) and/or Finish (GF) commands. If the server receives a command it does not un- derstand, or cannot execute, it should respond with an Error (E) packet con- taining a message like "Unimplemented Server Command" and both sides should set the packet sequence number back to 0, but the server should remain in server command wait. Only a GL or GF command should terminate server operation. - 29 - Server commands are as follows: S Send Initiate (exchange parameters, server waits for a file). R Receive Initiate (ask the server to send the specified files). I Initialize (exchange parameters). C Host Command. The data field contains a string to be executed as a command by the host system command processor. G Generic Kermit Command. Single character in data field (possibly followed by operands, shown in {braces}, optional fields in [brackets]) specifies the command: I Login [{~user[~password[~account]]}] C CWD, Change Working Directory [{~directory[~password]}] L Logout, Bye F Finish (Shut down the server, but don't logout). D Directory [{~filespec}] U Disk Usage Query [{~area}] E Erase (delete) {~filespec} T Type {~filespec} R Rename {~oldname~newname} K Copy {~source~destination} W Who's logged in? (Finger) [{~user ID or network host[~options]}] M Send a short Message {~destination~text} H Help [{~topic}] Q Server Status Query Tilde as used above ("~") is a length field, encoded using char(), for the 6 operand that follows it. X Text header. Allows transfer of text to the user's screen in response to a generic or host command. This works just like file transfer except that the destination "device" is the screen rather than a file. KERMIT does not provide a mechanism for suspending and continuing a trans- action. This means that text sent to the user's screen should not be frozen for long periods (i.e. not longer than the timeout period times the retry threshold). Between transactions, when the server has no tasks pending, it may send out periodic NAKs (always with type 1 checksums) to prevent a deadlock in case a command was sent to it but was lost. These NAKs can pile up in the local "user" Kermit's input buffer (if it has one), so the user Kermit should be prepared to clear its input buffer before sending a command to a server. _______________ 6 This is an incompatible change from previous editions of this manual, in which the tilde was inserted literally. - 30 - 9.2.1. The R Command 9.2.1. The R Command 9.2.1. The R Command The R packet tells the server to send the files specified by the name in the data field of the R packet. Since we can't assume that the two Kermits are running on like systems, the local (user) Kermit must parse the file specifica- tion as a character string and let the server to check it. If the server likes ___ __ _______________ the filespec, it sends a Send-Init (S) packet -- not an acknowledgement! -- to the user, and then completes the file-sending transaction, as described above. If the server cannot send the file, it should respond with an error packet con- taining a reason, like "File not found" or "Read access required". 9.2.2. Short and Long Replies 9.2.2. Short and Long Replies 9.2.2. Short and Long Replies Any request made of a server may be answered in either of two ways, and any User Kermit that makes such a request should be prepared for either kind of reply: _ _____ _____ - A short reply. This consists of a single ACK packet, which may con- tain text in its data field. For instance, the user might send a disk space query to the server, and the server might ACK the request with a short character string in the data field, such as "12K bytes free". The user KERMIT should display this text on the screen. _ ____ _____ - A long reply. This proceeds exactly like a file transfer (and in some cases it may be a file transfer). It begins with either a a File-He7der (F) packet (optionally followed by one or more Attributes packets ), or a Text-Header (X) packet. Then comes an arbitrary num- ber of Data (D) packets, then an End-Of-File (Z) packet, and finally a Break-Transmission (B) packet. 9.2.3. Additional Server Commands 9.2.3. Additional Server Commands 9.2.3. Additional Server Commands The following server commands request the server to perform tasks other than sending or receiving files. Almost any of these can have either short or long replies. For instance, the Generic Erase (GE) command may elicit a simple ACK, or a stream of packets containing the names of all the files it erased (or didn't erase). These commands are now described in more detail; arguments are as provided in commands typed to the user KERMIT; no transformations to any kind of normal or canonic form are done -- filenames and other operands are in the syntax of the server's host system. _______________ 7 See section 9.5 for a description of the Attributes packet. - 31 - I Login. For use when a KERMIT server is kept perpetually running on a dedi- cated line. This lets a new user obtain an identity on the server's host system. If the data field is empty, this removes the user's identity, so that the next user does not get access to it. A dedicated server such as this should probably disallow the L and F generic commands, listed below. L Logout, Bye. This shuts down the server entirely, causing the server it- self to log out its own job. This is for use when the server has been started up manually by the user, who then wishes to shut it down remotely. F Finish. This is to allow the user to shut down the server, putting its terminal back into normal (as opposed to binary or raw) mode, and putting the server's job back at system command level, still logged in, so that the user can connect back to the job. C CWD. This sets the default directory or area for file transfer on the server's host. With no operands, this command sets the default area to be the user's own default area. D Directory. Send a directory listing to the user. The user program can display it on the terminal or store it in a file, as it chooses. The directory listing should contain file sizes and creation dates as well as file names, if possible. A wildcard or other file-group designator may be specified to ask the server list only those files that match. If no operand is given, all files in the current area will be shown. U Disk Usage Query. The server responds with the amount of space used and the amount left free to use, in K bytes (or other units, which should be specified). E Erase (delete). Delete the specified file or file group. T Type. Send the specified file or file group, indicating (by starting with an X packet rather than an F packet, or else by using the Type attribute) that the file is to be displayed on the screen, rather than stored. R Rename. Change the name of the file as indicated. The string indicating the new name may contain other attributes, such as protection code, per- mitted by the host. K Copy. Produce a new copy of the file or file group, as indicated, leaving the source file(s) unmodified. W Who's logged in? (Finger). With no arguments, list all the users who are logged in on the server's host system. If an argument is specified, provide more detailed information on the specified user or network host. M Short Message. Send the given short (single-packet) message to the in- dicated user's screen. - 32 - 9.2.4. Host Commands 9.2.4. Host Commands 9.2.4. Host Commands Host commands are conceptually simple, but may be hard to implement on some systems. The C packet contains a text string in its data field which is simply fed to the server's host system command processor; any output from the proces- sor is sent back to the user in KERMIT packets, as either a short or long reply. Implementation of this facility under UNIX, with its forking process structure and i/o redirection via pipes, is quite natural. On other systems, it could be virtually impossible. 9.2.5. Exchanging Parameters Before Server Commands 9.2.5. Exchanging Parameters Before Server Commands 9.2.5. Exchanging Parameters Before Server Commands In basic KERMIT, the Send-Init exchange is always sufficient to configure the two sides to each other. During server operation, on the other hand, some transactions may not begin with a Send-Init packet. For instance, when the user sends an R packet to ask the server to send a file, the server chooses what block check option to use. Or if the user requests a directory listing, the server does not know what packet length to use. The solution to this problem is the "I" (Init-Info) packet. It is exactly like a Send-Init packet, and the ACK works the same way too. However, receipt of an I packet does not cause transition to file-send state. The I-packet exchange simply allows the two sides to set their parameters, in preparation for the next transaction. Servers should be able to receive and ACK "I" packets when in server command wait. User KERMITs need not send "I" packets, however; in that case, the serv- er will assume all the defaults for the user listed on page 17. 9.3. Alternate Block Check Types 9.3. Alternate Block Check Types 9.3. Alternate Block Check Types There are two optional kinds of block checks: ____ _ Type_2 A two-character checksum based on the low order 12 bits of the arithmetic sum of the characters in the packet (from the LEN field through the last data character, inclusive) as follows: 1 2 --------+--------------+-------------+ ...data | char(b6-b11) | char(b0-b5) | --------+--------------+-------------+ For instance, if the 16-bit result is 154321 (octal), then the 2 character block check would be "C1". ____ _ Type_3 Three-character 16-bit CRC-CCITT. The CRC calculation treats the data it - 33 - operates upon as a string of bits with the low order bit of the first character first and the high order bit of the last character last. The in- itial value of the CRC is taken as 0; the 16-bit CRC is the remainder after 16 12 5 _ _ _ dividing the data bit string by the polynomial X +X +X +1 (this calcula- tion can actually be done a character at a time, using a simple table lookup algorithm). The result is represented as three printable characters at the end of the packet, as follows: 1 2 3 --------+---------------+--------------+-------------+ ...data | char(b12-b15) | char(b6-b11) | char(b0-b5) | --------+---------------+--------------+-------------+ For instance, if the 16-bit result is 154321 (octal), then the 3 character block check would be "-C1". The single-character checksum has proven quite adequate in practice. The other options can be used only if both sides agree to do so via Init packet (S or I) exchange. The 2 and 3 character block checks should only be used under con- ditions of severe line noise and packet corruption. Since type 2 and 3 block checks are optional, not all KERMITs can be expected to understand them. Therefore, during initial connection, communication must begin using the type 1 block check. If type 2 or 3 block checks are agreed to ____ _____ during the "I" or "S" packet exchange, the switch will occur only after the Send-Init has been sent and ACK'd with a type 1 block check. This means that the first packet with a type 2 or 3 block check must always be an "F" or "X" packet. Upon completion of a transaction, both sides must switch back to type _____ 1. The transaction is over after a "B" or "E" packet has been sent and ACK'd, or after any error that terminates the transaction prematurely or abnormally. A server that has completed a transaction and is awaiting a new command may send out periodic NAKs for that command (packet 0). Those NAKs must have type 1 block checks. 9.4. Interrupting a File Transfer 9.4. Interrupting a File Transfer 9.4. Interrupting a File Transfer This section describes an optional feature of the KERMIT protocol to allow graceful interruption of file transfer. This feature is unrelated to server operation. To interrupt sending a file, send an EOF ("Z") packet in place of the next data packet, including a "D" (for Discard) in the data field. The recipient ACKs the Z packet normally, but does not retain the file. This does not interfere with older Kermits on the receiving end; they will not inspect the data field and will close the file normally. The mechanism can be triggered by typing an interrupt character at the console of the sending KERMIT program. If a (wildcard) file group is being sent, it is possible to skip to the next file or to terminate the entire batch; the protocol is the same in either case, but the desired action could be selected by different interrupt characters, e.g. CTRL-X - 34 - to skip the current file, CTRL-Z to skip the rest of the batch. To interrupt receiving a file, put an "X" in the data field of an ACK for a data packet. To interrupt receiving an entire file group, use a "Z". The user could trigger this mechanism by typing an interrupt character by typing, say, CTRL-X and CTRL-Z, respectively, at the receiving KERMIT's console. A sender that was aware of the new feature, upon finding one of these codes, would act as described above, i.e. send a "Z" packet with a "D" code; a sender that did not implement this feature would simply ignore the codes and continue sending. In this case, and if the user wanted the whole batch to be cancelled (or only one file was being sent), the receiving KERMIT program, after determining that the sender had ignored the "X" or "Z" code, could send an Error (E) packet to stop the transfer. The sender may also choose to send a Z packet containing the D code when the it detects that the file it is sending cannot be sent correctly and completely -- for instance, after sending some packets correctly, it gets an i/o error reading the file. Or, it notices that the "8th bit" of a file byte is set when the file is being sent as a text file and no provision has been made for trans- mitting the 8th bit. 9.5. Transmitting File Attributes 9.5. Transmitting File Attributes 9.5. Transmitting File Attributes The optional Attributes (A) packet provides a mechanism for the sender of a file to provide additional information about it. This packet can be sent if the receiver has indicated its ability to process it by setting the Attributes bit in the capability mask. If both sides set this bit in the Kermit Capability Word, then the sender, after sending the filename in the "F" packet and receiving an acknowledgement, may (but does not have to) send an "A" packet to provide file attribute information. ___ Setting the Attributes bit in the capability mask does not indicate support for any particular attributes, only that the receiver is prepared to accept the "A" packet. The attributes are given in the data field of the "A" packet. The data field consists of 0 or more subfields, which may occur in any order. Each subfield is of the following form: +-----------+--------------+------+ | ATTRIBUTE | char(LENGTH) | DATA | +-----------+--------------+------+ where ATTRIBUTE is a single printable character other than space, LENGTH is the length of the data characters (0 to 94), with 32 added to produce a single printable character, and ______ DATA is length characters worth of data, all printable characters. - 35 - No quoting or prefixing is done on any of this data. More than one attribute packet may be sent. The only requirement is that all the A packets for a file must immediately follow its File header (or X) packet, and precede the first Data packet. There may be 93 different attributes, one for each of the 93 printable ASCII characters other than space. These are assigned in ASCII order. ! (ASCII 33) Length. The data field gives the length in K (1024) bytes, as a printable decimal number, e.g. "!#109". This will allow the receiver to determine in advance whether there is sufficient room for the file, and/or how long the transfer will take. " (ASCII 34) Type. The data field can contain some indicator of the nature of the file. Note that only sequential files can be supported by the KERMIT protocol. Operands are enclosed in {braces}, optional items in [brackets]. A[{xx}] ASCII text, containing no 8-bit quantities, logical records (lines) delimited by the (quoted) control character sequence {xx}, represented here by its printable counterpart (MJ = CRLF, J = LF, etc). For instance AMJ means that the ap- pearance of #M#J (the normal prefixed CRLF sequence) in a file data packet indicates the end of a record. If {xx} is omitted, MJ will be assumed. B[{xx}] Binary. {xx} indicates in what manner the file is binary: 8 (default) The file is a sequence of 8-bit bytes, which must be saved as is. The 8th bit may be sent "bare", or prefixed according to the Send-Init negotiation about 8th-bit prefixing. 36 The file is a PDP-10 format binary file, in which five 7-bit bytes are fit into one 36-bit word, with the final bit of each word being represented as the "parity bit" of every 5th character (perhaps prefixed). D{x} Variable length undelimited records. Each logical record begins with an {x}-character ASCII length field (similar to ANSI tape format "D"). F{xxxx} Fixed-length undelimited records. Each logical record is {xxxx} bytes long. I[{x}] Image. The file is being sent exactly as it is represented on the system of origin. For use between like systems. There are {x} usable bits per character, before prefixing. For instance, to send binary data from a system with 9-bit - 36 - bytes, it might be convenient to send three 6-bit characters for every two 9-bit bytes. Default {x} is 8. # (ASCII 35) Creation Date, expressed as "[yy]yymmdd[ hh:mm[:ss]]" (ISO standard format), e.g. 831009 23:59. The time is optional; if given, it should be in 24-hour format, and the seconds may be omitted, and a single space should separate the time from the date. $ (ASCII 36) Creator's ID, expressed as a character string of the given length. % (ASCII 37) Account to charge the file to, character string. & (ASCII 38) Area in which to store the file, character string. ' (ASCII 39) Password for above, character string. ( (ASCII 40) Block Size. The file is to be stored with the given block size. This may be useful when sending files to or from IBM mainframes, VAX/VMS, or other systems where files may have this attribute. ) (ASCII 41) Access: N New, the normal case -- create a new file of the given name. S Supersede (overwrite) any file of the same name. A Append to file of the given name. * (ASCII 42) Encoding: A ASCII, normal ASCII encoding with any necessary prefixing, etc. H Hexidecimal "nibble" encoding. X Encrypted. E EBCDIC (sent as if it were a binary file). S Sixbit Character set (equivalent to I6). R Radix50 # (ASCII 43) Disposition (operands are specified in the syntax of the receiver's host system): M{user(s)} Send the file as Mail to the specified user(s). O{destination} Send the file as a lOng terminal message to the specified destination (terminal, job, or user). - 37 - S[{options}] Submit the file as a batch job, with any specified options. P[{options}] Print the file on a system printer, with any specified options, which may specify a particular printer, forms, etc. T Type the file on the screen. L[{aaa}] Load the file into memory at the given address, if any. X[{aaa}] Load the file into memory at the given address and eXecute it. , (ASCII 44) Protection. Protection code for the file, in the syntax of the receiver's host file system. With no operand, store according to the system's default protection for the destination area. - (ASCII 45) Protection. Protection code for the file with respect to the "public" or "world", expressed in generically in a 6-bit quantity (made printable by char()), in which the bits have the following meaning: b0: Read Access b1: Write Access b2: Execute Access b3: Append Access b4: Delete Access b5: Directory Listing A one in the bit position means allow the corresponding type of ac- cess, a zero means prohibit it. Others can be imagined, and can be added later if needed. However, two impor- tant points should be noted: - The receiver may have absolutely no way of honoring, or even record- ing, a given attribute. For instance, CP/M-80 has no slot for crea- tion date or creator's ID in its FCB; the DEC-20 has no concept of block size, etc. - The sender may have no way of determining the correct values of any of the attributes. This is particularly true when sending files of foreign origin. The "A" packet mechanism only provides a way to send certain information about a file to the receiver, with no provision or guarantee about what the receiver - 38 - may do with it. That information may be obtained directly from the file's directory entry (FCB, FDB, ...), or specified via user command. The ACK to the "A" packet may in turn have information in its data field. However, no complicated negotiations about file attributes may take place, so the net result is that the receiver may either refuse the file or accept it. The receiver may reply to the "A" packet with any of the following codes in the data field of the ACK packet: (empty data field) I accept the file, go ahead and send it. N[{xxx}] I refuse the file as specified, don't send it; {xxx} is a string of zero or more of the attribute characters listed above, to specify what attributes I object to (e.g. "!" means it's too long, "&" means I don't have write access to the specified area, etc). Y[{xxx}] I agree to receive the file, but I cannot honor attributes {xxx}, so I will store the file according to my own defaults. Y (degenerate case of Y{xxx}, equivalent to , above) How the receiver actually replies is an implementation decision. A NAK in response to the "A" packet means, of course, that the receiver did not receive the "A" correctly, not that it refuses to receive the file. - 39 - CHAPTER 10 CHAPTER 10 CHAPTER 10 KERMIT COMMANDS KERMIT COMMANDS KERMIT COMMANDS The following list of KERMIT commands and terms is suggested. It is not in- tended to recommend a particular style of command parsing, only to promote a consistent vocabulary, both in documentation and in choosing the names for com- mands. 10.1. Basic Commands 10.1. Basic Commands 10.1. Basic Commands SEND This verb tells a Kermit program to send one or more files from its own file structure. RECEIVE This verb should tell a Kermit program to expect one or more files to arrive. GET This verb should tell a user Kermit to send one or more files. Some Kermit implementations have separate RECEIVE and GET commands; others use RECEIVE for both purposes, which creates confusion. Since it can be useful, even necessary, to specify different names for source and destination files, these commands should take operands as follows (optional operands in [brackets]): SEND local-source-filespec [remote-destination-filespec] If the destination file specification is included, this will go in the file header packet, instead of the file's local name. RECEIVE [local-destination-filespec] If the destination filespec is given, the incoming file will be stored under that name, rather than the one in the file header pakcet. GET remote-source-filespec [local-destination-filespec] If the destination filespec is given, the incoming file will be stored under that name, rather than the one in the file header packet. ___ If a file group is being sent or received, alternate names should not be used. 10.2. Program Management Commands 10.2. Program Management Commands 10.2. Program Management Commands EXIT Leave the KERMIT program, doing whatever cleaning up must be done -- deassigning of devices, closing of files, etc. QUIT Leave the KERMIT program without cleaning up, in such a manner as to allow further manipulation of the files and devices. PUSH Preserve the current KERMIT environment and enter the system command processor. TAKE Read and execute KERMIT program commands from a local file. - 40 - 10.3. Terminal Emulation Commands 10.3. Terminal Emulation Commands 10.3. Terminal Emulation Commands CONNECT This verb, valid only for a local Kermit, means to go into terminal emulation mode; present the illusion of being directly connected as a terminal to the remote system. Provide an "escape character" to allow the user to "get back" to the local system. The escape character, when typed, should take a single-character argument; the following are sug- gested: 0 Transmit a NUL B Transmit a BREAK C Close the connection, return to local KERMIT command level P Push to system command processor Q Quit logging (if logging is being done) R Resume logging S Show status of connection ? Show the available arguments to the escape character _ ______ ____ __ ___ ______ _________ (a second copy of the escape character) Transmit the escape character itself Lower case equivalents should be accepted. If any invalid argument is typed, issue a beep. Also see the SET command. 10.4. Special User-Mode Commands 10.4. Special User-Mode Commands 10.4. Special User-Mode Commands These commands are used only by Users of Servers. BYE This command sends a message to the remote server to log itself out, and upon successful completion, the local Kermit program to terminate. FINISH This command causes the remote server to shut itself down gracefully without logging out its job. 10.5. Commands Whose Object Should Be Specified 10.5. Commands Whose Object Should Be Specified 10.5. Commands Whose Object Should Be Specified Some Kermit implementations include various local file management services and commands to invoke them. For instance, an implementation might have commands to let you get directory listings, delete files, switch disks, and inquire about free disk space without having to exit and restart the program. In ad- dition, remote servers may also provide such services. A user Kermit must be able to distinguish between commands aimed at its own system and those aimed at the remote one. When any confusion is possible, such a command may be prefixed by one of the following "object prefixes": REMOTE Ask the remote Kermit server to provide this service. LOCAL Perform the service locally. - 41 - If the "object prefix" is omitted, the command should be executed locally. The services include: LOGIN This should be used in its timesharing sense, to create an identity ("job", "session", "access", "account") on the system. CWD Change Working Directory. This is ugly, but more natural verbs like CONNECT and ATTACH are too imprecise. CWD is the ARPAnet file transfer standard command to invoke this function. DIRECTORY Provide a list of the names, and possibly other attributes, of the files in the current working directory (or the specified directory). SPACE Tell how much space is used and available for storing files in the cur- rent working directory (or the specified directory). DELETE Delete the specified files. ERASE This could be a synomym for DELETE, since its meaning is clear. (It doesn't seem wise to include UNDELETE or UNERASE in the standard list; most systems don't support such a function, and users' expectations should not be toyed with...) COPY Make a new copy of the specified file with the specified name. RENAME Change the name of the specified file. TYPE Display the contents of the specified file(s) at the terminal. SUBMIT Submit the specified file(s) for background (batch) processing. PRINT Print the specified file(s) on a printer. MOUNT Request a mount of the specified tape, disk, or other removable storage medium. WHO Show who is logged in (e.g. to a timesharing system), or give infor- mation about a specified user or network host. MAIL Send electronic mail to the specified user(s). MESSAGE Send a terminal message (on a network or timesharing system). HELP Give brief information about how to use KERMIT. SET Set various parameters relating to debugging, transmission, file mode, and so forth. SHOW Display settings of SET parameters, capabilities in force, etc. - 42 - STATISTICS Give information about the performance of the most recent file transfer -- elapsed time, effective baud rate, various counts, etc. HOST Pass the given command string to the specified (i.e. remote or local) host for execution in its own command language. 10.6. The SET Command 10.6. The SET Command 10.6. The SET Command A SET command should be provided to allow the user to tailor a connection to the peculiarities of the communication path, the local or remote file system, etc. Here are some parameters that should be SET-able: FILE attributes Almost any of the attributes listed above in the Attributes section (9.5). The most common need is to tell the KERMIT program whether an incoming or outbound file is text or binary. DEBUGGING Display or log the packet traffic, packet numbers, and/or program states. Useful for debugging new versions of KERMIT, novel combina- tions of KERMIT programs, etc. DELAY How many seconds a remote (non-server) KERMIT should wait before send- ing the Send-Init packet, to give the user time to escape back to the local KERMIT and type a RECEIVE command. DUPLEX For terminal emulation, specify FULL or HALF duplex echoing. END-OF-LINE Specify any line terminator that must be used after a packet. ESCAPE Specify the escape character for terminal emulation. HANDSHAKE Specify any line-access negotiation that must be used or simulated during file transfer. For instance, a half duplex system will often need to "turn the line around" after sending a packet, in order to give you permission to reply. A common handshake is XOFF; the current user of the line transmits an XOFF when done transmitting data. LINE Specify the line or device designator for the connection. This is for use in a KERMIT program that can run in either remote or local mode; the default line is the controlling terminal (for remote operation). If an external device is used, local operation is presumed. LOG Specify a local file in which to keep a log of the transaction. There may be logs for debugging purposes (packet traffic, state transitions, etc) and for auditing purposes (to record the name and disposition of each file transferred). - 43 - MARKER Change the start-of-packet marker from the default of SOH (CTRL-A) to some other control character, in case one or both systems has problems using CTRL-A for this purpose. PACKET-LENGTH The maximum length for a packet. This should normally be no less than 30 or 40, and can never be greater than 96. Short packets can be an advantage on noisy lines; they reduce the probabily of a particular packet being corrupted, as well as the retransmission overhead when corruption does occur. PADDING The number of padding characters that should be sent before each packet, and what the padding character should be. Rarely necessary. PARITY Specify the parity (ODD, EVEN, MARK, SPACE, NONE) of the physical con- nection. If other than none, the "8th bit" cannot be used to transmit data and must not be used by either side in block check computation. PAUSE How many seconds to pause after receiving a packet before sending the next packet. Normally 0, but when a system communication processor or front end has trouble keeping up with the traffic, a short pause be- tween packets may allow it to recover its wits; hopefully, something under a second will suffice. PREFIX Change the default prefix for control characters, 8-bit characters, or repeated quantities. EIGHT-BIT-PREFIXING Specify that "8th bit" prefixing must be done; normally it will not be done. REPEAT-COUNT-PROCESSING Change the default for repeat count processing. Normally, it will be done if both KERMIT programs agree to do it. RETRY The maximum number of times to attempt to send or receive a packet be- fore giving up. The normal number is about 5, but the user should be able to adjust it according to the condition of the line, the load on the systems, etc. TIMEOUT Specify the length of the timer to set when waiting for a packet to ar- rive. 10.7. Macros 10.7. Macros 10.7. Macros In addition to the individual set commands, a "macro" facility is recommended to allow users to combine the characteristics of specific systems into a single SET option. For example: - 44 - DEFINE IBM = PARITY ODD, DUPLEX HALF, HANDSHAKE XOFF DEFINE UNIX = PARITY NONE, DUPLEX FULL DEFINE TELENET = PARITY MARK This could be done by providing a fancy runtime parser for commands like this (which could be automatically TAKEn from the user's KERMIT initialization file upon program startup), or simply hardwired into the SET command table. With these definitions in place, the user would simply type "SET IBM", "SET UNIX", and so forth, to set up the program to communication to the remote sys- tem. - 45 - CHAPTER 11 CHAPTER 11 CHAPTER 11 TERMINAL EMULATION TERMINAL EMULATION TERMINAL EMULATION The local system must be able to act as a terminal so that the user can connect to the remote system, log in, and start up the remote KERMIT. Terminal emulation should be provided by any KERMIT program that runs locally, so that the user need not exit and restart the local KERMIT program in order to switch between terminal and protocol operation. On smaller systems, this is particularly important for various reasons -- restarting the program and typing in all the necessary SET commands is too inconvenient and time-consuming; in some micros, switching in and out of terminal emulation may cause carrier to drop, etc. Only bare-bones terminal emulation need be supplied by KERMIT; there is no need to emulate any particular kind of "smart" terminal. Simple "dumb" terminal emulation is sufficient to do the job. Emulation of fancier terminals is nice to have, however, to take advantage of the remote system's editing and display capabilities. In some cases, microcomputer firmware will take care of this. To build emulation for a particular type of terminal into the program, you must interpret and act upon escape sequences as they arrive at the port. No error checking is done during terminal emulation. It is "outside the protocol"; characters go back and forth "bare". Terminal emulation through KERMIT is no better than actually using a real terminal. Some KERMIT implementations may allow logging of the terminal emulation session to a local file. Such a facility allows "capture" of remote typescripts and files, again with no error checking or correction. When this facility is provided, it is also desirable to have a convenient way of "toggling" the log- ging on and off. If the local system does not provide system- or firmware-level flow control, like XON/XOFF, the terminal emulation program should attempt to simulate it, especially if logging is being done. The terminal emulation facility should be able to handle either remote or local echoing (full or half duplex), any required handshake, and it should be able to transmit any parity required by the remote side or the communication medium. A terminal emulator works by continuously sampling both console input from the local terminal and input from the communication line. Simple input and output functions will not suffice, however, since if you ask for input from a certain ____ device and there is none available, you will generally hang until input does become available, during which time you will be missing input from the other device. Thus you must have a way to bounce back and forth regardless of whether input is available. Several mechanisms are commonly used: - Continuously jump back and forth between the port status register and the console status register, checking the status bits for input available. This is only practical on single-user, single-process - 46 - systems, where the CPU has nothing else to do. - Issue an ordinary blocking input request for the port, but enable in- terrupts on console input, or vice versa. - Handle port input in one process and console input in another, paral- lel process. The UNIX KERMIT program listed in this manual uses this method. Any input at the port should be displayed immediately on the screen. Any input from the console should be output immediately to the port. In addition, if the connection is half duplex, console input should also be sent immediately to the screen. The terminal emulation code must examine each console character to determine whether it is the "escape character". If so, it should take the next character as a special command, which it executes. These commands are described above, in section 10.3. - 47 - CHAPTER 12 CHAPTER 12 CHAPTER 12 WRITING A KERMIT PROGRAM WRITING A KERMIT PROGRAM WRITING A KERMIT PROGRAM A basic KERMIT implementation can usually be written as a relatively small program, self-contained in a single source file. However, it is often the case that a program written to run on one system will be adapted to run on other systems as well. In that case, it is best to avoid having totally divergent sources, because when new features are added to (or bugs fixed in) the system- independent parts of the program -- i.e. to the protocol itself -- only one im- plementation will reap the benefits initially, and the other will require pain- ful, error-prone "retrofitting" to bring it up to the same level. Thus, if there is any chance that a KERMIT program will run on more than one machine, or under more than one operating system, or support more than one kind of port or modem, etc, it is desirable to isolate the system-dependent parts in a way that makes the common parts usable by the various implementations. There are several approaches: 1. Runtime support. If possible, the program can inspect the hardware or inquire of the system about relevant parameters, and configure itself dynamically at startup time. This is hardly ever possible. 2. Conditional compilation (or assembly). If the number of systems or options to be supported is small, the system dependent code can be enclosed in conditional compilation brackets (like IF WIDGET-8000 .... ENDIF). An example is provided in UNIX KERMIT listing included with this manual. However, as the number of system dependencies to be supported grows, this method becomes unwieldy and error-prone -- installing support for system X may well break the pre-existing support for system Y. 3. Modular composition. When there is a potentially large number of options a program should support, it should be broken up into separate modules (source files), with clearly specified, simple calling conventions. This allows people with new options to provide their own support for them in an easy way, without endangering any existing support. Suggested modules for a KERMIT program are: - System-Indendent protocol handling: state switching, packet formation, encoding (prefixing) and decoding, etc. - User Interface: the command parser. Putting this in a separate module allows plug-in of command parsers to suit the user's taste, to mimic the style of the host system command parser or some popular application, etc. - Screen i/o: Allows various terminals to be supported; this module would contain the screen control codes, cursor position- ing routines, etc. - Port i/o: Allows support of various port hardware. This module - 48 - can define the port status register location, the status bits, and so forth, and can implement the functions to read and write characters at the port. - Modem control: This module would support any kind of "intelligent" modem, which is not simply a transparent exten- sion of the communications port. Such modems may accept spe- cial commands to perform functions like dialing out, redialing a recent number, hanging up, etc. - Console input: This module would supply the function to get characters from the console; it would know about the status register locations and bits, interrupt structure, key-to- character mappings, etc. - File i/o: This module contains all the knowledge about the host system's file structure; how to open and close files, perform "get next file" operations, read and write files, determine and set their attributes, detect the end of a file, and so forth, and provides the functions, including buffering, to get a character from a file and put a character to a file. This module may also provide file management services for local files -- directory listings, deleting, renaming, copying, and so forth. - Terminal emulation: This module would provide terminal emula- tion by calling upon the other system-dependent modules. - Definitions and Data: Separate modules might also be kept for compile-time parameter definitions and for global runtime data. The language to be used in writing a KERMIT program is more than a matter of taste. The primary consideration is that the language provide the necessary functionality and speed. For instance, a microcomputer implementation of BASIC may not allow the kind of low-level access to device registers needed to do terminal emulation, or to detect console input during file transfer, or even if it can do these things, it might not be able to run fast enough do drive the communication line at the desired baud rate. The second consideration in choosing a language is portability. This is used in two senses: (1) whether the language public domain (or, equivalently, provided "free" as part of the basic system), and (2) whether it well standar- dized and in wide use on a variety of systems. A language that is portable in both senses is to be preferred. A new KERMIT program should be thoroughly documented; one of the hallmarks of KERMIT is its documentation. The documentation should be at both the user level (how to use the program, what the commands are, etc, similar to the ______ _____ _____ documentation presently found in the Kermit Users Guide), and the implemen- tation level (describe system dependencies, give pointers for adapting to new systems, and so forth). - 49 - Finally, a bootstrap procedure should be provided. KERMIT is generally dis- tributed on magnetic tape to large central sites; the users at those sites need ways of "downloading" the various implementations to their micros and other local systems. A simple bootstrap procedure would consist of precise instruc- tions on how to accomplish an "unguarded" capture of the program. Perhaps a simple, short program can be written for each each end that will do the job; listings and instructions can be provided for the user to type in and run these programs. - 50 - I. PACKET TYPES I. PACKET TYPES I. PACKET TYPES For reference, here is a complete list of all the defined KERMIT packet types and subtypes. Required types are marked with an asterisk (*). Y* Acknowledge (ACK) N* Negative acknowledge (NAK) S* Send initiate (exchange parameters) I Initialize (exchange parameters). F* File header A File attributes D* Data packet Z* End of file (EOF) B* Break transmission (EOT) E* Error R Receive Initiate (ask the server to send the specified files). C Host Command. G Generic Kermit Command. Subcommands: I Login C CWD, Change Working Directory L Logout, Bye F Finish D Directory U Disk Usage Query E Erase, Delete T Type R Rename K Copy W Who's logged in? M Short Message H Help Q Server Status Query - 51 - II. LIST OF FEATURES II. LIST OF FEATURES II. LIST OF FEATURES There's no true linear scale along which to rate Kermit implementations. A basic, minimal implementation provides file transfer in both directions, and, for microcomputers (PC's, workstations, other single user systems), terminal emulation. Even within this framework, there can be variations. For instance, ____ _____ can the program send a file group in a single command, or must a command be issued for each file? Can it time out? Here is a list of features that may be present; for any KERMIT implementation, the documentation should show whether these features exist, and how to invoke them. - File groups. Can it send a group of files with a single command, using "wildcard", pattern, or list notation? Can it successfully send or receive a group of files of mixed types? Can it recover from an error on a particular file and go on to the next one? Can it keep a log of the files involved showing the disposition of each? - Filenames. Can it take action to avoid overwriting a local file when a new file of the same name arrives? Can it convert filenames to and from "normal form"? - File Attributes. Can transfer binary as well as text files? Can it send and receive Attribute packets? - 8th-Bit prefixing. Can it send and receive 8-bit data through a 7-bit channel using the prefixing mechanism? - Repeat-Count processing. Can it send and receive data with repeated characters replaced by a prefix sequence? - Terminal Emulation. Does it have a terminal emulation facility? Does it provide various communication options, such as duplex, parity, and handshake selection? Can it transmit all ASCII charac- ters? Can it transmit BREAK? Can it log the remote session locally, to provide unguarded file capture? - Communications Options. Can duplex, parity, handshake, and line ter- minator be specified for file transfer? - Block Check Options. In addition to the basic single-character checksum, can the two-character checksum and the three-character CRC be selected? - Basic Server. Can it run in server mode, accepting commands to send or receive files, and to shut itself down? - Advanced Server. Can it accept server commands to delete files, provide directory listings, send messages, and forth? - Issue Commands to Server. Can it send commands to a server, and handle all possible responses? - 52 - - Host Commands. Can it parse and send remote "host commands"? If it is a server, can it pass these commands to the host system command processor and return the results to the local user Kermit? - Interrupt File Transfers. Can it interrupt sending or receiving a file? Can it respond to interrupt requests from the other side? - Local File Management Services. Are there commands to get local directory directory listings, delete local files, and so forth? - File Attributes. Can it send file attribute information about local files, and can deal with incoming file attribute information? - Debugging Capability. Can packet traffic be logged or examined? - 53 - III. A KERMIT PROGRAM III. A KERMIT PROGRAM III. A KERMIT PROGRAM What follows is a listing of a real production version of KERMIT, written in 8 the C language . It is designed to run under various versions of the UNIX operating system. The basic KERMIT functionality is present, but very little in the way of optional features. Only the most rudimentary (UNIX-style) com- mand parser is provided. The program illustrates many of the considerations described in this manual, with respect to the protocol, the program design, and so forth. It must be emphasized that this is a bare minimum implementation of Kermit. Anyone writing a new Kermit from scratch is encouraged to look at the source ______ _____ for one of the more advanced implementations as a model (check the Kermit Users _____ Guide for a list of KERMIT implementations and their features). Although you may not understand the language it's written in, there should be profuse com- ments that can be useful. The following program uses decimal notation for numbers, and tochar() rather than char() for integer-to-character conversion. /* * K e r m i t File Transfer Utility * * UNIX Kermit, Columbia University, 1981, 1982, 1983 * Bill Catchings, Bob Cattani, Chris Maio, Frank da Cruz, Alan Crosswell * * Also: Jim Guyton, Rand Corporation * Walter Underwood, Ford Aerospace * * usage: kermit c [lbe line baud escapechar] to connect * kermit s [d..iflb line baud] file ... to send files * kermit r [d..iflb line baud] to receive files * * where c=connect, s=send, r=receive, * d=debug, i=image mode, f=no filename conversion, l=tty line, * b=baud rate, e=escape char. * * For remote Kermit, format is either: * kermit r to receive files * or kermit s file ... to send files * */ _______________ 8 ___ _ ___________ ________ Kernighan & Ritchie, The C Programming Language: Prentice-Hall (1978) - 54 - /* * Modification History: * * Oct. 17 Included fixes from Alan Crosswell (CUCCA) for IBM_UTS: * - Changed MYEOL character from \n to \r. * - Change char to int in bufill so getc would return -1 on * EOF instead of 255 (-1 truncated to 8 bits) * - Added read() in rpack to eat the EOL character * - Added fflush() call in printmsg to force the output * NOTE: The last three changes are not conditionally compiled * since they should work equally well on any system. * * Changed Berkeley 4.x conditional compilation flag from * UNIX4X to UCB4X. * Added support for error packets and cleaned up the printing * routines. */ #include /* Standard UNIX definitions */ /* Conditional compilation for different machines/operating systems */ /* One and only one of the following lines should be 1 */ #define UCB4X 1 /* Berkeley 4.x UNIX */ #define TOPS_20 0 /* TOPS-20 */ #define IBM_UTS 0 /* Amdahl UTS on IBM systems */ #define VAX_VMS 0 /* VAX/VMS (not yet implemented) */ /* Conditional compilation for the different Unix variants */ /* 0 means don't compile it, nonzero means do */ #if UCB4X #define V6_LIBS 0 /* Dont't use retrofit libraries */ #define NO_FIONREAD 0 /* We have ioctl(FIONREAD,...) for flushinput() */ #define NO_TANDEM 0 /* We have TANDEM line discipline (xon/xoff) */ #endif #if IBM_UTS #define V6_LIBS 0 /* Don't use retrofit libraries */ #define NO_FIONREAD 1 /* No ioctl(FIONREAD,...) for flushinput() */ #define NO_TANDEM 1 /* No TANDEM line discipline (xon/xoff) */ #endif - 55 - #if V6_LIBS #include #include #include #else #include #include #include #endif #if NO_TANDEM #define TANDEM 0 /* define it to be nothing if it's unsupported */ #endif /* Symbol Definitions */ #define MAXPACKSIZ 94 /* Maximum packet size */ #define SOH 1 /* Start of header */ #define CR 13 /* ASCII Carriage Return */ #define SP 32 /* ASCII space */ #define DEL 127 /* Delete (rubout) */ #define ESCCHR '^' /* Default escape character for CONNECT */ #define MAXTRY 10 /* Times to retry a packet */ #define MYQUOTE '#' /* Quote character I will use */ #define MYPAD 0 /* Number of padding characters I will need */ #define MYPCHAR 0 /* Padding character I need (NULL) */ #if IBM_UTS #define MYEOL '\r' /* End-Of-Line character for UTS systems */ #else #define MYEOL '\n' /* End-Of-Line character I need */ #endif #define MYTIME 10 /* Seconds after which I should be timed out */ #define MAXTIM 60 /* Maximum timeout interval */ #define MINTIM 2 /* Minumum timeout interval */ #define TRUE -1 /* Boolean constants */ #define FALSE 0 /* Macro Definitions */ - 56 - /* * tochar: converts a control character to a printable one by adding a space. * * unchar: undoes tochar. * * ctl: converts between control characters and printable characters by * toggling the control bit (ie. ^A becomes A and A becomes ^A). */ #define tochar(ch) ((ch) + ' ') #define unchar(ch) ((ch) - ' ') #define ctl(ch) ((ch) ^ 64 ) /* Global Variables */ int size, /* Size of present data */ rpsiz, /* Maximum receive packet size */ spsiz, /* Maximum send packet size */ pad, /* How much padding to send */ timint, /* Timeout for foreign host on sends */ n, /* Packet number */ numtry, /* Times this packet retried */ oldtry, /* Times previous packet retried */ ttyfd, /* File descriptor of tty for I/O, 0 if remote */ remote, /* -1 means we're a remote kermit */ image, /* -1 means 8-bit mode */ debug, /* indicates level of debugging output (0=none) */ filnamcnv, /* -1 means do file name case conversions */ filecount; /* Number of files left to send */ char state, /* Present state of the automaton */ padchar, /* Padding character to send */ eol, /* End-Of-Line character to send */ escchr, /* Connect command escape character */ quote, /* Quote character in incoming data */ **filelist, /* List of files to be sent */ *filnam, /* Current file name */ recpkt[MAXPACKSIZ], /* Receive packet buffer */ packet[MAXPACKSIZ]; /* Packet buffer */ FILE *fp, /* File pointer for current disk file */ *log; /* File pointer for Logfile */ jmp_buf env; /* Environment ptr for timeout longjump */ - 57 - /* * m a i n * * Main routine - parse command and options, set up the * tty lines, and dispatch to the appropriate routine. */ main(argc,argv) int argc; /* Character pointers to and count of */ char **argv; /* command line arguments */ { char *ttyname, /* tty name for LINE argument */ *cp; /* char pointer */ int speed, /* speed of assigned tty, */ cflg, rflg, sflg; /* flags for CONNECT, RECEIVE, SEND */ struct sgttyb rawmode, /* Controlling tty raw mode */ cookedmode, /* Controlling tty cooked mode */ ttymode; /* mode of tty line in LINE option */ if (argc < 2) usage(); /* Make sure there's a command line */ cp = *++argv; argv++; argc -= 2; /* Set up pointers to args */ /* Initialize these values and hope the first packet will get across OK */ eol = CR; /* EOL for outgoing packets */ quote = '#'; /* Standard control-quote char "#" */ pad = 0; /* No padding */ padchar = NULL; /* Use null if any padding wanted */ speed = cflg = sflg = rflg = 0; /* Turn off all parse flags */ ttyname = 0; /* Default is remote mode */ #if UCB4X /* Default to 7-bit masking, CRLF */ image = FALSE; /* translation and filename case */ filnamcnv = TRUE; /* conversion for UNIX systems */ #else image = TRUE; /* Default to no processing for */ filnamcnv = FALSE; /* non-UNIX systems */ #endif escchr = ESCCHR; /* Default escape character */ while ((*cp) != NULL) /* Parse characters in first arg. */ switch (*cp++) { case 'c': cflg++; break; /* C = Connect command */ case 's': sflg++; break; /* S = Send command */ case 'r': rflg++; break; /* R = Receive command */ - 58 - case 'd': /* D = Increment debug mode count */ debug++; break; case 'f': filnamcnv = FALSE; /* F = don't do case conversion */ break; /* on filenames */ case 'i': /* I = Image (8-bit) mode */ image = TRUE; break; /* (this is default for non-UNIX) */ case 'l': /* L = specify tty line to use */ if (argc--) ttyname = *argv++; else usage(); if (debug) printf("Line to remote host is %s\n",ttyname); break; case 'e': /* E = specify escape char */ if (argc--) escchr = **argv++; else usage(); if (debug) printf("Escape char is \"%c\"\n",escchr); break; case 'b': /* B = specify baud rate */ #if UCB4X if (argc--) speed = atoi(*argv++); else usage(); if (debug) printf("Line speed to remote host is %d\n",speed); break; #else printmsg("Speed setting implemented for Unix only."); exit(1); #endif } /* Done parsing */ if ((cflg+sflg+rflg) != 1) /* Only one command allowed */ usage(); - 59 - if (ttyname) /* If LINE was specified, we */ { /* operate in local mode */ ttyfd = open(ttyname,2); /* Open the tty line */ if (ttyfd < 0) { printmsg("Cannot open %s",ttyname); exit(1); } remote = FALSE; /* Indicate we're in local mode */ } else /* No LINE specified so we operate */ { /* in remote mode (ie. controlling */ ttyfd = 0; /* tty is the communications line) */ remote = TRUE; } /* Put the proper tty into the correct mode */ if (remote) /* If remote, use controlling tty */ { gtty(0,&cookedmode); /* Save current mode so we can */ gtty(0,&rawmode); /* restore it later */ rawmode.sg_flags |= (RAW|TANDEM); rawmode.sg_flags &= ~(ECHO|CRMOD); stty(0,&rawmode); /* Put tty in raw mode */ } else /* Local, use assigned line */ { gtty(ttyfd,&ttymode); ttymode.sg_flags |= (RAW|TANDEM); ttymode.sg_flags &= ~(ECHO|CRMOD); #if UCB4X /* Speed changing for UNIX only */ if (speed) /* User specified a speed? */ { switch(speed) /* Get internal system code */ { case 110: speed = B110; break; case 150: speed = B150; break; case 300: speed = B300; break; case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; - 60 - default: printmsg("Bad line speed."); exit(1); } ttymode.sg_ispeed = speed; ttymode.sg_ospeed = speed; } #endif /* UCB4X */ stty(ttyfd,&ttymode); /* Put asg'd tty in raw mode */ } /* All set up, now execute the command that was given. */ if (debug) { printf("Debugging level = %d\n\n",debug); if (cflg) printf("Connect command\n\n"); if (sflg) printf("Send command\n\n"); if (rflg) printf("Receive command\n\n"); } if (cflg) connect(); /* Connect command */ if (sflg) /* Send command */ { if (argc--) filnam = *argv++; /* Get file to send */ else { if (remote) stty(0,&cookedmode); /* Restore controlling tty's modes */ usage(); /* and give error */ } fp = NULL; /* Indicate no file open yet */ filelist = argv; /* Set up the rest of the file list */ filecount = argc; /* Number of files left to send */ if (sendsw() == FALSE) /* Send the file(s) */ printmsg("Send failed."); /* Report failure */ else /* or */ printmsg("done."); /* success */ } if (rflg) /* Receive command */ { if (recsw() == FALSE) /* Receive the file(s) */ printmsg("Receive failed."); else /* Report failure */ printmsg("done."); /* or success */ } - 61 - if (remote) stty(0,&cookedmode); /* Restore controlling tty's modes */ } /* * s e n d s w * * Sendsw is the state table switcher for sending files. It loops until * either it finishes, or an error is encountered. The routines called * by sendsw are responsible for changing the state. * */ sendsw() { char sinit(), sfile(), sdata(), seof(), sbreak(); state = 'S'; /* Send initiate is the start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ while(TRUE) /* Do this as long as necessary */ { if (debug) printf("sendsw state: %c\n",state); switch(state) { case 'S': state = sinit(); break; /* Send-Init */ case 'F': state = sfile(); break; /* Send-File */ case 'D': state = sdata(); break; /* Send-Data */ case 'Z': state = seof(); break; /* Send-End-of-File */ case 'B': state = sbreak(); break; /* Send-Break */ case 'C': return (TRUE); /* Complete */ case 'A': return (FALSE); /* "Abort" */ default: return (FALSE); /* Unknown, fail */ } } } /* * s i n i t * * Send Initiate: send this host's parameters and get other side's back. */ char sinit() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */ spar(packet); /* Fill up init info packet */ - 62 - flushinput(); /* Flush pending input */ spack('S',n,6,packet); /* Send an S packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': return(state); /* NAK, try it again */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, stay in S state */ return(state); /* and try again */ rpar(recpkt); /* Get other side's init info */ if (eol == 0) eol = '\n'; /* Check and set defaults */ if (quote == 0) quote = '#'; numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ return('F'); /* OK, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, try again */ default: return('A'); /* Anything else, just "abort" */ } } /* * s f i l e * * Send File Header. */ char sfile() { int num, len; /* Packet number, length */ char filnam1[50], /* Converted file name */ *newfilnam, /* Pointer to file name to send */ *cp; /* char pointer */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */ - 63 - if (fp == NULL) /* If not already open, */ { if (debug) printf(" Opening %s for sending.\n",filnam); fp = fopen(filnam,"r"); /* open the file to be sent */ if (fp == NULL) /* If bad file pointer, give up */ { error("Cannot open file %s",filnam); return('A'); } } strcpy(filnam1, filnam); /* Copy file name */ newfilnam = cp = filnam1; while (*cp != '\0') /* Strip off all leading directory */ if (*cp++ == '/') /* names (ie. up to the last /). */ newfilnam = cp; if (filnamcnv) /* Convert lower case to upper */ for (cp = newfilnam; *cp != '\0'; cp++) if (*cp >= 'a' && *cp <= 'z') *cp ^= 040; len = cp - newfilnam; /* Compute length of new filename */ printmsg("Sending %s as %s",filnam,newfilnam); spack('F',n,len,newfilnam); /* Send an F packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, stay in F state */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ size = bufill(packet); /* Get first data from file */ return('D'); /* Switch state to D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in F state */ default: return('A'); /* Something else, just "abort" */ } } - 64 - /* * s d a t a * * Send File Data */ char sdata() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */ spack('D',n,size,packet); /* Send a D packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ if ((size = bufill(packet)) == EOF) /* Get data from file */ return('Z'); /* If EOF set state to that */ return('D'); /* Got data, stay in state D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in D */ default: return('A'); /* Anything else, "abort" */ } } /* * s e o f * * Send End-Of-File. */ char seof() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ - 65 - spack('Z',n,0,packet); /* Send a 'Z' packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless it's NAK for next packet, */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, hold out */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ if (debug) printf(" Closing input file %s, ",filnam); fclose(fp); /* Close the input file */ fp = NULL; /* Set flag indicating no file open */ if (debug) printf("looking for next file...\n"); if (gnxtfl() == FALSE) /* No more files go? */ return('B'); /* if not, break, EOT, all done */ if (debug) printf(" New file is %s\n",filnam); return('F'); /* More files, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in Z */ default: return('A'); /* Something else, "abort" */ } } /* * s b r e a k * * Send Break (EOT) */ char sbreak() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* If too many tries "abort" */ spack('B',n,0,packet); /* Send a B packet */ switch (rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63:num); /* unless NAK for previous packet, */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ - 66 - case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ return('C'); /* Switch state to Complete */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: return(state); /* Receive failure, stay in B */ default: return ('A'); /* Other, "abort" */ } } /* * r e c s w * * This is the state table switcher for receiving files. */ recsw() { char rinit(), rfile(), rdata(); /* Use these procedures */ state = 'R'; /* Receive-Init is the start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ while(TRUE) { if (debug) printf(" recsw state: %c\n",state); switch(state) /* Do until done */ { case 'R': state = rinit(); break; /* Receive-Init */ case 'F': state = rfile(); break; /* Receive-File */ case 'D': state = rdata(); break; /* Receive-Data */ case 'C': return(TRUE); /* Complete state */ case 'A': return(FALSE); /* "Abort" state */ } } } /* * r i n i t * * Receive Initialization */ - 67 - char rinit() { int len, num; /* Packet length, number */ if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ switch(rpack(&len,&num,packet)) /* Get a packet */ { case 'S': /* Send-Init */ rpar(packet); /* Get the other side's init data */ spar(packet); /* Fill up packet with my init info */ spack('Y',n,6,packet); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet type, "abort" */ } } /* * r f i l e * * Receive File Header */ char rfile() { int num, len; /* Packet number, length */ char filnam1[50]; /* Holds the converted file name */ if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */ - 68 - switch(rpack(&len,&num,packet)) /* Get a packet */ { case 'S': /* Send-Init, maybe our ACK lost */ if (oldtry++ > MAXTRY) return('A'); /* If too many tries "abort" */ if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again with */ spar(packet); /* our Send-Init parameters */ spack('Y',num,6,packet); numtry = 0; /* Reset try counter */ return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ if (oldtry++ > MAXTRY) return('A'); if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,0); numtry = 0; return(state); /* Stay in this state */ } else return('A'); /* Not previous packet, "abort" */ case 'F': /* File Header (just what we want) */ if (num != n) return('A'); /* The packet number must be right */ strcpy(filnam1, packet); /* Copy the file name */ if (filnamcnv) /* Convert upper case to lower */ for (filnam=filnam1; *filnam != '\0'; filnam++) if (*filnam >= 'A' && *filnam <= 'Z') *filnam |= 040; if ((fp=fopen(filnam1,"w"))==NULL) /* Try to open a new file */ { error("Cannot create %s",filnam1); /* Give up if can't */ return('A'); } else /* OK, give message */ printmsg("Receiving %s as %s",packet,filnam1); spack('Y',n,0,0); /* Acknowledge the file header */ oldtry = numtry; /* Reset try counters */ numtry = 0; /* ... */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) return ('A'); /* Need right packet number here */ spack('Y',n,0,0); /* Say OK */ return('C'); /* Go to complete state */ - 69 - case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return ('A'); /* Some other packet, "abort" */ } } /* * r d a t a * * Receive Data */ char rdata() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */ switch(rpack(&len,&num,packet)) /* Get packet */ { case 'D': /* Got Data packet */ if (num != n) /* Right packet? */ { /* No */ if (oldtry++ > MAXTRY) return('A'); /* If too many tries, abort */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* Previous packet again? */ spack('Y',num,6,packet); /* Yes, re-ACK it */ numtry = 0; /* Reset try counter */ return(state); /* Don't write out data! */ } else return('A'); /* sorry, wrong number */ } /* Got data with right packet number */ bufemp(packet,len); /* Write the data to the file */ spack('Y',n,0,0); /* Acknowledge the packet */ oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ n = (n+1)%64; /* Bump packet number, mod 64 */ return('D'); /* Remain in data state */ - 70 - case 'F': /* Got a File Header */ if (oldtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ if (num == ((n==0) ? 63:n-1)) /* Else check packet number */ { /* It was the previous one */ spack('Y',num,0,0); /* ACK it again */ numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ } else return('A'); /* Not previous packet, "abort" */ case 'Z': /* End-Of-File */ if (num != n) return('A'); /* Must have right packet number */ spack('Y',n,0,0); /* OK, ACK it. */ fclose(fp); /* Close the file */ n = (n+1)%64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case FALSE: /* Didn't get packet */ spack('N',n,0,0); /* Return a NAK */ return(state); /* Keep trying */ default: return('A'); /* Some other packet, "abort" */ } } /* * c o n n e c t * * Establish a virtual terminal connection with the remote host, over an * assigned tty line. */ connect() { int pid, /* Holds process id of child */ connected; /* Boolean connect flag */ char bel = '\07', c; struct sgttyb rawmode, /* Controlling tty raw mode */ cookedmode; /* Controlling tty cooked mode */ - 71 - if (remote) /* Nothing to connect to in remote */ { /* mode, so just return */ printmsg("No line specified for connection."); return; } gtty(0,&cookedmode); /* Save current mode so we can */ gtty(0,&rawmode); /* restore it later */ rawmode.sg_flags |= (RAW|TANDEM); rawmode.sg_flags &= ~(ECHO|CRMOD); stty(0,&rawmode); /* Put tty in raw mode */ pid = fork(); /* Start fork to get typeout from remote host */ if (pid) /* Parent: send type-in to remote host */ { printmsg("connected...\r"); connected = TRUE; /* Put us in "connect mode" */ while (connected) { read(0,&c,1); /* Get a character */ if ((c&0177) == escchr) /* Check for escape character */ { read(0,&c,1); if ((c&0177) == escchr) write(ttyfd,&c,1); else switch (c&0177) { case 'c': case 'C': connected = FALSE; write(0,"\r\n",2); break; case 'h': case 'H': write(0,"\r\nYes, I'm still here...\r\n",26); break; - 72 - default: write(0,&bel,1); break; } } else { /* If not escape charater, */ write(ttyfd,&c,1); /* write it out */ c = NULL; /* Nullify it (why?) */ } } kill(pid,9); /* Done, kill the child */ wait(0); /* and bury him */ stty(0,&cookedmode); /* Restore tty mode */ printmsg("disconnected."); return; /* Done */ } else /* Child does the reading from the remote host */ { while(1) /* Do this forever */ { read(ttyfd,&c,1); write(1,&c,1); } } } /* * KERMIT utilities. */ clkint() /* Timer interrupt handler */ { longjmp(env,TRUE); /* Tell rpack to give up */ } /* * s p a c k * * Send a Packet */ spack(type,num,len,data) char type, *data; int num, len; { int i; /* Character loop counter */ char chksum, buffer[100]; /* Checksum, packet buffer */ register char *bufp; /* Buffer pointer */ - 73 - if (debug>1) /* Display outgoing packet */ { if (data != NULL) data[len] = '\0'; /* Null-terminate data to print it */ printf(" spack type: %c\n",type); printf(" num: %d\n",num); printf(" len: %d\n",len); if (data != NULL) printf(" data: \"%s\"\n",data); } bufp = buffer; /* Set up buffer pointer */ for (i=1; i<=pad; i++) write(ttyfd,&padchar,1); /* Issue any padding */ *bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */ *bufp++ = tochar(len+3); /* Send the character count */ chksum = tochar(len+3); /* Initialize the checksum */ *bufp++ = tochar(num); /* Packet number */ chksum += tochar(num); /* Update checksum */ *bufp++ = type; /* Packet type */ chksum += type; /* Update checksum */ for (i=0; i> 6)+chksum)&077; /* Compute final checksum */ *bufp++ = tochar(chksum); /* Put it in the packet */ *bufp = eol; /* Extra-packet line terminator */ write(ttyfd, buffer,bufp-buffer+1); /* Send the packet */ } /* * r p a c k * * Read a Packet */ rpack(len,num,data) int *len, *num; /* Packet length, number */ char *data; /* Packet data */ { int i, done; /* Data character number, loop exit */ char t, /* Current input character */ type, /* Packet type */ cchksum, /* Our (computed) checksum */ rchksum; /* Checksum received from other host */ - 74 - #if UCB4X /* TOPS-20 can't handle timeouts... */ if (setjmp(env)) return FALSE; /* Timed out, fail */ signal(SIGALRM,clkint); /* Setup the timeout */ if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME; alarm(timint); #endif /* UCB4X */ while (t != SOH) /* Wait for packet header */ { read(ttyfd,&t,1); t &= 0177; /* Handle parity */ } done = FALSE; /* Got SOH, init loop */ while (!done) /* Loop to get a packet */ { read(ttyfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = t; /* Start the checksum */ *len = unchar(t)-3; /* Character count */ read(ttyfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = cchksum + t; /* Update checksum */ *num = unchar(t); /* Packet number */ read(ttyfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ cchksum = cchksum + t; /* Update checksum */ type = t; /* Packet type */ for (i=0; i<*len; i++) /* The data itself, if any */ { /* Loop for character count */ read(ttyfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynch if SOH */ cchksum = cchksum + t; /* Update checksum */ data[i] = t; /* Put it in the data buffer */ } data[*len] = 0; /* Mark the end of the data */ read(ttyfd,&t,1); /* Get last character (checksum) */ rchksum = unchar(t); /* Convert to numeric */ read(ttyfd,&t,1); /* get EOL character and toss it */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ done = TRUE; /* Got checksum, done */ } - 75 - #if UCB4X alarm(0); /* Disable the timer interrupt */ #endif if (debug>1) /* Display incoming packet */ { if (data != NULL) data[*len] = '\0'; /* Null-terminate data to print it */ printf(" rpack type: %c\n",type); printf(" num: %d\n",*num); printf(" len: %d\n",*len); if (data != NULL) printf(" data: \"%s\"\n",data); } /* Fold in bits 7,8 to compute */ cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */ if (cchksum != rchksum) return(FALSE); return(type); /* All OK, return packet type */ } /* * b u f i l l * * Get a bufferful of data from the file that's being sent. * Only control-quoting is done; 8-bit & repeat count prefixes are * not handled. */ bufill(buffer) char buffer[]; /* Buffer */ { int i, /* Loop index */ t; /* Char read from file */ char t7; /* 7-bit version of above */ i = 0; /* Init data buffer pointer */ while((t = getc(fp)) != EOF) /* Get the next character */ { t7 = t & 0177; /* Get low order 7 bits */ - 76 - if (t7 < SP || t7==DEL || t7==quote) /* Does this char require */ { /* special handling? */ if (t=='\n' && !image) { /* Do LF->CRLF mapping if !image */ buffer[i++] = quote; buffer[i++] = ctl('\r'); } buffer[i++] = quote; /* Quote the character */ if (t7 != quote) { t = ctl(t); /* and uncontrolify */ t7 = ctl(t7); } } if (image) buffer[i++] = t; /* Deposit the character itself */ else buffer[i++] = t7; if (i >= spsiz-8) return(i); /* Check length */ } if (i==0) return(EOF); /* Wind up here only on EOF */ return(i); /* Handle partial buffer */ } /* * b u f e m p * * Put data from an incoming packet into a file. */ bufemp(buffer,len) char buffer[]; /* Buffer */ int len; /* Length */ { int i; /* Counter */ char t; /* Character holder */ for (i=0; i Right angle bracket 0 063 077 3F 6F ? Question mark 1 064 100 40 7C @ "At" sign - 84 - Upper-case alphabetic characters (letters): .....ASCII.... EBCDIC ___ ___ ___ ___ ___ ____ _______ Bit Dec Oct Hex Hex Char Remarks 0 065 101 41 C1 A 0 066 102 42 C2 B 1 067 103 43 C3 C 0 068 104 44 C4 D 1 069 105 45 C5 E 1 070 106 46 C6 F 0 071 107 47 C7 G 0 072 110 48 C8 H 1 073 111 49 C9 I 1 074 112 4A D1 J 0 075 113 4B D2 K 1 076 114 4C D3 L 0 077 115 4D D4 M 0 078 116 4E D5 N 1 079 117 4F D6 O 0 080 120 50 D7 P 1 081 121 51 D8 Q 1 082 122 52 D9 R 0 083 123 53 E2 S 1 084 124 54 E3 T 0 085 125 55 E4 U 0 086 126 56 E5 V 1 087 127 57 E6 W 1 088 130 58 E7 X 0 089 131 59 E8 Y 0 090 132 5A E9 Z More punctuation characters: .....ASCII.... EBCDIC ___ ___ ___ ___ ___ ____ _______ Bit Dec Oct Hex Hex Char Remarks 1 091 133 5B AD [ Left square bracket 0 092 134 5C E0 \ Backslash 1 093 135 5D BD ] Right square bracket 1 094 136 5E 5F ^ Circumflex, up arrow 0 095 137 5F 6D _ Underscore, left arrow 0 096 140 60 79 ` Accent grave - 85 - Lower-case alphabetic characters (letters): .....ASCII.... EBCDIC ___ ___ ___ ___ ___ ____ _______ Bit Dec Oct Hex Hex Char Remarks 1 097 141 61 81 a 1 098 142 62 82 b 0 099 143 63 83 c 1 100 144 64 84 d 0 101 145 65 85 e 0 102 146 66 86 f 1 103 147 67 87 g 1 104 150 68 88 h 0 105 151 69 89 i 0 106 152 6A 91 j 1 107 153 6B 92 k 0 108 154 6C 93 l 1 109 155 6D 94 m 1 110 156 6E 95 n 0 111 157 6F 96 o 1 112 160 70 97 p 0 113 161 71 98 q 0 114 162 72 99 r 1 115 163 73 A2 s 0 116 164 74 A3 t 1 117 165 75 A4 u 1 118 166 76 A5 v 0 119 167 77 A6 w 0 120 170 78 A7 x 1 121 171 79 A8 y 1 122 172 7A A9 z More punctuation characters: .....ASCII.... EBCDIC ___ ___ ___ ___ ___ ____ _______ Bit Dec Oct Hex Hex Char Remarks 0 123 173 7B C0 { Left brace (curly bracket) 1 124 174 7C 4F | Vertical bar 0 125 175 7D D0 } Right brace (curly bracket) 0 126 176 7E 7E ~ Tilde Finally, one more nonprintable character: 0 127 177 7F 07 DEL Delete, rubout - 86 - INDEX INDEX INDEX Protocol 4 8th Bit 6 Raw Mode 9 ACK 8 Records 11 ASCII 7, 81 Remote 6, 9 Reserved Fields 17 Baud 9 Binary Files 10, 11 Send-Init 15 Binary Mode 9 Sequential Files 4 Bit Positions 6 Server 6 Block Check 13 SOH 9 Bootstrap 48 Text Files 11 Capabilies 16 Timeout 24 Char(x) 7 Transaction 19 Checksum 13 Transaction Log 23 Control Characters 13, 82 TTY 6 Ctl(x) 8 Unchar(x) 7 Duplex 10 User 6 EBCDIC 9, 81 XON/XOFF 10, 23, 82 End-Of-Line (EOL) 9, 14 Errors 20 Fatal Errors 20 File Names 21 Flow Control 10, 23 Full Duplex 10 Half Duplex 10 Host 6 Initial Connection 15 KERMIT 4 Language, Programming 48 Line Terminator (see End-Of-Line) Local 6 Logical Records 11 NAK 8 Normal Form for File Names 21 Packet 8, 13 Padding 9 Parity 82 Printable Files 11 Program, Kermit 47, 53 - i - Table of Contents Table of Contents Table of Contents 1. Introduction 1. Introduction 1. Introduction 4 1.1. Background 4 1.2. Overview 4 2. Definitions 2. Definitions 2. Definitions 6 2.1. General Terminology 6 2.2. Numbers 6 2.3. Character Set 7 2.4. Conversion Functions 7 2.5. Protocol Jargon 8 3. System Requirements 3. System Requirements 3. System Requirements 9 4. Printable Text versus Binary Data 4. Printable Text versus Binary Data 4. Printable Text versus Binary Data 11 4.1. Printable Text Files 11 4.2. Binary Files 11 5. Packet Format 5. Packet Format 5. Packet Format 13 6. Initial Connection 6. Initial Connection 6. Initial Connection 15 7. File Transfer 7. File Transfer 7. File Transfer 19 7.1. Timeouts, NAKs, and Retries 20 7.2. Errors 20 7.3. Heuristics 21 7.4. File Names 21 7.5. Robustness 22 7.6. Flow Control 23 8. Basic KERMIT Protocol State Table 8. Basic KERMIT Protocol State Table 8. Basic KERMIT Protocol State Table 24 9. Optional Features 9. Optional Features 9. Optional Features 27 9.1. 8th-Bit and Repeat Count Prefixing 27 9.2. Server Operation 28 9.2.1. The R Command 30 9.2.2. Short and Long Replies 30 9.2.3. Additional Server Commands 30 9.2.4. Host Commands 32 9.2.5. Exchanging Parameters Before Server Commands 32 9.3. Alternate Block Check Types 32 9.4. Interrupting a File Transfer 33 9.5. Transmitting File Attributes 34 - ii - 10. KERMIT Commands 10. KERMIT Commands 10. KERMIT Commands 39 10.1. Basic Commands 39 10.2. Program Management Commands 39 10.3. Terminal Emulation Commands 40 10.4. Special User-Mode Commands 40 10.5. Commands Whose Object Should Be Specified 40 10.6. The SET Command 42 10.7. Macros 43 11. Terminal Emulation 11. Terminal Emulation 11. Terminal Emulation 45 12. Writing a KERMIT Program 12. Writing a KERMIT Program 12. Writing a KERMIT Program 47 I. Packet Types I. Packet Types I. Packet Types 50 II. List of Features II. List of Features II. List of Features 51 III. A KERMIT Program III. A KERMIT Program III. A KERMIT Program 53 IV. The ASCII Character Set IV. The ASCII Character Set IV. The ASCII Character Set 81 Index Index Index 86