IMD 1.16: 1/06/2007 9:43:53 FOGCPM.154 --FOGCPM154KERMIT80DOC KERMIT80DOC !"KERMIT80DOC#$%&'()*+,-./012KERMIT80DOCH3456789:;-01-00 87 -CPM154 DOC KERMIT TXT,<=>?@APROTO DOCBCDEFGHIJKLMNOPQPROTO DOCRSTUVWXYZ[\]^_`aPROTO DOCbcdefghijklmnopqPROTO DOCrstuvwxyz{|}~PROTO DOCPROTO DOCPROTO DOCThis is the disk name.  1 1. CP/M-80 KERMIT Program: Bill Catchings, Columbia University, with contributions from Charles Carvalho (ACC), Bernie Eiben (DEC), Nick Bush (Stevens), John Bray (University of Tennessee), Bruce Tanner (Cerritos College), Greg Small (University of California at Berkeley), Kimmo Laaksonen (Helskini University of Technology), and many others. Language: 8080 Assembler or MAC80 Version: 4.03 Date: December 6, 1984 Documentation: Charles Carvalho, ACC; Frank da Cruz, Columbia KERMIT-80 Capabilities At A Glance: Local operation: Yes Remote operation: No Transfers text files: Yes Transfers binary files: Yes Wildcard send: Yes ^X/^Z interruption: Yes Filename collision avoidance: Yes Can time out:  Yes 8th-bit prefixing: Yes Repeat count prefixing: No Alternate block checks: Yes Terminal emulation: Yes, VT52 and others Communication settings: Yes; duplex, parity Transmit BREAK: Yes; some versions IBM communication: Yes Transaction logging: No Session logging (raw download): Yes Raw upload: Yes Act as server: No Talk to server: Yes; SEND, GET, FIN, BYE Advanced commands for servers: No Local file management: Yes; DIR, ERA, SET DEFAULT disk Handle file attributes: No Command/init files: No Printer control: Yes, limited 1.1. Summary of CP/M CP/M-80 (version 2.2) has only five built-in commands, and they all deal with files; other functions are done by invoking programs. CP/M file specifications are of the form DEV:XXXXXXXX.YYY, where DEV: is a device name, normally the A: or B: floppy. If omitted, the device name defaults to your connected dis- kette. XXXXXXXX is a filename of up to 8 characters. 2 YYY is the file type, up to 3 characters. File names and file types may contain letters, digits, and some special characters, including dash, dollar sign, and underscore, but no imbedded spaces. Upper and lower case letters are equivalent. "Wildcard" file-group specifications are permitted in file names and file types (but not device names) within certain contexts; a "*" matches a whole field, a "?" matches a single character, including space. Ex- amples: "*.F??" specifies all files whose types start with F and are 1, 2, or 3 characters long; "F?.*" specifies all files whose names start with F and are no more than two characters long (before the trailing spaces). The five CP/M commands are: DIR file Lists the the names of the specified files. The default file specification is "*.*". Example: "DIR B:*.FOR". ERA file Erases (deletes) the specified file(s); wildcards al- lowed. REN new old Changes the name of a file from old to new, e.g. "REN NEW.FOR=OLD.FOR". SAVE Saves the specified number of memory blocks into a file. TYPE file Types the specified file on the screen, e.g. "TYPE FOO.TXT". The most important programs are: STAT Gives statistics on disk usage; sets and displays IOBYTE. PIP Peripheral Interchange Program. Copies files. In response to the "*" prompt, give a command of the form disk:outfile=disk:infile Wildcards ("*" for a whole field or "?" for a letter)  can be used. Examples: "A:=B:*.*" to copy a whole disk, "A:=B:*.FOR" to copy all the Fortran programs from disk B to disk A. If the disk specification is omitted, your "connected" disk is assumed. Command line arguments are also accepted, e.g. "PIP A:=B:*.*". For further information on CP/M, consult your microcomputer manual or a CP/M handbook. 3 1.2. Kermit-80 Description Since Kermit-80 runs on a standalone micro, it is always in control of the screen -- it is always local. Thus, it always keeps the screen up- dated with the file name and the packet number, whether sending or receiving. Kermit-80 is capable of an imprecise or "fuzzy" timeout on an input request, and can break deadlocks automatically. In most cases, this is not important, because the KERMIT on the other side is most likely able to handle the timeouts. The timeouts done by Kermit-80 are fuzzy because they depend on the speed of the processor and other fac- tors that can vary from system to system. If despite the timeout capability, the transmission appears to be stuck (and you can tell that this has happened if the screen fails to change for a while) you can type carriage return to have the micro do what it would have done on a timeout, namely NAK the expected packet to cause to foreign host to send it again (or, if the micro is sending, to retransmit the last packet). Micro/micro or micro/IBM-mainframe trans- fers could require this kind of manual intervention. File transfers may be interrupted in several ways. Control-C This will return you to Kermit-80 command level im- mediately, so that you can connect back to the remote system, or take any other desired action. Control-X When sending a file, this will terminate the sending of the current file with a signal to the KERMIT on the other side to discard what it got so far. If there are more files to be sent, KERMIT-80 will go on to the next one. When receiving a file, KERMIT-80 will send a sig- nal to the remote KERMIT to stop sending this file. If the remote KERMIT understands this signal (not all im- plementations of KERMIT do), it will comply, otherwise the file will keep coming. In any case, the remote KER- MIT will go on to the next file in the group, if any. Control-Z Like Control-X, except if a file group is being trans- mitted, this will stop the transmission of the entire group. If only a single file is being transmitted, it works exactly like Control-X. Carriage Return If you type a carriage return Kermit-80 will resend the current packet. You may do this repeatedly, up to the packet retry limit (somewhere between 5 and 16 times) for a particular packet. KERMIT-80 COMMANDS KERMIT-80 uses the DECSYSTEM-20 keyword style command language. Each keyword may be abbreviated to its minumum unique length. "?" may be typed to request a menu of the available options for the current field at any point in a command. ESC may be typed at any point in a command to fill out the current keyword or filename; if sufficient characters have not been typed to identify the current field uniquely, KERMIT-80 4 will sound a beep and allow you to continue from that point. CONNECT Establish a "virtual terminal" connection to any host that may be connected to the serial port, i.e. pass all typein to the serial port and display all input from the serial port on the screen. Also, emulate a DEC VT52 to allow cursor control, screen clearing, etc., if VT52-EMULATION is ON (see below), in which case you should also set your terminal type on the remote host to VT52. (Some versions emulate other terminals.) The es- cape character differs from micro to micro; when you issue the CONNECT command, the micro will print a message telling you how to get back. The escape sequence is generally an uncommonly- used control character, like CTRL-backslash or CTRL-rightbracket, followed by a single letter "command". C Close Connection, return to Kermit-80> command level. S Display Status of connection, but maintain remote connec- tion. ? List available single-character commands. 0 (zero) Send a null (0) character. B Send a BREAK signal. Only some systems provide this func- tion. ^] (or whatever - a second copy of the escape character) Send the escape character itself to the remote host. SEND filespec Send file(s) specified by filespec to the remote Kermit. The filespec may contain CP/M wildcards. RECEIVE Receive file(s) from the remote Kermit. Store them under the names provided in the file headers supplied by the remote host. If the names aren't legal, use as many legal characters from the name as possible (see the description of SET FILE-WARNING below). If there's a conflict, and FILE-WARNING is ON, warn the user and try to build a unique name for the file by adding "&" characters to the name. GET filespec When Kermit-80 is talking to a Kermit Server on the host, you should use the GET command to request the server to send files to you, for example: get hlp:k*.hlp Limitation: If you request an alternate block check type using the SET BLOCK command, the GET command will not communicate it to the remote server. If you want to have type 2 or 3 block checks done when getting files from the server, you have to is- sue the appropriate SET BLOCK command to the remote KERMIT be- fore putting it in server mode. LOG filespec When CONNECTed to a foreign host as a terminal, log the terminal session to the specified diskette file. This functionality depends to some extent on the remote host's ability to do XON/XOFF flow control, and does not guarantee a complete 5 transcript (after all, that's what the KERMIT protocol is for). The log file is closed when the connection is closed by typing the escape character followed by the single-character command "C". TRANSMIT filespec Send the specified  file to the system on the other end of the connection as though it were being typed at the terminal, one line at a time. No KERMIT protocol is involved. You must manually confirm each line. This is useful for sending files to systems that don't have a KERMIT program. During transmission, you may type the escape character followed by one of these single-character commands: C Cease transmission R Re-transmit the previous line BYE When talking to a remote Kermit Server, this command shuts down the server and logs it out, and also exits from Kermit-80 to CP/M command level. LOGOUT Like BYE, but leaves you at Kermit-80 command level. FINISH Like LOGOUT, but shuts down the remote server without logging it out. Leaves you at Kermit-80 command level; subsequent CONNECT commands will put you back at host system command level. VERSION Show the name, edit number, and edit date of several of the modules that make up Kermit-80. SET parameter [value] Set the specified parameter to the specified value. Possible settings: WARNING ON (or OFF) Warn user of filename conflicts when receiving files from remote host, and attempt to generate a unique name by adding "&" characters to the given name. ON by default. VT52-EMULATION ON (or OFF) When connected as a terminal to a foreign host, controls whether the micro emulates a VT52 or runs in "native mode". VT52 emulation is ON by default, except on micros that already have terminal functionality built in, such as the DEC VT180 and DECmate (these act as VT100-series terminals). Some systems emulate other terminals, like the ADM3A; see table 1-3.  LOCAL-ECHO ON (or OFF) When you CONNECT to a remote host, you must set LOCAL- ECHO ON if the host is half duplex, OFF if full duplex. OFF by default. ESCAPE Change the escape character for virtual terminal connec- tions. Kermit-80 will prompt you for the new escape 6 character, which you enter literally. BAUD-RATE Change the baud rate of the communications port. This command only works on some systems. value is the numeric baud rate (300, 9600, etc.) desired. Type SET BAUD followed by a question mark for a list of supported baud rates. On systems that do not support this com- mand, you must set the port baud rate from CP/M or other setup mechanism outside of KERMIT-80. PARITY Sets parity for outgoing characters to one of the fol- lowing: NONE, SPACE, MARK, EVEN, or ODD. On input, if parity is NONE, then the 8th bit is kept (as data), otherwise it is stripped and ignored. The parity set- ting applies to both terminal connection and file trans- fer. If you set parity to anything other than none, KERMIT-80 will attempt to use "8th bit prefixing" to transfer binary files. If the other KERMIT is also capable of 8th bit prefixing, then binary files can be transferred successfully; if not, the 8th bit of each data byte will be lost (you will see a warning on your screen if this happens). TIMER ON (or OFF) Enable or disable the "fuzzy timer". The timer is off by default, because in the normal case KERMIT-80 is com-  municating with a mainframe KERMIT that has its own timer. Mainframe KERMIT timers tend to be more precise or adaptable to changing conditions. You should SET TIMER ON if you are communicating with a KERMIT that does not have a timer. You should SET TIMER OFF if you are communicating over a network with long delays. IBM ON (or OFF) Allow the transfer of files to and from an IBM mainframe computer. This makes Kermit-80 wait for the IBM tur- naround character (XON), ignore parity on input, add ap- propriate parity to output, and use local echoing during CONNECT. As distributed, KERMIT-80 uses MARK parity for IBM communication. If you don't give this command, IBM mode is OFF. Since IBM VM/CMS KERMIT does not have timeout capability, SET IBM ON also turns on the "fuzzy timer" automatically. BLOCK-CHECK-TYPE The options are: 1-CHARACTER-CHECKSUM Normal, default, standard 6-bit checksum. 2-CHARACTER-CHECKSUM A 12-bit checksum encoded as two characters. 3-CHARACTER-CRC-CCITT A 16-bit CCITT-format Cyclic Redundancy Check, encoded as 3 characters. 7 The 2 and 3 character options should only be used under conditions of extreme line noise. Many implementations of KERMIT only support the single character checksum. FILE-MODE Tells KERMIT-80 what kind of file it is sending, so that KERMIT can correctly determine the end of the file. SET FILE BINARY means to send all the 128-byte blocks of the file, including the last block in its entirety; SET FILE ASCII is used for text files, and transmission stops when the first Control-Z is encountered anywhere in the file (this is the CP/M convention for marking the end of a text file). SET FILE DEFAULT tells Kermit to attempt to determine the file type by examining the file being transmitted. If a Control-Z appears before the last block of the file, it is assumed to be BINARY; if, when the first Control-Z is encountered, the remainder of the file contains only control-Z's, it is assumed to be a text file. Unfortunately, not all programs fill the remainder of the last record of a text file with Control-Z's, so this algorithm is not always successful. If binary transmission is used on a text file, some ex- traneous characters (up to 127 of them) may appear at the end of the file on the target system. If ASCII transmission is used on a binary file, the entire file will not be sent if it happens to contain any data bytes that correspond to Control-Z. DEFAULT-DISK This allows you to set the default disk as source and destination of file transfers. In addition, issuing this command causes you to switch to the specified disk and log it in, write-enabled. The colon must be in- cluded in the disk name (A:). The selected disk appears in your KERMIT-80 prompt, for instance Kermit-80 A:> PORT Allows you to switch between different communication ports. This command is not available on all systems.  Type SET PORT ? for a list of valid options for your system. PRINTER ON or OFF. Turns copying of CONNECT session to printer on and off. No attempt is made to do buffering or flow control; Kermit assumes the printer can keep up. DEBUG ON or OFF. Enables/disables displaying of packets on the screen during file transfer. DIRECTORY This provides a directory listing of the specified files. If no files are specified, all files on the default disk are listed. File sizes, in K, are included. You may interrupt the listing at any time by typing any character. The listing (even if interrupted) concludes with a display of the amount of free 8 storage left on the disk. ERASE This executes the CP/M ERA command on the specified file(s). The names of the files being erased are not displayed. 1.3. Kermit-80 Flavors Many of the systems supported use an external terminal, rather than a built-in console. Kermit may be further customized for these systems by defining (at assembly time) the terminal type to be used. If the ter- minal type is unknown or does not match any of the existing terminal op- tions, the generic "CRT" option may be selected. In this case, Kermit cannot do fancy screen control during file transfer; it simply types the file names, packet numbers, and messages in sequence across and down the screen. This works best if you can put your micro or terminal in "autowrap" mode; otherwise the packet numbers will pile up in the rightmost column; the filenames and messages will always appear on a new line, however. If no specific terminal has been selected, Kermit cannot do VT52 emulation; it can act as a "dumb terminal" (sometimes called a "glass TTY"), or else its own built in terminal firmware provides cursor control functions independent of the Kermit program. 1.3.1. Generic Kermit-80 "Generic Kermit-80" is an implementation of Kermit that should run on any 8080-compatible CP/M 2.2 system with no modification at all, or per- haps only a minor one. Unlike other Kermit-80 implementations, it con- tains no system-dependent manipulation of the serial port. All I/O is done with standard CP/M BIOS calls, and I/O redirection is done using the CP/M IOBYTE function, which, according to the Digital Research CP/M Operating System Manual, is an optional feature of any particular CP/M implementation. If your system does not provide the IOBYTE function, Generic Kermit-80 will not work; furthermore, not all systems that im- plement IOBYTE do so in the same way. The SET PORT command may be used to select the devices to be used for input and output. Table 1-1 lists the options to the SET PORT command and their effects. ------------------------------------------------------------------ SET PORT xxx input from output to CRT CRT: CRT: PTR PTR: PTP: TTY TTY: TTY: UC1 UC1: UC1: UR1 UR1: UP1: UR2 UR2: UP2: Table 1-1: Kermit-80 SET PORT Options ------------------------------------------------------------------ The default is SET PORT PTR. In all cases, the console (CON:) and list (LST:) devices used are those selected when Kermit is started. 9 The reason all Kermit-80 implementations aren't generic is that a good deal of speed is sacrificed by getting all services from the operating system. While a specific implementation of Kermit-80 may be able to operate at 4800, 9600, or even 19200 baud, Generic Kermit will fail to work on some systems at speeds in excess of 1200 baud. In addition, many features of Kermit require more specific knowledge of the hardware involved -- Generic Kermit cannot send a BREAK signal, or change the baud rate. 1.3.2. CP/M 3 Kermit CP/M 3 Kermit should run on most CP/M 3 (CP/M-Plus) systems. It uses the auxilliary port (AUX:) to communicate to the remote Kermit. The SET BAUD and SET PORT commands are not supported; nor can a BREAK be sent. Like Generic Kermit, a terminal may be selected at assembly time. 1.3.3. System-Specific Versions There are also many versions of Kermit-80 tailored to specific systems. Most of these operate uniformly, but some of them take advantage (or suffer limitations) of the specific system. Here are some of the spe- cial features for particular systems: Apple II -- two variations: APMMDM: Apple with Z80 Softcard and Micromodem II in slot 2 Dialout capability provided in connect command; user is prompted for phone number if carrier is not present. During connect mode, ^]D drops carrier. BYE command also causes carrier to be dropped. AP6551: Apple with Z80 Softcard, and one of several 6551-based com- munication cards; the slot number is a compile-time parameter (default is slot 2). SET BAUD-RATE supported; speeds are 110-19200 baud. BigBoard II: Uses serial port A. To use port B, change mnport, mnprts, and baudrt and reassemble. Can generate BREAK. SET BAUD-RATE supported; speeds are 300-38400 baud. Digicomp Delphi 100: SET BAUD-RATE supported; speeds are 50-19200 baud. CPT-85xx word processors: Can generate BREAK. SET BAUD-RATE supported; speeds are 50-9600 baud. DEC DECmate II word processor (with Z80 card): Can generate BREAK. DEC VT180 (Robin):  10 Three output ports, referred to as COMMUNICATIONS, GENERAL, and PRINTER. Can generate BREAK. Intertec SuperBrain: SET BAUD-RATE supported; speeds are 50-19200 baud. Kaypro: Should work on most Kaypro models, as well as some related systems (Ferguson BigBoard I, Xerox 820). For the newer Kaypros with mul- tiple ports, Kermit uses the one labeled "serial data"; it cannot use the serial printer or internal modem ports (but it should be possible to modify the values for mnport, mnprts, and baudrt to do this). Can generate BREAK. SET BAUD-RATE supported; speeds are 50-19200 baud. Morrow Decision I: Uses the Multi-I/O board. Port 1 is the console, port 3 is the com- munications line. SET BAUD-RATE supported; speeds are 75-56000 baud. Nokia MicroMikko: Will not echo control-O (which locks keyboard). SET BAUD-RATE sup- ported; speeds are 75-9600 baud. Ohio Scientific: Doesn't have screen control. Osborne 1:Uses serial line, not internal modem. Left-arrow key generates ("delete" or "rubout" character) during connect mode. SET BAUD-RATE supported; speeds are 300 and 1200 baud. TRS-80: Two versions, one for Lifeboat CP/M, one for Pickles & Trout CP/M. 1.4. Installation of Kermit-80 Kermit-80 was written originally for the Intertec SuperBrain in lowest- common-denominator 8080 code with the standard assembler, ASM (single source module, no macros, no advanced instructions), so that it could be assembled on any CP/M-80 system (the 8080 assembler is distributed as a standard part of CP/M-80, whereas the fancier Z80 or macro assemblers are normally commercial products). It has since been modified to run on many other systems as well. Kermit-80 should be able to run on any 8080-, 8085- or Z80-based microcomputer under CP/M with appropriate minor changes to reflect the port i/o a nd screen control for the system (see below). The proliferation of new systems supported by Kermit-80 made the program grow so large and complicated that it had to be broken up into system- independent and system-dependent modules, as of version 4 (this was done by Charles Carvalho of ACC). Each module is composed of multiple files. This has reduced the time and disk space necessary for assembly; Kermit-80 may once again be assembled on a CP/M system with roughly 150Kbytes of space. The majority of the code does not need to be reas- sembled to support a new system. Unfortunately, it can no longer be as- sembled with ASM, since ASM does not support multiple input files. To 11 allow it to be assembled on any CP/M system, the public-domain assembler LASM is included in the distribution kit; Kermit-80 may also be as- sembled with Microsoft's M80 (not supplied), or cross-assembled on a DEC-10 or DEC-20 with MAC80 (also supplied in the distribution kit). In theory, any 8080 assembler supporting the INCLUDE directive ought to work, as well. All versions of Kermit-80 are assembled from the same set of sources, with system dependencies taken care of by assembly-time conditionals within the system-dependent module (eventually, the system-dependent module will itself be broken up into multiple files, one for each system). The most important system dependencies are terminal emulation (when CONNECTed to the remote host) and screen handling, which are de- pendent on the individual micro's escape codes (these features are table driven and easily modified for other CP/M systems), and the lowest level i/o routines for the serial communications port. The port routines are best done only with BDOS calls, but some systems do not allow this, primarily because the BDOS routines strip the parity bit during port i/o, and the parity bit is used for data when transmitting binary files. Kermit-80's I/O routines must check the port status and go elsewhere if no input is available; this allows for virtual terminal connection, keyboard interruption of stuck transmissions, etc. On systems that fully implement I/O redirection via the optional CP/M IOBYTE facility, this may be done by switching the IOBYTE definition. On others, however, IN/OUT instructions explicitly referencing the port device registers must be used. CP/M-80 KERMIT versions 3.8 and later include a "fuzzy timer" that al- lows a timeout to occur after an interval ranging from 5 to 20 seconds (depending upon the speed of the processor and the operating system routines) during which expected input does not appear at the port. In this case, retransmission occurs automatically. In any case, you may type a carriage return during transmission to simulate a timeout when the transfer appears to be stuck. 1.4.1. Organization of Kermit-80 Kermit-80 consists of two modules, each of which is generated from mul- tiple source files. The first module contains the system-independent code; the second module is configured for a particular system and merged with the system-independent module to produce a customized Kermit-80. The distribution kit contains: - the system-independent module, CP4KER.HEX; - the system-dependent modules, CP4*.HEX (see table 1-2); - the source files, CP4*.ASM, - the DEC-10/DEC-20 cross-assembler and linker, MAC80.* and LINK80.*, - the public-domain CP/M assembler, LASM.*, - the public-domain CP/M load/patch utility, MLOAD.* 12 ------------------------------------------------------------------------ Symbol Filename System AP6551 CP4APL Apple II, Z80 Softcard, 6551 ACIA in serial interface APMMDM CP4APM Apple II, Z80 Softcard, Micromodem II in slot 2 BBII CP4BB2 BigBoard II (terminal required) BRAIN CP4BRN Intertec SuperBrain. CPM3 CP4CP3 "generic": CP/M 3.0 (CP/M Plus) systems (terminal req'd) DELPHI CP4DEL Digicomp Delphi 100 (terminal required) DMII CP4DM2 DECmate II with CP/M option GENER CP4GEN "Generic": CPM 2.2 systems with IOBYTE (terminal req'd) HEATH CP4H89 Heath/Zenith H89. KPII CP4KPR Kaypro-II (and 4; probably supports all Kaypro systems) MDI CP4MDI Morrow Decision I (terminal required) MIKKO CP4MIK MikroMikko MMDI CP4UDI Morrow Micro Decision I (terminal required) OSBRN1 CP4OSB Osborne 1 OSI CP4OSI Ohio Scientific ROBIN CP4ROB DEC VT180 TELCON CP4TEL TELCON Zorba portable TRS80LB CP4TLB TRS-80 model II with Lifeboat 2.25C CP/M Display TRS80PT CP4TPT TRS-80 model II with Pickles + Trout CP/M Display VECTOR CP4VEC Vector Graphics. Z100 CP4Z00 Z-100 under CP/M-85 "symbol" is the symbol used to select the target system, in CP4TYP.ASM; "filename" is the name under which the module is supplied in the distrib ution. Table 1-2: Systems supported by Kermit-80 ------------------------------------------------------------------------ 1.4.2. Downloading Kermit-80 You'll need either a pre-configured .COM file or the system-independent module, CP4KER, in binary (.COM) or hex (.HEX) format and the system-de- pendent overlay for your system (from table 1-2). If your system is not listed in the table, get the generic CP/M 2.2 Kermit or the generic CP/M 3 Kermit. If you already have a version of Kermit on your micro and you want to install a new version, simply use your present version to get the new files. Transfer the files to your system and skip ahead to "merging the modules". If you do not have a copy of Kermit on your micro, and you cannot borrow a Kermit floppy but you do have access to a mainframe computer with a copy of the Kermit-80 distribution, you should read this section. There are several ways to get Kermit from a host system to your micro. The easiest is to "download" the necessary "hex" files into your micro's memory and then save it on the disk. If you have a terminal emulator program on your micro which can save a copy of the session to disk, con- nect to your host, and type the necessary files. Exit from the emulator, saving the session log, and edit the session log to extract 13 the hex files. Skip ahead to "merging the files". The following is a procedure which, though far from foolproof, should allow you to get a version of Kermit to your CP/M based micro. It depends upon the host prompt, or at least the first character of the host prompt, being some character that cannot appear in a hex file (the valid characters for hex files are the digits 0-9, the upper case let- ters A-F, the colon ``:'', carriage return, and line feed). As soon the prompt character is encountered, the transfer will terminate. If your host does not issue a prompt that will accommodate this scheme, you can achieve the same effect by adding an atsign ``@'' to the very end of the hex file before sending it from the host. The program below looks for an atsign (the normal DEC-20 prompt, hex 40). DECSYSTEM-10 users would look for a dot, hex 2E. 1. On your micro, connect to a floppy disk with plenty of free space. Run DDT and type in the following (the comments should not be typed in; they are there just to tell you what's happening): -a100 ;Begin assembling code at 100. 0100 lxi h,ffe ;Where to put HEX file. 0103 shld 300 ;Save the address. 0106 mvi e,d ;Get a CR. 0108 mvi c,4 ;Output function. 010A call 5 010D mvi c,3 ;Input function. 010F call 5 0112 ani 7f ;Turn off the parity. 0114 cpi 40 ;Our DEC-20 prompt atsign?  0116 jz 124 ;Yes, we have whole file. 0119 lhld 300 ;Get the pointer. 011C mov m,a ;Else, store the char. 011D inx h ;Increment the pointer. 011E shld 300 ;Save the pointer. 011F jmp 10d ;Go around again. 0124 mvi a,1a ;Get a control-Z. 0126 lhld 300 ;Get the pointer. 0129 mov m,a ;Store the char. 012A shld 300 ;Save the pointer. 012D lxi h,1000 ;Pointer to file. 0130 shld 310 ;Save the pointer. 0133 mvi c,16 ;Make file. 0135 lxi d,5c 0138 call 5 013B lhld 310 ;Get the file pointer. 013E xchg ;Put it in DE. 013F mvi c,1a ;Set DMA. 0141 call 5 0144 mvi c,15 ;Write DMA to file. 0146 lxi d,5c 0149 call 5 014C lhld 310 ;Get the file pointer. 014F lxi d,80 ;Get the DMA size. 0152 dad d ;Adjust file pointer. 0153 shld 310 ;Save it. 14 0156 lda 301 ;Get high order byte. 0159 cmp h ;Have we passed the end? 015A jm 170 ;Yes. 015D jz 163 ;Maybe. 0160 jmp 13b ;No. 0163 lda 300 ;Get low order byte. 0166 cmp l ;Passed the end? 0167 jm 170 ;Yes. 016A jz 170 ;Yes. 016D jmp 13b ;Not quite. 0170 mvi c,10 ;Close file. 0172 lxi d,5c 0175 call 5 0178 ret 0179 -^C ;(control-C):Return to CP/M A>SAVE 1 FETCH.COM ;Save this program; ; we need to run it twice. 2. Connect to your  host using a terminal or a terminal emulation facility. Ensure that your host does not have your terminal in "page mode". E.g. on the DEC-20, give the Exec command TERMINAL NO PAUSE END-OF-PAGE. 3. Tell the host to display the first hex file (the system-independent module) at your terminal. E.g. on the DEC-20, give the Exec command TYPE CP4KER.HEX, without a ter- minating carriage return. 4. Return to your micro. Make sure your IOBYTE is set so that RDR: and PUN: correspond to the I/O port that is connected to the DEC-20 (this would normally be the case unless you have done something special to change things). Load the program you entered in the first step with DDT, and use it to capture the first hex file: DDT FETCH.COM -icp4ker.hex ;Setup FCB for file CP4KER.HEX. -g100,179 ;Execute the program. Now there should be a file CP4KER.HEX on your connected disk. 5. Return to the host, and tell it to display the second hex file (the system-dependent module for your configuration). Again, do not type the terminating carraige return. 6. Return to your micro, and run the capture program again: DDT FETCH.COM -icp4ovl.hex ;Setup FCB to create CP4OVL.HEX -g100,179 ;Execute the program. Now there should be a file CP4OVL.HEX on your connected disk. Merging the files: 15 1. For purposes of illustration, we will assume the system-de- pendent overlay is called "cp4ovl.hex". The two hex files may be combined with MLOAD or DDT. If you already have a running Kermit, you can transfer MLOAD.HEX to your system and create MLOAD.COM by running LOAD. If you're bootstrapping Kermit, you could transfer MLOAD.HEX to your system the same way you got the other two .HEX files, but it's probably simpler to use DDT to get Kermit running, and get MLOAD later if you need it. 2. Using MLOAD, the two pieces may be easily merged: A>mload kermit40=cp4ker,cp4ovl [some messages about program size, etc.] A> 3. If you don't have MLOAD running, it's a bit more complex: A>ddt cp4ker.hex NEXT PC 3500 0100 -icp4ovl.hex -r NEXT PC xxxx 0000 -^C A>save dd kermit40.com The page count ("dd") used in the SAVE command is calculated from the last address ("xxxx") given by DDT in response to the R command: drop the last two digits and add 1 if they were not zero, then convert from hexadecimal (base 16) to decimal (base 10): 384F becomes 39 hex, which is 57 decimal (3 times 16 plus 9) -- but 3700 becomes 37 hex, or 55 decimal (consult an introductory computing book if you don't under- stand number base conversion). 4. Note that CP/M hex files have checksums on each line. If there were any transmission errors during the downloading process, MLOAD or DDT will notice a bad checksum and will report an error (something like "Illegal Format"). If you get any errors during loading, either fix the hex file lo- cally with an editor, or repeat the transfer. You now should have a running version of Kermit-80, called KERMIT40.COM. Test your new Kermit by running it. If it gives you a prompt, it might be OK. (don't delete your old one yet...). Instead of a prompt, you could get one of two messages indicating that the configuration infor- mation is invalid: ?Kermit has not been configured for a target system or ?Consistency check on configuration failed 16 Of course, neither of these messages should appear if you're building Kermit from the distribution kit. The first message indicates that the overlay was not found where the system-independent module expected to find it, probably because the overlay address is incorrect; the second indicates that the version of CP4LNK used in the system-dependent module is incompatible with the system-independent module. Once you are satisfied that KERMIT40 works correctly, you should rename your old KERMIT.COM to something else, like OKERMIT.COM, and rename KERMIT40.COM to KERMIT.COM. 1.4.3. Assembling Kermit-80 from the sources Kermit-80 is built in two pieces from the following 12 files: The system-independent files: CP4KER.ASM header file CP4DEF.ASM definitions for both KERMIT and KERSYS CP4MIT.ASM initialization, main loop, miscellaneous commands (BYE, EXIT, LOG, SET, SHOW, STATUS, and VERSION) CP4PKT.ASM the KERMIT protocol handler (SEND, RECEIVE, LOGOUT, and FI NISH commands) CP4TT.ASM the transparent commands (TRANSMIT, CONNECT) CP4CPM.ASM CP/M commands (DIR, ERA) CP4WLD.ASM the wildcard handler CP4CMD.ASM the command parser CP4UTL.ASM utility routines and data CP4LNK.ASM linkage area description The system-dependent files: CP4TYP.ASM system selection CP4SYS.ASM system-specific code The system-independent module contains all of the system-independent files except for CP4LNK.ASM, which is assembled into the system-depend- ent module to provide the structures needed to connect the two modules. As distributed, the system-independent module is named CP4KER.HEX. If you have a copy of CP4KER.HEX, you do not need to reassemble the system- independent module to configure Kermit for your system. The system-dependent module consists of CP4TYP.ASM, CP4DEF.ASM, CP4LNK.ASM, and CP4SYS.ASM. One copy of the system-dependent module is supplied already assembled for each supported system; the filename may be obtained from table 1-2. After assembling the two pieces separately, they are combined with DDT or MLOAD into a system-specific Kermit. If you want to rebuild the system-independent module, the only change you may need to make is to select the assembler to be used, in CP4KER.ASM. Define one of MAC80, M80, or LASM to TRUE to select it as the assembler; the others should be defined FALSE. Assuming you have the Microsoft Macro Assembler package (M80/L80), you'll need to do the following: 17 A>m80 cp4ker=cp4ker.asm A>l80 /p:100,cp4ker,cp4ker/n/e This will produce CP4KER.COM. If you are using LASM instead, do this: A>lasm cp4ker LASM will generate CP4KER.HEX and CP4KER.PRN. LASM allows options to be specified in the same way as the standard assembler, ASM, so the command A>lasm cp4ker.abz will read the source files from drive A, send the .HEX file to drive B, and suppress the listing file. If you have access to a TOPS-10 or TOPS-20 system, you can cross-assemble Kermit there with MAC80, producing CP4KER.HEX: .run mac80 *=cp4ker.asm If you want to generate a system-dependent overlay for a particular sys- tem, or want to change the terminal supported, you'll need to check three areas in CP4TYP.ASM: First, the overlay start ADDRESS. The symbol "ovladr" is EQUated to the address of "LNKFLG" in the system-independent module, as the starting address of the overlay (3400H for version 4.03). You'll need to know this value if you're building the overlay with M80/L80. You won't nor- mally need to change this value. Second, the assembler being used. Again, define one of MAC80, M80, and LASM to be TRUE to select it, and define the others to be FALSE. The two modules (system-independent and system-dependent) do not need to be built with the same assembler. Third, the system configuration. Locate your system in table 1-2, then define the appropriate symbol TRUE, and the rest FALSE. If the system comes with a builtin console terminal, define all the terminal switches FALSE. If the system uses an external terminal as the console, locate the terminal in table 1-3 and define the appropriate symbol TRUE, and the remainder FALSE. If the terminal is not listed in table 1-3, use the CRT switch; in this case, VT52 emulation is not supported. In addition, there are a few general and system-specific symbols which may be altered to fit your system: APSLOT For Apple with 6551 ACIA, defines the slot number of the serial card CPUSPD Processor speed in units of 100KHz (currently used only for bbII and kpII for timing loops) TAC For users connecting through ARPAnet TACs: set to TRUE 18 if you wish the default TACTRAP status to be ON. (This may be overridden with the SET TACTRAP command). If you're not connecting through a TAC, set tac to FALSE and ignore tacval. TACVAL For ARPANET TAC users: defines the default TAC intercept character (may be overridden with the SET TACTRAP command) If you are just assembling an existing configuration, you'll need to edit CP4TYP.ASM only. If you are adding support for a new system, you should not modify CP4DEF.ASM or CP4LNK.ASM; if you do, you'll have to change the system- independent module also. Eventually, CP4SYS.ASM will be split into separate files, each of which will generate one or more related systems. When this happens, you'll want to pick the one closest to your system to use as a starting point. After editing CP4TYP.ASM as necessary, assemble and link the overlay as follows: - With M80 (where "xxxx" is the hex value of ovladr from  CP4LNK.ASM): A>m80 cp4typ=cp4typ.asm A>l80 /p:xxxx,cp4typ,cp4typ/n/x/e - With LASM: A>lasm cp4typ - With MAC80 on TOPS-10: .run mac80 *=cp4typ.asm - With MAC80 on TOPS-20: @run mac80 *=cp4typ.asm The overlay (cp4typ.hex) may then be merged with the system-independent module as described above (creating a runnable Kermit from the distribu- tion kit). If you have a TOPS-10 or TOPS-20 system and already have a running Kermit-80 v3.9 or later, you can merge the two .HEX files into a .COM file with LINK80, and transfer the new .COM file to your micro with Ker- mit: - Tops-10: .copy kernew.hex=cp4ker.hex,cp4typ.hex .link80 kernew - Tops-20: 19 @append cp4ker.hex,cp4typ.hex (to) kernew.hex @link80 kernew producing KERNEW.COM. If LINK80 says "?Data overlaid", you have an old version of LINK80, and will have to transfer the .HEX files to the micro and merge them there. ------------------------------------------------------------------------ Symbol Terminal description crt Basic CRT, no cursor positioning adm3a ADM3A Display or lookalike smrtvd Netronics Smartvid-80 tvi925 TVI925, Freedom 100 vt52 VT52 or VT52 emulator such as Heath H19, H29, etc. vt100 VT100 or emulator (most ANSI terminals should work) Table 1-3: Terminals known to Kermit-80 ------------------------------------------------------------------------ 1.5. Adding Support For A New System Kermit-80 is built from a common set of source files; the system-depend- ent module makes heavy use of conditional assembly (this complication will be removed in future releases). The system dependencies arise from attempts to answer some questions: 1. What kind of terminal is to be supported? For many micros, the console is an integral part of the sys- tem, but others can use an external terminal. In either case, the commands to manipulate the screen (position the curser, erase the screen, etc) must be defined. 2. How is the serial line accessed? For systems supporting the IOBYTE function, this is straightforward; the symbol "IOBYT" is defined TRUE. If the serial line is accessed with IN and OUT instructions, it may be possible to use the simple I/O routines provided. In this case, the symbol "INOUT" is defined TRUE, the MNPORT and MNPRTS are defined to be the data and control addresses, respectively, and bit masks for testing for "input data available" and "output buffer empty" must be defined. If the interface is strange, leave IOBYT and INOUT set to FALSE, and provide the I/O routines. 3. What initialization is necessary? You may wish to set the baud rate or configure the serial line at startup. Examples for a number of devices are present. 20 4. What special features are to be supported? You may want to provide the capability to select one of several serial lines with the SET PORT command, or to change the speed of the serial line with the SET BAUD-RATE command. To do this, you'll need to build a command table, using the systems already supported as examples. The ability to send a BREAK signal is desirable. Again, examples for several dif- ferent interfaces (ACIA, SIO, etc) are present. 1.6. Notes on New Features in Kermit-80 Version 4 Debugging aids: SET DEBUG ON will add two fields to the SEND/RECEIVE display, labelled "Spack" and "Rpack". These display the last packet sent and received. Of course, this slows down the transfer, especially if the console is an external terminal. SET DEBUG OFF removes these fields. The VERSION command displays the name, edit number, and edit date of several of the modules that make up Kermit. TAC support: ARPAnet TACs (and many other communication devices such as terminal concentrators, modems, port contention units, network PADs, etc) use a printing character (normally "@") as an intercept character, to allow commands to be issued to the TAC. In order to send this character to the host, it must be typed twice. The command "SET TAC CHARACTER" to Kermit enables the TACtrap and asks the user to specify the TAC intercept character. This character will be automatically doubled when it appears in Kermit protocol messages (sent by the SEND or RECEIVE commands) or when it appears in a file being sent with the TRANSMIT command. It is not automatically doubled when typed by the user in CONNECT mode. "SET TAC ON" enables the TACtrap but does not change the TAC intercept character, which is initially "@". "SET TAC OFF" disables the TACtrap. (These comments apply equally to any com- munication device that uses a printable attention character which it will pass through if doubled.) File buffering: Previous versions of Kermit-80 buffered only one sector (128 bytes) at a time during file transfer operations. This version buffers 16Kbytes at a time, reducing the number of times the floppy drive must be spun up and down, and increasing the effective throughput of the link. If the disk transfer rate is too slow, howver, the remote Kermit may time out and retransmit packets. This will show up on the screen in the "Retries:" field; if this occurs after disk activity, you may want to increase the timeout value on the remote Kermit, or reas- semble Kermit with a smaller value for MAXSEC (in CP4SYS.ASM). This buffer is also used by the TRANSMIT command; the log file enabled by the LOG command is still written a sector at a time.  21 1.7. Future Work Work that needs to be done in future releases includes: - Merge in support for additional CP/M-80 systems, particularly those for which support was recently added to the monolithic v3.x source. - Break up CP4SYS into discrete source files, one for each sys- tem. These source files should serve as simple models for ad- ding support for new systems to Kermit-80 -- only the very basic screen definitions, flags, i/o primitives, initializa- tions, and so forth should appear in each system-dependent file. - Make the file-stepping mechanism faster (buffer the FCB's in th chunks of 16 or 32 or 64). Currently, to access the n file in a directory requires n(n+1)/2 lookups... - Addition of missing features -- compression of repeated characters during packet transmission, transmission of file attributes (particularly size, so that "percent done" can be displayed for both incoming and outbound files), advanced com- mands for servers (REMOTE DIRECTORY, etc), command macros and initialization files, login scripts, remote operation and server mode, etc etc. i Index 8080 8, 10 XON/XOFF 4 ARPAnet 20 Z80 10 Attention Character 20 Baud 6 BIOS 8 Block Check 6 Bootstrap 12 BYE 5 Connect 4 CP/M 10 Downloading 12 Eighth-Bit Prefix 6 Escape Character 4, 5 File-Warning 4 FINISH 5 Generic Kermit-80 8 GET 4 IBM 6 Intercept Character 20 Local 3 Local-Echo 5 LOG 4 LOGOUT 5 NAK 3 Parity 6 RECEIVE 4 SEND 4 SET 5 TAC 20 Timeout 3, 11 TIMER 6 TRANSMIT 5 VERSION 5 Virtual Terminal 4 VT100 5 VT52 5 Warning 5 i Table of Contents 1. CP/M-80 KERMIT 1 1.1. Summary of CP/M 1 1.2. Kermit-80 Description 3 1.3. Kermit-80 Flavors 8 1.3.1. Generic Kermit-80 8 1.3.2. CP/M 3 Kermit 9 1.3.3. System-Specific Versions  9 1.4. Installation of Kermit-80 10 1.4.1. Organization of Kermit-80 11 1.4.2. Downloading Kermit-80 12 1.4.3. Assembling Kermit-80 from the sources 16 1.5. Adding Support For A New System 19 1.6. Notes on New Features in Kermit-80 Version 4 20 1.7. Future Work 21 Index i ii List of Tables Table 1-1: Kermit-80 SET PORT Options 8 Table 1-2: Systems supported by Kermit-80 12 Table 1-3: Terminals known to Kermit-80 19  Date: Fri 22 Jun 84 18:19:34-EDT From: Frank da Cruz Subject: Comparing Kermit with Other Packages To: Info-Kermit@COLUMBIA-20 First let me say that there seem to be two major kinds of commercial packages: the kind that use some variation of MODEM protocol, and the kind that use their own proprietary protocols. First, MODEM (please, any MODEM aficionados feel free to correct any of this)... MODEM and Kermit are similar in that they both use back-and-forth ACK/NAK protocols over asynchronous telecommunication lines. However, MODEM sends fixed-length packets with 128 8-bit data bytes, KERMIT sends variable length packets (up to 96 characters in length) with either 7- or 8-bit data bytes. The MODEM packet control fields use all 8 bits; Kermit control fields only use 7. There are several consequences of all this: MODEM can't work at all over a 7-bit channel, even for text files, because the checksum and other control fields will be wrong. This means that  MODEM can't be used over public packet-switched networks like TELENET, or with hosts that require use of character parity, like IBM mainframes. Kermit can send both text and binary files over either 7-bit channels or 8-bit channels, but the data gets longer if you have to squeeze it through a narrower hole. Certain computing or communication equipment cannot accept 128 characters at a time. Their buffers aren't that big. Kermit can accommodate these systems, but MODEM cannot. Many systems cannot accept all ASCII characters, particularly control characters, transparently (see the message about PRIME above for one of many possible examples). MODEM provides no mechanism for encoding otherwise taboo characters. Non-CPM systems, which do not necessarily allocate files in units of 128 bytes or follow the CTRL-Z end-of-file convention, will often have junk at the end of a file received by MODEM. MODEM, to the best of my knowledge, does not have a good mechanism for transmitting a group of files; Kermit has it built into the protocol. Kermit protocol also includes optional features for management of remote files -- directory listings, file deletion, quota checking, etc. Many of the Kermit programs support these optional features. MODEM sends the file bytes exactly as is, whereas Kermit gives you some options for reformatting and compressing. A "text" file is transformed to "canonical form" by Kermit, i.e. a stream of ASCII characters with the "records" (lines) separated by (encoded) CR/LF sequences, so that it may be stored in useful form on the target system. Thus, Kermit may be used on record-oriented systems (like IBM VM/CMS) or on stream-oriented systems like Unix where there record boundaries may be different (LF instead of CRLF); Kermits on those systems that don't store text files in the canonical manner do the appropriate conversions. In addition, Kermit may also be told to send files as-is. On the other hand, MODEM works nicely between like systems (especially CP/M systems) -- it's more efficient than Kermit because it doesn't have to encode and decode the data, and the packets are somewhat longer. Also, much greater attention has been given in MODEM programs to modems themselves, and MODEM programs are typically able to control dialout modems from various manufacturers, and to run in "remote mode" when dialed up from the "back port" of a micro (but the forthcoming MS-DOS Kermit will have this ability also). MODEM provides the ability to dynamically switch between 8-bit and 16-bit block checks depending on the error rate; KERMIT provides 6, 12, and 16 bit block checks, but one of these must be selected ahead of time and will be used throughout the transfer. There's more, but in short I think that, on balance, Kermit is more flexible and more easily adaptable to new systems; hence its rapid spread to a wide variety of micros, minis, and mainframes. Now, as to commercial packages with proprietary protocols -- well, who knows? In some cases, these protocols may be superior to Kermit in every way. But you have certain problems with any commercial package: Are implementations available for all the systems you want them for? If not, will the vendor write the missing implementations? When? For how much money? Does the protocol make assumptions (like full duplex communication, 8-bit data path) that would lock out certain classes of systems? Do you have enough money to buy the software licenses for your mainframes and each and every one of your micros? Some sites have thousands of micros. A typical commercial file transfer package costs $500-$5000 dollars for the mainframe end and $50-$500 for each micro. Can your vendor fix bugs in a timely fashion? If you had sources, you could fix them yourself, but most vendors don't provide sources. Many commercial packages are very fancy, both in the protocol and the user interface. But they often tend to be specially tailored to a certain combination of systems and/or applications. Kermit is not as fancy as a commercial product that knows how to dial up Dow-Jones and look up your stocks, reformat the data as it comes in, and display it in a color pie chart, all upon a single keystroke. But then that package probably can't exchange text and binary files with 50 or 60 different kinds of systems in a relatively uniform and consistent way. Comments, rebuttals, are invited. - Frank ------------------------------ frames and each and every one of your micros? Some sites have thousands of micros. A typical commercial file transfer package costs $500-$5000 dollars for the mainframe end and $50-$500 for each micro. Can your vendor fix bugs in a timely fashion? If you had sources, you could fix them yourself, but most vendors don't provide sources. Many commercial packages are very fancy, both in the protocol and the user interface. But they often tend to be specially tailored to a certain combin KERMIT PROTOCOL MANUAL Protocol Version 3 1 Frank da Cruz, Bill Catchings Columbia University Center for Computing Activities New York, New York 10027 29 April 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 - Preface to the Protocol Manual In the second edition, the Kermit manual contained everything -- user's guide, protocol description, appendices describing the operation of various microcom- puters, etc. Due to the proliferation of Kermit implementations, and to the growing number of users who aren't interested in the protocol, the manual has been split in two -- a Users Guide and a Protocol Manual. This is the Protocol Manual. It is intended for use by those who wish to produce a new implemen- tation of Kermit. Readers are assumed to be thoroughly familiar with the Ker- mit Users Guide. In splitting the manual into two parts, some new material was added to each part. This part has a new state table, descriptions of some of the features new to version 2 of the protocol (8-bit quoting, server functions). A minor bug was fixed in the KERMIT.C listing. Version 3 differs from version 2 by al- lowing for optional checksum types and data compression. The version 3 manual also clarifies some minor points that were left unstated in the version 2 manual, and the KERMIT.C listing has been replaced by one for an actual produc- tion UNIX KERMIT. 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. To avoid confusion, 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 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. - 2 - 1. The KERMIT Protocol 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. 1.1. Background The KERMIT file transfer protocol is intended for use in an environment where there is a diverse mixture of computers of all types -- micros, workstations, laboratory computers, timesharing systems. All these systems need have in com- mon is the ability to communicate in ASCII over ordinary serial telecommunica- tion lines. KERMIT makes no assumptions about the speed, flow control, or duplex of the systems involved. Various protocols for transferring files over TTY lines already existed when KERMIT was developed. Unlike many of its predecessors, KERMIT is not truly full duplex or "asynchronous"; in order to accommodate itself to half-duplex systems (and to the DEC-20, with its "Achilles Heel" front end), it does not "stack" packets and it does not send long packets; it normally waits for a reply to each packet it sends. Thus transfer rates cannot be achieved that are as high as those for truly asynchronous full duplex protocols. Nevertheless, KERMIT runs at 50-80% efficiency (user bits / baud rate). Its half duplex mode of communication allows it to be implemented on computers with either full or half duplex terminal communications, and in fact it presently runs on IBM mainframes (half duplex), UNIX systems (full duplex, but line-oriented ), and on character-oriented full duplex systems (TOPS-20, most micros). The primary design goals of KERMIT are reliability, portability, simplicity, and file transparency (for textual files). Efficiency has been sacrificed to some extent for portability (especially to work for half duplex systems) and for simplicity. Complex approaches (like multiprocessing/scheduling schemes, multiplexed physical links, multichannel logical links, etc) were were avoided so that the KERMIT specification can be easily implemented on any computer, and that the person who works from the specification has some chance of understand- ing it. The procedure for running KERMIT tends to be complicated because it is intended for individual, rather than system, use. Host servers, embedded signon procedures, etc, are not required so that use of KERMIT will be relatively uniform between any two systems, and any ordinary user can establish a connec- tion. Actually, version 2 of the protocol simplifies the "user interface" a great deal by allowing a server or "slave" mode of operation -- the server is not a permanent feature of the host, but is cranked up by the user as needed. But once running on the user's line, the server simplifies things a great deal. In the following sections, we define some terminology, discuss some minimal re- quirements for host systems, describe the packet format and the protocol. A state table for the protocol is given, and a listing is provided of an actual working implementation of the Kermit "Kernel" in the C language. - 3 - 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 systems -- buffering, duplex, parity, character set, file organization, etc. The service provided is minimal -- no attempt is made at an "integrated" link between two systems. KERMIT provides terminal connection and file transfer, period. File transfer is accomplished by 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 philosophy, 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 highest level to perform any transformations that may be necessary. 1.3. Definitions All numbers in the following text are expressed in octal (base 8) notation un- less otherwise specified. ASCII character mnemonics: NUL Null, idle, ASCII character 0. SOH Start-of-header, ASCII character 1. SP Space, blank, ASCII 40. CR Carriage return, ASCII 15. LF Linefeed, ASCII 12. CRLF A carriage-return linefeed sequence. DEL Delete, rubout, ASCII 177. A control character is considered to be any ASCII character in the range 0 through 37, or the DEL character (177). A printable ASCII character is considered to be any character in the range 40 (SP) through 176 (tilde). Several 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, so these are functions that operate upon the numeric value of single AS- CII characters. char(x) = x+40 Transforms the integer x, which is assumed to lie in the range 0 to 136, into a printable ASCII character; 0 becomes SP, 1 be- comes "!", etc. unchar(x) = x-40 Transforms the character x, which is assumed to be in the printable range (SP through tilde), into an integer in the range 0 to 136. ctl(x) = x XOR 100 Maps between control characters and their printable represen- - 4 - 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 37), or the result of applying CTL to a true control character (i.e. 100 to 137). The transformation is the ex- pected one, viz. ^A becomes A and vice versa. ACK stands for "Acknowledge", a packet that acknowledges receipt of another packet. Not to be confused with the ASCII character ACK. NAK stands for "Negative Acknowledge". A packet that says a packet was received in bad condition (e.g. bad checksum), the wrong packet was received, or an expected packet was never received. Not to be confused with the ASCII character NAK. 1.4. Host System Requirements In order to run on as many different systems as possible, KERMIT makes the fol- lowing assumptions: 1. All printable ASCII characters are acceptable as input to the host and will not be transformed in any way. 2. A single nonprintable ASCII character can be used for synchroniza- tion. The character is normally Control-A (SOH, ASCII 1), but can be redefined. 3. If a host requires a line terminator for terminal input, that ter- minator must be a single ASCII character, presumably a control character such as CR or LF. 4. When using a job's controlling terminal for file transfer, the sys- tem must allow the KERMIT program to set the terminal to half duplex, infinite width (no "wraparound" or CRLF insertion by the operating system), and no translation of incoming or outgoing characters (for instance, raising lowercase letters to uppercase, transforming control characters to printable sequences, etc). In short, the terminal must be put in "raw" mode, and, hopefully, res- tored afterwards to normal operation. 5. The host's terminal input buffer is at least long enough to receive the longest ACK packet (the ACK to the send-initiate packet can be 10 or 12 characters long). _______________ 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 per- mit. - 5 - 6. If a host requires padding, the padding character is in the range ASCII 0-37 or ASCII 177. 7. Both communicating hosts are capable of 8-bit terminal i/o if Kermit is to transfer binary files. The last item may be circumvented for those hosts which insist upon having a parity bit; version 2 of Kermit provides a new 8-bit quoting mechanism, which is described later. KERMIT does not assume: 1. Anything about baud rate. 2. That the host can do XON/XOFF or any other kind of flow control. This kind of flow control can be initiated behind Kermit's back by commands to the host computers. If the hosts support any kind of flow control, then it should be used if possible, since it will cut down on retransmission due to buffering problems. 3. That the host is capable of full duplex operation. Any mixture of half and full duplex hosts is supported. 1.5. Data Representation For transmission between unlike systems, files must be assigned to either of two catagories: printable or binary. A printable file is defined to be one that will make sense on the foreign system -- a document, program source, tex- tual data, etc. A binary file is one that will (and probably can) not make sense on the foreign system -- an executable program, numbers stored in inter- nal format, etc. When binary files are transmitted to an unlike system, it is important only that they can be brought back to the original system (or one like it) intact; no special conversions are necessary during transmission. But for printable 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. All characters are transmitted and interpreted in 7- or 8-bit ASCII. If any conversion is necessary to or from ASCII it is the responsibility of the non- ASCII host do so. It is assumed that the computers implementing this protocol can transmit and receive the printable ASCII characters between 040 and 176 (octal), i.e. space through tilde, without translation. Similarly, it is the responsibility of systems that do not store printable files as sequences of lines delimited by CRLFs to perform the necessary conversions upon input and output. For instance, IBM mainframes might strip trailing blanks on output and add them back on input; UNIX would prepend a CR to its normal record ter- minator, LF, upon output and discard it upon input. Since computers can't be expected to distinguish a printable file from a binary file -- especially one originating from an unlike system -- the user will generally have to give a command to Kermit to tell it whether to perform these conversions. Any ASCII control characters (0-37 octal) and DEL (177 octal) are preceded by a special quote character and mapped to characters in the printable range on - 6 - transmission and unquoted and unmapped upon receipt. This is to prevent un- predicatable actions that can occur when the remote host receives raw control characters (for instance, it might interpret them as flow control signals). 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. 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 control the parity bit, a special prefix character may be prepended, as described below. Data compression is also allowed. A special prefix character will denote that the following character is a repeat count, and the next character is the one to be repeated. These prefix characters can be combined in various ways; for instance a control character with its 8th bit set may be repeated n times, the repeat prefix may be quoted as a data character, etc. See the appendix for a listing of the ASCII alphabet, with EBCDIC equivalents. 1.6. Packet Format The KERMIT protocol is built around exchange of packets of the following for- mat: or where all fields consist of ASCII characters, and: mark Is a synchronization character to mark the beginning of the packet. In standard KERMIT, this is SOH (Control-A, ASCII 1), but may be redefined. count 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. Does not include end of line or padding characters, which are outside the packet and are strictly for the benefit of the operating system. seq The packet sequence number, modulo 100, ranging from 0 to 77 (octal). Sequence numbers "wrap around" to 0 after each group of 64 (decimal) packets. type The packet type, a single ASCII character, one of the following: D Data packet Y Acknowledge (ACK) N Negative acknowledge (NAK) - 7 - S Send initiate B Break transmission F File header Z End of file (EOF) E Error The following are new packet types for version 2 of the protocol. Not all of them have been implemented, and some may never be at all, but their use should be reserved. These packet types have been added to allow for a "Kermit Server", which receives all its commands from the other Kermit, rather than directly from the user. R Receive Initiate. Ask the server to send the specified file(s). C Host Command. The data field contains a string to be executed as a command by the host. 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 Connect, 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 E Erase (delete) {filespec} T Type {filespec} S Submit for batch processing {filespec~options} P Print {filespec~options} W Who's logged in? (Finger) [{user ID}] M Send a Message {user or line ID} H Help Q Server Status Query Note that tilde ("~") is chosen to delimit fields when a command takes more than one operand, on the assumption that tildes are not found in user IDs, passwords, directory names, or account desig- nators on systems that might support Kermit servers. X Text header. Allows transfer of text to the other Kermit'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. data The "contents" of the packet, if any contents are required in the given type of packet, interpreted according to the packet type. Nonprintable ASCII characters (and possibly 8-bit and/or repeated characters) are quoted with prefix characters and suitably transformed. Quoted or prefixed sequences may not be broken across packets. Logical records in printable files are delimited with quoted CRLFs. Any quote charac- ters are included in the count. check A block check on the characters in the packet between, but not includ- ing, the mark and the checksum itself, taken modulo 100 (octal). The check for each packet is computed by both hosts, and must agree if a packet is to be accepted. There are presently 3 types of checks (bit 0 - 8 - is the least significant): 1. Single-character arithmetic sum (REQUIRED); only six bits of the arithmetic sum are included. In order that all the bits of each character contribute to this quantity, the 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 chksum = (s + ((s AND 300)/100)) AND 77 The final result is transformed by CHAR. This is the default block check, and all Kermits must be capable of per- forming it. 2. Two-character arithmetic sum (optional). Bits 6-11 form the first character (via CHAR), bits 0-5 form the second (also via CHAR). 3. Three-character 16-bit CRC-CCITT (optional). The 16-bit CRC 16 12 5 formed from the generating polynomial X +X +X +1 is par- celled into three printable characters, via CHAR: bits 12-15 in the first, 6-11 in the second, and 0-5 in the third. This option will be described in greater detail should it ever actually be implemented. The single-character checksum has proven quite adequate in practice. The other options can be used only if both sides agree to do so. Any line terminator that may be required by the host 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. The contents of the data field for each type of packet may vary depending upon the state of the transmission. For instance, the acknowledgement to a send-in- itiate packet contains various parameters (timing and buffer-size information, etc.), whereas when in file-receiving state, the acknowledgment packet contains no data. 1.7. Smart and Dumb Kermits A "smart" Kermit is one that is capable of timing out; a "dumb" Kermit is one that cannot. A timeout feature is desirable so that Kermit won't wait forever for expected data to arrive. While timing out lets you detect when the remote system or program crashes, the most important use of timeouts is to prevent deadlocks, such as might happen when all or part of a packet is lost in trans- mission (leaving the receiving Kermit waiting for the packet that never ar- rived, and the sending Kermit for the ACK that is never sent). In any conversation between two Kermits, one smart Kermit is sufficient to - 9 - prevent deadlocks. Two smart Kermits also work reliably together. Two dumb Kermits, however, must be watched carefully. The local Kermit should keep some sort of running confirmation on the screen, so that the user can detect when transmission stops. For instance, microcomputer Kermits keep the current packet number on the screen, so that the user can watch it changing. Some provision should be made in a dumb Kermit for manual intervention; for in- stance, if input appears at the keyboard while waiting for a packet, then send a NAK for the expected packet or resend the current one. 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. 1.8. Local and Remote Kermits "Local" refers to the host that has control of the user's terminal; "remote" refers to the other host. "Sending" refers to the host that is sending a file; "receiving" refers the host receiving a file. If the local Kermit is sending, the remote Kermit is receiving. And vice versa. A microcomputer is always in control of the screen, so it can always be con- sidered local. An implementation of Kermit for a multi-terminal system must be able to determine whether it is in control of the terminal or not. In general, if it is sending packets to its controlling terminal (primary output, stdout, TTY:, KB:, or whatever) then it is a remote Kermit; if it is sending packets to an assigned terminal or device (e.g. as specified by the SET LINE command), it is a local Kermit and it should update the screen. At initialization, a Kermit program should determine whether it is local or remote and set a flag that can be used later to determine how it updates the screen, handles errors, etc. 1.9. User and Server Kermits A Kermit Server is always a remote Kermit, a "slave". Unlike ordinary inter- active Kermits, it does not have a "user interface"; it gets all its commands from another Kermit. Most Kermits are not capable of acting as servers, but when a server is available, it is desirable that all implementations of Kermit know how to talk to it. The server is a concept new to version 2 of the Kermit protocol and differs from earlier Kermits by the addition of several new packet types (Receive Init, Generic Command, Host Command). Kermits that want to talk to servers should implement handling for these new packet types. Old Kermits can still send files to servers, but they have no way to ask a server to send files, and no way to shut down a remote server (other than connecting to it and killing it with some host function like ^C). Note that between transactions, when the server has no tasks pending, it sends out periodic NAKs 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. - 10 - 1.10. Initial Connection Protocol The user starts the remote Kermit first via a virtual terminal connection, and then escapes back to the local host and starts or continues the local Kermit. 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 will be retransmitted periodically until the receiving Kermit acknowledges it). The data field in the send-init packet is optional; trailing fields can be omitted to accept default values. <8-bit-quote> where: 1. bufsiz The sending Kermit's maximum buffer size. If none specified, the default value of 96 (decimal) is assumed. The receiving Kermit should send packets no longer than this length. 2. timout The number of seconds after which the sending Kermit wishes to be timed out if no packets have been successfully received by the receiving Ker- mit, provided the receiving Kermit is capable of timeouts. If none specified, the receiving Kermit's default is accepted. The normal value is in the 5-15 second range. A value of 0 means "don't time me out". This value is taken as a guideline rather than an absolute, and may be adjusted on a per-packet basis by timesharing systems depending upon system load. 3. npad The number of padding characters the sending Kermit needs preceding each packet. Some systems may require padding; for instance, some half duplex systems may need some time to "turn the line around". If none specified, or a value of 0 (ASCII NUL) is specified, no padding is done and the contents of the next field is ignored. 4. pad  The character the sending Kermit wants used for padding. Normally NUL (ASCII 0), but some IBM systems want DEL (ASCII 177). If npad is non- zero but pad is omitted, 0 will be used as a padding character. 5. eol The desired line terminator for incoming packets. Only a single con- trol character, transformed by CHAR (not CTL!), is permitted in this field. Hosts cannot specify printable terminators or multi-character terminator sequences. If none specified, carriage return (CR, ASCII 15) is used. 6. quote The printable ASCII character the sending Kermit will use when quoting control characters, in the range 41-76 or 140-176. If none specified, "#" is used. This character is taken literally. 7. 8-Bit-Quote Specify quoting mechanism for 8-bit quantities. A quoting mechanism is necessary when sending binary files to hosts which prevent use of the 8th bit for data. When elected, the quoting mechanism will be used by - 11 - both hosts, and the quote character must be in the range 41-76 or 140-176, but different 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 41-76 or 140-176 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 recommended 8th-bit quoting prefix character is "&". Anything Else: 8-bit quoting will not be done. 8. chktype The type of block check. The only values presently allowed in this field are "1", "2", and "3", though future implementations may allow others. These values specify the single- and double-character arith- metic checksums, or the three-character CRC, described above. If any- thing other than "1" or "2", or if this field is omitted, "1" will be used. The sender requests the desired type of checksum in this field; if the receiver replies with the same type in its ACK then the re- quested type will be used, otherwise the single-character arithmetic checksum must be used ("1"). Both sides, of course, must use the same checksum type. 9. repeat The prefix character to be used to indicate a repeated character. This can be any printable character other than blank (which denotes no repeat count prefix), but "~" is recommended. Both sides must agree (as they must for the block check type), or else repeat counts will not be done. Groups of 4 identical characters or more may be transmitted more efficiently using a repeat count, though an individual implemen- tation may wish to set a higher threshhold. 10-11. Reserved Fields Sites who wish to add their own parameters to the initial connection negotiation must start at field 12 (decimal). Any intervening fields may be left blank (that is, they may contain the space character). The receiving Kermit responds with an ACK ("Y") packet containing the same in- formation as it applies to itself. From that point, both Kermits are "configured" to communicate with each other. In the case of 8-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: bufsiz: system dependent - 12 - npad, pad: 0, no padding. eol: CR (carriage return) quote: the character "#" 8-bit-quote: none, don't do 8-bit quoting chktype: "1", single-character checksum repeat: No repeat count processing Note that there are no prolonged negotiations during this initial connection protocol -- 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 some padding or a special end of line character in order to read the send-init packet. For this reason, there should be SET command parameters to allow the user to specify whatever may be necessary to get the first packet through. When Kermit is running as a server, it is possible for the user side to send a rcv-init packet to it, telling it to fetch some files. Since we can't assume that the two Kermits are running on like systems, the local (user) Kermit must parse the file specification as a character string and let the server to check it. If the server likes the filespec, it sends a send-init packet -- not an acknowledgement! -- to the user, and then behaves as described above. The server may also recognize some kinds of "bureaucratic" packets (containing com- mands to type a file, provide a directory listing, access a directory, etc). In fact, it will sit and listen for packets forever, until it gets one that tells it to shut itself down. 1.11. Prefix Quoting Quoting is used for control characters, and may also be used for 8-bit quan- tities or repeat counts. When more than one type of quoting is in effect, a single character can be preceded by more than one quote character. A receiver will never do any kind of quoting, since quoting can only occur in the data field, and the receiver only send 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 quoting is a spe- cial case, since it is normally not desirable to use it because it increases both processing and transmission overhead. However, since it is the only 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 quot- ing, since most senders will not normally do it by default. The following table should clarify Kermit's quoting mechanism: - 13 - Quoted With Character Representation Repeat Count A A ~(A ["(" is ASCII 40 - 32 = 6] ^A #A ~(#A 'A &A ~(&A '^A &#A ~(&#A # ## ~(## '# &## ~(&## & #& ~(#& '& &#& ~(&#& ~ #~ ~(#~ '~ &#~ ~(&#~ A represents any printable character, ^A represents any control character, 'x 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 quote character "#" is most closely bound to the data charac- ter, followed by the 8-bit prefix, followed by the repeat count; in other words, the order should be: repeat prefix and count, 8-bit quote, control quote, the data character itself. To illustrate, note that &#& is not equiv- alent to #&&. And finally, note that: Quoting sequences must not be broken across packets. 1.12. The KERMIT Protocol The protocol is defined over a transaction. A transaction consists of the suc- cessful or unsuccessful transfer of one or more files. An initial connection is made for each transaction, and the connection is broken at the end of a transaction. The machine sending the file(s) transmits a send-initiate packet. Upon ack- nowledgement, a file header packet (containing the file name as data) is sent, followed by as many data packets as necessary to transmit the file. The file is followed by an end of file packet. The sending machine waits for an ack- nowledgment of each packet from the receiving machine. When all the files are transmitted, an end of transmission packet is sent. If a host times out wait- ing for an acknowledgement, it tries to retransmit the unacknowledged packet several times. If a host times out waiting for some other kind of packet, it can send either a NAK packet for the expected packet or another ACK for the last packet it got. If any packet is garbled or lost in transmission (the lat- ter is detected when the sequence number increases by more than 1, modulo 100, the former by a bad checksum), the host that received it sends a NAK for the garbled or missing packet. The prodecure is the same when a Kermit server is involved, except that user may send a receive-initiate packet, which merely requests the server to send back a send-initiate packet, followed by the files requested.  A few heuristics are useful: 1. A NAK for the current packet is equivalent to an ACK for the pre- - 14 - 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, because it's already there! 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 either in receive mode, or ac- ting as a server, in which case it has 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. 1.13. KERMIT Protocol State Table The KERMIT protocol consists of a set of states, and rules for what to do when changing from one state to another. State changes normally 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 pack- ets. "Smart" Kermits can time out while waiting for a packet. Timeouts have been omitted from the following state table for simplicity, but the action is the same as if the expected packet had been received in bad condition -- it is NAK'd. A local Kermit can print error messages on its own screen. If an error occurs in the remote Kermit, an error message cannot simply be printed at the "terminal" because it will come to the local Kermit in the packet data stream, and will be discarded because it's not a valid packet. Therefore, remote Ker- mits should handle error conditions by sending Error packets containing the text of the error message, and then taking appropriate action, such as breaking transmission with a Break packet. Error conditions generally arise in low level routines which are outside the scope of the state table -- for instance, trying to write onto a full or write-protected disk. Kermit servers always return to "start" state after an error. Here's the state table for version 2 of Kermit; it differs from version 1 only by the addition of the "super state" (which is different for "user" and - 15 - "server" Kermits). Version 1 always starts out in state S or R. Note that 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. STATE EVENT ACTION NEW STATE -- SUPER STATE -- User Mode start Want to send (none) S Want to rcv Send rcv-init R Server Mode start Get send-init (none) R Get rcv-init Find file to send S Can't find file, give error start Get "G" cmd ACK, Execute generic command start Get "C" cmd ACK, Execute host command start (other) Report error start -- SEND STATES -- Send Send-Init Packet S Get NAK,bad ACK (None) S Get good ACK Set remote's parms, 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 - 16 - -- RECEIVE STATES -- Wait for Send-Init Packet R Get Send-Init ACK w/local parms RF (Other) (None) A Wait for File-Header Packet RF Get Send-Init ACK w/local parms (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 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 1.14. Low-Level Considerations The preceding state table shows the packet level protocol. When writing a new Kermit, you still must worry about building the packets and getting them in and out of your machine. This work is best done by low level routines with names like "send-packet", "receive-packet", "get-character", "send-character", etc. The packet-level routines -- which do quoting, build checksums, etc -- would be fairly standard in any implementation of Kermit. Low level i/o routines, however, must be customized for each machine or operating system. Some operat- ing systems make i/o very easy, while others require you to pay a lot of atten- tion to small details. The C program in the next section is an example where the operating system (UNIX in this case) does all the work; you send and receive characters simply by using system READ and WRITE functions. A few general low-level considerations are worth mentioning: End of Line  If your host does not require a record terminator for terminal input -- that is, if it can "wake up" on every character -- then you don't have to worry about line terminators on in- coming packets; you can just skip over everything between the end of a packet and the beginning of the next one. On the other hand, you must supply whatever terminator the other host requires (it tells you what that is in its send-init packet, or in its acknowledgement to yours). Padding Some hosts may require padding, a sequence of "idle characters" (typically NUL or DEL). You have to worry about sending them. - 17 - You don't have to worry about them on input though, since they come between packets, and will probably have been eaten by some other process or interface anyway (or else why would you need them?). Timeout When doing input on the serial port, it is desirable to get an interrupt to wake you up after a certain amount of time if nothing comes in. Or, if you have a port status register, you can have a loop that looks at it a certain number of times be- fore giving up. Or, you can check both the port and the keyboard each time through the loop, which allows wakeup from hung protocol when the user gives typein. Quoting Once characters have been successfully received, quoted control characters, prefixed 8-bit bytes, or repeat-count sequences must be fixed. Similarly, the quoting transformations must be done when filling a packet, before sending it out or computing the block check. Parity Character-level routines must know how to handle the parity bit. This is normally controlled by the settings of some flags that say whether incoming characters have data or parity in the 8th bit, and whether the 8th bit must be used for parity on outgoing characters, and if so, what kind of parity. Handshake When dealing with record-oriented or half duplex systems, you may have to worry about line turnaround. Again, the user nor- mally sets a special flag, which should be checked before send- ing a packet. For instance, when communicating with an IBM host, a packet cannot be sent until you have an XON. Local file i/o In addition to port i/o, each Kermit must know how to do i/o to its own file structure. The DEC-20 has to worry about whether the file is to be opened in 8-bit or 7-bit mode, and should make sure not to try  to send certain kinds of files (directories, archived files, RMS files, etc). IBM VM/CMS Ker- mit must worry about LRECL, BLKSIZE, RECFM, and so on. Micros must worry about ^Zs at end of file, and funny files created by word processing software. Most systems have to worry about conflicts arising when an incoming file has the same name as an existing file. Terminal emulation When doing terminal emulation (although this is outside the protocol), Kermit must worry about whether to echo characters locally or to let the host do it; it must do whatever must be done with parity bits in both directions; it must interpret screen control codes; it must watch out for the escape charac- ter. Here, for instance, is more or less what a micro has to do to send a packet (which is already built, with all quoting done): 1. Loop thru all chars in packet, building checksum. 2. Add eol if required. 3. Padding? Yes, send n pad chars. - 18 - 4. Sending to IBM? Yes, wait for XON. 5. Timed out? Whoops, give up. 6. Send each character. To send a character: 1. Get port status. 2. Ready? No, repeat previous step. 3. Set parity bit appropriately. 4. Output the character. Getting a character: 1. Get port status. 2. If no character, then check console. 3. If nothing either place, back to step 1. 4. Got char from port. Doing parity? Yes, turn it off. 5. Dispatch appropriately. - 19 - 2. The KERMIT Program What follows is a listing of a real production version of KERMIT, written in the C language, that runs under the UNIX operating system. This program imple- ments version 1 of the protocol, and even that not entirely (for instance, er- ror packets are not sent or processed). Only the most rudimentary command par- ser is provided; the Kermit Users Guide shows the commands that more advanced Kermits have. 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 -- Kermit-20, Kermit-80, Kermit-86 -- as a model. Although you may not understand the language they're written in, there are profuse comments that can be useful. /* * 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 * * usage: kermit [csr][dlbe line baud escapechar] [f1 f2 ...] * * where c=connect, s=send [files], r=receive, d=debug, * l=tty line, b=baud rate, e=escape char (decimal ascii code). * For "host" mode Kermit, format is either "kermit r" to * receive files, or "kermit s f1 f2 ..." to send f1 .. fn. * */ #include /* Standard UNIX definitions */ #include #include #include /* Conditional Compilation: 0 means don't compile it, nonzero means do */ #define UNIX 0 /* Conditional compilation for UNIX */ #define TOPS_20 1 /* Conditional compilation for TOPS-20 */ #define VAX_VMS 0 /* Ditto for VAX/VMS */ #define IBM_UTS 0 /* Ditto for Amdahl UTS on IBM systems */ /* Symbol Definitions */ #define MAXPACK 94 /* Maximum packet size */ #define SOH 1 /* Start of header */ #define SP 32 /* ASCII space */ #define CR 015 /* ASCII Carriage Return */ #define DEL 127 /* Delete (rubout) */ #define CTRLD 4 #define BRKCHR CTRLD /* Default escape character for CONNECT */ - 20 - #define MAXTRY 5 /* 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 */ #define MYEOL '\n' /* End-Of-Line character I need */ #define MYTIME 5 /* Seconds after which I should be timed out */ #define MAXTIM 20 /* Maximum timeout interval */ #define MINTIM 2 /* Minumum timeout interval */ #define TRUE -1 /* Boolean constants */ #define FALSE 0 /* Global Variables */ int size, /* Size of present data */ n, /* Message number */ rpsiz, /* Maximum receive packet size */ spsiz, /* Maximum send packet size */ pad, /* How much padding to send */ timint, /* Timeout for foreign host on sends */ numtry, /* Times this packet retried */ oldtry, /* Times previous packet retried */ fd, /* File pointer of file to read/write */ remfd, /* File pointer of the host's tty */ image, /* -1 means 8-bit mode */ remspd, /* Speed of this tty */ host, /* -1 means we're a host-mode kermit */ debug; /* -1 means debugging */ 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[MAXPACK], /* Receive packet buffer */ packet[MAXPACK]; /* Packet buffer */ struct sgttyb rawmode, /* Host tty "raw" mode */ cookedmode, /* Host tty "normal" mode */ remttymode; /* Assigned tty line "raw" mode */ jmp_buf env; /* Environment ptr for timeout longjump */ /* * m a i n * * Main routine - parse command and options, set up the * tty lines, and dispatch to the appropriate routine. */ - 21 - main(argc,argv) int argc; /* Character pointer for */ char **argv; /* command line arguments */ { char *remtty,*cp; /* tty for CONNECT, char pointer */ int speed, cflg, rflg, sflg; /* speed of assigned tty, */ /* flags for CONNECT, RECEIVE, SEND */ if (argc < 2) usage(); /* Make sure there's a command line. */ cp = *++argv; argv++; argc -= 2; /* Set up pointers to args */ /* Initialize this side's SEND-INIT parameters */ eol = CR; /* EOL for outgoing packets */ quote = MYQUOTE; /* 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 */ remtty = 0; /* Default is host (remote) mode */ image = UNIX; /* Default to 8-bit mode for UNIX, */ /* 7-bit CRLF mode for others */ escchr = BRKCHR; /* Default escape character */ while ((*cp) != NULL) /* Get a character from the cmd line */ switch (*cp++) /* Based on what the character is, */ {  /* do one of the folloing */ case '-': break; /* Ignore dash (UNIX style) */ case 'c': cflg++; break; /* C = CONNECT command */ case 's': sflg++; break; /* S = SEND command */ case 'r': rflg++; break; /* R = RECEIVE command */ case 'e': if (argc--) /* E = specify escape char */ escchr = atoi(*argv++); /* as ascii decimal number */ else usage(); if (debug) fprintf(stderr,"escape char is ascii %d\n",escchr); break; case 'l': if (argc--) /* L = specify tty line to use */ remtty = *argv++; else usage(); if (debug) fprintf(stderr,"line %s\n",remtty); break; #if UNIX /* This part only for UNIX systems */ case 'b': if (argc--) speed = atoi(*argv++); /* Set baud rate */ else usage(); if (debug) fprintf(stderr,"speed %d\n",speed); break; case 'i': image = TRUE; break; /* Image (8-bit) mode */ #endif /* UNIX */ case 'd': debug = TRUE; break; /* Debug mode */ } /* Done parsing */ if ((cflg+sflg+rflg) != 1) usage(); /* Only one command allowed */ - 22 - remfd = 0; /* Start out as a host (remote) */ host = TRUE; if (remtty) /* If another tty was specified, */ { remfd = open(remtty,2); /* open it */ if (remfd < 0) /* check for failure */ { fprintf(stderr,"Kermit: cannot open %s\n",remtty); exit(-1); /* Failed, quit. */ } host = FALSE; /* Opened OK, flag local (not host) */ } /* Put the tty(s) into the correct modes */ gtty(0,&cookedmode); /* Save current mode for later */ gtty(0,&rawmode); rawmode.sg_flags |= (RAW|TANDEM); rawmode.sg_flags &= ~(ECHO|CRMOD); gtty(remfd,&remttymode); /* If local kermit, get mode of */ /* assigned tty */ remttymode.sg_flags |= (RAW|TANDEM); remttymode.sg_flags &= ~(ECHO|CRMOD); #if UNIX /* 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; default: fprintf(stderr,"bad line speed\n"); } remttymode.sg_ispeed = speed; remttymode.sg_ospeed = speed; } #endif /* UNIX */ if (remfd) stty(remfd,&remttymode); /* Put asg'd tty in raw mode */ /* All set up, now execute the command that was given. */ if (cflg) connect(); /* CONNECT command */ - 23 - if (sflg) /* SEND command */ { if (argc--) filnam = *argv++; /* Get file to send */ else usage(); filelist = argv; if (host) stty(0,&rawmode); /* Put tty in raw mode if remote */ if (sendsw() == FALSE) /* Send the file(s) */ printf("Send failed.\n"); /* Report failure */ else /* or */ printf("OK\n"); /* success */ if (host) stty(0,&cookedmode); /* Restore tty */ } if (rflg) /* RECEIVE command */ { if (host) stty(0,&rawmode); /* Put tty in raw mode if remote */ if (recsw() == FALSE) /* Receive the file */ printf("Receive failed.\n"); /* Report failure */  else /* or */ printf("OK\n"); /* success */ if (host) stty(0,&cookedmode); /* Restore tty */ } } usage() /* Give message if user makes */ { /* a mistake in the command */ fprintf(stderr, "usage: kermit [csr][di][lbe] [line] [baud] [esc char] [f1 f2 ...]\n"); exit(); } /* * 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(),seof(),sdata(),sbreak(); - 24 - 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 */ { switch(state) { case 'D': state = sdata(); break; /* Data-Send state */ case 'F': state = sfile(); break; /* File-Send */ case 'Z': state = seof(); break; /* End-of-File */ case 'S': state = sinit(); break; /* Send-Init */ case 'B': state = sbreak(); break; /* Break-Send */ case 'C': return (TRUE); /* Complete */ case 'A': return (FALSE); /* "Abort" */ default: return (FALSE); /* Unknown, fail */ } } } /* * s i n i t * * Send Initiate: Send my parameters, get other side's back. */ char sinit() { int num, len; /* Packet number, length */ if (debug) fprintf(stderr,"sinit\n"); if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */ spar(packet); /* Fill up with init info */ if (debug) fprintf(stderr,"n = %d\n",n); #if UNIX if (host) /* Clear any pending input */ ioctl(); /* like stacked-up NAKs */ else ioctl(remfd,TIOCFLUSH,0); #endif /* UNIX */ spack('S',n,6,packet); /* Send an S packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': return(state); /* NAK */ - 25 - case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, stay in S state */ rpar(recpkt); /* Get other side's init info */ if (eol == 0) eol = '\n'; /* Check and set defaults */ if (quote == 0) quote = '#'; /* Control-prefix quote */ numtry = 0; /* Reset try counter */ n = (n+1)%64; /* Bump packet count */ if (debug) fprintf(stderr,"Opening %s\n",filnam); fd = open(filnam,0); /* Open the file to be sent */ if (fd < 0) return('A'); /* if bad file descriptor, give up */ if (!host) printf("Sending %s\n",filnam); return('F'); /* OK, switch state to F */ case FALSE: return(state); /* Receive failure, stay in S state */ default: return('A'); /* Anythig else, just "abort" */ } } /* * s f i l e * * Send File Header. */ char sfile() { int num, len; /* Packet number, length */ if (debug) fprintf(stderr,"sfile\n"); if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */ for (len=0; filnam[len] != '\0'; len++); /* Add up the length */ #if UNIX /* Don't know why this is here */ len++; /* Add 1 */ #endif /* But leaves an extra null */ spack('F',n,len,filnam); /* Send an F packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ if (n != (num=(--num<0)?63:num)) /* unless NAK for next packet, */ return(state); /* which is just like an ACK */ /* for this packet, 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 */ - 26 - case FALSE: return(state); /* Receive failure, stay in F state */ default: return('A'); /* Something esle, just "abort" */ } } /* * 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, */ if (n != (num=(--num<0)?63:num)) /* unless NAK for next packet, */ return(state); /* which is just like an ACK */ /* for this packet, 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 FALSE: return(state); /* Receive failure, stay in D */ default: return('A'); /* Anything else, "abort" */ } } /* * s e o f * * Send End-Of-File. */ - 27 - char seof() { int num, len; /* Packet number, length */ if (debug) fprintf(stderr,"seof\n"); if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */ spack('Z',n,0,packet); /* Send a 'Z' packet */ if (debug) fprintf(stderr,"seof1 "); switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, fail */ if (n != (num=(--num<0)?63:num)) /* ...unless for previous packet, */ return(state); /* in which case, fall thru to ... */ case 'Y': /* ACK */ if (debug) fprintf(stderr,"seof2 "); 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) fprintf(stderr,"closing %s, ",filnam); close(fd); /* Close the input file */ if (debug) fprintf(stderr,"ok, getting next file\n"); if (gnxtfl() == FALSE) /* No more files go? */ return('B'); /* if not, break, EOT, all done */ if (debug) fprintf(stderr,"new file is %s\n",filnam); return('F'); /* More files, switch state to F */ case FALSE: return(state); /* Receive failure, stay in state 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 (debug) fprintf(stderr,"sbreak\n"); 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, fail */ if (n != (num=(--num<0)?63:num)) /* ...unless for previous packet, */ return(state); /* in which case, fall thru to ... */ case 'Y': /* ACK */ if (n != num) return(state); /* If wrong ACK, fail */ - 28 - numtry = 0; /* Reset try counter */ n = (n+1)%64; /* and bump packet count */ return('C'); /* switch state to Complete */ case FALSE: return(state); /* Receive failure, stay in state B */ default: return ('A'); /* Other, "abort" */ } } /* * r e c s w * * This is the state table switcher for receiving files.  */ recsw() { char rinit(),rdata(),rfile(); /* Use these procedures */ state = 'R'; /* Receive is the start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ while(TRUE) switch(state) /* Do until done */ { case 'D': state = rdata(); break; /* Data receive state */ case 'F': state = rfile(); break; /* File receive state */ case 'R': state = rinit(); break; /* Send initiate state */ case 'C': return(TRUE); /* Complete state */ case 'A': return(FALSE); /* "Abort" state */ } } /* * r i n i t * * Receive Initialization */ 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-Send state */ - 29 - case FALSE: return (state); /* Didn't get a packet, keep waiting */ default: return('A'); /* Some other packet type, "abort" */ } } /* * r f i l e * * Receive File Header */ char rfile() { int num, len; /* Packet number, length */ if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */ 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 */ spar(packet); /* with 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, */ if (num != n) return('A'); /* which is what we really want */ /* The packet number must be right */ if (!getfil(packet)) /* Try to open a new file */ { fprintf(stderr,"Could not create %s\n"); /* Give up if can't */ return('A'); } else /* OK, give message */ if (!host) printf("Receiving %s\n",packet); 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 */ - 30 - 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 */ case FALSE: return(state); /* Couldn't get packet, 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, give up */ 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); /* Stay in D, don't write out data! */ } else return('A'); /* sorry wrong number */ } /* Got data with right packet number */ bufemp(packet,fd,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 */ 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" */ - 31 - case 'Z': /* End-Of-File */ if (num != n) return('A'); /* Must have right packet number */ spack('Y',n,0,0); /* OK, ACK it. */ close(fd); /* Close the file */ n = (n+1)%64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case FALSE: return(state); /* No packet came, keep waiting */ 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 parent; /* Fork handle */ char c = NULL, r = '\r'; if (host) /* If in host mode, nothing to connect to */ { fprintf(stderr,"Kermit: nothing to connect to\n"); return; } parent = fork(); /* Start fork to get typeout from remote host */ - 32 - if (parent) /* Parent passes typein to remote host */ { printf("Kermit: connected.\r\n"); /* Give message */ stty(0,&rawmode); /* Put tty in raw mode */ read(0,&c,1); /* Get a character */ while (c != escchr) /* Check for escape character */ { /* Not it */ write(remfd,&c,1); /* Write the character on screen */ c = NULL; /* Nullify it */ read(0,&c,1);  /* Get next character */ } /* Until escape character typed */ kill(parent,9); /* Done, get rid of fork */ stty(0,&cookedmode); /* Restore tty mode */ printf("\nKermit: disconnected.\n"); /* Give message */ return; /* Done */ } else /* Child does the reading from the remote host */ { while(1) /* Do this forever */ { read(remfd,&c,1); write(1,&c,1); } } } /* * KERMIT utilities. */ clkint() /* Timer interrupt handler */ { longjmp(env,TRUE); /* Tell rpack to give up */ } /* tochar converts a control character to a printable one by adding a space */ char tochar(ch) char ch; { return(ch + ' '); /* make sure not a control char */ } /* unchar undoes tochar */ char unchar(ch) char ch; { re turn(ch - ' '); /* restore char */ } - 33 - /* * ctl turns a control character into a printable character by toggling the * control bit (ie. ^A becomes A and A becomes ^A). */ char ctl(ch) char ch; { return(ch ^ 64); /* toggle the control bit */ } /* * 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 */ bufp = buffer; /* Set up buffer pointer */ for (i=1; i<=pad; i++) write(remfd,&padchar,1); /* Issue any padding */ *bufp++ = SOH; /* Packet marker, ASCII 1 (SOH) */ chksum = tochar(len+3); /* Initialize the checksum */ *bufp++ = tochar(len+3); /* Send the character count */ chksum = chksum + tochar(num); /* Init checksum */ *bufp++ = tochar(num); /* Packet number */ chksum = chksum + type; /* Accumulate checksum */ *bufp++ = type; /* Packet type */ for (i=0; i MAXTIM) || (timint < MINTIM)) timint = MYTIME; alarm(timint); if (host) /* Clear any pending input, */ ioctl(); /* like stacked-up ACKs */ else ioctl(remfd,TIOCFLUSH,0); #endif /* UNIX */ while (t != SOH) read(remfd,&t,1); /* Wait for packet header */ done = FALSE; /* Got SOH, init loop */ while (!done) /* Loop to get a packet */ { read(remfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ chksum = t; /* Start the checksum */ *len = unchar(t)-3; /* Character count */ read(remfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ chksum = chksum + t; /* Accumulate checksum */ *num = unchar(t); /* Packet number */ read(remfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ chksum = chksum + t; /* Accumulate checksum */ type = t; /* Packet type */ for (i=0; i<*len; i++) /* The data itself, if any */ { /* Loop for character count */ read(remfd,&t,1); /* Get character */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynch if SOH */ chksum = chksum + t; /* Accumulate checksum */ data[i] = t; /* Put it in the data buffer */ } data[*len] = 0; /* Mark the end of the data */ - 35 - read(remfd,&t,1); /* Get last character (checksum) */ if (!image) t &= 0177; /* Handle parity */ if (t == SOH) continue; /* Resynchronize if SOH */ done = TRUE; /* Got checksum, done */ } #if UNIX alarm(0); /* Disable the timer interrupt */ #endif chksum = (chksum + (chksum & 192) / 64) & 63; /* Fold bits 7,8 into chksum */ if (chksum != unchar(t)) return(FALSE); /* Check the checksum, fail if bad */ 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. */ - 36 - bufill(buffer) char buffer[]; /* Buffer */ { int i; /* Loop index */ char t,t7; i = 0; /* Init data buffer pointer */ while(read(fd,&t,1) > 0) /* Get the next character */ { if (image) /* In 8-bit mode? */ { t7 = t & 0177; /* Yes, look at low-order 7 bits */ if (t7 < SP || t7==DEL || t7==quote) /* Control character? */ { /* Yes, */ buffer[i++] = quote; /* quote this character */ if (t7 != quote) t = ctl(t); /* and uncontrollify */ } } else /* Else, ASCII text mode */  { t &= 0177; /* Strip off the parity bit */ if (t < SP || t == DEL || t == quote) /* Control character? */ { /* Yes */ if (t=='\n') /* If newline, squeeze CR in first */ { buffer[i++] = quote; buffer[i++] = ctl('\r'); } buffer[i++] = quote; /* Insert quote */ if (t != quote) t=ctl(t); /* Uncontrollified the character */ } } buffer[i++] = t; /* Deposit the character itself */ 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 * * Get data from an incoming packet into a file. */ bufemp(buffer,fd,len) char buffer[]; /* Buffer */ int fd, len; /* File pointer, length */ { int i; /* Counter */ char t; /* Character holder */ - 37 - for (i=0; i 0); /* Return false if file won't open */ } /* * g n x t f l * * Get next file in a file group */ gnxtfl() { if (debug) fprintf(stderr, "gnxtfl\n"); filnam = *(filelist++); if (filnam == 0) return FALSE; /* If no more, fail */ else return TRUE; /* else succeed */ } /* * s p a r * * Fill the data array with my send-init parameters * */ - 38 - spar(data) char data[]; { data[0] = tochar(MAXPACK); /* Biggest packet I can receive */ data[1] = tochar(MYTIME); /* When I want to be timed out */ data[2] = tochar(MYPAD); /* How much padding I need */ data[3] = ctl(MYPCHAR); /* Padding character I want */ data[4] = tochar(MYEOL); /* End-Of-Line character I want */ data[5] = MYQUOTE; /* Control-Quote character I send */ } /* r p a r * * Get the other host's send-init parameters * */ rpar(data) char data[]; { spsiz = unchar(data[0]); /* Maximum send packet size */ timint = unchar(data[1]); /* When I should time out */ pad = unchar(data[2]); /* Number of pads to send */ padchar = ctl(data[3]); /* Padding character to send */ eol = unchar(data[4]); /* EOL character I must send */ quote = data[5]; /* Incoming data quote character */ } - 39 - I. The ASCII Character Set ASCII Code (ANSI X3.4-1968) There are 128 characters in the ASCII (American national Standard Code for In- formation Interchange) "alphabet". The characters are listed in order of ASCII value; the columns are labeled as follows: Bit Even parity bit for ASCII character. ASCII Dec Decimal (base 10) rep"resentation. ASCII Oct Octal (base 8) representation. ASCII Hex Hexadecimal (base 16) representation. EBCDIC Hex EBCDIC hexadecimal equivalent for Kermit translate tables. Char Name or graphical representation of character. Remark Description of character. The first group consists of nonprintable 'control' characters: .....ASCII.... EBCDIC Bit Dec Oct Hex Hex Char Remarks 0 000 000 00 00 NUL ^@, Null, Idle 1 001 001 01 01 SOH ^A, Start of heading 1 002 002 02 02 STX ^B, Start of text 0 003 003 03 03 ETX ^C, End of text 1 004 004 04 37 EOT ^D, End of transmission 0 005 005 05 2D ENQ ^E, Enquiry 0 006 006 06 2E ACK ^F, Acknowledge 1 007 007 07 2F BEL ^G, Bell, beep, or fleep 1 008 010 08 16 BS ^H, Backspace 0 009 011 09 05 HT ^I, Horizontal tab 0 010 012 0A 25 LF ^J, Line feed 1  011 013 0B 0B VT ^K, Vertical tab 0 012 014 0C 0C FF ^L, Form feed (top of page) 1 013 015 0D 0D CR ^M, Carriage return 1 014 016 0E 0E SO ^N, Shift out 0 015 017 0F 0F SI ^O, Shift in 1 016 020 10 10 DLE ^P, Data link escape 0 017 021 11 11 DC1 ^Q, Device control 1, XON 0 018 022 12 12 DC2 ^R, Device control 2 1 019 023 13 13 DC3 ^S, Device control 3, XOFF 0 020 024 14 3C DC4 ^T, Device control 4 1 021 025 15 3D NAK ^U, Negative acknowledge 1 022 026 16 32 SYN ^V, Synchronous idle 0 023 027 17 26 ETB ^W, End of transmission block 0 024 030 18 18 CAN ^X, Cancel 1 025 031 19 19 EM ^Y, End of medium 1 026 032 1A 3F SUB ^Z, Substitute 0 027 033 1B 27 ESC ^[, Escape, prefix, altmode 1 028 034 1C 1C FS ^\, File separator 0 029 035 1D 1D GS ^], Group separator 0 030 036 1E 1E RS ^^, Record separator 1 031 037 1F 1F US ^_, Unit separator The last four are usually associated with the control version of backslash, right square bracket, uparrow (or circumflex), and underscore, respectively, - 40 - but some terminals do not transmit these control characters. The following characters are printable: First, some punctuation characters. .....ASCII.... EBCDIC Bit Dec Oct Hex Hex Char Remarks 1 032 040 20 40 SP Space, blank 0 033 041 21 5A ! Exclamation mark 0 034 042 22 7F " Doublequote 1 035 043 23 7B # Number sign, pound sign 0 036 044 24 5B $ Dollar sign 1 037 045 25 6C % Percent sign 1 038 046 26 50 & Ampersand 0 039 047 27 7D ' Apostrophe, accent acute 0 040 050 28 4D ( Left parenthesis 1 041 051 29 5D ) Right parenthesis 1 042 052 2A 5C * Asterisk, star 0 043 053 2B 4E + Plus sign 1 044 054 2C 6B , Comma 0 045 055 2D 60 - Dash, hyphen, minus sign 0 046 056 2E 4B . Period, dot 1 047 057 2F 61 / Slash Numeric characters: .....ASCII.... EBCDIC Bit Dec Oct Hex Hex Char Remarks 0 048 060 30 F0 0 Zero 1 049 061 31 F1 1 One 1 050 062 32 F2 2 Two 0 051 063 33 F3 3 Three 1 052 064 34 F4 4 Four 0 053 065 35 F5 5 Five 0 054 066 36 F6 6 Six 1 055 067 37 F7 7 Seven 1 056 070 38 F8 8 Eight 0 057 071 39 F9 9 Nine More punctuation characters: .....ASCII.... EBCDIC Bit Dec Oct Hex Hex Char Remarks 0 058 072 3A 7A : Colon 1 059 073 3B 5E ; Semicolon 0 060 074 3C 4C < Left angle bracket 1 061 075 3D 7E = Equal sign 1 062 076 3E 6E > Right angle bracket 0 063 077 3F 6F ? Question mark 1 064 100 40 7C @ "At" sign - 41 - 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 - 42 - 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  - 43 - Index 8-Bit-Quote 10 Server 7, 9, 12 SET 12 ACK 4 Smart 8 ASCII 4, 5, 39 Timeout 8, 14 Baud 5 Binary Files 5 Unchar(x) 3 Char(x) 3 XON/XOFF 5, 39 Checksum 7, 11 Control Characters 5, 39 Ctl(x) 3 Deadlock 8 Dumb 8 Duplex 5 EBCDIC 39 End-Of-Line (EOL) 4, 8, 10 Full Duplex 5 Half Duplex 5, 10 Initial Connection Protocol 10 KERMIT 2 Kermit Server 7, 9 Line 9 Line Terminator (see End-Of-Line) Local 9 Logical Records 5 Microcomputer 9  NAK 4 Octal 3 Packet 6 Padding 4, 10 Parity 5, 39 Printable Files 5 Program, Kermit 19 Protocol 2 Quote 10 Records 5 Remote 4, 9 Repeat Count 11 Reserved Fields 11 - i - Table of Contents 1. The KERMIT Protocol 2 1.1. Background 2 1.2. Overview 3 1.3. Definitions 3 1.4. Host System Requirements 4 1.5. Data Representation 5 1.6. Packet Format 6 1.7. Smart and Dumb Kermits 8 1.8. Local and Remote Kermits 9 1.9. User and Server Kermits 9 1.10. Initial Connection Protocol 10 1.11. Prefix Quoting 12 1.12. The KERMIT Protocol 13 1.13. KERMIT Protocol State Table 14 1.14. Low-Level Considerations 16 2. The KERMIT Program 19 I. The ASCII Character Set 39 Index 43  5 1.6. Packet Format 6 1.7. Smart and Dumb $ This is the release date of the disk.  Fog Library Disk FOG-CPM.154 Copyright (1987) by Fog International Computer Users Group to the extent not copyrighted by the original author for the exclusive use and enjoyment of its members. Any reproduction or distribution for profit or personal gain is strictly forbidden. For information, contact FOG, P. O. Box 3474, Daly City, CA. 94015-0474. as part of the description of a file indicates that the program is distributed on a "try first, pay if you like it" basis. If you find the program(s) meet your need, please refer to the author's documentation for information on becoming a registered user. Only by registering and paying for the programs you like and use will the authors of such programs continue development. Often, more complete documentation, additional modules, and new releases are available only to registered users. Disk 2 of 4. Kermit. Filename Description -01-00 .87 This is the release date of the disk. -CPM154 .DOC This is the description of the disk contents. KERMIT80.DOC 7A28 57K ver. 4.05 [Kermit 33 of 50] Documentation for microcomputer versions of Kermit. KERMIT .TXT 502B 6K ver. 4.05 [Kermit 34 of 50] PROTO .DOC 8811 99K ver. 4.05 [Kermit 35 of 50] ten, more complete documentation, additional modules, and new releases are available only to registered users. Disk 2 of 4. Kermit. Filename Description -01-00 .87 This is the release date of the disk. -CPM154 .DOC T%&'