B6800 KERMIT DOCUMENTATION
                ----- ------ -------------

                        12/12/84

                Randy McLaughlin
                Metro-II
                360 Colborne
                St Paul, MN 55102
		(612)227-9261


Accompanying this document are several files which may be of assistance
to anyone attempting to implement Kermit on Burroughs Large System com-
puters.  We implemented Kermit on a B6800 for communications with
Kermit on an Altos 586 running under Xenix.  Because this implementation
depends upon NDL support, users of Bx900 and A-series machines will not
be able to implement Kermit without writing similar NDLII code.  Users
of smaller Burroughs machines will also find that the NDL and the main
program, which is written in ALGOL are also not applicable to their
environment.  In any case, I hope that the enclosed files are at least
helpful as a model for other implementations.

The following files are included:
    B68KERMIT.ALG	This is the source of the B6800 ALGOL program.
    B68KERMIT.NDL	NDL request sets to replace READTELETYPE and
			    WRITETELETYPE and associated DEFINE's.
    B68KERMIT.DOC	This file--documentation of the B6800 Kermit.

Appendixes to this document provide the source for the following programs
which we use on the Altos to simplify communication with B6800 Kermit.
    kersh               XENIX shell for specifying files to be trans-
                            ferred and for initiating Kermit on the
                            B6800 for each transfer.
    crend.c             A program used by KERSH to send a message to
                            the B6800 terminated by a CR rather that
                            a NEWLINE.
    waitkerm            A program used by KERSH.  Once Kermit has been
                            RUN on the B6800, WAITKERM waits for the
                            B6800 Kermit to signal that it is running.


SOME HISTORY
---- -------
My original approach to implementing Kermit was to write a single
ALGOL program which provided the entire Kermit service, from
packetizing and depacketizing messages to specification of files
to transfer.  This program, once run, would stay in the mix until
specifically told to terminate.  It would then process any number of
file transfers requested from the remote end.

One big problem with the above aproach was that Kermit was too sluggish.
A file transfer would frequently fail because of the delay imposed
transferring the data from the DCP to the main system, waking the DCC,
and then waking the Kermit application.  Especially in a full mix,
Kermit would simply take too long to acknowledge a packet.  I thus
resorted to moving the depacketing and acknowledgement functions to
NDL.  The path towards this solution was guided by earlier work I
had done implementing a different, but somewhat similar protocol for
file transfers to and from Apples.  As Kermit, and the earlier Apple
program we not MCS's, but were instead run under CANDE, and because
the same line had to accomodate both the file transfer protocol and
the generic TTY interface, I had to resort to some tricks to get the
NDL to switch protocols.

I also encountered problems which again were familiar from work on the
Apple interface.  One is that the file naming conventions on the B6800
do not correspond to either those on an Apple or a UNIX machine.  Both
Kermit and the Apple program assume that one intends to use the same
name for the file on both ends of the transfer.  I therefore wanted to
provide facilities for specifying the file name for both ends of the
link.  Another more substantial problem is that the B6800 likes to
work with fixed record length, whereas the other machines use a vari-
able length format.  When transfering from the B6800 to another computer
simply stripping off trailing blanks and separating records with a
CR and a LF.  Coming the other way though, either a facility had to
be provided to allow specification of record and block sizes, or some
kind of assumption had to be made.  Although additional code could have
been added to allow specification of these parameters inside of a large
continuous B6800 Kermit, human interaction with a program on the other
machine would be cleaner and easier, and these attributes can be spec-
ified at run time under CANDE without any additional code.

Thus the decision was made to change the B6800 Kermit to exist only for
the duration of a single file transfer, returning to CANDE between
transfers.  This also allowed any additional file manipulation to be
done under CANDE without subjecting the user to manually terminating
and reinitiating the transfer.  This was also natural considering the
frequency that only a single file needs to be transferred.  The name
of the file, its record and block size, and any other attributes are
thus specified through the mechanism of file equation.  Indeed,
the direction of transfer is specified through use of the MYUSE file
attribute.  A shell was then written on the Altos to ask for the per-
tenent attributes, format them into a CANDE RUN statement and pass it
on to the B6800.  This was much easier to write and to use than the
older approach.

THE NDL TO PROGRAM INTERFACE
--- --- -- ------- ---------
Because any program except an MCS has very little control over NDL and
because of the requirement that generic TTY traffic not be affected
in any way by the imposition of the Kermit protocol on top of the TTY
protocol, no obvious means existed for the Kermit program to tell the
NDL that it should now expect and acknowledge Kermit packets.  However
a slighly tricky means did exist for communicating this state change.
This trick relies on two unlikely elements in the format of data to be
transmitted which when occuring together signify the special state
change signal.  One is the specific request that no carriage control
be done (ALGOL WRITE(<filename> [STOP], ...) ).  In our shop, this is
used only infrequently.  The other key to a protocol signal is that the
first character of the message begins with an EBCDIC character in the
range 4"B0" to 4"BF".  Since these do not translate to any ASCII char-
acter, they resemble an invalid punch on a WFL deck--something you
should never find in the first (or any other position) of a record.

Most of the characters were already defined for Apple protocol state
changes, but 4"BF" was not, and was chosen to represent a Kermit
protocol selection.  At this point the only Kermit protocol service
available in NDL is to automatically receive and acknowledge data
("D") packets.

To initiate Kermit auto receive in the NDL then, the Kermit program
writes (with STOP) a message consisting of the 4"BF" character,
the Pad Count (as found in an "S" packet), the Pad Character,
the maximum packet length, the sequence number of the packet last
recieved (which will be acked), and the type of packet involved.
At this point only the sequence number (in the range 4"20" to 4"5F")
is significant, the other values are ignored.  The message must consist
of exactly this number of characters to be seen as a request to
initiate Kermit auto receive.

The NDL will then verify proper formation of packets, sequence numbers,
and checksums.  If the packet is a "D" (data) packet, it is then either
ACKed or NAKed depending on the results of the tests.  If a packet other
than a "D" packet is received, it is passed through the DCP to the
program and NDL auto receive is terminated, returning the NDL to normal
TTY handling.  In order to distinguish data from packets received in
auto receive mode from packets which are passed through unchecked and
unprocessed, data from auto receive packets is marked by a leading
4"BF" character.  Any messages read by the Kermit application which are
not preceded  by the 4"BF" mark must be verified programmatically for
form and content and programmatically acknowledged.  There are sit-
uations where only the single 4"BF" character is returned to the appli-
cation.  In this case auto receive is still in force, no data is present
and the message can be ignored.  A break indication (bit 13 in the IO
result word) indicates a timeout has occured, probably because Kermit
at the other end has terminated without warning.

Note that when NDL auto receive is initiated, it will issue an ACK for
a packet of the sequence number specified in the characters following
4"BF".  The sequence number is then incremented, and auto receive ini-
tiated.  Messages then read by the application which start with the
4"BF" auto receive mark need no acknowledgement from the application.
Once a message is read which is not marked with 4"BF", it and subsequent
messages must be acknowledged in the appropriate manner from the appli-
cation unless auto receive is reinitiated.  Auto receive can be re-
initiated, if needed, the same way it is originally initiated.  Remember
that the first action of such an initiation is to send an ACK packet.


THE NDL REQUEST SETS
--- --- ------- ----
Included with this tape are replacement READTELETYPE and WRITETELETYPE
NDL request sets.  These work with unmodified SPEEDSENSE and CONTENTION
controls.  These request sets make heavy use of the DEFINE facility
and a number of defines are also included at the beginning of the file.
Those DEFINEs which precede the READTELETYPE request are common to both
requests and should be placed in your NDL before the first declaration
of a control or request.  Because of the close relationship between
the Kermit protocol and our local Apple file xfer protocol, I have not
attempted to untangle them and have included all of these two request
sets as currently implemented.  This should probably have no effect on
your operation, as the Apple code will only be entered if specifically
requested by use of the WRITE([STOP]) construct and a leading 4"B0" to
4"BE" code, something not likely to accidently occur.  If you desire
cleaner code, or if you have local patches to incorporate, I leave
the task of modifying (and more painfully, testing) the request sets
to you.

I have selected sequence ranges such that the supplied code can be
dropped right in in some empty ranges in the 34PR1 SYMBOL/SOURCENDL.
Be sure to patch out the original READTELETYPE and WRITETELETYPE
requests.

One other important patch which must be made is to change the
declaration of all terminals using the new request sets to specify
CODE = ASCII(BINARY).  As this will vary depending upon the structure
of your NDL, I have not attempted to include any lines of this patch
in the provided file.


THE KERMIT ALGOL PROGRAM
--- ------ ----- -------
As described above, the B6800 Kermit application is written in ALGOL,
handles one file transfer (in either direction) and relies upon
file attribute equation for specification of what to transfer and
the format of the file.  The file to be transfered from or to has
an internal name of FYLE and defaults to KIND=DISK and FRAMESIZE=8.
If MYUSE is INPUT then FYLE will be the source of a file transfer from
the B6800 to your other computer.  If MYUSE is OUTPUT the file transfer
will be from your other computer into FYLE.  TITLE will have to be
set to actual name of the B6800 file involved in the transfer.
You may also want to set NEWFILE to an appropriate value.

If MYUSE is INPUT, setting the DEPENDENTSPECS attribute is usually the
only other attribute equation needed.  It will then allow the system
to set the record and block sizes as appropriate.  Any other relevant
attributes may also be equated as well.

If MYUSE is OUTPUT, you will need to specify MAXRECSIZE and BLOCKSIZE.
By default, these will be in character (byte) units, though the
FRAMESIZE attribute may be used to override this default.  You may
let the system calculate a default AREASIZE or set this attribute
specifically.  Likewise with AREAS.  Of course, you can set any other
attributes as well.

The Kermit protocol specifies that an "F" packet must sent from the
sender to the receiver of a file before file transfer commences.  This
packet is conventionally used to provide the name of the file to trans-
fer to at the receiving end.  When the B6800 is the receiver, the
content of this packet is ignored, relying instead upon file equation
at run time.  When the B6800 is the sender, though, the other computer
will be expecting the "F" packet to contain a file name.  Since the name
used on the B6800 probably differs from the name to be used on the
other computer, this name must also be specified at run time.  The
mechanism for specifying this is through a string parameter to the
program.  This parameter must also be provided when the B6800 serves as
the receiver, but is ignored and may consist of an empty string.

In addition, at the time the Kermit application is run, it may be
placed into monitor mode by specifying a TASKVALUE of 1.  This is
done by the task equation VALUE=1 from CANDE.  Since TASKVALUE defaults
to zero, the TASKVALUE equation needs only to be made when monitor mode
is to be requested.  When in monitor mode, all traffic to the remote
(datacom) file is sent in both character and hex representations to
the printer.  This can be quite useful in debugging situations and
I would reccommend setting it the first few times you run Kermit, both
to check what is going on and to provide a baseline example should you
later encounter trouble or make modifications.

To summarize the syntax for running the Kermit application from CANDE is
as follows:
    To transfer a file to the B6800:
        --- RUN KERMIT(""); ------------------------>
                             !              A
                             --- VALUE=1; --!

        >---FILE FYLE(MYUSE=OUT,MAXRECSIZE=<mrsz>,BLOCKSIZE=<blksz> -->

        >---TITLE=<B6800 file title>, <any other attibutes>   ) ---!

        Where <mrsz> ::= size of a record in characters
              <blksz>::= size of a block in characters
              <B6800 file title> ::= a name for the file to be created
              <any other attributes> ::= any other file attribute
                                         equations which should be used


    To transfer from the B6800:
        --- RUN KERMIT("<destination file name">);------------------>
                                                   !             A
                                                   --- VALUE=1;--!

        >----FILE FYLE(MYUSE=IN,DEPENDENTSPECS,TITLE=<B6800 name> -->

        >----<any other attributes> --- ) -----!

        Where <destination file name> ::= the name of the file to trans-
                                          fer to
              <B6800 name>  ::= the name of the file on the B6800 from
                                which to transfer data.
              <any other attributes> ::= any other file attribute
                                         equations which apply


    For example:

        RUN KERMIT("");VALUE=1;FILE FYLE(MYUSE=OUT,MAXRECSIZE=90,
                        BLOCKSIZE=1800,TITLE="A/NEW/FILE/IS/BORN")

            Will start Kermit receiving a file to be named
            A/NEW/FILE/IS/BORN under your usercode.  Monitor mode
            is requested.


        RUN KERMIT("/usr/randy/junk.file");FILE FYLE(MYUSE=IN,
                    DEPENDENTSPECS,TITLE="(BURRO)JUNK/FILE")

            Will start Kermit sending JUNK/FILE from the BURRO usercode
        to the other computer where it will create a file called
        /usr/randy/junk.file.  Monitor mode is not requested.

The Kermit application is designed for an environment where someone
who wishes to initiate a file transfer to or from the B6800 is at
a terminal connected to a micro or mini computer using the "connect"
facility of Kermit, or some other terminal program to allow logging
on to the B6800 and initiating Kermit on the B6800.  Once initiated,
Kermit will verify the file attributes specified and if no error is
found, Kermit will open its remote file and send a DEL character to
indicate that it is up and running.  If an attribute error is found
or if for some other reason Kermit finds that it cannot perform the
requested transfer, Kermit will send a message describing the error
followed by a NAK character.  Using a terminal program (or Kermit
"connect") the user would have to wait while the B6800 started its
Kermit until seeing CANDE return the "?#" indication that it has
opened a remote file, and then waiting briefly to see if any error
messages are sent before terminating the terminal connection and
initiating their local Kermit.  I have included the source for a program
which does that waiting.  It sends the text of all messages received
from the B6800 to default output (presumably the operator's terminal)
until B6800 Kermit send either a DEL or a NAK, at which point the program
terminates.  The source for this program, waitkerm.c can be found in 
Appendix C.

I have also included a XENIX shell which allows a user to initiate any
number of Kermit transfers to/from the B6800.  It forms the proper
CANDE RUN statement, sends it to CANDE and then uses waitkerm to wait
for B6800 Kermit to signal its presence.  The shell will then fire off
a local Kermit to communicate with B6800 Kermit.  I would suggest that
you use it, or a similar shell or program to similarly isolate the user
from the complexities of the interface, or at least to reduce the volume
of typing necessary to get things going.

Because the B6800 expects lines entered from a terminal to terminate with
a CR, rather than a newline, the ECHO command doesn't work.  The source for
a simple echo program which emits a CR rather than a NL is included in 
Appendix B.  It produces a program called crend, which is used in many places
in the inclulded shell.

If B6800 Kermit encounters an error that it cannot resolve, it will send
an "E" packet before terminating.  The "E" packet will contain a
description of the error encountered.  Not all Kermits display the
text contained in an "E" packet, but I would reccommend adding that
capability so you can be aware of what happened if B6800 Kermit decides
to abandon you.

I have included only the source for the Kermit application.  If you
wish to use it as is, it requires only a simple ALGOL compile.  No
unusual task or file equations are needed at compile time.

APPENDIX A.   
-------- -
Kersh, a UNIX shell for initiating Kermit transfers to/from a B6800:

tty=/dev/tty5
speed=1200
setmode $tty $speed &

trap " " 2
trap " " 3
echo A program to dial the B6800 was initiated at this point
echo Wait for the B6800 to respond, then log on, and then hit control-c
kermit cle $tty 3

while test "$RESPONSE" != "q"
do
    echo '(s)end, (r)eceive, (c)onnect or (q)uit?'
    read RESPONSE

    case $RESPONSE in
 	Q)      
            RESPONSE="q"
            ;;
	d|D)
	    echo 'set debug on(+) or off(-)?'
	    read DEBUG
	    if test "$DEBUG" = on
		then DEBUG="+"
	    fi
	    ;;
	c|C)
	    echo Connecting to remote system.
	    echo Type control-c to return to local system.
	    kermit cle $tty 3
	    ;;
	s|r|S|R)
            case $RESPONSE in
                    s|S)    echo Enter name of local file to send
		            read LOCNAME
			    echo  Enter name of file to create remotely
 			    read RMTNAME
			    echo What is the maximum record size?
			    read MAXRSZ
			    echo What is the block size to be?
			    read BLKSZ
			    echo Enter any other attributes for destination file

			    read ATTB
			    echo -n 'R KERMIT("");' >$tty
			    if test "$DEBUG" = +
			    then echo -n "VALUE=1;" > $tty
			    fi
			    echo -n 'FILE FYLE(MYUSE=OUT,MAXRECSIZE=' >$tty   
			    echo -n "$MAXRSZ, BLOCKSIZE= $BLKSZ" >$tty
			    echo -n ',TITLE=' "$RMTNAME" > $tty
			    if test "$ATTB" != ""
			    then   echo -n ", $ATTB" > $tty
			    fi 
			    crend ')' > $tty
			    ;;
	          R|r)      echo Enter name of remote file to copy
		            read RMTNAME
			    echo Enter name of file to create locally  
			    read LOCNAME
			    echo Enter any other attributes for the remote file
			    read ATTB
			    echo -n "R KERMIT(\"$LOCNAME\");" > $tty
			    if test "$DEBUG" = +
			    then echo -n "VALUE=1;" > $tty
			    fi
			    echo -n 'FILE FYLE(MYUSE=IN,'  > $tty
			    echo -n 'DEPENDENTSPECS,TITLE=' > $tty
			    echo -n "$RMTNAME" > $tty
			    if test "$ATTB" != ""
			    then echo -n ", $ATTB" > $tty
			    fi
			    crend ')' > $tty
			    ;;
		*)	    ;;
	    esac

	    echo Waiting for kermit on the remote system.
	    if waitkerm $tty
	    then
	        case $RESPONSE in
	       	    r|R) kermit rldm $tty 
		    ;;
		    s|S) kermit sld $tty $LOCNAME
		    ;;
	        esac

	        crend > $tty
	        crend ?END > $tty
	    else echo
	    fi
	    ;;
	*)  ;;
    esac

done

echo -n terminating
crend > $tty
echo -n '.'
sleep 2 
crend '?END' >$tty
echo -n '.'
sleep 2 
crend SA REC >$tty
echo -n '.'
sleep 2 
crend BYE >$tty
echo -n '.'
kill -9 `ps -a|grep tty5|grep setmode|awk '{print $1}'`
stty 0 >$tty
echo


APPENDIX B.
-------- --
crend-- an echo program which terminates a line with a CR instead of a NL:

main (argc,argv)
int argc;
char *argv[];
  {
    while (--argc>0)
    	printf("%s%c",*++argv,(argc>1)?' ':'\r');
  }


APPENDIX C.
-------- -
waitkerm-- a program which waits for B6800 Kermit to start functioning:

/* This program waits for the B6800 Kermit program to come up and signal
   that it is ready.  It will normally return zero but will return a non-
   zero value if B6800 Kermit did not properly begin.

   The name of the line to the B6800 is specified in the command line following
   waitkerm.

   For example, to wait for kermit to come up on a B6800 connected thru a modem
   which is connected to the TTY5 port:
	waitkerm /dev/tty5
*/
#include <stdio.h>
#include <signal.h>
#include <sgtty.h>
struct sgttyb termio;

main(argc,argv)  
    int argc;
    char **argv;
{
    int cflag, fd;
    char c, getone();
    int failure(), success();

    signal(SIGHUP, failure);
    signal(SIGINT, success);
    setbuf(stdin,(char *)0);
    setbuf(stdout,(char *)0);
    setbuf(stderr,(char *)0);  

    if ((fd = open (*++argv,2)) < 0) {
	printf("Can't open %s\n",*argv);
	exit(1);
    }
    ioctl(fd,TIOCGETP,&termio);  /* get the terminal io structure */
    termio.sg_flags &= ~(ECHO | CRMOD);  /* turn off echo and crmod modes */
    termio.sg_flags |= CBREAK;  /* return each character as soon as typed */
    ioctl(fd,TIOCSETP,&termio);

    while (c != '\177') {
	read(fd,&c,1);
	if (c == '\025') failure();
        putchar(c);
    }
    exit(0);     
}
success()
{
    exit(0);
}
failure()
{
    exit(1);
}