KERMIT PROTOCOL MANUAL Fifth Edition Frank da Cruz

KERMIT PROTOCOL MANUAL Fifth Edition Frank da Cruz
KERMIT PROTOCOL MANUAL
Fifth Edition
Frank da Cruz
Columbia University Center for Computing Activities
New York, New York 10027
3 April 1984
Copyright (C) 1981,1982,1983,1984
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.
Preface to the Fourth Edition
Page 1
Preface to the Fourth Edition
The fourth edition (November 1983) of the KERMIT Protocol Manual
incorporates
some new ideas that grew from our experience in attempting to implement
some of
the features described in earlier editions, particularly user/server
functions.
These include a mechanism to allow batch transfers to be interrupted
gracefully
for either the current file or the entire batch of files; a "capability
mask";
a protocol extension for passing file attributes. In addition, numbers
are now
written in decimal notation rather than octal, which was confusing
to many
readers. Also, several incompatible changes were made in minor areas
where no
attempts at an implementation had yet been made; these include:
- The format and interpretation of the operands to the server
commands.
- Usurpation of the reserved fields 10-11 of the Send-Init packet,
and
addition of new reserved fields.
Most of the remaining material has been rewritten and reorganized, and
much new
material added, including a section on the recommended vocabulary for
documentation and commands.
The previous edition of the Protocol Manual attempted to define
"protocol version 3"; this edition abandons that concept. Since KERMIT development
is an
unorganized, disorderly, distributed enterprise, no requirement can be
imposed
on KERMIT implementors to include a certain set of capabilities in
their implementations.
Rather, in this edition we attempt to define the
basic
functionality of KERMIT, and then describe various optional functions.
The key principle is that any implementation of KERMIT should work
with any
other, no matter how advanced the one or how primitive the other. The
capabily
mask and other Send-Init fields attempt to promote this principle.
FIFTH EDITION
The fifth edition (March 1984) attempts to clarify some fine points
that had
been left ambiguous in the 4th edition, particularly with respect to
when and
how prefix encoding is done, and when it is not, and about switching
between
block check types. A mechanism is suggested (in the Attributes
section) for
file archiving, and several attributes have been rearranged and some
others added (this should do no harm, since no one to date has attempted to
implement
the attributes packet). A more complete protocol state table is
provided, a
few minor additions are made to the collection of packet types.
A FEW WORDS...
Before deciding to write a new version of KERMIT, please bear in mind
that the
philosophy of KERMIT has always been that is not, and never should
become, a
commercial product, sold for profit. Its goal is to promote
communication and
sharing, and KERMIT itself should be freely shared, and not sold.
Media and
reproduction costs may be recouped if desired, but profit should not be
the motive.
Vendors of commercial software, however, may request permission
to include KERMIT with, or in, their programs provided certain conditions are
met,
including that credit for the protocol be given to Columbia and that the
price
of the product not be raised substantially beyond media and reproduction
costs
Preface to the Fourth Edition
Page 2
for inclusion of KERMIT. Contact the KERMIT group at Columbia if you
have any
questions about this. Prospective KERMIT implementors should check with
us in
any case, to be sure that someone else has not already done, or started
to do,
the same thing you propose to do.
KERMIT is distributed from Columbia University on magnetic tape.
Complete ordering instructions can be found in the Kermit Users Guide. Direct
inquiries
about KERMIT to:
KERMIT Distribution
Columbia University Center for Computing Activities
7th Floor, Watson Laboratory
612 West 115th Street
New York, NY 10025
ACKNOWLEDGEMENTS
Bill Catchings and I designed the basic KERMIT protocol at Columbia
University
in 1981.
For ideas, we looked at some of the ANSI models (X3.57,
X3.66), the
ISO OSI model, some real-world "asynchronous protocols" (including the
Stanford
Dialnet project, the University of Utah TTYFTP project), as well as at
file
transfer on full-blown networks like DECnet and ARPAnet.
Bill wrote the first two programs to implement the protocol, one
for the
DEC-20, one for a CP/M-80 microcomputer, and in the process worked out
most of
the details and heuristics required for basic file transfer. Meanwhile,
Daphne
Tzoar and Vace Kundakci, also of Columbia, worked out the additional
details
necessary for IBM mainframe communication.
Much credit should also go to Bernie Eiben of Digital Equipment
Corporation for
promoting widespread use of KERMIT and for adding many insights into
how it
should operate, and to Nick Bush and Bob McQueen of Stevens Institute of
Tech-
nology, for many contributions to the "advanced" parts of the protocol,
and for
several major KERMIT implementations.
Thanks to the many people all over the world who have contributed new
KERMIT
implementations, who have helped with KERMIT distribution through
various user
groups, and who have contributed to the quality of the protocol and its
many
implementations by reporting or fixing problems, criticizing the
design, or
suggesting new features.
DISCLAIMER
No warranty of the software nor of the accuracy of the documentation
surrounding it is expressed or implied, and neither the authors nor Columbia
University
acknowledge any liability resulting from program or documentation errors.
Introduction
Page 3
1. Introduction
This manual describes the KERMIT protocol. It is assumed that you
understand
the purpose and operation of the Kermit file transfer facility,
described in
the Kermit Users Guide, and basic terminology of data communications
and computer programming.
1.1. Background
The KERMIT file transfer protocol is intended for use in an environment
where
there may be a diverse mixture of computers -- micros, personal
computers,
workstations, laboratory computers, timesharing systems -- from a
variety of
manufacturers.
All these systems need have in common is the ability
to communicate in ASCII over ordinary serial telecommunication lines.
KERMIT was originally designed at Columbia University to meet the need
for file
transfer between our DECSYSTEM-20 and IBM 370-series mainframes and
various
microcomputers.
It turned out that the diverse characteristics of these
three
kinds of systems resulted in a design that was general enough to fit
almost any
system. The IBM mainframe, in particular, strains most common
assumptions
about how computers communicate.
1.2. Overview
The KERMIT protocol is specifically designed for character-oriented
transmission over serial telecommunication lines. The design allows for the
restrictions and peculiarities of the medium and the requirements of diverse
operating
environments -- buffering, duplex, parity, character set, file
organization,
etc. The protocol is carried out by KERMIT programs on each end of the
serial
connection sending "packets" back and forth; the sender sends file
names, file
contents, and control information; the
(positively or
negatively) each packet.
receiver
acknowledges
The packets have a layered design, more or less in keeping with the
ANSI and
ISO philosophies, with the outermost fields used by the data link
layer to
verify data integrity, the next by the session layer to verify
continuity, and
the data itself at the application level.
Connections between systems are established by the ordinary user. In a
typical
case, the user runs KERMIT on a microcomputer, enters terminal emulation,
connects to a remote host computer (perhaps by dialing up), logs in, runs
KERMIT
on the remote host, and then issues commands to that KERMIT to start a
file
transfer, "escapes" back to the micro, and issues commands to that
KERMIT to
start its side of the file transfer. Files may be transferred singly
or in
groups.
Basic KERMIT provides only file transfer, and that is provided for
sequential
files only, though the protocol attempts to allow for various types of
sequential files.
Microcomputer implementations of KERMIT are also
expected to
provide terminal emulation, to facilitate the initial connection.
More advanced implementations simplify the "user interface" somewhat by
allowing the KERMIT on the remote host to run as a "server", which can
transfer
files in either direction upon command from the local "user" Kermit. The
serv-
Introduction
Page 4
er can also provide additional functionality, such as file
management, messages, mail, and so forth. Other optional features also exist,
including a
variety of block check types, a mechanism for passing 8-bit data
through a
7-bit communication link, a way to compressing a repeated sequence of
characters, and so forth.
As local area networks become more popular, inexpensive, and
standardized, the
demand for KERMIT and similar protocols may dwindle, but will never
wither away
entirely. Unlike hardwired networks, KERMIT gives the ordinary user the
power
to establish reliable error-free connections between any two
computers; this
may always be necessary for one-shot or long-haul connections.
Definitions
Page 5
2. Definitions
2.1. General Terminology
TTY: This is the term commonly used for a device which is connected to
a computer over an EIA RS-232 serial telecommunication line. This device is
most
commonly an ASCII terminal, but it may be a microcomputer or even a
large
multi-user computer emulating an ASCII terminal.
Most computers
provide
hardware (RS-232 connectors and UARTs) and software (device drivers) to
support
TTY connections; this is what makes TTY-oriented file transfer
protocols like
KERMIT possible on almost any system at little or no cost.
LOCAL: When two machines are connected, the LOCAL machine is the one
which you
interact with directly, and which is in control of the terminal. The
"local
Kermit" is the one that runs on the local machine. A local Kermit always
communicates over an external device (the micro's communication port, an
assigned
TTY line, etc).
REMOTE: The REMOTE machine is the one on the far side of the connection,
which
you must interact with "through" the local machine. The "remote
Kermit" runs
on the remote machine. A remote Kermit usually communicates over
its own
"console", "controlling terminal", or "standard i/o" device.
HOST: Another word for "computer", usually meaning a computer that can
provide
a home for multiple users or applications. This term should be avoided
in KERMIT lore, unless preceded immediately by LOCAL or REMOTE, to denote which
host
is meant.
SERVER: An implementation of remote Kermit that can accept commands in
packet
form from a local Kermit program, instead of directly from the user.
USER: In addition to its usual use to denote the person using a
system or
program, "user" will also be used refer to the local Kermit program,
when the
remote Kermit is a server.
2.2. Numbers
All numbers in the following text are expressed in decimal (base
notation
unless otherwise specified.
10)
Numbers are also referred to in terms of their bit positions in a
computer
word. Since KERMIT may be implemented on computers with various word
sizes, we
start numbering the bits from the "right" -- bit 0 is the least
significant.
Bits 0-5 are the 6 least significant bits; if they were all set to
one, the
value would be 63.
A special quirk in terminology, however, refers to the high order bit
of a
character as it is transmitted on the communication line, as the "8th
bit".
More properly, it is bit 7, since we start counting from 0. References
to the
"8th bit" generally are with regard to that bit which ASCII
transmission sets
aside for use as a parity bit. KERMIT concerns itself with whether
this bit
can be usurped for the transmission of data, and if not, it may
resort to
"8th-bit prefixing".
Definitions
Page 6
2.3. Character Set
All characters are in ASCII (American national Standard Code for
Information
Interchange) representation, ANSI standard X3.4-1968. All
implementations of
KERMIT transmit and receive characters only in ASCII. The ASCII
character set
is listed in Appendix V.
ASCII character mnemonics:
NUL
SOH
SP
CR
LF
CRLF
DEL
Null, idle, ASCII character 0.
Start-of-header, ASCII character 1 (Control-A).
Space, blank, ASCII 32.
Carriage return, ASCII 13 (Control-M).
Linefeed, ASCII 10 (Control-J).
A carriage-return linefeed sequence.
Delete, rubout, ASCII 127.
A control character is considered to be any byte whose low order 7 bits
are in
the range 0 through 31, or equal to 127. In this document, control
characters
are written in several ways:
Control-A
This denotes ASCII character 1, commonly referred
"Control-A".
Control-B is ASCII character 2, and so forth.
to
as
CTRL-A This is a common abbreviation for "Control-A". A control
character is
generally typed at a computer terminal by holding down the key
marked
CTRL and pressing the corresponding alphabetic character, in
this case
"A".
^A
"Uparrow" notation for CTRL-A.
control
characters in this fashion.
Many computer
systems
"echo"
A printable ASCII character is considered to be any character in the
range 32
(SP) through 126 (tilde).
2.4. Conversion Functions
Several conversion functions are useful in the description of the
protocol and
in the program example. The machine that Kermit runs on need operate
only on
integer data; these are functions that operate upon the numeric value of
single
ASCII characters.
char(x) = x+32
range
Transforms the integer x, which is assumed to lie in the
0
to 94, into a printable ASCII character; 0 becomes SP,
1 becomes "!", 3 becomes "#", etc.
unchar(x) = x-32
Transforms the character x, which
in
is
assumed
to
be
the
printable
range
(SP
through
tilde),
into an integer
in the
range 0 to 94.
ctl(x) = x XOR 64
Maps between control characters and their printable
representations, preserving the high-order bit.
If x is a
control
Definitions
Page 7
character, then
x = ctl(ctl(x))
that
is,
the
same function is used to controllify and
uncontrollify.
The argument is assumed to be a true control
character (0 to 31, or 127), or the result of applying CTL to a
true
control character (i.e. 63 to 95). The
transformation is a
mnemonic one -- ^A becomes A and vice versa.
2.5. Protocol Jargon
A Packet is a clearly delimited string of characters, comprised of
"control
fields" nested around data; the control fields allow a KERMIT program to
determine whether the data has been transmitted correctly and completely. A
packet
is the unit of transmission in the KERMIT protocol.
ACK stands for "Acknowledge". An ACK is a packet that is sent to
acknowledge
receipt of another packet. Not to be confused with the ASCII character
ACK.
NAK stands for "Negative Acknowledge". A NAK is a packet sent to say
that a
corrupted or incomplete packet was received, the wrong packet was
received, or
an expected packet was not received. Not to be confused with the ASCII
character NAK.
A timeout is an event that can occur if expected data does not arrive
within a
specified amount of time. The program generating the input request can
set a
"timer interrupt" to break it out of a nonresponsive read, so that
recovery
procedures may be activated.
System Requirements
Page 8
3. System Requirements
The KERMIT protocol requires that:
- The host can send and receive characters using 7- or 8-bit ASCII
encoding over an EIA RS-232 physical connection, either hardwired
or
dialup.
- All
host
printable
ASCII
characters are acceptable as input to the
1
and will not be transformed in any way . Similarly, any
intervening
network or communications equipment ("smart modems", TELENET,
terminal concentrators, port selectors, etc) must not transform or
swallow any printable ASCII characters.
- A single ASCII control character can pass from one system to
the
other without transformation.
This character is used for
packet
synchronization. The character is normally Control-A (SOH, ASCII
1),
but can be redefined.
- If a host requires a line terminator for terminal input, that
terminator must be a single ASCII control character, such as CR or
LF,
distinct from the packet synchronization character.
- When using a job's controlling terminal for file transfer, the
system
must allow the KERMIT program to set the terminal to no echo,
infinite width (no "wraparound" or CRLF insertion by the
operating
system), and no "formatting" of incoming or outgoing characters
(for
instance, raising lowercase letters to uppercase, transforming
control characters to printable sequences, etc). In short, the
terminal
must be put in "binary" or "raw" mode, and, hopefully, restored
afterwards to normal operation.
- The
host's terminal input processor should be capable of receiving
a
single burst of 40 to 100 characters at normal
speeds.
This is the typical size of packet.
transmission
Note that most of these requirements rule out the use of KERMIT
through IBM
3270 / ASCII protocol converters.
KERMIT does not require:
- That the connection run at any particular baud rate.
- That the system can do XON/XOFF or any other kind of flow
control.
System- or hardware-level flow control can help, but it's not
necessary. See section 5.7.
- That the system is capable of full duplex operation.
Any mixture
of
_______________
1
If they are translated to another character set, like EBCDIC, the
KERMIT
program must be able to reconstruct the packet as it appeared on the
communication line, before transformation.
System Requirements
Page 9
half and full duplex systems is supported.
- That the system can transmit or receive 8-bit bytes. KERMIT
will
take advantage of 8-bit connections to send binary files; if an 8bit
connection is not possible, then binary files may be sent using
an
optional prefix encoding.
Printable Text versus Binary Data
Page 10
4. Printable Text versus Binary Data
For transmission between unlike systems, files must be assigned to
either of
two catagories: printable text or binary.
A printable text file is one that can make sense on an unlike system -- a
document, program source, textual data, etc. A binary file is one that
will not
(and probably can not) make sense on an unlike system -- an executable
program,
numbers stored in internal format, etc. On systems with 8-bit bytes,
printable
2
ASCII files will have the high order bit of each byte set to zero (since
ASCII
is a 7-bit code) whereas binary files will use the high order bit of
each byte
for data, in which case its value can vary from byte to byte.
Many computers have no way to distinguish a printable file from a binary
file
-- especially one originating from an unlike system -- so the user may
have to
give an explicit command to Kermit to tell it whether to perform these
conversions.
4.1. Printable Text Files
A primary goal of KERMIT is for printable text files to be useful on the
target
system after transfer. This requires a standard representation for text
during
transmission.
KERMIT's standard is simple: 7-bit ASCII
characters, with
"logical records" (lines) delimited by CRLFs. It is the responsibility
of systems that do not store printable files in this fashion to perform the
necessary
conversions upon input and output. For instance, IBM mainframes might
strip
trailing blanks on output and add them back on input; UNIX would
prepend a CR
to its normal record terminator, LF, upon output and discard it upon
input. In
addition, IBM mainframes must do EBCDIC/ASCII translation for text files.
No other conversions (e.g. tab expansion) are performed upon text files.
This
representation is chosen because it corresponds to the way text
files are
stored on most microcomputers and on many other systems. In many common
cases,
no transformations are necessary at all.
4.2. Binary Files
Binary files are transmitted as though they were a sequence of
characters. The
difference from printable files is that the status of the "8th bit"
must be
preserved. When binary files are transmitted to an unlike system, the
main objective is that they can be brought back to the original system (or
one like
it) intact; no special conversions should be done during transmission,
except
to make the data fit the transmission medium.
For binary files, eight bit character transmission is permissible as
long as
the two Kermit programs involved can control the value of the parity
bit, and
_______________
2
There are some exceptions, such as systems that store text files
in socalled "negative ASCII", or text files produced by word processors that
use the
high order bit to indicate underline or boldface attributes.
Printable Text versus Binary Data
Page 11
no intervening communications equipment will change its value. In that
case,
the 8th bit of a transmitted character will match that of the original
data
byte, after any control-prefixing has been done. When one or both sides
cannot
control the parity bit, a special prefix character may be
inserted, as
described below.
Systems that do not store binary data in 8-bit bytes, or whose word size
is not
a multiple of 8, may make special provisions for "image mode" transfer
of binary files. This may be done within the basic protocol by having the two
sides
implicitly agree upon a scheme for packing the data into 7- or 8-bit
ASCII
characters, or else the more flexible (but optional) file attributes
feature
may be used.
The former method is used on PDP-10 36-bit word
machines, in
which text is stored five 7-bit bytes per word; the value of the "odd
bit" is
sent as the parity bit of every 5th word.
File Transfer
Page 12
5. File Transfer
The file transfer protocol takes place over a transaction. A transaction
is an
exchange of packets beginning with a Send-Init (S) packet, and ending
with a
3
Break Transmission (B) or Error (E) packet , and may include the
transfer of
one or more files, all in the same direction. In order to minimize the
unforseen, KERMIT packets do not contain any control characters except one
specially
designated to mark the beginning of a packet. Except for the packet
marker,
only printable characters are transmitted.
The following sequence
characterizes basic Kermit operation; the sender is the machine that is
sending
files; the receiver is the machine receiving the files.
1. The sender transmits a Send-Initiate (S) packet to specify
its
parameters (packet length, timeout, etc; these are explained
below).
2. The receiver sends an ACK (Y) packet, with its own parameters in
the
data field.
3. The sender transmits a File-Header (F) packet, which contains
the
file's name in the data field. The receiver ACKs the F packet,
with
no data in the data field of the ACK (optionally, it may contain
the
name under which the receiver will store the file).
4. The sender sends the contents of the file, in Data (D) packets.
Any
data not in the printable range is prefixed and replaced by a
printable equivalent. Each D packet is acknowledged before the next
one
is sent.
5. When all the file data has been sent, the sender
OfFile (Z) packet. The receiver ACKs it.
sends
an
End-
6. If there is another file to send, the process is repeated
beginning
at step 3.
7. When no more files remain to be sent, the sender transmits an
EndOf-Transmission (B) packet.
The receiver ACKs it. This ends
the
transaction, and closes the logical connection (the physical
connection remains open).
Each packet has a sequence number, starting with 0 for the Send Init.
The acknowledgment (ACK or NAK) for a packet has the same packet number as the
packet
being acknowledged. Once an acknowledgment is successfully received the
packet
number is increased by one, modulo 64.
If the sender is remote, it waits for a certain amount of time
(somewhere in
the 5-30 second range) before transmitting the Send-Init, to give the
user time
to escape back to the local KERMIT and tell it to receive files.
_______________
3
A transaction should also be considered terminated
or the
other has stopped without sending an Error packet.
when
one
side
File Transfer
Page 13
5.1. Conditioning the Terminal
KERMIT is most commonly run with the user sitting at a microcomputer,
connected
through a communications port to a remote timesharing system. The
remote KERMIT is using its job's own "controlling terminal" for file transfer.
While the
microcomputer's port is an ordinary device, a timesharing job's
controlling
terminal is a special one, and often performs many services that would
interfere with normal operation of KERMIT. Such services include echoing (on
full
duplex systems), wrapping lines by inserting carriage return linefeed
sequences
at the terminal width, pausing at the end of a screen or page full of
text,
displaying system messages, alphabetic case conversion, control
character intepretation, and so forth.
Mainframe KERMIT programs should be
prepared to
disable as many of these services as possible before packet
communication
begins, and to restore them to their original condition at the end of a
transaction. Disabling these services is usually known as "putting the
terminal in
binary mode."
KERMIT's use of printable control character equivalents, variable
packet
lengths, redefinable markers and prefixes, and allowance for any
characters at
all to appear between packets with no adverse effects provide a great
deal of
adaptability for those systems that do not allow certain (or any) of
these features to be disabled.
5.2. Timeouts, NAKs, and Retries
If a KERMIT program is capable of setting a timer interrupt, or setting a
time
limit on an input request, it should do so whenever attempting to read a
packet
from the communication line, whether sending or receiving files. Having
read a
packet, it should turn off the timer.
If the sender times out waiting for an acknowledgement, it should send
the same
packet again, repeating the process a certain number of times up to a
retry
limit, or until an acknowledgement is received.
If the receiver
times out
waiting for a packet, it can send either a NAK packet for the expected
packet
or another ACK for the last packet it got.
If a packet from the sender is garbled or lost in transmission (the
latter is
detected when the sequence number increases by more than 1, modulo
64, the
former by a bad checksum), the receiver sends a NAK for the garbled or
missing
packet.
If an ACK or a NAK from the receiver is garbled or lost, the
sender
ignores it; in that case, one side or the other will time out and
retransmit.
A retry count is maintained, and there is a retry threshold,
normally set
around 5.
Whenever a packet is resent -- because of a timeout, or
because it
was NAK'd -- the counter is incremented. When it reaches the
threshold, the
transaction is terminated and the counter reset.
If neither side is capable of timing out, a facility for manual
intervention
must be available on the local KERMIT. Typically, this will work by
sampling
the keyboard (console) periodically; if input, such as a CR, appears,
then the
same action is taken as if a timeout had occurred. The local KERMIT
keeps a
running display of the packet number or byte count on the screen to
allow the
user to detect when traffic has stopped. At this point, manual
intervention
should break the deadlock.
File Transfer
Page 14
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.
Normally, only one side should be doing timeouts, preferably the side
with the
greatest knowledge of the "environment" -- system load, baud rate,
and so
forth, so as to optimally adjust the timeout interval for each packet.
If both
sides are timing out, their intervals should differ sufficiently to
prevent
collisions.
5.3. Errors
During file transfer, the sender may encounter an i/o error on the disk,
or the
receiver may attempt to write to a full or write-protected device.
Any
condition that will prevent successful transmission of the file is called a
"fatal
error".
Fatal errors should be detected, and the transfer shut down
gracefully, with the pertinent information provided to the user.
Error
packets
provide a mechanism to do this.
If a fatal error takes place on either the sending or receiving side,
the side
which encountered the error should send an Error (E) packet. The E
packet contains a brief textual error message in the data field.
Both the
sender and
receiver should be prepared to receive an Error packet at any time
during the
transaction. Both the sender and receiver of the Error packet should
halt, or
go back into into user command mode (a server should return to server
command
wait). The side that is local should print the error message on the
screen.
There is no provision for sending nonfatal error messages, warnings, or
information messages during a transaction. It would be possible to add such
a fea-
ture, but this would require both sides agree to use it through setting
of a
bit in the capability mask, since older KERMITs that did not know about
such a
feature would encounter an unexpected packet type and would enter the
fatal error state. In any case, the utility of such a feature is questionable,
since
there is no guarantee that the user will be present to see such messages
at the
time they are sent; even if they are saved up for later perusal in a
"message
box", their significance may be long past by the time the user reads
them. See
the section on Robustness, below.
5.4. Heuristics
During any transaction, several heuristics are useful:
1. A NAK for the current packet is equivalent to an ACK for the
previous packet (modulo 64).
This handles the common situation
in
which a packet is successfully received, and then ACK'd, but the
ACK
is lost. The ACKing side then times out waiting for the next
packet
and NAKs it. The side that receives a NAK for packet n+1
while
waiting for an ACK for packet n simply sends packet n+1.
2. If packet n arrives more than once, simply ACK it and discard
it.
This can happen when the first ACK was lost. Resending the ACK
is
necessary and sufficient -- don't write the packet out to the
file
again!
File Transfer
Page 15
3. When opening a connection, discard the contents of the line's
input
buffer before reading or sending the first packet.
This is
especially important if the other side is in receive mode (or acting
as
a server), in which case it may have been sending out periodic
NAKs
for your expected SEND-INIT or command packet. If you don't
do
this, you may find that there are sufficient NAKs to prevent
the
transfer -- you send a Send-Init, read the response, which is an
old
NAK, so you send another Send-Init, read the next old NAK, and
so
forth, up to the retransmission limit, and give up before getting
to
the ACKs that are waiting in line behind all the old NAKs.
If
the
number of NAKs is below the cutoff, then each packet may be
transmitted multiply.
4. Similarly, before sending a packet, you should clear the input
buffer (after looking for any required handshake character). Failure
to
clear the buffer could result in propogation of the repetition of
a
packet caused by stacked-up NAKs.
5.5. File Names
The syntax for file names can vary widely from system to system.
avoid
problems, it is suggested that filenames be represented in the File
Header (F)
packet in a "normal form", by default (that is, there should be an
option to
override such conversions).
To
1. Delete all pathnames and attributes from the file
specification.
The file header packet should not contain directory or device
names;
if it does, it may cause the recipient to try to store the file
in
an inaccessible or nonexistent area, or it
may
result
in
a
very
strange filename.
2. After stripping any pathname, convert the remainder of the
file
specification to the form "name.type", with no restriction on
length
(except that it fit in the data field of the F packet), and:
a. Include no more than one dot.
b. Use digits, uppercase letters only in name and type.
Special characters like "$", "_", "-", "&", and so forth should be
disallowed,
since they're sure to cause problems on one system or another.
The recipient, of course, cannot depend upon the sender to follow this
convention, and should still take precautions. However, since most file
systems embody the notion of a file name and a file type, this convention will
allow
these items to be expressed in a way that an unlike system can
understand. The
particular notation is chosen simply because it is the most common.
The recipient must worry about the length of the name
of the
file name.
If either is too long, they must be
result
(whether truncated or not) is the same as the name of
already exists in the same area, the recipient should have the
some special action to avoid writing over the original file.
and type
fields
truncated.
If the
a file that
ability to take
KERMIT implementations that convert file specifications to normal
form by
default should have an option to override this feature. This would
be most
File Transfer
Page 16
useful when transferring files between like systems, perhaps used in
conjunction with "image mode" file transfer. This could allow, for instance,
one UNIX
system to send an entire directory tree to another UNIX system.
5.6. Robustness
A major feature of the KERMIT protocol is the ability to transfer
multiple
files.
Whether a particular KERMIT program can actually send multiple
files
depends on the capabilities of the program and the host operating system
(any
KERMIT program can receive multiple files).
If a KERMIT program can send multiple files, it should make every
attempt to
send the entire group specified. If it fails to send a particular
file, it
should not terminate the entire batch, but should go on the the next
one, and
proceed until an attempt has been made to send each file in the group.
Operating in this robust manner, however, gives rise to a problem: the
user
must be notified of a failure to send any particular file.
Unfortunately, it
is not sufficient to print a message to the screen since the user may
not be
physically present.
A better solution would be to have the sender
optionally
keep a log of the transaction, giving the name of each file for which
an attempt was made, and stating whether the attempt was successful, and if
not, the
reason.
Additional aids to robustness are described in the Optional
Features
section, below.
5.7. Flow Control
On full duplex connections, XON/XOFF flow control can generally be used
in conjunction with KERMIT file transfer with no ill effects. This is because
XOFFs
are sent in the opposite direction of packet flow, so they will not
interfere
with the packets themselves. XON/XOFF, therefore, need not be
implemented by
the KERMIT program, but can done by the host system. If the host
system
provides this capability, it should be used -- if both sides can
respond
XON/XOFF signals, then buffer overruns and the resulting costly
packet
retransmissions can be avoided.
Beware, however, of the following situation: remote Kermit is sending
periodic
NAKs, local system is buffering them on the operating system level
(because the
user has not started the local end of the file transfer yet); local line
buffer
becomes full, local systems sends XOFF, remote starts buffering them up
on its
end, user finally starts file transfer on local end, clears buffer,
local
operating system sends XON, and then all the remotely buffered NAKs
show up,
causing the packet echoing problem described above, despite the buffer
clearing.
Flow control via modem signals can also be used when available.
Note that flow control should not be confused with "handshake" or
"line
turnaround" techniques that are used on simplex or half-duplex
communication
lines.
File Transfer
Page 17
5.8. Basic KERMIT Protocol State Table
The KERMIT protocol can be described as a set of states and
transitions, and
rules for what to do when changing from one state to another.
State
changes
occur based on the type of packets that are sent or received, or
errors that
may occur. Packets always go back and forth; the sender of a file always
sends
data packets of some kind (init, header, data) and the receiver always
returns
ACK or NAK packets.
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 responses may occur; these are shown
in the
EVENT column. For each event, an appropriate ACTION is taken, and the
protocol
enters a NEW STATE.
The following table specifies basic KERMIT operation. Timeouts and
error conditions have been omitted from the following table for simplicity, but
the action is as described above. Server operation and some of the advanced
features
are also omitted. A full-blown state table is given subsequently.
File Transfer
Page 18
STATE
EVENT
ACTION
NEW STATE
-- SEND STATES -Send Send-Init Packet
S
Get NAK,bad ACK (None)
Get good ACK
Set remote's params, open file
(Other)
(None)
S
SF
A
Send File-Header Packet
SF
Get NAK,bad ACK (None)
Get good ACK
Get bufferful of file data
(Other)
(None)
SF
SD
A
Send File-Data Packet
SD
Get NAK,bad ACK
Get good ACK
(End of file)
(Other)
(None)
Get bufferful of file data
(None)
(None)
SD
SD
SZ
A
Send EOF Packet
SZ
Get NAK,bad ACK
Get good ACK
(No more files)
(Other)
(None)
Get next file to send
(None)
(None)
SZ
SF
SB
A
Send Break (EOT) Packet
SB
Get NAK,bad ACK (None)
Get good ACK
(None)
(Other)
(None)
SB
C
A
-- RECEIVE STATES -Wait for Send-Init Packet
R
Get Send-Init
ACK w/local params
(Other)
(None)
RF
A
Wait for File-Header Packet
RF
Get Send-Init
ACK w/local params
(previous ACK was lost)
Get Send-EOF
ACK (prev ACK lost)
Get Break
ACK
Get File-Header Open file, ACK
(Other)
(None)
RF
RF
C
RD
A
Wait for File-Data Packet
RD
Get previous
packet(D,F)
Get EOF
Get good data
(Other)
ACK it again
ACK it, close the file
Write to file, ACK
(None)
RD
RF
RD
A
File Transfer
Page 19
-- STATES COMMON TO SENDING AND RECEIVING -C
A
(Send Complete)
("Abort")
start
start
Packet Format
Page 20
6. Packet Format
6.1. Fields
The KERMIT protocol is built around exchange of packets of the
following format:
+------+-----------+-----------+------+------------+-------+
| MARK | char(LEN) | char(SEQ) | TYPE |
DATA
| CHECK |
+------+-----------+-----------+------+------------+-------+
where all fields consist of ASCII characters.
The fields are:
MARK
The synchronization character that marks the beginning of
packet.
This should normally be CTRL-A, but may be redefined.
the
LEN
The number of ASCII characters within the packet that
follow this
field, in other words the packet length minus two. Since this
number
is transformed to a single character via the char() function,
packet
character counts of 0 to 94 (decimal) are permitted, and 96
(decimal)
is the maximum total packet length. The length does not
include endof-line or padding characters, which are outside the packet
and are
strictly for the benefit of the operating system or
communications
equipment, but it does include the block check characters.
SEQ
The packet sequence number, modulo 64, ranging from 0 to 63.
Sequence
numbers "wrap around" to 0 after each group of 64 packets.
TYPE
types
The
packet type, a single ASCII character.
are required:
D
Y
N
S
B
F
Z
Data packet
Acknowledge (ACK)
Negative acknowledge (NAK)
Send initiate (exchange parameters)
Break transmission (EOT)
File header
End of file (EOF)
The following packet
E
T
Error
Reserved for internal use
The NAK packet is used only to indicate that the expected
was
not received correctly, never to supply other kinds of
information,
such as refusal to perform a requested service. The NAK packet
always
has an empty data field. The T "packet" is used internally
by many
KERMIT programs to indicate that a timeout occurred.
packet
DATA
given
The "contents" of the packet, if any contents are required in the
type of packet, interpreted according to
the
packet
type.
Control
characters (bytes whose low order 7 bits are in the ASCII control
range
0-31, or 127) are preceded by a special prefix character,
normally "#",
and "uncontrollified" via ctl(). A prefixed sequence may not be
broken
across packets. Logical records in printable files are
delimited with
CRLFs, suitably prefixed (e.g. "#M#J"). Logical records need not
correspond to packets. Any prefix characters are included in the
count.
Packet Format
Page 21
Optional
described
later.
encoding
for 8-bit data and repeated characters is
CHECK
A block check on the characters in the packet between, but not
including, the mark and the block check itself. The check for each
packet is
computed by both hosts, and must agree if a packet is to be
accepted.
A single-character arithmetic checksum is the normal and required
block
check. Only six bits of the arithmetic sum are included.
In
order
that all the bits of each data character contribute to this
quantity,
bits 6 and 7 of the final value are added to the quantity
formed by
bits 0-5.
Thus if s is the arithmetic sum of the ASCII
characters,
then
check = char((s + ((s AND 192)/64)) AND 63)
capable
This is the default block check, and all Kermits must be
of
performing it. Other optional block check types are described
later.
The block check is based on the ASCII values of all the
characters in
the packet, including control fields and prefix characters.
Non-ASCII
systems must translate to ASCII before performing the block
check calculation.
6.2. Terminator
Any line terminator that is required by the system may be appended
to the
packet; this is carriage return (ASCII 15) by default. Line
terminators are
not considered part of the packet, and are included 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 when
sending to that host. The terminator can be specified in the initial
connection exchange.
Some KERMIT implementations also use the terminator for another
reason
-- speed.
Some systems are not fast enough to take in a packet and
decode it
character by character at high baud rates; by blindly reading and
storing all
characters between the MARK and the EOL, they are able to absorb the
incoming
characters at full speed and then process them at their own rate.
6.3. Other Interpacket Data
The space between packets may be used for any desired purpose.
Handshaking
characters may be necessary on certain connections, others may require
screen
control or other sequences to keep the packets flowing.
Packet Format
Page 22
6.4. Encoding, Prefixing, Block Check
MARK, LEN, SEQ, TYPE, and CHECK are control fields. Control fields are
always
literal single-character fields, except that the CHECK field may be
extended by
one or two additional check characters.
Each control field is
encoded by
char() or taken literally, but never prefixed. The control fields
never contain 8-bit data.
The DATA field contains a string of data characters in which any
control
characters are encoded printably and preceded with the control
prefix. The
decision to prefix a character in this way depends upon whether its low
order 7
bits are in the ASCII control range, i.e. 0-31 or 127. Prefix characters
that
appear in the data must themselves be prefixed by the control prefix,
but unlike control characters, these retain their literal value in the packet.
The treatment of the high order ("8th") bit of a data byte is as follows:
- If the communication channel allows 8 data bits per character,
then
the original value of the 8th bit is retained in the prefixed
character. For instance, a data byte corresponding to a Control-A with
the
8th bit set would be send as a control prefix, normally "#",
without
the 8th bit set, followed by ctl(^A) with the 8th bit set. In
binary
notation, this would be
00100011 10000001
In this case, the 8th bit is figured into all
calculations.
- If
the
block
check
communication channel or one of the hosts required parity
on
each character, and both sides were capable of 8th-bit
prefixing,
then the 8th bit will be used for parity, and must not be included
in
the block check.
8th bit prefixing is an option feature described
in
greater detail in Section 8, below.
- If parity is being used but 8th-bit prefixing is not being done,
then
the value of the 8th bit of each data byte will be lost and
binary
files will not be transmitted correctly. Again, the 8th bit does
not
figure into the block check.
The data fields of all packets are subject to prefix encoding, except S,
I, and
A packets, and their ACKs (see below).
Initial Connection
Page 23
7. Initial Connection
Initial connection occurs when the user has started up a Kermit program
on both
ends of the physical connection. One Kermit has been directed (in one
way or
another) to send a file, and the other to receive it.
The receiving Kermit waits for a "Send-Init" packet from the sending
Kermit.
It doesn't matter whether the sending Kermit is started before or
after the
receiving Kermit (if before, the Send-Init packet should be
retransmitted
periodically until the receiving Kermit acknowledges it). The data
field of
the Send-Init packet is optional; trailing fields can be omitted (or
left
blank, i.e. contain a space) to accept or specify default values.
The Send-Init packet contains a string of configuration information in
its data
field.
The receiver sends an ACK for the Send-Init, whose data field
contains
its own configuration parameters. The data field of the Send-Init and
the ACK
to the Send-Init are literal, that is, there is no prefix encoding.
This is
because the two parties will not know how to do prefix encoding until
after the
configuration data is exchanged.
It is important to note that newly invented fields are added at
right, so
that old KERMIT programs that do not have code to handle the
fields will
act as if they were not there. For this reason, the default
for any
field, indicated by blank, should result in the behavior that
before
the new field was defined or added.
the
new
value
occurred
1
2
3
4
5
6
7
8
9
10...
+------+------+------+------+------+------+------+------+------+------| MAXL | TIME | NPAD | PADC | EOL | QCTL | QBIN | CHKT | REPT | CAPAS
+------+------+------+------+------+------+------+------+------+------The fields are as follows (the first and second person "I" and "you"
used
are
to distinguish the two sides). Fields are encoded printably using the
char()
function unless indicated otherwise.
1. MAXL
to 94
The maximum length packet I want
(decimal).
to
receive,
a
number
up
You respond with the maximum you want me to send.
This
allows systems to adjust to each other's buffer sizes, or to
the condition of the transmission medium.
2. TIME
while
The number of seconds after which I want you to
waiting
for a packet from me.
time
me
out
You respond with the amount of
time I
should wait for packets from you.
to
This allows the two sides
accommodate
to different line speeds or other factors that could
cause
timing problems.
Only one side needs to time out.
If
both
sides
time out, then the timeout intervals should not be close
together.
3. NPAD
incoming
The
number
of
padding
characters
packet; you respond in kind.
I want to precede each
Padding may be necessary
when
sending
to
a half duplex system that requires some time to change the
direction of transmission, although in practice
this
situation
is
more
commonly handled by a "handshake" mechanism.
4. PADC
The control character I need for padding, if any,
transformed by
ctl() (not char()) to make it printable. You respond in kind.
Normally NUL (ASCII 0), some systems use DEL (ASCII 127). This
field is
Initial Connection
Page 24
to be ignored if the value NPAD is zero.
5. EOL
The character I need to terminate an incoming packet, if
any. You
respond in kind. Most systems that require a line
terminator for
terminal input accept carriage return for this purpose (note,
because
there is no way to specify that no EOL should be sent, it
would have
been better to use ctl() for this field rather than char(), but
it's
too late now).
6. QCTL
control
(verbatim)
The printable ASCII character I will use to quote
characters, normally and by default "#".
the
You respond
with
one
you will use.
The following fields relate to
KERMIT
protocol, described in section 8.
7. QBIN
quote
the
use of OPTIONAL features of the
(verbatim) The printable ASCII character
characters
I
want
to
use
to
which have the 8th bit set, for transmitting binary
files
when the parity bit cannot be used for data.
kind
Since
this
of
quoting
increases
both
processor
and transmission overhead,
it is
normally to be avoided.
in
If used, the quote character must be
the
range
ASCII 33-62 ("!" through ">") or 96-126 ("`" through
"~"), but
different from the control-quoting character.
This field
is
interpreted as follows:
Y
N
&
I agree to 8-bit quoting if you request it.
I will not do 8-bit quoting.
(or any other character in the range 33-62 or 96-126) I
want to
do 8-bit quoting using this character (it will
if
be
done
the
other
Kermit
puts
a Y in this field, or responds with
the same
prefix character, such as &).
quoting
The
recommended
8th-bit
prefix character is "&".
Anything Else : 8-bit quoting will not be done.
Note that this scheme allows either side to initiate the
request, and
the order does not matter. For instance, a micro capable of
8-bit
communication will normally put a "Y" in this field
whereas a
mainframe that uses parity will always put an "&". No
matter who
sends first, this combination will result in election of
8th-bit
quoting.
8. CHKT
charac-
Check
Type, the method for detecting errors.
"1" for single-
ter checksum (the normal and required method), "2" for
two-
character
checksum (optional), "3" for three-character CRC-CCITT
(optional).
If your response agrees, the designated method will be used;
otherwise the single-character checksum will be used.
9. REPT
The prefix character I will use to indicate a repeated
character.
This can be any printable character in the range ASCII 3362 or
96-126, but different from the control and 8th-bit prefixes.
SP (32)
denotes no repeat count processing is to be done. Tilde ("~")
is the
recommended and normal repeat prefix. If you don't respond
identically, repeat counts will not be done. Groups of at least 3
or 4
identical characters may be transmitted more efficiently
using a
repeat count, though an individual implementation may wish to
set a
different threshhold.
Initial Connection
Page 25
10-?. CAPAS
A bit mask, in which each bit position corresponds to a
capability of
KERMIT, and is set to 1 if that capability is present, or 0 if
it is
not. Each character contains a 6-bit field (transformed by
CHAR()),
whose low order bit is set to 1 if another capability byte
follows,
and to 0 in the last capability byte. The capabilities
defined so
far are:
#1
#2
#3
Reserved
Reserved
Ability to accept "A" packets (file attributes)
The capability byte as defined so far would then look like:
bit5 bit4 bit3 bit2 bit1 bit0
+----+----+----+----+----+----+
| #1 | #2 | #3 | -- | -- | 0 |
+----+----+----+----+----+----+
If
all
these capabilities were "on", the value of the byte
would be
70 (octal).
When capabilities 4, 5 and 6 are added,
the
capability
mask will look like this:
bit5 bit4 bit3 bit2 bit1 bit0
+----+----+----+----+----+----+
bit5 bit4 bit3 bit2 bit1 bit0
+----+----+----+----+----+---
| #1 | #2 | #3 | #4 | #5 |
| #6 | -- | -- | -- | -- |
-+
1 |
0
|
+----+----+----+----+----+----+
+----+----+----+----+----+---
-+
Next 4: Reserved Fields
Sites that wish to add their own parameters to the initial
connection
negotiation must start at the 5th field after the last
capability
byte. Any intervening fields may be left blank (that is,
they may
contain the space character). These fields are reserved for
future
use by the standard KERMIT protocol.
The control, 8th-bit, and repeat prefixes must be distinct.
The receiving Kermit responds with an ACK ("Y") packet in the same
format to
indicate its own preferences, options, and parameters. The ACK need
not contain the same number of fields as the the Send-Init. From that point,
the two
KERMIT programs are "configured" to communicate with each other
for the
remainder of the transaction. In the case of 8th-bit quoting, one side
must
specify the character to be used, and the other must agree with a "Y"
in the
same field, but the order in which this occurs does not matter.
Similarly for
checksums -- if one side requests 2 character checksums and the
other side
responds with a "1" or with nothing at all, then single-character
checksums
will be done, since not all implementations can be expected to do 2character
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.
Kermit implementations should know what to do in these cases, namely
apply appropriate defaults. The defaults should be:
MAXL:
80
Initial Connection
Page 26
NPAD:
PADC:
EOL:
QCTL:
QBIN:
CHKT:
REPT:
MASK:
0, no padding
0 (NUL)
CR (carriage return)
the character "#"
none, don't do 8-bit quoting
"1", single-character checksum
No repeat count processing
All zeros (no special capabilities)
There are no prolonged negotiations in the initial connection sequence -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 require certain parity, some padding, handshaking, or a special end
of line
character in order to read the Send-Init packet. For this reason, there
should
be a way for the user the user to specify whatever may be necessary to
get the
first packet through.
A parity field is not provided in the Send-Init packet because it could
not be
of use. If the sender requires a certain kind of parity, it will also be
sending it. If the receiver does not know this in advance, i.e. before
getting the
Send-Init, it will not be able to read the Send-Init packet.
Optional Features
Page 27
8. Optional Features
The foregoing sections have discussed basic, required operations for any
KERMIT
implementation. The following sections discuss optional and advanced
features.
8.1. 8th-Bit and Repeat Count Prefixing
Prefix quoting of control characters is mandatory. In addition,
prefixing may
also be used for 8-bit quantities or repeat counts, when both KERMIT
programs
agree to do so.
8th-bit prefixing can allow 8-bit binary data pass
through
7-bit physical links. Repeat count prefixing can improve the
throughput of
certain kinds of files dramatically; binary files (particularly
executable
programs) and structured text (highly indented or columnar text) tend to
be the
major beneficiaries.
When more than one type of prefixing is in effect, a single data
character can
be preceded by more than one prefix character. Repeat count
processing can
only be requested by the sender, and will only be used by the sender
if the
receiver agrees.
8th-bit prefixing is a special case because its use
is normally not desirable, since it increases both processing and transmission
overhead.
However, since it is the only straightforward mechanism for
binary file
transfer available to those systems that usurp the parity bit, a receiver
must
be able to request the sender to do 8th-bit quoting, since most
senders will
not normally do it by default.
The repeat prefix is followed immediately by a single-character repeat
count,
encoded printably via char(), followed by the character itself
(perhaps
prefixed by control or 8th bit quotes, as explained below). The repeat
count
may express values from 0 to 94. If a character appears more than 94
times in
a row, it must be "cut off" at 94, emitted with all appropriate
prefixes, and
"restarted".
The following table should clarify Kermit's quoting
mechanism
(the final line shows how a sequence of 120 consecutive NULs would be
encoded):
Character
A
^A
'A
'^A
#
'#
&
'&
~
'~
NUL
Quoted
Representation
A
#A
&A
&#A
##
&##
#&
&#&
#~
&#~
#@
With
Repeat Count for 6
~(A
["(" is ASCII 40 - 32 = 6]
~(#A
~(&A
~(&#A
~(##
~(&##
~(#&
~(&#&
~(#~
~(&#~
~~#@~:#@ [120 NULs]
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
"&" immediately following a "~" denote repeat counts, not control characters or
8-bit
characters. The control quote character "#" is most closely bound to the
data
character, then the 8-bit prefix, then the repeat count; in other
words, the
Optional Features
Page 28
order is:
repeat prefix and count, 8-bit quote, control quote, and
the data
character itself. To illustrate, note that &#A is not equivalent to #&A.
When the parity bit is available for data, then 8th-bit quoting should
not be
done, and the 8th bit of the prefixed character will have the same value
as the
8th bit of the original data byte. In that case, the table looks like
this:
Character
'A
'^A
'#
'&
'~
Quoted
Representation
'A
#'A
#'#
'&
#'~
With
Repeat Count for 6
~('A
~(#'A
~(#'#
~('&
~(#'~
Note that since 8th bit quoting is not being done, "&" is not being used
as an
8th bit prefix character, so it does not need to be quoted with "#".
Also,
note that the 8th bit is set on the final argument of the repeat
sequence, no
matter how long, and not on any of the prefix characters.
Finally, remember the following rules:
- Prefixed sequences must not be broken across packets.
- Control, 8th-bit, and repeat count prefixes must be distinct.
- Data fields of all packets must pass through the prefix
encoding
mechanism, except for S, I, and A packets, and ACKs to those
packets.
In the first rule above, note that a prefixed sequence means a single
character
and all its prefixes, like ~%&#X, not a sequence like #M#J, which
is two
prefixed sequences.
8.2. Server Operation
A KERMIT server is a KERMIT program running remotely with no "user
interface".
All commands to the server arrive in packets from the local KERMIT.
SERVER
operation is much more convenient than basic operation, since the user
need
never again interact directly with the remote KERMIT program after once
starting it up in server mode, and therefore need not issue complementary
SEND and
RECEIVE commands on the two sides to get a file transfer started;
rather, a
single command (such as SEND or GET) to the local KERMIT suffices.
KERMIT servers can also provide services beyond file transfer.
Between transactions, a Kermit server waits for packets containing server
commands. The packet sequence number is always set back to 0 after a
transaction.
A Kermit server in command wait should be looking for packet 0, and
command
packets sent to servers should also be packet 0. Certain server commands
will
result in the exchange of multiple packets. Those operations proceed
exactly
like file transfer.
A KERMIT server program waiting for a command packet is said to be in
"server
command wait".
Once put into server command wait, the server should
never
leave it until it gets a command packet telling it to do so. This means
that
after any transaction is terminated, either normally or by any kind of
error,
Optional Features
Page 29
the server must go back into command wait. While in command wait, a
server may
elect to send out periodic NAKs for packet 0, the expected command
packet.
Since the user may be disconnected from the server for long periods of
time
(hours), the interval between these NAKs should be significantly
longer than
the normal timeout interval (say, 30-60 seconds, rather than 5-10). The
periodic NAKs are useful for breaking the deadlock that would occur if a
local
program was unable to time out, and sent a command that was lost. On the
other
hand, they can cause problems for local KERMIT programs that cannot clear
their
input buffers, or for systems that do XON/XOFF blindly, causing the
NAKs to
buffered in the server's host system output buffer, to be suddenly
released en
masse when an XON appears. For this reason, servers should have an
option to
set the command-wait wakeup interval, or to disable it altogher.
Server operation must be implemented in two places: in the server
itself, and
in any KERMIT program that will be communicating with a server.
The
server
must have code to read the server commands from packets and respond to
them.
The user KERMIT must have code to parse the user's server-related
commands, to
form the server command packets, and to handle the responses to those
server
commands.
8.2.1. Server Commands
Server commands are listed below. Not all of them have been
implemented, and
some may never be, but their use should be reserved. Although
server-mode
operation is optional, certain commands should be implemented in every
server.
These include Send-Init (S), Receive-Init (R), and the Generic
Logout (GL)
and/or Finish (GF) commands. If the server receives a command it does
not un-
derstand, or cannot execute, it should respond with an Error (E)
packet containing a message like "Unimplemented Server Command" and both sides
should set
the packet sequence number back to 0, and the server should remain in
server
command wait. Only a GL or GF command should terminate server operation.
Server commands are as follows:
S
Send Initiate (exchange parameters, server waits for a file).
R
Receive Initiate (ask the server to send the specified files).
I
Initialize (exchange parameters).
X
Text header. Allows transfer of text to the user's screen in
response to a
generic or host command. This works just like file transfer
except that
the destination "device" is the screen rather than a file. Data
field may
contain a filename, title, or other heading.
C
Host Command. The data field contains a string to be executed as a
command
by the host system command processor.
K
KERMIT Command.
The data field contains a string in the
interactive command language of the KERMIT server (normally a SET command) to be
executed
as if it were typed in at command level.
G
Generic Kermit Command. Single character in data field (possibly
followed
by operands, shown in {braces}, optional fields in [brackets])
specifies
the command:
I
C
L
F
D
Login [{*user[*password[*account]]}]
CWD, Change Working Directory [{*directory[*password]}]
Logout, Bye
Finish (Shut down the server, but don't logout).
Directory [{*filespec}]
Optional Features
Page 30
U
E
T
R
K
W
M
H
Q
P
J
V
Disk Usage Query [{*area}]
Erase (delete) {*filespec}
Type {*filespec}
Rename {*oldname*newname}
Copy {*source*destination}
Who's logged in? (Finger) [{*user ID or network host[*options]}]
Send a short Message {*destination*text}
Help [{*topic}]
Server Status Query
Program {*[program-filespec][*program-commands]}
Journal {*command[*argument]}
Variable {*command[*argument[*argument]]}
Note that field length encoding is used within the data field
of all
Generic command packets, but not within the data fields of the other
packets, such as S, I, R, X, K, and C.
Asterisk as used above ("*") represents a single-character length
field, encoded using char(), for the operand that follows it; thus lengths from 0
to 94
may be specified.
This allows multiple operands to be clearly
delimited
regardless of their contents.
All server commands that send arguments in their data fields should
pass
through the prefix encoding mechanism.
Thus if a data character or
length
field happens to correspond to an active prefix character, it must
itself be
prefixed.
The field length denotes the length of the field before
prefix encoding and (hopefully) after prefix decoding. For example, to send a
generic
command with two fields, "ABC" and "ZZZZZZZZ", first each field
would be
prefixed by char() of its length, in this case char(3) and char(8),
giving
"#ABC(ZZZZZZZZ".
But "#" is the normal control prefix character so it
must be
prefixed itself, and the eight Z's can be condensed to 3 characters
using a
repeat prefix (if repeat counts are in effect), so the result after
encoding
would be "##ABC(~(Z" (assuming the repeat prefix is tilde ("~"). The
recipient
would decode this back into the original "#ABC(ZZZZZZZZ" before
attempting to
extract the two fields.
Since a generic command must fit into a single packet, the program
sending the
command should ensure that the command actually fits, and should not
include
length fields that point beyond the end of the packet. Servers,
however,
should be defensive and not attempt to process any characters beyond the
end of
the data field, even if the argument length field would lead them to do
so.
8.2.2. Timing
KERMIT does not provide a mechanism for suspending and continuing a
transaction.
This means that text sent to the user's screen should not be
frozen
for long periods (i.e. not longer than the timeout period times the
retry
threshold).
Between transactions, when the server has no tasks pending, it may
send out
periodic NAKs (always with type 1 checksums) to prevent a deadlock in
case a
command was sent to it but was lost. These NAKs can pile up in the
local
"user" Kermit's input buffer (if it has one), so the user Kermit
should be
prepared to clear its input buffer before sending a command to a
server.
Meanwhile, servers should recognize that some systems provide no function
to do
Optional Features
Page 31
this (or even when they do, the process can be foiled by system flow
control
firmware) and should therefore provide a way turn off or slow down the
commandwait NAKs.
8.2.3. The R Command
The R packet, generally sent by a local Kermit program whose user typed
a GET
command, tells the server to send the files specified by the name in
the data
field of the R packet. Since we can't assume that the two Kermits are
running
on like systems, the local (user) Kermit must parse the file
specification as a
character string and let the server to check it. If the server can
open and
read the specified file, it sends a Send-Init (S) packet -- not an
acknowledgement! -- to the user, and then completes the file-sending
transaction, as
described above.
If the server cannot send the file, it should respond with an error (E)
packet
containing a reason, like "File not found" or "Read access required".
8.2.4. The K Command
The K packet can contain a character string which the server interprets
as a
command in its own interactive command language. This facility is
useful for
achieving the same effect as a direct command without having to shut
down the
server, connect back to the remote system, continue it (or start a new
one),
and issue the desired commands. The server responds with an ACK if the
command
was executed successfully, or an error packet otherwise. The most
likely use
for the K packet might be for transmitting SET commands, e.g. for
switching between text and binary file modes.
8.2.5. Short and Long Replies
Any request made of a server may be answered in either of two ways,
and any
User Kermit that makes such a request should be prepared for either
kind of
reply:
- A short reply. This consists of a single ACK packet, which may
contain text in its data field. For instance, the user might send
a
disk space query to the server, and the server might ACK the
request
with a short character string in the data field, such as "12K
bytes
free". The user KERMIT should display this text on the screen.
- A
long
reply.
This proceeds exactly like a file transfer (and
in
some cases it may be a file transfer).
It begins
with
one
of
the
following:
* A File-Header (F) packet (optionally followed by one or more
Attributes packets; these are discussed later);
* A Text-Header (X) packet.
* A Send-Init (S) Packet, followed by an X or F packet.
After
pack-
the
X or F packet comes an arbitrary number of Data (D)
Optional Features
Page 32
ets, then an End-Of-File (Z) packet, and finally a BreakTransmission
(B) packet, as for ordinary file transfer.
A long reply should begin with an S packet unless an I-packet exchange
has already taken place, and the type 1 (single-character) block check is being
used.
8.2.6. Additional Server Commands
The following server commands request the server to perform tasks other
than
sending or receiving files. Almost any of these can have either short
or long
replies. For instance, the Generic Erase (GE) command may elicit a
simple ACK,
or a stream of packets containing the names of all the files it
erased (or
didn't erase). These commands are now described in more detail;
arguments are
as provided in commands typed to the user KERMIT (subject to prefix
encoding);
no transformations to any kind of normal or canonic form are done -filenames
and other operands are in the syntax of the server's host system.
I
Login. For use when a KERMIT server is kept perpetually running on a
dedicated line. This lets a new user obtain an identity on the server's
host
system.
If the data field is empty, this removes the user's
identity, so
that the next user does not get access to it.
L
Logout, Bye. This shuts down the server entirely, causing the
server itself to log out its own job. This is for use when the server
has been
started up manually by the user, who then wishes to shut it down
remotely.
For a perpetual, dedicated server, this command simply removes the
server's
access rights to the current user's files, and leaves the server
waiting
for a new login command.
F
Finish. This is to allow the user to shut down
putting its
the
server,
terminal back into normal (as opposed to binary or raw) mode, and
putting
the server's job back at system command level, still logged in, so
that the
user can connect back to the job. For a perpetual, dedicated server,
this
command behaves as the L (BYE) command.
C
CWD.
Change Working Directory. This sets the default directory
or area
for file transfer on the server's host. With no operands, this
command
sets the default area to be the user's own default area.
D
Directory.
Send a directory listing to the user. The user
program can
display it on the terminal or store it in a file, as it chooses.
The
directory listing should contain file sizes and creation dates as
well as
file names, if possible. A wildcard or other file-group designator
may be
specified to ask the server list only those files that match.
If no
operand is given, all files in the current area should be shown.
U
Disk Usage Query.
used and
the amount left
should be
specified).
E
Erase (delete).
The server responds with the amount of
space
free to use, in K bytes (or other units, which
Delete the specified file or file group.
T
Type. Send the specified file or file group, indicating (by starting
with
an X packet rather than an F packet, or else by using the Type
attribute)
that the file is to be displayed on the screen, rather than stored.
Optional Features
Page 33
R
Rename. Change the name of the file or files as indicated. The
string indicating the new name may contain other attributes, such as
protection
code, permitted in file specifications by the host.
K
Copy. Produce a new copy of the file or file group, as indicated,
leaving
the source file(s) unmodified.
W
Who's logged in? (Finger). With no arguments, list all the users
who are
logged in on the server's host system.
If an argument is
specified,
provide more detailed information on the specified user or network
host.
M
Short Message.
Send
the indicated user's screen.
the given short (single-packet) message to
P
Program. This command has two arguments, program name
(filespec), and
command(s) for the program. The first field is required, but may
be left
null (i.e. zero length). If it is null, the currently loaded
program is
"fed" the specified command. If not null, the specified program is
loaded
and started; if a program command is given it is fed to the program
as an
initial command (for instance, as a command line argument on
systems that
support that concept). In any case, the output of the program is
sent back
in packets as either a long or short reply, as described above.
J
Journal. This command controls server transaction logging.
field
contains one of the following:
+
close
The data
Begin/resume logging transactions. If a filename is given,
any
currently open transaction and then open the specified file as
the new
transaction log. If no name given, but a log file was already
open,
resume logging to that file. If no filename was given and no
log was
open,
the
server
should
open
a
log
with
a
default
name,
like
TRANSACTION.LOG.
Stop logging transactions, but don't close the current
transaction log
file.
C
S
first.
Stop logging and close the current log.
Send the transaction log as a file.
If it was open, close it
Transaction logging is the recording of the progress of file
transfers. It
should contain entries showing the name of each file transferred,
when the
transfer began and ended, whether it completed successfully, and
if not,
why.
V
Set or Query a variable. The command can be S or Q. The first
argument is
the variable name. The second argument, if any, is the value.
S
Set the specified variable to the specified value. If the
value is
null, then undefine the variable. If the variable is null
then do
nothing.
If the variable did not exist before, create it. The
server
should respond with an ACK if successful, and Error packet
otherwise.
Q
Query the value of the named variable. If no variable is
supplied,
display the value of all active variables. The server
responds with
either a short or long reply, as described above. If a queried
vari-
Optional Features
Page 34
able does not exist, a null value is returned.
Variables are named by character strings, and have character string
values,
which may be static or dynamic. For instance, a server might have
built-in
variables like "system name" which never changes, or others like
"mail
status" which, when queried, cause the server to check to see if the
user
has any new mail.
8.2.7. Host Commands
Host commands are conceptually simple, but may be hard to implement
on some
systems. The C packet contains a text string in its data field which is
simply
fed to the server's host system command processor; any output from the
processor is sent back to the user in KERMIT packets, as either a short
or long
reply.
Implementation of this facility under UNIX, with its forking process
structure
and i/o redirection via pipes, is quite natural. On other systems, it
could be
virtually impossible.
8.2.8. Exchanging Parameters Before Server Commands
In basic KERMIT, the Send-Init exchange is always sufficient to
configure the
two sides to each other. During server operation, on the other hand,
some
transactions may not begin with a Send-Init packet. For instance,
when the
user sends an R packet to ask the server to send a file, the server
chooses
what block check option to use. Or if the user requests a directory
listing,
the server does not know what packet length to use.
The solution to this problem is the "I" (Init-Info) packet. It is
exactly like
a Send-Init packet, and the ACK works the same way too. However, receipt
of an
I packet does not cause transition to file-send state. The I-packet
exchange
simply allows the two sides to set their parameters, in preparation
for the
next transaction.
Servers should be able to receive and ACK "I" packets when in server
command
wait. User KERMITs need not send "I" packets, however; in that case, the
server will assume all the defaults for the user listed on page 25, or
whatever
parameters have been set by other means (e.g. SET commands typed to the
server
before it was put in server mode).
User Kermits which send I packets should be prepared to receive and
ignore an
Error packet in response. This could happen if the server has not
implemented
I packets.
8.3. Alternate Block Check Types
There are two optional kinds of block checks:
Type 2
A two-character checksum based on the low order 12 bits of the
arithmetic
sum of the characters in the packet (from the LEN field through
last
data character, inclusive) as follows:
the
Optional Features
Page 35
1
2
--------+--------------+-------------+
...data | char(b6-b11) | char(b0-b5) |
--------+--------------+-------------+
For instance, if the 16-bit result is 154321 (octal), then the 2
character
block check would be "C1".
Type 3
Three-character 16-bit CRC-CCITT. The CRC calculation treats the
data it
operates upon as a string of bits with the low order bit of the
first
character first and the high order bit of the last character last.
The initial value of the CRC is taken as 0; the 16-bit CRC is the remainder
after
16 12 5
dividing the data bit string by the polynomial X +X +X +1 (this
calculation can actually be done a character at a time, using a simple
table
lookup algorithm). The result is represented as three printable
characters
at the end of the packet, as follows:
1
2
3
--------+---------------+--------------+-------------+
...data | char(b12-b15) | char(b6-b11) | char(b0-b5) |
--------+---------------+--------------+-------------+
For instance, if the 16-bit result is 154321 (octal), then the 3
character
block check would be "-C1". The CRC technique chosen here agrees
with many
hardware implementations (e.g. the VAX CRC instruction). A useful
reference on table-driven CRC calculations can be found in "Bytewise CRC
Calculations" by Aram Perez in IEEE MICRO, June 1983, p.40.
The single-character checksum has proven quite adequate in practice. The
other
options can be used only if both sides agree to do so via Init packet (S
or I)
exchange. The 2 and 3 character block checks should only be used under
conditions of severe line noise and packet corruption.
Since type 2 and 3 block checks are optional, not all KERMITs can be
expected
to understand them. Therefore, during initial connection, communication
must
begin using the type 1 block check. If type 2 or 3 block checks are
agreed to
during the "I" or "S" packet exchange, the switch will occur only
after the
Send-Init has been sent and ACK'd with a type 1 block check. This
means that
the first packet with a type 2 or 3 block check must always be an "F"
or "X"
packet.
Upon completion of a transaction, both sides must switch back
to type
1 (to allow for the fact that neither side has any way of knowing
when the
other side has been stopped and restarted). The transaction is over
after a
"B" or "E" packet has been sent and ACK'd, or after any error that
terminates
the transaction prematurely or abnormally.
A consequence of the foregoing rule is that if a type 2 or 3 block check
is to
be used, a long reply sent by the server must begin with a SendInit (S)
packet, even if an I packet exchange had already occurred. If type 1
block
checks are being used, the S packet can be skipped and the transfer can
start
with an X or F packet.
A server that has completed a transaction and is awaiting a new
command may
send out periodic NAKs for that command (packet 0). Those NAKs must have
type
1 block checks.
Optional Features
Page 36
The use of alternate block check types can cause certain
complications. For
instance, if the server gets a horrible error (so bad that it doesn't
even send
an error packet) and reverts to command wait, sending NAKs for packet 0
using a
type 1 block check, while a transfer using type 2 or 3 block checks
was in
progress, neither side will be able to read the other's packets.
Communication
can also grind to a halt if A sends a Send-Init requesting, say, type 3
block
checks, B ACKs the request, switches to type 3 and waits for the X or F
packet
with a type 3 block check, but the ACK was lost, so A resends the S
packet with
a type 1 block check. Situations like this will ultimately resolve
themselves
after the two sides retransmit up to their retry threshhold, but can be
rectified earlier by the use of two heuristics:
- The packet reader can
the
block check type is 1.
assume
that if the packet type is "S",
- A NAK packet never has anything in its data field.
Therefore,
the
block check type can always be deduced by the packet reader from
the
length field of a NAK. In fact, it is the value of the length
field
minus 2.
A NAK can therefore be thought of as a kind of
"universal
synchronizer".
These heuristics tend violate the layered nature of the protocol,
since the
packet reader should normally be totally unconcerned with the
packet type
(which is of interest to the application level which invokes the
packet
reader).
A better design would have had each packet include an
indicator of
the type of its own block check; this would have allowed the block check
type
to be changed dynamically during a transaction to adapt to changing
conditions.
But it's too late for that now...
8.4. Interrupting a File Transfer
This section describes an optional feature of the KERMIT protocol to
allow
graceful interruption of file transfer. This feature is unrelated to
server
operation.
To interrupt sending a file, send an EOF ("Z") packet in place of the
next data
packet, including a "D" (for Discard) in the data field. The
recipient ACKs
the Z packet normally, but does not retain the file. This does not
interfere
with older Kermits on the receiving end; they will not inspect the data
field
and will close the file normally. The mechanism can be triggered by
typing an
interrupt character at the console of the sending KERMIT program.
If a
(wildcard) file group is being sent, it is possible to skip to the next
file or
to terminate the entire batch; the protocol is the same in either case,
but the
desired action could be selected by different interrupt characters, e.g.
CTRL-X
to skip the current file, CTRL-Z to skip the rest of the batch.
To interrupt receiving a file, put an "X" in the data field of an ACK
for a
data packet. To interrupt receiving an entire file group, use a "Z".
The user
could trigger this mechanism by typing an interrupt character by
typing, say,
CTRL-X and CTRL-Z, respectively, at the receiving KERMIT's console.
A
sender
that was aware of the new feature, upon finding one of these codes,
would act
as described above, i.e. send a "Z" packet with a "D" code; a sender
that did
not implement this feature would simply ignore the codes and continue
sending.
In this case, and if the user wanted the whole batch to be cancelled (or
only
one file was being sent), the receiving KERMIT program, after
determining that
Optional Features
Page 37
the sender had ignored the "X" or "Z" code, could send an Error (E)
packet to
stop the transfer.
The sender may also choose to send a Z packet containing the D code
when it
detects that the file it is sending cannot be sent correctly and
completely
-- for instance, after sending some packets correctly, it gets an i/o
error
reading the file. Or, it notices that the "8th bit" of a file byte is
set when
the file is being sent as a text file and no provision has been made for
transmitting the 8th bit.
8.5. Transmitting File Attributes
The optional Attributes (A) packet provides a mechanism for the
sender of a
file to provide additional information about it. This packet can be
sent if
the receiver has indicated its ability to process it by setting the
Attributes
bit in the capability mask.
If both sides set this bit in the
Kermit
capability mask, then the sender, after sending the filename in the "F"
packet
and receiving an acknowledgement, may (but does not have to) send an "A"
packet
to provide file attribute information.
Setting the Attributes bit in the capability mask does not indicate
support for
any particular attributes, only that the receiver is prepared to accept
the "A"
packet.
The attributes are given in the data field of the "A" packet. The data
field
consists of 0 or more subfields, which may occur in any order. Each
subfield
is of the following form:
+-----------+--------------+------+
| ATTRIBUTE | char(LENGTH) | DATA |
+-----------+--------------+------+
where
ATTRIBUTE is a single printable character other than space,
LENGTH
is the length of the data characters (0 to
added to
produce a single printable character, and
DATA
94),
with
32
is length characters worth of data, all printable characters.
No quoting or prefixing is done on any of this data.
More than one attribute packet may be sent. The only requirement is
that all
the A packets for a file must immediately follow its File header (or X)
packet,
and precede the first Data packet.
There may be 93 different attributes, one for each of the 93 printable
ASCII
characters other than space. These are assigned in ASCII order.
! (ASCII 33)
Length.
The data field gives the length in K (1024)
bytes, as a
printable decimal number, e.g. "!#109". This will allow the
receiver
to determine in advance whether there is sufficient room
for the
file, and/or how long the transfer will take.
Optional Features
Page 38
" (ASCII 34)
Type. The data field can contain some indicator of the nature
of the
file.
Operands are enclosed in {braces}, optional
items in
[brackets].
A[{xx}] ASCII text, containing no 8-bit quantities,
logical
records
(lines)
delimited by the (quoted) control character
sequence
{xx}, represented here by its
(MJ
printable
counterpart
=
CRLF,
J
=
LF,
etc).
For instance AMJ means that
the appearance of #M#J (the normal prefixed
in
CRLF
sequence)
a
file
data packet indicates the end of a record,
assuming the
current control prefix is "#".
If {xx} is omitted,
MJ
will
be assumed.
B[{xx}] Binary.
{xx} indicates in what manner the file is
binary:
8
(default)
The
file
is a sequence of 8-bit bytes,
which
must be saved as is.
"bare",
The 8th bit may be sent
or
prefixed
according
to
the
Send-Init negotiation
about
8th-bit prefixing.
36
The file is a PDP-10 format binary file,
in
which
five
7-bit
bytes are fit into one 36-bit word, with the
final
bit of each word being represented as the "parity
bit" of
every 5th character (perhaps prefixed).
D{x}
Moved from here to FORMAT attribute
F{x}
Moved from here to FORMAT attribute
I[{x}]
represented
Image.
on
systems.
the
The file is being sent exactly as it
system
of
origin.
is
For use between like
There are {x} usable bits per
character,
before
prefixing.
For
instance,
to
send binary data from a system with
9-bit
bytes, it might be convenient to send three 6-bit
characters
for every two 9-bit bytes.
Default {x} is 8.
# (ASCII 35)
Creation Date, expressed as "[yy]yymmdd[ hh:mm[:ss]]" (ISO
standard
julian format), e.g. 831009 23:59. The time is optional; if
given,
it should be in 24-hour format, and the seconds may be omitted,
and a
single space should separate the time from the date.
$ (ASCII 36)
Creator's ID, expressed as a character string of the given
length.
% (ASCII 37)
Account to charge the file to, character string.
& (ASCII 38)
Area in which to store the file, character string.
' (ASCII 39)
Password for above, character string.
( (ASCII 40)
Optional Features
Page 39
Block
Size.
The file has, or is to be stored with, the given
block
size.
) (ASCII 41)
Access:
N
New, the normal case -- create a new file of the given
S
A
Supersede (overwrite) any file of the same name.
Append to file of the given name.
name.
* (ASCII 42)
Encoding:
A
ASCII, normal ASCII encoding with any necessary prefixing,
etc.
H
Hexidecimal "nibble" encoding.
E
EBCDIC (sent as if it were a binary file).
X
Encrypted.
Q{x}
Huffman Encoded for compression. First x bytes of the
file
are
the key.
# (ASCII 43)
Disposition (operands
receiver's
host system):
to
are specified in the syntax of the
M{user(s)}
Send the file as Mail to the specified user(s).
O{destination}
Send the file as
a
lOng
terminal
message
the
specified destination (terminal, job, or user).
S[{options}]
Submit
the
file
as a batch job, with any
specified
options.
P[{options}]
Print
the
file
on
a
system
printer,
any
specified
options,
which
may
specify a
particular
printer, forms, etc.
address,
T
Type the file on the screen.
L[{aaa}]
if
Load the file into memory at the
given
with
any.
X[{aaa}]
address and
Load
the
file
into memory at the given
eXecute it.
A
Archive the file; save the file together with
the attribute packets that preceded it, so that it
can
be
sent
back
to
the system of origin with all
its attributes intact.
A file stored in this way
should be
specially marked so that the
sends
KERMIT
that
it
back will recognize the attribute information
as distinct from the file data.
, (ASCII 44)
Protection.
Protection code for the file, in the syntax
of the
receiver's host file system. With no operand, store according
to the
Optional Features
Page 40
system's default protection for the destination area.
- (ASCII 45)
Protection.
Protection code for the file with respect
to the
"public" or "world", expressed generically in a 6-bit quantity
(made
printable by char()), in which the bits have the following
meaning:
b0:
b1:
b2:
b3:
b4:
b5:
A
Read Access
Write Access
Execute Access
Append Access
Delete Access
Directory Listing
one
in the bit position means allow the corresponding type
of access, a zero means prohibit it.
For example, the letter "E" in
this
field
would
allow
read,
execute,
and
directory
listing
access
(unchar("E") = 69-32 = 37 = 100101 binary).
. (ASCII 46)
Machine and operating system of origin. This is useful in
conjunction with the archive disposition attribute. It allows a
file, once
archived, to be transferred among different types of systems,
retaining its archive status, until it finds its way to a machine
with the
right characteristics to de-archive it. The systems are
denoted by
codes; the first character is the major system designator, the
second
designates the specific model or operating system. A third
character
may be added to make further distinctions, for instance
operating
system version. The systems below do not form a complete
collection;
many more can and probably will be added.
A
Apple microcomputers
1
2
Apple II, DOS
Apple III
3
4
B
Sperry (Univac) mainframes
1
C
1100 series, EXEC
CDC mainframes
1
D
Macintosh
Lisa
Cyber series, NOS
DEC Systems
1
2
3
4
5
6
7
8
DECsystem-10/20,
DECsystem-10/20,
DECsystem-10/20,
DECsystem-10/20,
DECsystem-10/20,
DECsystem-10/20,
VAX-11, VMS
PDP-11, RSX-11
TOPS-10
TOPS-20
TENEX
ITS
WAITS
MAXC
Optional Features
Page 41
9
A
B
C
D
D
Honeywell mainframes
1
2
F
PDP-11, IAS
PDP-11, RSTS/E
PDP-11, RT-11
Professional-300, P/OS
Word Processor (WPS or DECmate), WPS
MULTICS systems
DPS series, running CP-6
Data General machines
1
2
RDOS
AOS
G
PR1ME machines, PRIMOS
H
Hewlett-Packard machines
1
2
I
HP-1000, RTE
HP-3000, MPE
IBM 370-series and compatible mainframes
1
2
3
4
5
6
VM/CMS
MVS/TSO
DOS
MUSIC
GUTS
MTS
J
Tandy microcomputers, TRSDOS
K
Atari micros, DOS
L-T Reserved
U
Portable Operating or File Systems
1
2
3
4
5
6
7
8
9
A
UNIX
Software Tools
CP/M-80
CP/M-86
CP/M-68K
MP/M
Concurrent CP/M
MS-DOS
UCSD p-System
MUMPS
/ (ASCII 47)
Format of the data within the packets.
A{xx}
Variable
length delimited records, terminated
by the
character sequence {xx}, where xx is a string
of
one
Optional Features
Page 42
or more control characters, represented here by
their
unprefixed
printable
equivalents,
e.g. MJ
for ^M^J
(CRLF).
D{x}
Variable length undelimited records.
Each
logical
record
begins
with
an
{x}-character ASCII
decimal
length field (similar to ANSI tape format "D").
For
example,
"D$"
would indicate 4-digit length
fields,
like "0132".
F{xxxx}
Fixed-length
undelimited
records.
Each
logical
record is {xxxx} bytes long.
R{x}
For record-oriented transfers, to be used in
combination
with
one
of
the
formats
given above.
Each
record begins (in the case of
after
D
format,
the
length field) with an x-character long position
field
indicating the byte position within the file at
which
this record is to be stored.
M{x}
For record-oriented transfers, to be used in
combination
with
one
of the formats given above.
Maximum
record length for a variable-length record.
0 (ASCII 48)
Special system-dependent parameters for storing the file on the
system of origin, for specification of exotic attributes not
covered explicitly by any of the KERMIT attribute descriptors. These are
given
as a character string in the system's own language, for
example a
list of DCB parameters in IBM Job Control Language.
[email protected] (ASCII 49-64)
Reserved
Other attributes can be imagined, and can be added later if needed.
However,
two important points should be noted:
- The receiver may have absolutely no way of honoring, or even
recording, a given attribute. For instance, CP/M-80 has no slot for
creation date or creator's ID in its FCB; the DEC-20 has no concept
of
block size, etc.
- The sender may have no way of determining the correct values of
any
of the attributes. This is particularly true when sending files
of
foreign origin.
The "A" packet mechanism only provides a way to send certain information
about
a file to the receiver, with no provision or guarantee about what the
receiver
may do with it. That information may be obtained directly from the
file's
directory entry (FCB, FDB, ...), or specified via user command.
The ACK to the "A" packet may in turn have information in its data
field.
However, no complicated negotiations about file attributes may take
place, so
the net result is that the receiver may either refuse the file or
accept it.
The receiver may reply to the "A" packet with any of the following codes
in the
data field of the ACK packet:
Optional Features
Page 43
<null>
(empty data field) I accept the file, go ahead and send it.
N[{xxx}]
I refuse the file as specified, don't send it; {xxx} is a
string of
zero or more of the attribute characters listed above, to specify
what
attributes I object to (e.g. "!" means it's too long, "&" means I
don't
have write access to the specified area, etc).
Y[{xxx}]
I agree to receive the file, but I cannot honor attributes
{xxx}, so I
will store the file according to my own defaults.
Y
(degenerate case of Y{xxx}, equivalent to <null>, above)
How the receiver actually replies is an implementation decision.
A
NAK in
response to the "A" packet means, of course, that the receiver did not
receive
the "A" correctly, not that it refuses to receive the file.
8.6. Advanced KERMIT Protocol State Table
The simple table presented previously is sufficient for a basic
KERMIT implementation. The following is a state table for the full Kermit
protocol, including both server mode and sending commands to a server Kermit. It
does not
include handling of the file attributes packet (A).
Note that states
whose
names start with "Send" always send a packet each time they are entered
(even
when the previous state was the same). States whose name starts with
"Rec",
always wait for a packet to be received (up to the timeout value), and
process
the received packet. States whose names do not include either send or
receive
do not process packets directly. These are states which perform some
local
operation and then change to another state.
The initial state is determined by the user's
command
command.
A
"server"
enters at Rec_Server_Idle. A "send" command enters at Send_Init. A
"receive"
command (the old non-server version, not a "get" command) enters at
Rec_Init.
Any generic command, the "get" command, and the "host" command enter at
either
Send_Server_Init or Send_Gen_Cmd, depending upon the expected response.
Under "Rec'd Msg", the packet type of the incoming message is shown,
followed
by the packet number in parentheses; (n) means the current packet number,
(n-1)
and (n+1) mean the previous and next packet numbers (modulo 64), (0)
means
packet number zero. Following the packet number may be slash and a
letter, indicating some special signal in the data field. For instance Z(n)/D
indicates
a Z (EOF) packet, sequence number n, with a "D" in the data field.
Under "Action", "r+" means that the retry count is incremented and
compared
with a threshhold; if the threshhold is exceeded, an Error packet is
sent and
the state changes to "Abort". "n+" means that the packet number is
incremented, modulo 64, and the retry count, r, is set back to zero.
Optional Features
Page 44
State
Rec'd Msg
Action
Next state
Rec_Server_Idle -- Server idle, waiting for a message
Set n and r to 0
I(0)
S(0)
R(0)
K, C or G(0)
Timeout
Other
Send ACK
Process params,
ACK with params, n+
Save file name
Short reply:
ACK(0)/reply
Long reply:
init needed
init not needed, n+
Send NAK(0)
Error
Rec_Server_Idle
Rec_File
Send_Init
Rec_Server_Idle
Send_Init
Open_File
Rec_Server_Idle
Rec_Server_Idle
Rec_Init -- Entry point for non-server RECEIVE command
Set n and r to 0
S(0)
Timeout
Other
Process params, send
ACK with params, n+
Send NAK(0), r+
NAK
Rec_File
Rec_Init
Abort
Rec_File -- Look for a file header or EOT message
F(n)
X(n)
B(n)
S(n-1)
Z(n-1)
Timeout
Other
Open file, ACK, n+
Prepare to type on
screen, ACK, n+
ACK
ACK with params, r+
ACK, r+
NAK, r+
NAK
Rec_Data
Rec_Data
Complete
Rec_File
Rec_File
Rec_File
Abort
Rec_Data -- Receive data up to end of file
D(n)
D(n-1)
Store data, ACK, n+;
If interruption wanted
include X or Z in ACK Rec_Data
Send ACK, r+
Rec-Data
Z(n)
Z(n)/D
F(n-1)
X(n-1)
Timeout
Other
Close file, ACK, n+
Discard file, ACK, n+
Send ACK, r+
Send ACK, r+
Send NAK, r+
Send E
Rec_File
Rec_File
Rec_Data
Rec_Data
Rec_Data
Abort
Optional Features
Page 45
Send_Init -- Also entry for SEND command
Set n and r to 0, send S(0) with parameters
Y(0)
N, Timeout
Other
Process params, n+
r+
r+
Open_File
Send_Init
Send_Init
Open_File -- Open file or set up text to send
Send_File
Send_File -- Send file or text header
Send F or X(n)
Y(n), N(n+1)
N, Timeout
Other
Get first buffer of
data, n+
r+
Send_Data or Send_Eof if
empty file or text
Send_File
Abort
Send_Data -- Send contents of file or textual information
Send D(n) with current buffer
Y(n), N(n+1)
n+, Get next buffer
Y(n)/X or Z
N, Timeout
Other
n+
r+
Send_Data or Send_Eof if
at end of file or text
Send_Eof
Send_Data
Abort
Send_Eof -- Send end of file indicator
Send Z(n); if interrupting send Z(n)/D
Y(n), N(n+1)
Open next file, n+
N, Timeout
Other
r+
Send_Break -- End of Transaction
Send_File if more, or
Send_Break if no more
or if interrupt "Z".
Send_Eof
Abort
Send B(n)
Y(n), N(0)
N(n), Timeout
Other
Complete
Send_Break
Abort
Optional Features
Page 46
Send_Server_Init - Entry for Server commands which expect large response.
Send I(0) with parameters
Y(0)
N, Timeout
E
Other
Process params
r+
Use default params
Send_Gen_Cmd
Send_Server_Init
Send_Gen_Cmd
Abort
Send_Gen_Cmd - Entry for Server commands which expect short response
(ACK)
Send G, R or C(0)
S(0)
X(1)
Y(0)
N, Timeout
Other
Process params,
ACK with params, n+
Setup to type on
terminal, n+
Type data on TTY
r+
Rec_File
Rec_Data
Complete
Send_Gen_Cmd
Abort
Complete -- Successful Completion of Transaction
Set n and r to 0;
If server, reset params, enter Rec_Server_Idle
otherwise exit
Abort -- Premature Termination of Transaction
Reset any open file, set n and r to 0
If server, reset params, enter Rec_Server_Idle
otherwise exit
Exit, Logout states
Exit or Logout
Note that the generic commands determine the next state as follows:
1. If the command is not supported, an error packet is sent and
the
next state is "Abort".
2. If the command generates a response which can be fit into the
data
portion of an ACK, an ACK is sent with the text (quoted
as
necessary) in the data portion.
3. If the command generates a large response or must send a file,
nothing is sent from the Rec_Server_Idle state, and the next state
is
either Send_Init (if either no I message was received or if
alter-
Optional Features
Page 47
nate
block
check types are to be used), or Open_File (if an I
message was received and the single character
block
check
is
to
be
used).
4. If
the
command
is
Logout,
an
ACK
is sent and the new state
is
Logout.
5. If the command is Exit, an ACK is sent and the new state is Exit.
KERMIT Commands
Page 48
9. KERMIT Commands
The following list of KERMIT commands and terms is suggested. It is
not intended to recommend a particular style of command parsing, only to
promote a
consistent vocabulary, both in documentation and in choosing the names
for commands.
9.1. Basic Commands
SEND
This verb tells a Kermit program to send one or more files from
its own
file structure.
RECEIVE This verb
files to
arrive.
GET
Some
should tell a Kermit program to expect one or more
This verb should tell a user Kermit to send one or more
Kermit
implementations
files.
have separate RECEIVE and GET commands;
others
use RECEIVE for both purposes, which creates confusion.
Since it can be useful, even necessary, to specify different names for
source
and destination files, these commands should take operands as follows
(optional
operands in [brackets]):
SEND local-source-filespec [remote-destination-filespec]
If the destination file specification is included, this will go
in the
file header packet, instead of the file's local name.
RECEIVE [local-destination-filespec]
If the destination filespec is given, the incoming file will be
stored
under that name, rather than the one in the file header pakcet.
GET remote-source-filespec [local-destination-filespec]
If the destination filespec is given, the incoming file will be
stored
under that name, rather than the one in the file header packet.
If a file group is being sent or received, alternate names should not be
used.
9.2. Program Management Commands
EXIT
done
Leave the KERMIT program, doing
whatever
cleaning
up
must
be
-- deassigning of devices, closing of files, etc.
QUIT
as to
Leave
the
KERMIT
program without cleaning up, in such a manner
allow further manipulation of the files and devices.
PUSH
Preserve the current KERMIT environment and enter
command
processor.
TAKE
the
system
Read and execute KERMIT program commands from a local file.
LOG
Specify
session
loggin.
a
log for file transfer transactions, or for terminal
KERMIT Commands
Page 49
9.3. Terminal Emulation Commands
CONNECT This verb, valid only for a local Kermit, means to go into
terminal
emulation mode; present the illusion of being directly connected
as a
terminal to the remote system. Provide an "escape character" to
allow
the user to "get back" to the local system. The escape
character, when
typed, should take a single-character argument; the following are
suggested:
0
B
C
(zero) Transmit a NUL
Transmit a BREAK
Close the connection, return to local KERMIT command
P
Q
R
S
?
(a
Push to system command processor
Quit logging (if logging is being done)
Resume logging
Show status of connection
Show the available arguments to the escape character
second copy of the escape character): Transmit the
level
escape
character itself
argument
Lower case equivalents should be accepted.
is
typed, issue a beep.
If any invalid
Also see the SET command.
9.4. Special User-Mode Commands
These commands are used only by Users of Servers.
BYE
This command sends a message to the remote server to log
itself out,
and upon successful completion, terminate the local Kermit
program.
FINISH This command causes the remote server to shut itself down
gracefully
without logging out its job, leaving the local KERMIT at KERMIT
command
level, allowing the user to re-CONNECT to the remote job.
9.5. Commands Whose Object Should Be Specified
Some Kermit implementations include various local file management
services and
commands to invoke them. For instance, an implementation might have
commands
to let you get directory listings, delete files, switch disks, and
inquire
about free disk space without having to exit and restart the program.
In addition, remote servers may also provide such services. A user Kermit
must be
able to distinguish between commands aimed at its own system and those
aimed at
the remote one. When any confusion is possible, such a command may be
prefixed
by one of the following "object prefixes":
REMOTE
Ask the remote Kermit server to provide this service.
LOCAL
Perform the service locally.
If the "object prefix" is omitted, the command should be executed
locally. The
services include:
KERMIT Commands
Page 50
LOGIN
This should be used in its timesharing sense, to create an
identity
("job", "session", "access", "account") on the system.
LOGOUT
To terminate a session that was initiated by LOGIN.
COPY
Make a new copy of the specified file with the specified name.
CWD
like
Change Working Directory.
This is ugly, but more
CONNECT and ATTACH are too imprecise.
natural
verbs
CWD is the ARPAnet file
transfer
standard command to invoke this function.
DIRECTORY
Provide a list of the names, and possibly other attributes,
of the
files in the current working directory (or the specified
directory).
DELETE
Delete the specified files.
ERASE
This could be a synomym for DELETE, since its meaning is clear.
(It doesn't seem wise to include UNDELETE
or
UNERASE
in
the
standard
list; most systems don't support such a function,
and
users' expectations should not be toyed with...)
KERMIT
com-
Send a command to the remote KERMIT server in its own interactive
mand syntax.
RENAME
Change the name of the specified file.
TYPE
Display the contents of the specified file(s) at the terminal.
SPACE
Tell how much space is used and available for storing files in
the current working directory (or the specified directory).
SUBMIT
Submit the specified file(s) for background (batch) processing.
PRINT
Print the specified file(s) on a printer.
MOUNT
Request a mount of the specified tape, disk, or other removable
storage
medium.
WHO
infor-
Show
who
is
logged in (e.g. to a timesharing system), or give
mation about a specified user or network host.
MAIL
Send electronic mail to the specified user(s).
MESSAGE Send a terminal message (on a network or timesharing system).
HELP
Give brief information about how to use KERMIT.
SET
mode,
Set various parameters relating to debugging, transmission, file
and so forth.
SHOW
Display settings of SET parameters, capabilities in force, etc.
STATISTICS
Give information about the performance of the most recent file
transfer
KERMIT Commands
Page 51
-- elapsed time, effective baud rate, various counts, etc.
HOST
local)
Pass
the
given command string to the specified (i.e. remote or
host for execution in its own command language.
LOGGING Open or close a remote transaction or debugging log.
9.6. The SET Command
A SET command should be provided to allow the user to tailor a
connection to
the peculiarities of the communication path, the local or remote file
system,
etc. Here are some parameters that should be SET-able:
BLOCK-CHECK
Specify the type of block check to be used: single character
checksum,
two-character checksum, 3-character CRC.
DEBUGGING
Display or log the packet traffic, packet numbers, and/or
program
states. Useful for debugging new versions of KERMIT, novel
combinations of KERMIT programs, etc.
DELAY
send-
How
many seconds a remote (non-server) KERMIT should wait before
ing the Send-Init packet, to give the user time to escape back
to
the
local KERMIT and type a RECEIVE command.
DUPLEX
For terminal emulation, specify FULL or HALF duplex echoing.
EIGHT-BIT-PREFIXING
Specify that "8th bit" prefixing must be done; normally it will
not be
done.
END-OF-LINE
Specify any line terminator that must be used after a packet.
ESCAPE
Specify the escape character for terminal emulation.
FILE attributes
Almost any of the attributes listed above
section
in
the
Attributes
(8.5).
The most common need is to tell the KERMIT program
whether an
incoming or outbound file is text or binary.
FLOW-CONTROL
Specify the flow control mechanism for the line, such as
XON/XOFF,
DTR/CTS, etc. Allow flow control to be turned off as well as on.
Flow
control is done only on full-duplex connections.
HANDSHAKE
Specify any line-access negotiation that must be used or
simulated
during file transfer. For instance, a half duplex system will
often
need to "turn the line around" after sending a packet, in order
to give
you permission to reply. A common handshake is XON (^Q); the
current
user of the line transmits an XON when done transmitting data.
LINE
Specify the line or device designator for the connection.
is for
This
KERMIT Commands
Page 52
use
in
a
KERMIT program that can run in either remote or local
mode;
the default line is the controlling terminal (for remote
operation).
If an external device is used, local operation is presumed.
LOG
There
Specify
a local file in which to keep a log of the transaction.
may be logs for debugging purposes (packet traffic, state
transitions,
etc) and for auditing purposes (to record the name and
disposition of
each file transferred).
MARKER
A) to
Change the start-of-packet marker from the default of SOH
some
(CTRL-
other control character, in case one or both systems has
problems
using CTRL-A for this purpose.
PACKET-LENGTH
The maximum length for a packet. This should normally be no less
than
30 or 40, and can never be greater than 96. Short packets can
be an
advantage on noisy lines; they reduce the probabily of a
particular
packet being corrupted, as well as the retransmission
overhead when
corruption does occur.
PADDING The number of padding characters that should be sent
each
packet, and what the padding character should be. Rarely
necessary.
before
PARITY Specify the parity (ODD, EVEN, MARK, SPACE, NONE) of the
physical connection. If other than none, the "8th bit" cannot be used to
transmit
data and must not be used by either side in block check
computation.
PAUSE
How many seconds to pause after receiving a packet before
sending the
next packet. Normally 0, but when a system communication
processor or
front end has trouble keeping up with the traffic, a short
pause be-
tween packets may allow it to recover its
something
under a second will suffice.
wits;
hopefully,
PREFIX Change the default prefix for control characters, 8-bit
characters, or
repeated quantities.
PROMPT
KERMIT
Change the program's prompt. This is useful when running
between two systems whose prompt is the same, to eliminate
confusion
about which KERMIT you are talking to.
REPEAT-COUNT-PROCESSING
Change the default for repeat count processing.
will be
done if both KERMIT programs agree to do it.
Normally, it
RETRY
The maximum number of times to attempt to send or receive a
packet before giving up. The normal number is about 5, but the user
should be
able to adjust it according to the condition of the line, the
load on
the systems, etc.
TIMEOUT Specify the length of the timer to set when waiting for a packet
to arrive.
KERMIT Commands
Page 53
9.7. Macros, the DEFINE Command
In addition to the individual set commands, a "macro" facility is
recommended
to allow users to combine the characteristics of specific systems into a
single
SET option. For example:
DEFINE IBM = PARITY ODD, DUPLEX HALF, HANDSHAKE XON
DEFINE UNIX = PARITY NONE, DUPLEX FULL
DEFINE TELENET = PARITY MARK
This could be done by providing a fancy runtime parser for commands like
this
(which could be automatically TAKEn from the user's KERMIT
initialization file
upon program startup), or simply hardwired into the SET command table.
With these definitions in place, the user would simply type "SET IBM",
"SET
UNIX", and so forth, to set up the program to communication to the
remote system.
Terminal Emulation
Page 54
10. Terminal Emulation
The local system must be able to act as a terminal so that the user can
connect
to the remote system, log in, and start up the remote KERMIT.
Terminal emulation should be provided by any KERMIT program that runs
locally,
so that the user need not exit and restart the local KERMIT program in
order to
switch between terminal and protocol operation. On smaller systems,
this is
particularly important for various reasons -- restarting the program and
typing
in all the necessary SET commands is too inconvenient and timeconsuming; in
some micros, switching in and out of terminal emulation may cause
carrier to
drop, etc.
Only bare-bones terminal emulation need be supplied by KERMIT; there is
no need
to emulate any particular kind of "smart" terminal. Simple "dumb"
terminal
emulation is sufficient to do the job. Emulation of fancier terminals is
nice
to have, however, to take advantage of the remote system's editing and
display
capabilities. In some cases, microcomputer firmware will take care of
this.
To build emulation for a particular type of terminal into the program,
you must
interpret and act upon escape sequences as they arrive at the port.
No error checking is done during terminal emulation. It is
"outside the
protocol"; characters go back and forth "bare". In this sense, terminal
emulation through KERMIT is no better than actually using a real terminal.
Some KERMIT implementations may allow logging of the terminal emulation
session
to a local file. Such a facility allows "capture" of remote
typescripts and
files, again with no error checking or correction. When this
facility is
provided, it is also desirable to have a convenient way of "toggling" the
logging on and off.
If the local system does not provide system- or firmware-level flow
control,
like XON/XOFF, the terminal emulation program should attempt to
simulate it,
especially if logging is being done.
The terminal emulation facility should be able to handle either remote or
local
echoing (full or half duplex), any required handshake, and it should be
able to
transmit any parity required by the remote side or the communication
medium.
A terminal emulator works by continuously sampling both console input
from the
local terminal and input from the communication line. Simple input and
output
functions will not suffice, however, since if you ask for input from a
certain
device and there is none available, you will generally block until input
does
become available, during which time you will be missing input from the
other
device. Thus you must have a way to bounce back and forth
regardless of
whether input is available. Several mechanisms are commonly used:
- Continuously jump back and forth between the port status register
and
the console status register, checking the status bits for
input
available. This is only practical on single-user, singleprocess
systems, where the CPU has nothing else to do.
- Issue an ordinary blocking input request for the port, but enable
interrupts on console input, or vice versa.
- Handle port input in one process and console input in another,
paral-
Terminal Emulation
Page 55
lel process.
The UNIX KERMIT program listed in this manual uses
this
method.
Any input at the port should be displayed immediately on the screen. Any
input
from the console should be output immediately to the port. In addition,
if the
connection is half duplex, console input should also be sent immediately
to the
screen.
The terminal emulation code must examine each console character to
determine
whether it is the "escape character". If so, it should take the next
character
as a special command, which it executes. These commands are described
above,
in section 9.3.
The terminal emulator should be able to send every ASCII character, NUL
through
DEL, and it should also be able to transmit a BREAK signal (BREAK is
not a
character, but an "escape" from ASCII transmission in which a 0 is put
on the
line for about a quarter of a second, regardless of the baud rate,
with no
framing bits). BREAK is important when communicating with various
systems,
such as IBM mainframes.
Finally, it is sometimes necessary to perform certain transformations on
the CR
character that is normally typed to end a line of input. Some systems
use LF,
EOT, or other characters for this function. To complicate matters,
intervening
communications equipment (particularly the public packet-switched
networks) may
have their own independent requirements. Thus if using KERMIT to
communicate
over, say, TRANSPAC with a system that uses LF for end-of-line, it
may be
necessary to transform CR into LFCR (linefeed first -- the CR tells the
network
to send the packet, which will contain the LF, and the host uses the
LF for
termination). The user should be provided with a mechanism for
specifying this
transformation, a command like "SET CR sequence".
Writing a KERMIT Program
Page 56
11. Writing a KERMIT Program
Before writing a new implementation of KERMIT or modifying an old one,
first be
sure to contact the KERMIT Distribution center at Columbia University
to make
sure that you're not duplicating someone else's effort, and that you
have all
the latest material to work from. If you do write or significantly
modify (or
document) a KERMIT program, please send it back to Columbia so that it
can be
included in the standard KERMIT distribution and others can benifit
from it.
It is only through this kind of sharing that KERMIT has grown from its
modest
beginnings to its present scale.
The following sections provide some hints on KERMIT programming.
11.1. Program Organization
A basic KERMIT implementation can usually be written as a relatively
small
program, self-contained in a single source file. However, it is often
the case
that a program written to run on one system will be adapted to run on
other
systems as well.
In that case, it is best to avoid having totally
divergent
sources, because when new features are added to (or bugs fixed in) the
systemindependent parts of the program -- i.e. to the protocol itself -- only
one implementation will reap the benefits initially, and the other will require
painful, error-prone "retrofitting" to bring it up to the same level.
Thus, if there is any chance that a KERMIT program will run on more
than one
machine, or under more than one operating system, or support more than
one kind
of port or modem, etc, it is desirable to isolate the system-dependent
parts in
a way that makes the common parts usable by the various implementations.
There
are several approaches:
1. Runtime support. If possible, the program can inspect the
hardware
or inquire of the system about relevant parameters, and
configure
itself dynamically at startup time. This is hardly ever possible.
2. Conditional compilation (or assembly).
If the number of systems
or
options
to
be supported is small, the system dependent code can
be
enclosed in conditional compilation brackets
(like
IF
IBMPC
....
ENDIF).
An example is provided in UNIX KERMIT listing included
with
this
manual.
However, as the number of system dependencies to
be
supported
grows,
this
method
becomes
unwieldy
and
error-
prone
-- installing support for system X tends to break the preexisting
support for system Y.
3. Modular composition.
When there is a potentially
large
number
of
options
a
program
should
support,
it
should
be broken up
into
separate modules (source
files),
with
clearly
specified,
simple
calling conventions. This allows people with new options to
provide
their own support for them in an easy way, without endangering
any
existing support. Suggested modules for a KERMIT program are:
- System-Indendent protocol
handling:
state
switching,
packet
formation, encoding (prefixing) and decoding, etc.
- User Interface: the command parser.
Putting this in a
separate
module
user's
allows
plug-in
of
command parsers to suit the
Writing a KERMIT Program
Page 57
taste,
to mimic the style of the host system command parser
or
some popular application, etc.
- Screen i/o: This module would contain the screen control
codes,
cursor positioning routines, etc.
- Port i/o: Allows support of various port hardware.
This
module
can define the port status register location, the status
bits,
and so forth, and can implement the functions to read and
write
characters at the port.
- Modem
control:
This
module
would
support
any
kind
of
"intelligent" modem, which is not simply a
transparent
extension
of
the communications port.
Such modems may accept
special commands to perform functions like dialing out,
redialing
a
recent
number,
hanging
up, etc., and may need special
initialization (for instance, setting modem signals like DTR).
- Console input: This module would supply
the
function
to
get
characters
from
the
console;
it would know about the
status
register
locations
and
bits,
interrupt
structure,
key-
tocharacter
mappings,
etc.,
and
could
also
implement
key
redefinitions, keystroke macros,
programmable
function
keys,
expanded control and meta functions, etc.
- Terminal
Emulation:
This
module
would
interpret escape
sequences in the incoming character
stream
(obtained
from
the
port i/o module) for the particular type of terminal being
emulated
and
interpret
them by making appropriate calls the
the
screen i/o module, and it would send user typein (obtained
from
the console input module) out the serial port (again using
the
port
i/o module).
Ideally, this module could be replacable
by
other modules to emulate different
kinds
of
terminals
(e.g.
ANSI, VT52, ADM3A, etc).
- File i/o: This module contains all the knowledge about the
host
system's
file
structure; how to open and close files,
perform
"get next file" operations, read and write files, determine
and
set their attributes, detect the end of a file, and
so
forth,
and
provides
the
functions,
including
buffering,
to get
a
character from a file and put a character
to
a
file.
This
module
may
also
provide
file
management services for
local
files -- directory listings, deleting, renaming,
copying,
and
so forth.
- Definitions
and
Data: Separate modules might also be kept
for
compile-time parameter definitions and for global runtime
data.
Writing a KERMIT Program
Page 58
11.2. Programming Language
The language to be used in writing a KERMIT program is more than a
matter of
taste. The primary consideration is that the language provide the
necessary
functionality and speed. For instance, a microcomputer implementation of
BASIC
may not allow the kind of low-level access to device registers needed
to do
terminal emulation, or to detect console input during file transfer, or
even if
it can do these things, it might not be able to run fast enough do
drive the
communication line at the desired baud rate.
The second consideration in choosing a language is portability. This
is used
in two senses: (1) whether the language is in the public domain (or,
equivalently, provided "free" as part of the basic system), and (2) whether
it is
well standardized and in wide use on a variety of systems. A language
that is
portable in both senses is to be preferred.
Whatever programming language is selected, it is important that all
lines in
the program source be kept to 80 characters or less (after expansion of
tabs).
This is because KERMIT material must often be shipped over RJE and other
cardformat communication links.
In addition, it is important that the names of all files used in
creating and
supporting a particular KERMIT implementation be (possibly a subset)
of the
form NAME.TYPE, where NAME is limited to six characters, and TYPE is
limited to
three, and where the NAME of each file begin with a common 2 or 3
character
prefix.
This is so that all related files will be grouped together in
an alphabetic directory listing, and so when all of the hundreds of KERMIT
related
files are placed together on a tape, all names will be both legal and
unique,
especially on systems (like PDP-11 operating systems) with restrictive
file
naming conventions.
11.3. Documentation
A new KERMIT program should be thoroughly documented; one of the
hallmarks of
KERMIT is its documentation. The documentation should be at both the
user
level (how to use the program, what the commands are, etc, similar
to the
documentation presently found in the Kermit Users Guide), and the
implementation level (describe system dependencies, give pointers for adapting
to new
systems, and so forth).
In addition, programs themselves should
contain
copious commentary.
Like program source, documentation should be kept
within
80-character lines.
If possible, a section for the implementation should be written for the
KERMIT
User Guide using the UNILOGIC Scribe formatting language (subsets of
which are
also to be found in some microcomputer text processing software such as
Perfect
Writer or Final Word), using the same general conventions as the
existic
Scribe-format implementation sections.
KERMIT programs should also contain a revision history, in which each
change is
briefly explained, assigned an "edit number", and the programmer and
site are
identified. The lines or sections comprising the edit should be marked
with
the corresponding edit number, and the KERMIT program, upon startup,
should announce its version and edit numbers, so that when users complain of
problems we
will know what version of the program is in question.
Writing a KERMIT Program
Page 59
The version number changes when the functionality has been changed
sufficiently
to require major revisions of user documentation. The edit number
should increase (monotonically, irrespective of version number) whenever a
change is
made to the program. The edit numbers are very important for program
management; after shipping out a version of, say, CP/M KERMIT-80, we often
receive
many copies of it, each containing its own set of changes, which we must
reconcile in some manner. Edit numbers help a great deal here.
11.4. Bootstrapping
Finally, a bootstrap procedure should be provided. KERMIT is
generally distributed on magnetic tape to large central sites; the users at those
sites need
ways of "downloading" the various implementations to their micros and
other
local systems. A simple bootstrap procedure would consist of precise
instructions on how to accomplish an "unguarded" capture of the program.
Perhaps a
simple, short program can be written for each each end that will do
the job;
listings and instructions can be provided for the user to type in and run
these
programs.
Packet Format and Types
Page 60
I. Packet Format and Types
KERMIT Packet Layout:
+------+-----+-----+------+------------+-------+
| MARK | LEN | SEQ | TYPE |
DATA
| CHECK |
+------+-----+-----+------+------------+-------+
Send-Init Data Field Layout:
1
2
3
4
5
6
7
8
9
10...
+------+------+------+------+------+------+------+------+------+------| MAXL | TIME | NPAD | PADC | EOL | QCTL | QBIN | CHKT | REPT | CAPAS
+------+------+------+------+------+------+------+------+------+------KERMIT packet
asterisk
(*):
Y*
N*
S*
I
F*
A
D*
Z*
B*
E*
R
C
K
T
G
types
and subtypes; required types are marked with an
Acknowledge (ACK)
Negative acknowledge (NAK)
Send initiate (exchange parameters)
Initialize (exchange parameters)
File header
File attributes
Data packet
End of file (EOF)
Break transmission (EOT)
Error
Receive Initiate (ask the server to send the specified files)
Host Command
KERMIT Command
Reserved for internal use
Generic Kermit Command; Subcommands:
I
C
L
F
D
U
E
T
R
K
W
M
H
Q
P
Login (or logout)
CWD, Change Working Directory
Bye
Finish
Directory
Disk Usage Query
Erase, Delete
Type
Rename
Copy
Who's logged in?
Short Message
Help
Server Status Query
Program Invocation
J
V
Journal Control
Variable Set/Query
List of Features
Page 61
II. List of Features
There's no true linear scale along which to rate Kermit
implementations. A
basic, minimal implementation provides file transfer in both directions,
and,
for microcomputers (PC's, workstations, other single user systems),
terminal
emulation. Even within this framework, there can be variations. For
instance,
can the program send a file group in a single command, or must a
command be
issued for each file? Can it time out? Here is a list of features that
may be
present; for any KERMIT implementation, the documentation should show
whether
these features exist, and how to invoke them.
- File groups. Can it send a group of files with a single
command,
using "wildcard", pattern, or list notation? Can it
successfully
send or receive a group of files of mixed types? Can it recover
from
an error on a particular file and go on to the next one? Can it
keep
a log of the files involved showing the disposition of each?
- Filenames. Can it take action to avoid overwriting a local file
when
a new file of the same name arrives? Can it convert filenames to
and
from legal or "normal form"?
- File types.
Can binary as well as text files be transmitted?
- 8th-Bit prefixing.
Can it send and
receive
8-bit
data
through
a
7-bit channel using the prefixing mechanism?
- Repeat-Count processing. Can it send and receive data with
repeated
characters replaced by a prefix sequence?
- Terminal Emulation. Does it have a terminal emulation
facility?
Does it provide various communication options, such as
duplex,
parity, and handshake selection? Can it transmit all ASCII
charac-
ters? Can it transmit BREAK? Can it log the remote session
locally,
to provide unguarded file capture?
- Communications Options. Can duplex, parity, handshake, and line
terminator be specified for file transfer?
- Block Check Options.
In addition to the basic singlecharacter
checksum, can the two-character checksum and the three-character
CRC
be selected?
- Basic Server. Can it run in server mode, accepting commands to
send
or receive files, and to shut itself down?
- Advanced Server. Can it accept server commands to
files,
provide directory listings, send messages, and forth?
- Issue Commands to Server.
and
handle all possible responses?
- Host Commands.
delete
Can it send commands to a server,
Can it parse and send remote "host commands"?
If
it
is a server, can it pass these commands to the host system
command
processor and return the results to the local user Kermit?
- Interrupt File Transfers.
a
Can it interrupt sending
or
receiving
List of Features
Page 62
file?
Can it respond to interrupt requests from the other side?
- Local File Management Services.
Are there commands to get
local
directory directory listings, delete local files, and so forth?
- File Attributes. Can it send file attribute information about
local
files, and can deal with incoming file attribute information?
Can
alternate dispositions be specified. Can files be archived?
- Debugging Capability.
examined,
single-stepped?
Can
packet
traffic
be
logged,
Unresolved Issues
Page 63
III. Unresolved Issues
KERMIT doesn't do everything.
do, or
could do better.
Here is a short list of things it doesn't
- KERMIT cannot be used through IBM 3270 protocol emulators. These
are
devices that allow asynchronous ASCII terminals or PCs to
communicate
with IBM mainframes as though they were synchronous full-screen
displays. The problems include: (a) the protocol converter
translates
from EBCDIC to ASCII -- that is, it assumes it is receiving
EBCDIC
when KERMIT is supposed to be sending ASCII -- according to its
own
translate table, which may vary from site to site, and is not
a
1-to-1 mapping in any case; (b) non-printing control characters
(like
SOH) cannot be sent at all; (c) the protocol converter looks for
3270
formatting commands and translates them to escape sequences for
the
ASCII terminal, possibly modifying packet data; (d) the IBM
system
automatically pauses at the end of each screenful; (e) the
protocol
converter thinks it knows what is "on the screen" and may attempt
to
optimize. In general, one never knows exactly how a
particular
protocol converter will work, or how it may differ from another
one.
Still, it may be possible to work around these problems if the
Kermits on either end are put into a special "3270 mode", "clear
the
screen" between each packet, and agree on some special convention
for
packet delimitation and data translation.
- Control character prefixing. This can get pretty expensive for
binary files or other files that contain lots of control
characters.
Since most hosts won't choke on every single control character,
it
might
be
a good idea for each host to inform the other of what
control characters it can receive "bare". On the other hand, this
could
backfire when the two hosts are connected by a network or device
that
chokes on control characters that neither of the hosts choke on.
For
hardwired connections with no unknown factors, however, many
control
characters could be sent "bare".
- When long sequences of characters in the control range are
being
sent, individually prefixing each character is costly.
Shiftin/
shift-out codes might be used more effectively here. Same for
long
strings of characters with the parity bit on, when 8th-bit
prefixing
is being done. The cost would be yet another set of prefix
characters, and the associated complexity of packet formation and
decoding.
- In some situations, certain printable characters can't get through
a
communication link.
For instance, a network terminal server
might
reserve "@" as its attention character. Should the protocol
allow
some way to encode such characters for translation? A set of
userdefinable escape sequences could be useful here.
- Ironically, some systems do not fare well with KERMIT's small
packet
sizes. These are typically big mainframes that expect to
communicate
with block mode terminals, receiving thousands of characters at
a
time. Such systems find that KERMIT is simply too expensive to
run.
Meanwhile, other systems that can run KERMIT with no difficulty
find
the performance disappointing (the efficiency generally works
out
somewhere between 50 and 80 percent, i.e. data characters divided
by
the speed of the the transmission line, in characters per
second).
Unresolved Issues
Page 64
These two problems could be solved in either of two ways:
allow
longer packets, or allow multiple data packets to be sent end to
end.
* Without changing the format or encoding of
the
packet
control
fields, it might be possible to have longer packets by
reserving
packet lengths of 0, 1, 2, 3 to be codes for bigger numbers
like
200,
500,
1000,
2000.
However,
the longer the packet,
the
greater
the
probability
of
corruption,
and
the
longer
to
retransmit
once
corrupted.
In addition, the adequacy of
the
single-character block check would
be
much
reduced
for
long
packets;
long packets should therefore be sent with type 2 or
3
block checks.
* It would be possible to extend the protocol to allow
transmission of data packets while ACKs were still outstanding, and
any
ACK would be taken as an ACK for the specified packet and
all
previous ones. A limit on the number of outstanding ACKs
could
be agreed upon; the maximum size of this "floating window"
would
have to be less than 64, which is where KERMIT packet
numbers
wrap around, and the window could not extend over a
wraparound
or else KERMIT would have no way of knowing whether n times
64
packets had been skipped. A floating window of 8 and a
packet
size of 95 would give about the same effect as 700character
packets.
A NAK would require the sender to back up all the
way
to the NAK'd packet. A future edition of the Protocol
Manual
might include a specification for floating windows.
A KERMIT Program
Page 65
IV. A KERMIT Program
What follows
written in
is
a listing of a real production version of KERMIT,
4
the C language . It is designed to run under various versions of the
UNIX
operating system.
The basic KERMIT functionality is present, but very
little
in the way of optional features. Only the most rudimentary (UNIX-style)
command parser is provided. The program illustrates many of the
considerations
described in this manual, with respect to the protocol, the program
design, and
so forth.
It must be emphasized that this is a bare minimum implementation of
Kermit.
Anyone writing a new Kermit from scratch is encouraged to look at the
source
for one of the more advanced implementations as a model (check the Kermit
Users
Guide for a list of KERMIT implementations and their features).
Although you
may not understand the language it's written in, there should be
profuse comments that can be useful.
The following program uses decimal notation for numbers,
rather
than char() for integer-to-character conversion.
and
tochar()
/*
* K e r m i t File Transfer Utility
*
* UNIX Kermit, Columbia University, 1981, 1982, 1983
*
Bill Catchings, Bob Cattani, Chris Maio, Frank da Cruz, Alan
Crosswell
*
* Also:
Jim Guyton, Rand Corporation
*
Walter Underwood, Ford Aerospace
*
* usage: kermit c [lbe line baud escapechar]
to connect
*
kermit s [d..iflb line baud] file ...
to send files
*
kermit r [d..iflb line baud]
to receive files
*
* where
c=connect, s=send, r=receive,
*
d=debug, i=image mode, f=no filename conversion, l=tty line,
*
b=baud rate, e=escape char.
*
* For remote Kermit, format is either:
*
kermit r
* or
kermit s file ...
*
*/
to receive files
to send files
_______________
4
Kernighan & Ritchie, The C Programming Language:
Prentice-Hall (1978)
A KERMIT Program
Page 66
/*
* Modification History:
*
* Oct. 17 Included fixes from Alan Crosswell (CUCCA) for IBM_UTS:
*
- Changed MYEOL character from \n to \r.
*
- Change char to int in bufill so getc would return -1 on
*
EOF instead of 255 (-1 truncated to 8 bits)
*
- Added read() in rpack to eat the EOL character
*
- Added fflush() call in printmsg to force the output
*
NOTE: The last three changes are not conditionally compiled
*
since they should work equally well on any system.
*
*
Changed Berkeley 4.x conditional compilation flag from
*
UNIX4X to UCB4X.
*
Added support for error packets and cleaned up the printing
*
routines.
*/
#include <stdio.h>
/* Standard UNIX definitions */
/* Conditional compilation for different machines/operating systems */
/* One and only one of the following lines should be 1 */
#define
#define
#define
#define
UCB4X
TOPS_20
IBM_UTS
VAX_VMS
1
0
0
0
/*
/*
/*
/*
Berkeley 4.x UNIX */
TOPS-20 */
Amdahl UTS on IBM systems */
VAX/VMS (not yet implemented) */
/* Conditional compilation for the different Unix variants */
/* 0 means don't compile it, nonzero means do */
#if UCB4X
#define V6_LIBS
0
#define NO_FIONREAD 0
flushinput() */
#define NO_TANDEM
0
*/
#endif
#if IBM_UTS
#define V6_LIBS
0
#define NO_FIONREAD 1
#define NO_TANDEM
1
#endif
/* Dont't use retrofit libraries */
/* We have ioctl(FIONREAD,...) for
/* We have TANDEM line discipline (xon/xoff)
/* Don't use retrofit libraries */
/* No ioctl(FIONREAD,...) for flushinput() */
/* No TANDEM line discipline (xon/xoff) */
#if V6_LIBS
#include <retrofit/sgtty.h>
#include <retrofit/signal.h>
#include <retrofit/setjmp.h>
#else
#include <sgtty.h>
#include <signal.h>
#include <setjmp.h>
#endif
A KERMIT Program
Page 67
#if NO_TANDEM
#define TANDEM
unsupported */
#endif
0
/* define it to be nothing if it's
/* Symbol Definitions */
#define
#define
#define
#define
#define
#define
MAXPACKSIZ
SOH
CR
SP
DEL
ESCCHR
94
1
13
32
127
'^'
/*
/*
/*
/*
/*
/*
#define
#define
#define
*/
#define
MAXTRY
MYQUOTE
MYPAD
10
'#'
0
/* Times to retry a packet */
/* Quote character I will use */
/* Number of padding characters I will need
MYPCHAR
0
/* Padding character I need (NULL) */
'\r'
/* End-Of-Line character for UTS systems */
'\n'
/* End-Of-Line character I need */
#define MYTIME
*/
#define MAXTIM
#define MINTIM
10
/* Seconds after which I should be timed out
60
2
/* Maximum timeout interval */
/* Minumum timeout interval */
#define TRUE
#define FALSE
-1
0
/* Boolean constants */
#if IBM_UTS
#define MYEOL
#else
#define MYEOL
#endif
Maximum packet size */
Start of header */
ASCII Carriage Return */
ASCII space */
Delete (rubout) */
Default escape character for CONNECT */
/* Macro Definitions */
/*
* tochar: converts a control character to a printable one by adding a
space.
*
* unchar: undoes tochar.
*
* ctl:
converts between control characters and printable characters
by
*
toggling the control bit (ie. ^A becomes A and A becomes ^A).
*/
#define tochar(ch) ((ch) + ' ')
#define unchar(ch)
#define ctl(ch)
((ch) - ' ')
((ch) ^ 64 )
/* Global Variables */
A KERMIT Program
Page 68
int
size,
rpsiz,
spsiz,
pad,
timint,
n,
numtry,
oldtry,
ttyfd,
remote */
remote,
image,
debug,
(0=none) */
filnamcnv,
filecount;
/*
/*
/*
/*
/*
/*
/*
/*
/*
char
state,
padchar,
eol,
escchr,
quote,
**filelist,
*filnam,
recpkt[MAXPACKSIZ],
packet[MAXPACKSIZ];
/*
/*
/*
/*
/*
/*
/*
/*
/*
FILE
*fp,
*log;
/* File pointer for current disk file */
/* File pointer for Logfile */
jmp_buf env;
Size of present data */
Maximum receive packet size */
Maximum send packet size */
How much padding to send */
Timeout for foreign host on sends */
Packet number */
Times this packet retried */
Times previous packet retried */
File descriptor of tty for I/O, 0 if
/* -1 means we're a remote kermit */
/* -1 means 8-bit mode */
/* indicates level of debugging output
/* -1 means do file name case conversions */
/* Number of files left to send */
Present state of the automaton */
Padding character to send */
End-Of-Line character to send */
Connect command escape character */
Quote character in incoming data */
List of files to be sent */
Current file name */
Receive packet buffer */
Packet buffer */
/* 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.
*/
main(argc,argv)
int argc;
*/
char **argv;
{
char *ttyname,
*cp;
int speed,
/* Character pointers to and count of
/* command line arguments */
/* tty name for LINE argument */
/* char pointer */
/* speed of assigned tty, */
cflg, rflg, sflg;
/* flags for CONNECT, RECEIVE,
SEND */
struct sgttyb
rawmode,
cookedmode,
ttymode;
option */
if (argc < 2) usage();
line */
cp = *++argv; argv++; argc -= 2;
/* Controlling tty raw mode */
/* Controlling tty cooked mode */
/* mode of tty line in LINE
/* Make sure there's a command
/* Set up pointers to args */
A KERMIT Program
Page 69
/*
*/
Initialize these values and hope the first packet will get across OK
eol = CR;
quote = '#';
"#" */
pad = 0;
padchar = NULL;
*/
speed = cflg = sflg = rflg = 0;
ttyname = 0;
#if UCB4X
*/
image = FALSE;
*/
filnamcnv = TRUE;
#else
image = TRUE;
*/
filnamcnv = FALSE;
#endif
/* EOL for outgoing packets */
/* Standard control-quote char
/* No padding */
/* Use null if any padding wanted
/* Turn off all parse flags */
/* Default is remote mode */
/* Default to 7-bit masking, CRLF
/* translation and filename case
/* conversion for UNIX systems */
/* Default to no processing for
/* non-UNIX systems */
escchr = ESCCHR;
/* Default escape character */
while ((*cp) != NULL)
/* Parse characters in first arg.
*/
switch (*cp++)
{
case 'c': cflg++; break;
case 's': sflg++; break;
case 'r': rflg++; break;
case 'd':
/* C = Connect command */
/* S = Send command */
/* R = Receive command */
/* D = Increment debug mode count
*/
debug++; break;
case 'f':
filnamcnv = FALSE;
/* F = don't do case conversion
*/
break;
case 'i':
image = TRUE; break;
/*
on filenames */
/* I = Image (8-bit) mode */
/* (this is default for non-UNIX)
*/
case 'l':
/* L = specify tty line to use */
if (argc--) ttyname = *argv++;
else usage();
if (debug) printf("Line to remote host is %s\n",ttyname);
break;
case 'e':
/* E = specify escape char */
if (argc--) escchr = **argv++;
else usage();
if (debug) printf("Escape char is \"%c\"\n",escchr);
break;
A KERMIT Program
Page 70
case 'b':
/* B = specify baud rate */
#if UCB4X
if (argc--) speed = atoi(*argv++);
else usage();
if (debug) printf("Line speed to remote host is
%d\n",speed);
break;
#else
printmsg("Speed setting implemented for Unix only.");
exit(1);
#endif
}
/* Done parsing */
if ((cflg+sflg+rflg) != 1)
usage();
/* Only one command allowed */
if (ttyname)
/* If LINE was specified, we */
{
/* operate in local mode */
ttyfd = open(ttyname,2);
/* Open the tty line */
if (ttyfd < 0)
{
printmsg("Cannot open %s",ttyname);
exit(1);
}
remote = FALSE;
/* Indicate we're in local mode
*/
}
else
operate */
{
controlling */
ttyfd = 0;
line) */
remote = TRUE;
}
/* No LINE specified so we
/* in remote mode (ie.
/* tty is the communications
/* Put the proper tty into the correct mode */
if (remote)
/* If remote, use controlling tty
*/
{
gtty(0,&cookedmode);
/* Save current mode so we can */
gtty(0,&rawmode);
/* restore it later */
rawmode.sg_flags |= (RAW|TANDEM);
rawmode.sg_flags &= ~(ECHO|CRMOD);
stty(0,&rawmode);
}
else
{
/* Put tty in raw mode */
/* Local, use assigned line */
gtty(ttyfd,&ttymode);
ttymode.sg_flags |= (RAW|TANDEM);
ttymode.sg_flags &= ~(ECHO|CRMOD);
A KERMIT Program
Page 71
#if UCB4X
/* Speed changing for UNIX only
*/
if (speed)
/* User specified a speed? */
{
switch(speed)
/* Get internal system code */
{
case 110: speed = B110; break;
case 150: speed = B150; break;
case 300: speed = B300; break;
case 1200: speed = B1200; break;
case 2400: speed = B2400; break;
case 4800: speed = B4800; break;
case 9600: speed = B9600; break;
default:
printmsg("Bad line speed.");
exit(1);
}
ttymode.sg_ispeed = speed;
ttymode.sg_ospeed = speed;
}
#endif /* UCB4X */
stty(ttyfd,&ttymode);
/* Put asg'd tty in raw mode */
}
/* All set up, now execute the command that was given. */
if (debug)
{
printf("Debugging level = %d\n\n",debug);
if (cflg) printf("Connect command\n\n");
if (sflg) printf("Send command\n\n");
if (rflg) printf("Receive command\n\n");
}
if (cflg) connect();
if (sflg)
{
if (argc--) filnam = *argv++;
else
{
if (remote)
stty(0,&cookedmode);
modes */
usage();
}
/* Connect command */
/* Send command */
/* Get file to send */
/* Restore controlling tty's
/* and give error */
fp = NULL;
filelist = argv;
/* Indicate no file open yet */
/* Set up the rest of the file
filecount = argc;
/* Number of files left to send
if (sendsw() == FALSE)
printmsg("Send failed.");
else
printmsg("done.");
/* Send the file(s) */
/* Report failure */
/* or */
/* success */
list */
*/
}
A KERMIT Program
Page 72
if (rflg)
/*
{
if (recsw() == FALSE)
/*
printmsg("Receive failed.");
else
/*
printmsg("done.");
/*
}
if (remote) stty(0,&cookedmode);
modes */
}
/*
*
*
*
*
*
*
*/
Receive command */
Receive the file(s) */
Report failure */
or success */
/* Restore controlling tty's
s e n d s w
Sendsw is the state table switcher for sending files. It loops until
either it finishes, or an error is encountered. The routines called
by sendsw are responsible for changing the state.
sendsw()
{
char sinit(), sfile(), sdata(), seof(), sbreak();
state = 'S';
/* Send initiate is the start
state */
n = 0;
/* Initialize message number */
numtry = 0;
/* Say no tries yet */
while(TRUE)
/* Do this as long as necessary
*/
{
if (debug) printf("sendsw state: %c\n",state);
switch(state)
{
case 'S':
state = sinit(); break; /* Send-Init */
case 'F':
state = sfile(); break; /* Send-File */
case 'D':
state = sdata(); break; /* Send-Data */
case 'Z':
state = seof();
break; /* Send-End-of-File */
case 'B':
state = sbreak(); break; /* Send-Break */
case 'C':
return (TRUE);
/* Complete */
case 'A':
return (FALSE);
/* "Abort" */
default:
return (FALSE);
/* Unknown, fail */
}
}
}
/*
* s i n i t
*
* Send Initiate: send this host's parameters and get other side's back.
*/
char sinit()
{
int num, len;
/* Packet number, length */
A KERMIT Program
Page 73
if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
spar(packet);
/* Fill up init info packet */
flushinput();
/* Flush pending input */
spack('S',n,6,packet);
switch(rpack(&len,&num,recpkt))
{
case 'N': return(state);
/* Send an S packet */
/* What was the reply? */
case 'Y':
if (n != num)
/* NAK, try it again */
/* ACK */
/* If wrong ACK, stay in S state
*/
return(state);
rpar(recpkt);
/* and try again */
/* Get other side's init info */
if (eol == 0) eol = '\n';
/* Check and set defaults */
if (quote == 0) quote = '#';
numtry = 0;
n = (n+1)%64;
return('F');
/* Reset try counter */
/* Bump packet count */
/* OK, switch state to F */
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE: return(state);
/* Receive failure, try again */
default: return('A');
/* Anything else, just "abort" */
}
}
/*
* s f i l e
*
* Send File Header.
*/
char sfile()
{
int num, len;
char filnam1[50],
*newfilnam,
*/
*cp;
/* Packet number, length */
/* Converted file name */
/* Pointer to file name to send
/* char pointer */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, give up */
A KERMIT Program
Page 74
if (fp == NULL)
/* If not already open, */
{
if (debug) printf("
Opening %s for sending.\n",filnam);
fp = fopen(filnam,"r");
/* open the file to be sent */
if (fp == NULL)
/* If bad file pointer, give up
*/
{
error("Cannot open file %s",filnam);
return('A');
}
}
strcpy(filnam1, filnam);
newfilnam = cp = filnam1;
while (*cp != '\0')
directory */
if (*cp++ == '/')
*/
newfilnam = cp;
if (filnamcnv)
/* Copy file name */
/* Strip off all leading
/* names (ie. up to the last /).
/* Convert lower case to upper
*/
for (cp = newfilnam; *cp != '\0'; cp++)
if (*cp >= 'a' && *cp <= 'z')
*cp ^= 040;
len = cp - newfilnam;
/* Compute length of new filename
*/
printmsg("Sending %s as %s",filnam,newfilnam);
spack('F',n,len,newfilnam);
switch(rpack(&len,&num,recpkt))
{
case 'N':
/* Send an F packet */
/* What was the reply? */
/* NAK, just stay in this state,
*/
num = (--num<0 ? 63:num);
/* unless it's NAK for next
if (n != num)
/* which is just like an ACK for
packet */
*/
return(state);
/* this packet so fall thru to...
*/
case 'Y':
/* ACK */
if (n != num) return(state); /* If wrong ACK, stay in F state
*/
numtry = 0;
n = (n+1)%64;
size = bufill(packet);
return('D');
/*
/*
/*
/*
Reset try counter */
Bump packet count */
Get first data from file */
Switch state to D */
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE: return(state);
/* Receive failure, stay in F
default:
/* Something else, just "abort"
state */
*/
}
}
return('A');
A KERMIT Program
Page 75
/*
* 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);
switch(rpack(&len,&num,recpkt))
{
case 'N':
/* Send a D packet */
/* What was the reply? */
/* NAK, just stay in this state,
*/
num = (--num<0 ? 63:num);
/* unless it's NAK for next
if (n != num)
/* which is just like an ACK for
packet */
*/
return(state);
/* this packet so fall thru to...
*/
case 'Y':
/* ACK */
if (n != num) return(state); /* If wrong ACK, fail */
numtry = 0;
/* Reset try counter */
n = (n+1)%64;
/* Bump packet count */
if ((size = bufill(packet)) == EOF) /* Get data from file */
return('Z');
/* If EOF set state to that */
return('D');
/* Got data, stay in state D */
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE: return(state);
/* Receive failure, stay in D */
default:
/* Anything else, "abort" */
return('A');
}
}
/*
* s e o f
*
* Send End-Of-File.
*/
char seof()
{
int num, len;
/* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
A KERMIT Program
Page 76
spack('Z',n,0,packet);
switch(rpack(&len,&num,recpkt))
{
case 'N':
/* Send a 'Z' packet */
/* What was the reply? */
/* NAK, just stay in this state,
*/
num = (--num<0 ? 63:num);
/* unless it's NAK for next
if (n != num)
/* which is just like an ACK for
packet, */
*/
return(state);
/* this packet so fall thru to...
*/
case 'Y':
/* ACK */
if (n != num) return(state); /* If wrong ACK, hold out */
numtry = 0;
/* Reset try counter */
n = (n+1)%64;
/* and bump packet count */
if (debug) printf("
Closing input file %s, ",filnam);
fclose(fp);
/* Close the input file */
fp = NULL;
/* Set flag indicating no file
open */
if (debug) printf("looking for next file...\n");
if (gnxtfl() == FALSE)
/* No more files go? */
return('B');
/* if not, break, EOT, all done
*/
if (debug) printf("
return('F');
New file is %s\n",filnam);
/* More files, switch state to F
*/
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE: return(state);
/* Receive failure, stay in Z */
default:
/* Something else, "abort" */
return('A');
}
}
/*
* s b r e a k
*
* Send Break (EOT)
*/
char sbreak()
{
int num, len;
/* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* If too many tries "abort" */
spack('B',n,0,packet);
switch (rpack(&len,&num,recpkt))
{
case 'N':
/* Send a B packet */
/* What was the reply? */
/* NAK, just stay in this state,
*/
num = (--num<0 ? 63:num);
/* unless NAK for previous
if (n != num)
/* which is just like an ACK for
packet, */
*/
return(state);
*/
/* this packet so fall thru to...
A KERMIT Program
Page 77
case 'Y':
/* ACK */
if (n != num) return(state); /* If wrong ACK, fail */
numtry = 0;
/* Reset try counter */
n = (n+1)%64;
/* and bump packet count */
return('C');
/* Switch state to Complete */
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE: return(state);
/* Receive failure, stay in B */
default:
/* Other, "abort" */
return ('A');
}
}
/*
* r e c s w
*
* This is the state table switcher for receiving files.
*/
recsw()
{
char rinit(), rfile(), rdata();
state = 'R';
state */
n = 0;
numtry = 0;
/* Use these procedures */
/* Receive-Init is the start
/* Initialize message number */
/* Say no tries yet */
while(TRUE)
{
if (debug) printf(" recsw state: %c\n",state);
switch(state)
/* Do until done */
{
case 'R':
state = rinit(); break; /* Receive-Init */
case 'F':
state = rfile(); break; /* Receive-File */
case 'D':
state = rdata(); break; /* Receive-Data */
case 'C':
return(TRUE);
/* Complete state */
case 'A':
return(FALSE);
/* "Abort" state */
}
}
}
/*
*
r i n i t
*
* Receive Initialization
*/
char rinit()
{
int len, num;
/* Packet length, number */
A KERMIT Program
Page 78
if (numtry++ > MAXTRY) return('A'); /* If too many tries, "abort" */
switch(rpack(&len,&num,packet))
{
case 'S':
rpar(packet);
/* Get a packet */
/* Send-Init */
/* Get the other side's init data
*/
spar(packet);
/* Fill up packet with my init
spack('Y',n,6,packet);
oldtry = numtry;
numtry = 0;
n = (n+1)%64;
return('F');
/*
/*
/*
/*
/*
info */
ACK with my parameters */
Save old try count */
Start a new counter */
Bump packet number, mod 64 */
Enter File-Receive state */
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE:
spack('N',n,0,0);
return(state);
/* Didn't get packet */
/* Return a NAK */
/* Keep trying */
default:
"abort" */
}
}
return('A');
/* Some other packet type,
/*
* r f i l e
*
* Receive File Header
*/
char rfile()
{
int num, len;
char filnam1[50];
*/
/* Packet number, length */
/* Holds the converted file name
if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
switch(rpack(&len,&num,packet))
{
case 'S':
/* Get a packet */
/* Send-Init, maybe our ACK lost
*/
if (oldtry++ > MAXTRY) return('A'); /* If too many tries
"abort" */
if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
{
/* Yes, ACK it again with */
spar(packet);
/* our Send-Init parameters */
spack('Y',num,6,packet);
numtry = 0;
/* Reset try counter */
return(state);
/* Stay in this state */
}
else return('A');
/* Not previous packet, "abort"
*/
A KERMIT Program
Page 79
case 'Z':
/* End-Of-File */
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) /* Previous packet, mod 64? */
{
/* Yes, ACK it again. */
spack('Y',num,0,0);
numtry = 0;
return(state);
/* Stay in this state */
}
else return('A');
/* Not previous packet, "abort"
*/
case 'F':
/* File Header (just what we
want) */
if (num != n) return('A');
/* The packet number must be
strcpy(filnam1, packet);
/* Copy the file name */
right */
if (filnamcnv)
/* Convert upper case to lower */
for (filnam=filnam1; *filnam != '\0'; filnam++)
if (*filnam >= 'A' && *filnam <= 'Z')
*filnam |= 040;
if ((fp=fopen(filnam1,"w"))==NULL) /* Try to open a new file
*/
{
error("Cannot create %s",filnam1); /* Give up if can't */
return('A');
}
else
/* OK, give message */
printmsg("Receiving %s as %s",packet,filnam1);
spack('Y',n,0,0);
oldtry = numtry;
numtry = 0;
n = (n+1)%64;
return('D');
/*
/*
/*
/*
/*
Acknowledge the file header */
Reset try counters */
... */
Bump packet number, mod 64 */
Switch to Data state */
case 'B':
/* Break transmission (EOT) */
if (num != n) return ('A'); /* Need right packet number here
*/
spack('Y',n,0,0);
return('C');
/* Say OK */
/* Go to complete state */
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
case FALSE:
spack('N',n,0,0);
/* Didn't get packet */
/* Return a NAK */
return(state);
default:
}
}
return ('A');
/* Keep trying */
/* Some other packet, "abort" */
A KERMIT Program
Page 80
/*
* r d a t a
*
* Receive Data
*/
char rdata()
{
int num, len;
/* Packet number, length */
if (numtry++ > MAXTRY) return('A'); /* "abort" if too many tries */
switch(rpack(&len,&num,packet))
/* Get packet */
{
case 'D':
/* Got Data packet */
if (num != n)
/* Right packet? */
{
/* No */
if (oldtry++ > MAXTRY)
return('A');
/* If too many tries, abort */
if (num == ((n==0) ? 63:n-1)) /* Else check packet number
*/
{
/* Previous packet again? */
spack('Y',num,6,packet); /* Yes, re-ACK it */
numtry = 0;
/* Reset try counter */
return(state);
/* Don't write out data! */
}
else return('A');
/* sorry, wrong number */
}
/* Got data with right packet number */
bufemp(packet,len);
/* Write the data to the file */
spack('Y',n,0,0);
/* Acknowledge the packet */
oldtry = numtry;
/* Reset the try counters */
numtry = 0;
/* ... */
n = (n+1)%64;
/* Bump packet number, mod 64 */
return('D');
/* Remain in data state */
case 'F':
/* Got a File Header */
if (oldtry++ > MAXTRY)
return('A');
/* If too many tries, "abort" */
if (num == ((n==0) ? 63:n-1)) /* Else check packet number */
{
/* It was the previous one */
spack('Y',num,0,0);
/* ACK it again */
numtry = 0;
/* Reset try counter */
return(state);
/* Stay in Data state */
}
else return('A');
/* Not previous packet, "abort"
*/
case 'Z':
/* End-Of-File */
if (num != n) return('A');
/* Must have right packet number
spack('Y',n,0,0);
fclose(fp);
n = (n+1)%64;
return('F');
/*
/*
/*
/*
*/
OK, ACK it. */
Close the file */
Bump packet number */
Go back to Receive File state
*/
case 'E':
prerrpkt(recpkt);
return('A');
/* Error packet received */
/* Print it out and */
/* abort */
A KERMIT Program
Page 81
case FALSE:
spack('N',n,0,0);
return(state);
/* Didn't get packet */
/* Return a NAK */
/* Keep trying */
default:
/* Some other packet, "abort" */
return('A');
}
}
/*
* c o n n e c t
*
* Establish a virtual terminal connection with the remote host, over an
* assigned tty line.
*/
connect()
{
int pid,
connected;
char bel = '\07',
c;
/* Holds process id of child */
/* Boolean connect flag */
struct sgttyb
rawmode,
cookedmode;
/* Controlling tty raw mode */
/* Controlling tty cooked mode */
if (remote)
/* Nothing to connect to in
remote */
{
/* mode, so just return */
printmsg("No line specified for connection.");
return;
}
gtty(0,&cookedmode);
gtty(0,&rawmode);
rawmode.sg_flags |= (RAW|TANDEM);
rawmode.sg_flags &= ~(ECHO|CRMOD);
stty(0,&rawmode);
pid = fork();
*/
/* Save current mode so we can */
/* restore it later */
/* Put tty in raw mode */
/* Start fork to get typeout from remote host
A KERMIT Program
Page 82
if (pid)
/* Parent: send type-in to remote
host */
{
printmsg("connected...\r");
connected = TRUE;
/* Put us in "connect mode" */
while (connected)
{
read(0,&c,1);
/* Get a character */
if ((c&0177) == escchr)
/* Check for escape character */
{
read(0,&c,1);
if ((c&0177) == escchr)
write(ttyfd,&c,1);
else
switch (c&0177)
{
case 'c':
case 'C':
connected = FALSE;
write(0,"\r\n",2);
break;
case 'h':
case 'H':
write(0,"\r\nYes, I'm still here...\r\n",26);
break;
default:
write(0,&bel,1);
break;
}
}
else
{
write(ttyfd,&c,1);
c = NULL;
}
}
kill(pid,9);
wait(0);
stty(0,&cookedmode);
printmsg("disconnected.");
return;
}
else
/* If not escape charater, */
/* write it out */
/* Nullify it (why?) */
/* Done, kill the child */
/* and bury him */
/* Restore tty mode */
/* Done */
/* Child does the reading from the remote host
*/
{
while(1)
{
/* Do this forever */
read(ttyfd,&c,1);
write(1,&c,1);
}
}
}
A KERMIT Program
Page 83
/*
*
*/
KERMIT utilities.
clkint()
{
longjmp(env,TRUE);
}
/* Timer interrupt handler */
/* Tell rpack to give up */
/*
* s p a c k
*
* Send a Packet
*/
spack(type,num,len,data)
char type, *data;
int num, len;
{
int i;
char chksum, buffer[100];
register char *bufp;
/* Character loop counter */
/* Checksum, packet buffer */
/* Buffer pointer */
if (debug>1)
/* Display outgoing packet */
{
if (data != NULL)
data[len] = '\0';
/* Null-terminate data to print
it */
printf(" spack type: %c\n",type);
printf("
num: %d\n",num);
printf("
len: %d\n",len);
if (data != NULL)
printf("
data: \"%s\"\n",data);
}
bufp = buffer;
/* Set up buffer pointer */
for (i=1; i<=pad; i++) write(ttyfd,&padchar,1); /* Issue any padding
*/
*bufp++ = SOH;
/* Packet marker, ASCII 1 (SOH)
*bufp++ =
chksum =
*bufp++ =
chksum +=
*bufp++ =
chksum +=
/*
/*
/*
/*
/*
/*
*/
tochar(len+3);
tochar(len+3);
tochar(num);
tochar(num);
type;
type;
Send the character count */
Initialize the checksum */
Packet number */
Update checksum */
Packet type */
Update checksum */
A KERMIT Program
Page 84
for (i=0; i<len; i++)
/* Loop for all data characters
*/
{
*bufp++ = data[i];
chksum += data[i];
/* Get a character */
/* Update checksum */
}
chksum = (((chksum&0300) >> 6)+chksum)&077; /* Compute final checksum
*/
*bufp++ = tochar(chksum);
*bufp = eol;
/* Put it in the packet */
/* Extra-packet line terminator
*/
write(ttyfd, buffer,bufp-buffer+1); /* Send the packet */
}
/*
* r p a c k
*
* Read a Packet
*/
rpack(len,num,data)
int *len, *num;
char *data;
{
int i, done;
exit */
char t,
type,
cchksum,
rchksum;
host */
/* Packet length, number */
/* Packet data */
/* Data character number, loop
/*
/*
/*
/*
Current input character */
Packet type */
Our (computed) checksum */
Checksum received from other
#if UCB4X
/* TOPS-20 can't handle
timeouts... */
if (setjmp(env)) return FALSE;
/* Timed out, fail */
signal(SIGALRM,clkint);
/* Setup the timeout */
if ((timint > MAXTIM) || (timint < MINTIM)) timint = MYTIME;
alarm(timint);
#endif /* UCB4X */
while (t != SOH)
{
read(ttyfd,&t,1);
t &= 0177;
}
/* Wait for packet header */
done = FALSE;
while (!done)
{
/* Got SOH, init loop */
/* Loop to get a packet */
/* Handle parity */
read(ttyfd,&t,1);
if (!image) t &= 0177;
if (t == SOH) continue;
cchksum = t;
*len = unchar(t)-3;
/*
/*
/*
/*
/*
Get character */
Handle parity */
Resynchronize if SOH */
Start the checksum */
Character count */
read(ttyfd,&t,1);
if (!image) t &= 0177;
if (t == SOH) continue;
cchksum = cchksum + t;
*num = unchar(t);
/*
/*
/*
/*
/*
Get character */
Handle parity */
Resynchronize if SOH */
Update checksum */
Packet number */
A KERMIT Program
Page 85
read(ttyfd,&t,1);
if (!image) t &= 0177;
if (t == SOH) continue;
cchksum = cchksum + t;
type = t;
/*
/*
/*
/*
/*
Get character */
Handle parity */
Resynchronize if SOH */
Update checksum */
Packet type */
for (i=0; i<*len; i++)
{
read(ttyfd,&t,1);
if (!image) t &= 0177;
if (t == SOH) continue;
cchksum = cchksum + t;
data[i] = t;
}
data[*len] = 0;
/*
/*
/*
/*
/*
/*
/*
The data itself, if any */
Loop for character count */
Get character */
Handle parity */
Resynch if SOH */
Update checksum */
Put it in the data buffer */
read(ttyfd,&t,1);
/* Get last character (checksum)
rchksum = unchar(t);
read(ttyfd,&t,1);
/* Convert to numeric */
/* get EOL character and toss it
if (!image) t &= 0177;
if (t == SOH) continue;
done = TRUE;
/* Handle parity */
/* Resynchronize if SOH */
/* Got checksum, done */
/* Mark the end of the data */
*/
*/
}
#if UCB4X
alarm(0);
#endif
/* Disable the timer interrupt */
if (debug>1)
/* Display incoming packet */
{
if (data != NULL)
data[*len] = '\0';
/* Null-terminate data to print
it */
printf(" rpack type: %c\n",type);
printf("
num: %d\n",*num);
printf("
len: %d\n",*len);
if (data != NULL)
printf("
data: \"%s\"\n",data);
}
/* Fold in bits 7,8 to compute */
cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */
if (cchksum != rchksum) return(FALSE);
return(type);
}
/* All OK, return packet type */
/*
*
*
*
*
*
*/
b u f i l l
Get a bufferful of data from the file that's being sent.
Only control-quoting is done; 8-bit & repeat count prefixes are
not handled.
A KERMIT Program
Page 86
bufill(buffer)
char buffer[];
{
int i,
t;
char t7;
/* Buffer */
/* Loop index */
/* Char read from file */
/* 7-bit version of above */
i = 0;
while((t = getc(fp)) != EOF)
{
t7 = t & 0177;
/* Init data buffer pointer */
/* Get the next character */
/* Get low order 7 bits */
if (t7 < SP || t7==DEL || t7==quote) /* Does this char require */
{
/* special handling? */
if (t=='\n' && !image)
{
/* Do LF->CRLF mapping if !image
*/
buffer[i++] = quote;
buffer[i++] = ctl('\r');
}
buffer[i++] = quote;
if (t7 != quote)
{
t = ctl(t);
t7 = ctl(t7);
}
}
if (image)
buffer[i++] = t;
/* Quote the character */
/* and uncontrolify */
/* Deposit the character itself
*/
else
buffer[i++] = t7;
if (i >= spsiz-8) return(i);
}
if (i==0) return(EOF);
return(i);
/* Check length */
/* Wind up here only on EOF */
/* Handle partial buffer */
}
/*
*
b u f e m p
*
* Put data from an incoming packet into a file.
*/
bufemp(buffer,len)
char buffer[];
int
len;
/* Buffer */
/* Length */
{
int i;
char t;
/* Counter */
/* Character holder */
A KERMIT Program
Page 87
for (i=0; i<len; i++)
{
t = buffer[i];
if (t == MYQUOTE)
{
t = buffer[++i];
if ((t & 0177) != MYQUOTE)
char? */
t = ctl(t);
}
if (t==CR && !image)
*/
continue;
/* Loop thru the data field */
/*
/*
/*
/*
/*
Get character */
Control quote? */
Yes */
Get the quoted character */
Low order bits match quote
/* No, uncontrollify it */
/* Don't pass CR if in image mode
putc(t,fp);
}
}
/*
* g n x t f l
*
* Get next file in a file group
*/
gnxtfl()
{
if (debug) printf("
gnxtfl: filelist = \"%s\"\n",*filelist);
filnam = *(filelist++);
if (filecount-- == 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
*
*/
spar(data)
char data[];
{
data[0] =
receive */
data[1] =
data[2] =
data[3] =
tochar(MAXPACKSIZ);
tochar(MYTIME);
tochar(MYPAD);
ctl(MYPCHAR);
/* Biggest packet I can
/* When I want to be timed out */
/* How much padding I need */
/* Padding character I want */
data[4] = tochar(MYEOL);
/* End-Of-Line character I want
data[5] = MYQUOTE;
/* Control-Quote character I send
*/
*/
}
A KERMIT Program
Page 88
/* r p a r
*
* Get the other host's send-init parameters
*
*/
rpar(data)
char data[];
{
spsiz = unchar(data[0]);
timint = unchar(data[1]);
pad = unchar(data[2]);
padchar = ctl(data[3]);
eol = unchar(data[4]);
quote = data[5];
*/
}
/*
/*
/*
/*
/*
/*
Maximum send packet size */
When I should time out */
Number of pads to send */
Padding character to send */
EOL character I must send */
Incoming data quote character
/*
* f l u s h i n p u t
*
* Dump all pending input to clear stacked up NACK's.
* (Implemented only for Berkeley Unix at this time).
*/
#if UCB4X&(~NO_FIONREAD)
flushinput()
{
long int count;
*/
long int i;
loop */
ioctl(ttyfd, FIONREAD, &count);
read */
if (!count) return;
flush */
while (count)
{
i = (count<sizeof(recpkt)) ?
/* Number of bytes ready to read
/* Number of bytes to read in
/* See how many bytes pending
/* If zero, then no input to
/* Loop till all are flushed */
/* Read min of count and size of
*/
count : sizeof(recpkt);
read(ttyfd, recpkt, i);
count -= i;
*/
}
}
/* the read buffer */
/* Read a bunch */
/* Subtract from amount to read
#else
flushinput()
/* Null version for non-Berkeley Unix */
{}
#endif /* UCB4X&(~FIONREAD) */
A KERMIT Program
Page 89
/*
*
*
*
*
*
*
*/
Kermit printing routines:
usage - print command line options showing proper syntax
printmsg - like printf with "Kermit: " prepended
error - like printmsg if local kermit; sends a error packet if remote
prerrpkt - print contents of error packet received from remote host
/*
* u s a g e
*
* Print summary of usage info and quit
*/
usage()
{
#if UCB4X
printf("Usage:
mode)\n");
printf("or:
printf("or:
mode)\n");
#else
printf("Usage:
mode)\n");
printf("or:
printf("or:
mode)\n");
#endif
exit(1);
}
kermit c[lbe line baud esc.char]
(connect
kermit s[diflb line baud] file ...
kermit r[diflb line baud]
(send mode)\n");
(receive
kermit c[le line esc.char]
(connect
kermit s[difl line] file ...
kermit r[difl line]
(send mode)\n");
(receive
/*
* p r i n t m s g
*
* Print message on standard output if not remote.
*/
/*VARARGS1*/
printmsg(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
if (!remote)
{
printf("Kermit: ");
printf(fmt,a1,a2,a3,a4,a5);
printf("\n");
fflush(stdout);
/* force output (UTS needs it) */
}
}
A KERMIT Program
Page 90
/*
*
*
*
*
*
*
*/
e r r o r
Print error message.
If local, print error message with printmsg.
If remote, send an error packet with the message.
/*VARARGS1*/
error(fmt, a1, a2, a3, a4, a5)
char *fmt;
{
char msg[80];
int len;
if (remote)
{
sprintf(msg,fmt,a1,a2,a3,a4,a5); /* Make it a string */
len = strlen(msg);
spack('E',n,len,msg);
/* Send the error packet */
}
else
printmsg(fmt, a1, a2, a3, a4, a5);
return;
}
/*
* p r e r r p k t
*
* Print contents of error packet received from remote host.
*/
prerrpkt(msg)
char *msg;
{
printf("Kermit aborting with following error from remote
host:\n%s\n",msg);
return;
}
The ASCII Character Set
Page 91
V. The ASCII Character Set
ASCII Code (ANSI X3.4-1968)
There are 128 characters in the ASCII (American national Standard Code
for Information Interchange) "alphabet". The characters are listed in order of
ASCII
value; the columns are labeled as follows:
Bit
ASCII Dec
ASCII Oct
ASCII Hex
EBCDIC Hex
tables.
Char
Remark
Even parity bit for ASCII character.
Decimal (base 10) representation.
Octal (base 8) representation.
Hexadecimal (base 16) representation.
EBCDIC hexadecimal equivalent for Kermit translate
Name or graphical representation of character.
Description of character.
The first group consists of nonprintable 'control' characters:
Bit
0
1
1
0
1
0
0
1
1
0
0
1
0
1
1
0
1
0
0
1
0
1
1
0
0
1
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
000
000
00
00
001
001
01
01
002
002
02
02
003
003
03
03
004
004
04
37
005
005
05
2D
006
006
06
2E
007
007
07
2F
008
010
08
16
009
011
09
05
010
012
0A
25
011
013
0B
0B
012
014
0C
0C
013
015
0D
0D
014
016
0E
0E
015
017
0F
0F
016
020
10
10
017
021
11
11
018
022
12
12
019
023
13
13
020
024
14
3C
021
025
15
3D
022
026
16
32
023
027
17
26
024
030
18
18
025
031
19
19
Char
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
HT
LF
VT
FF
CR
SO
SI
DLE
DC1
DC2
DC3
DC4
NAK
SYN
ETB
CAN
EM
Remarks
^@, Null, Idle
^A, Start of heading
^B, Start of text
^C, End of text
^D, End of transmission
^E, Enquiry
^F, Acknowledge
^G, Bell, beep, or fleep
^H, Backspace
^I, Horizontal tab
^J, Line feed
^K, Vertical tab
^L, Form feed (top of page)
^M, Carriage return
^N, Shift out
^O, Shift in
^P, Data link escape
^Q, Device control 1, XON
^R, Device control 2
^S, Device control 3, XOFF
^T, Device control 4
^U, Negative acknowledge
^V, Synchronous idle
^W, End of transmission block
^X, Cancel
^Y, End of medium
1
0
1
0
0
1
026
027
028
029
030
031
032
033
034
035
036
037
1A
1B
1C
1D
1E
1F
3F
27
1C
1D
1E
1F
SUB
ESC
FS
GS
RS
US
^Z,
^[,
^\,
^],
^^,
^_,
Substitute
Escape, prefix, altmode
File separator
Group separator
Record separator
Unit separator
The last four are usually associated with the control version of
backslash,
right square bracket, uparrow (or circumflex), and underscore,
respectively,
The ASCII Character Set
Page 92
but some terminals do not transmit these control characters.
The following characters are printable:
First, some punctuation characters.
Bit
1
0
0
1
0
1
1
0
0
1
1
0
1
0
0
1
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
032
040
20
40
033
041
21
5A
034
042
22
7F
035
043
23
7B
036
044
24
5B
037
045
25
6C
038
046
26
50
039
047
27
7D
040
050
28
4D
041
051
29
5D
042
052
2A
5C
043
053
2B
4E
044
054
2C
6B
045
055
2D
60
046
056
2E
4B
047
057
2F
61
Char
SP
!
"
#
$
%
&
'
(
)
*
+
,
.
/
Remarks
Space, blank
Exclamation mark
Doublequote
Number sign, pound sign
Dollar sign
Percent sign
Ampersand
Apostrophe, accent acute
Left parenthesis
Right parenthesis
Asterisk, star
Plus sign
Comma
Dash, hyphen, minus sign
Period, dot
Slash
Char
0
1
2
3
4
5
6
7
8
9
Remarks
Zero
One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Numeric characters:
Bit
0
1
1
0
1
0
0
1
1
0
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
048
060
30
F0
049
061
31
F1
050
062
32
F2
051
063
33
F3
052
064
34
F4
053
065
35
F5
054
066
36
F6
055
067
37
F7
056
070
38
F8
057
071
39
F9
More punctuation characters:
Bit
0
1
0
1
1
0
1
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
058
072
3A
7A
059
073
3B
5E
060
074
3C
4C
061
075
3D
7E
062
076
3E
6E
063
077
3F
6F
064
100
40
7C
Char
:
;
<
=
>
?
@
Remarks
Colon
Semicolon
Left angle bracket
Equal sign
Right angle bracket
Question mark
"At" sign
The ASCII Character Set
Page 93
Upper-case alphabetic characters (letters):
Bit
0
0
1
0
1
1
0
0
1
1
0
1
0
0
1
0
1
1
0
1
0
0
1
1
0
0
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
065
101
41
C1
066
102
42
C2
067
103
43
C3
068
104
44
C4
069
105
45
C5
070
106
46
C6
071
107
47
C7
072
110
48
C8
073
111
49
C9
074
112
4A
D1
075
113
4B
D2
076
114
4C
D3
077
115
4D
D4
078
116
4E
D5
079
117
4F
D6
080
120
50
D7
081
121
51
D8
082
122
52
D9
083
123
53
E2
084
124
54
E3
085
125
55
E4
086
126
56
E5
087
127
57
E6
088
130
58
E7
089
131
59
E8
090
132
5A
E9
Char
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Remarks
More punctuation characters:
Bit
1
0
1
1
0
0
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
091
133
5B
AD
092
134
5C
E0
093
135
5D
BD
094
136
5E
5F
095
137
5F
6D
096
140
60
79
Char
[
\
]
^
_
`
Remarks
Left square bracket
Backslash
Right square bracket
Circumflex, up arrow
Underscore, left arrow
Accent grave
The ASCII Character Set
Page 94
Lower-case alphabetic characters (letters):
Bit
1
1
0
1
0
0
1
1
0
0
1
0
1
1
0
1
0
0
1
0
1
1
0
0
1
1
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
097
141
61
81
098
142
62
82
099
143
63
83
100
144
64
84
101
145
65
85
102
146
66
86
103
147
67
87
104
150
68
88
105
151
69
89
106
152
6A
91
107
153
6B
92
108
154
6C
93
109
155
6D
94
110
156
6E
95
111
157
6F
96
112
160
70
97
113
161
71
98
114
162
72
99
115
163
73
A2
116
164
74
A3
117
165
75
A4
118
166
76
A5
119
167
77
A6
120
170
78
A7
121
171
79
A8
122
172
7A
A9
Char
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
Remarks
More punctuation characters:
Bit
0
1
0
0
.....ASCII.... EBCDIC
Dec
Oct Hex Hex
123
173
7B
C0
124
174
7C
4F
125
175
7D
D0
126
176
7E
7E
Char
{
|
}
~
Remarks
Left brace (curly bracket)
Vertical bar
Right brace (curly bracket)
Tilde
Finally, one more nonprintable character:
0
127
177
7F
07
DEL
Delete, rubout
Index
Page 95
Index
8th Bit
Names
5, 27
NAK
7, 36
Normal Form for File
15
ACK
7
ASCII
6, 10, 91
Baud
8
Binary Files
Packet
Parity
Prefix
Prefixed
9, 10
7, 20
22, 26, 91
27, 30
Sequence
28
Binary Mode
8
Bit Positions
5
Printable Files
Program, Kermit
Block Check
21, 22
Bootstrap
59
BREAK
55
Protocol
10
56,
65
Capabilies
25
CAPAS
25
Char(x)
6
Checksum
21
Control Character
6
Control Characters
20, 91
Control Fields
22
Ctl(x)
6
3
Raw Mode
8
Records
10
Remote
5, 8
Repeat Prefix
27
Reserved Fields
25
Send-Init
23
Sequence Number
12
Sequential Files
3
Server
5
Server Command Wait
28
Data Encoding
DEFINE
53
Duplex
8
22
EBCDIC
8, 10, 91
Edit Number
58
Encoding
27, 30
End-Of-Line (EOL)
Errors
14
Server Commands
Server Operation
Short Reply
31
SOH
8
8, 21
Fatal Errors
14
File Names
15
Flow Control
8, 16
Full Duplex
8
GET Command
31
Half Duplex
Host
5
8
Initial Connection
Tab Expansion
10
Text Files
10
Timeout
7
Transaction
12
Transaction Log
16
TTY
5
Unchar(x)
User
5
XON/XOFF
23
32
28
6
8, 16, 91
KERMIT
3
Language, Programming
58
Line Terminator
21
Line Terminator (see End-Of-Line)
Local
5
Logical Record
10
Logical Records
10
Long Reply
31
Table of Contents
Page i
Table of Contents
1. Introduction
3
1.1. Background
3
1.2. Overview
3
2. Definitions
5
2.1.
5
2.2.
5
2.3.
6
2.4.
6
2.5.
7
General Terminology
Numbers
Character Set
Conversion Functions
Protocol Jargon
3. System Requirements
8
4. Printable Text versus Binary Data
10
4.1. Printable Text Files
10
4.2. Binary Files
10
5. File Transfer
12
5.1.
13
5.2.
13
5.3.
14
5.4.
14
5.5.
15
5.6.
16
Conditioning the Terminal
Timeouts, NAKs, and Retries
Errors
Heuristics
File Names
Robustness
5.7. Flow Control
16
5.8. Basic KERMIT Protocol State Table
17
6. Packet Format
20
6.1.
20
6.2.
21
6.3.
21
6.4.
22
Fields
Terminator
Other Interpacket Data
Encoding, Prefixing, Block Check
7. Initial Connection
23
8. Optional Features
27
8.1. 8th-Bit and Repeat Count Prefixing
27
8.2. Server Operation
28
8.2.1. Server Commands
29
8.2.2. Timing
30
8.2.3. The R Command
31
8.2.4. The K Command
31
8.2.5. Short and Long Replies
31
8.2.6. Additional Server Commands
32
8.2.7. Host Commands
34
8.2.8. Exchanging Parameters Before Server Commands
34
Table of Contents
Page ii
8.3.
34
8.4.
36
8.5.
37
8.6.
43
Alternate Block Check Types
Interrupting a File Transfer
Transmitting File Attributes
Advanced KERMIT Protocol State Table
9. KERMIT Commands
48
9.1.
48
9.2.
48
9.3.
49
9.4.
49
9.5.
49
9.6.
51
9.7.
53
Basic Commands
Program Management Commands
Terminal Emulation Commands
Special User-Mode Commands
Commands Whose Object Should Be Specified
The SET Command
Macros, the DEFINE Command
10. Terminal Emulation
54
11. Writing a KERMIT Program
56
11.1.
56
11.2.
58
11.3.
58
11.4.
59
Program Organization
Programming Language
Documentation
Bootstrapping
I. Packet Format and Types
60
II. List of Features
61
III. Unresolved Issues
63
IV. A KERMIT Program
65
V. The ASCII Character Set
91
Index
95
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement