home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / d / cray.cft < prev    next >
Text File  |  2020-01-01  |  100KB  |  2,618 lines

  1. !-cr.filing-!
  2.       subroutine makedata(seq, result)
  3.       implicit integer(a-z)
  4.       ! Function : This routine is called from the SEND state to make
  5.       !            a new 'D' packet. It gets file data from the character
  6.       !            buffer, calling the virtual disk read routine BUFIN
  7.       !            whenever the buffer is empty. Logical Rtne. BUFIN
  8.       !            evaluates .false. iff a disk read fails; it sets
  9.       !            its second argument .true. iff the current buffer
  10.       !            contains the EOF indicator. Makedata converts CTSS
  11.       !            EOL characters to quoted CR,LF sequences, and other
  12.       !            embedded file control characters to the standard
  13.       !            Kermit quoted/controlified sequences.
  14.       !  Called Procedures : bufin, errorpkt, kctl, kchar
  15.  
  16.       parameter( full = 0, lastpkt = 1, nopkt = 3, err = 4)
  17.       parameter( US = 037b, FS = 034b, SOH = 1, CR=13, LF=10)
  18.       parameter( px = 1, ok = 0 )
  19.       parameter( rpmax = 94, cutoff = 4 )
  20.       logical bufin, last, lastbuf, debug, native, quote8, repeat
  21.  
  22.       character *504 buffer
  23.       character *104 packet(2)
  24.       character cmdstr*80, report*40
  25.       character kchar, cksum, quote, kctl, pchar, old
  26.       character eolseq*4, pktseq*6
  27.       character*9 myparms, hisparms, defaults
  28.  
  29.       common /packets/ packet
  30.       common /buffers/ buffer
  31.       common /pkstats/  bptr, bufhold, maxpack, lastbuf, rpcount
  32.       common /runparms/ myparms, hisparms, defaults
  33.       common /strings/ cmdstr, report
  34.       common /environ/ debug, native, quote8, repeat
  35.  
  36.       pkptr = 5                          !  pt to 1st data char in pkt
  37.       quote = myparms(6:6)             !  quote char to send
  38.       eolseq = quote//kctl(char(CR))
  39.      !         // quote // kctl(char(LF))
  40.       if (rpcount.gt.0) then             ! remnant left from last pkt
  41.         old = buffer(bptr-1:bptr-1)      !  repeated char for comparison
  42.       end if
  43.  
  44. 10    continue                           !  top of packing loop
  45.       if (bptr.gt.bufhold)  then         !  buffer empty
  46.         if (rpcount.gt.0) then           !  we are in a run
  47.           ! Truncate run at end of buffer
  48.           bptr = bptr - 1                !  index last char of run
  49.           go to 100                      !  put remnant in pkt first
  50.         else if (.not.(lastbuf))then     !  there's file data left
  51.           !  use next test to force evaluation of read fn :
  52.           if (.not.(bufin(buffer,last))) then
  53.             report = 'file read error.'
  54.             result = err
  55.             go to 900                    !  exit with the bad news
  56.           else if (last) then            !  this evaluation got last chunk
  57.             lastbuf = .true.             !  remember this
  58.           end if
  59.         else if (pkptr.gt.5) then        !  final packet a shorty
  60.           result = lastpkt
  61.           go to 400                      !  go polish it off now
  62.         else                             !  starting pkt - no data to pack
  63.           result = nopkt
  64.           go to 900                      !  go return with this news now
  65.         end if
  66.       end if                             !  if buffer empty
  67.       pchar = buffer(bptr:bptr)          !  get next buffer char
  68.       if (repeat)  then                  !  we're doing repeat prefixing
  69.         if (rpcount.eq.0) then           !  start a new scope
  70.           old = pchar
  71.           rpcount = 1
  72.           bptr = bptr + 1
  73.           go to 10                       !  go get next data character
  74.         else if (pchar.eq.old) then      !  old scope continues
  75.           rpcount = rpcount + 1
  76.           if (rpcount.lt.rpmax) then
  77.             bptr = bptr + 1
  78.             go to 10
  79.           end if                         !  else truncate here
  80.         else                             !  pchar ends old scope
  81.           bptr = bptr - 1                !  index last char of run
  82.         end if                           !  if rpcount
  83.       else                               !  we're not doing repeats
  84.         old = pchar
  85.         rpcount = 1
  86.       end if
  87.  
  88. 100   continue
  89.       savect = rpcount
  90.       !  First look for the special cases :
  91.       if ((native).and.(old.eq.char(FS))) then
  92.         if (pkptr.gt.5) then             !  EOF found - truncate pkt
  93.           result = lastpkt
  94.           go to 400
  95.         else                             !  starting pkt  & hit EOF
  96.           result = nopkt
  97.           go to 900
  98.         end if
  99.       else                               !  these are the std cases
  100.         j = 1                            !  minimum length we need
  101.         !  Does char need a repeat prefix ?
  102.         if ((repeat).and.(rpcount.ge.cutoff)) then
  103.           pktseq(j:j+1) = '~' //kchar(rpcount)
  104.           j = j+2
  105.           rpcount = 1
  106.         end if                         !  if repeat prefixed
  107.         if ((quote8).and.(ichar(old).ge.200b)) then
  108.           pktseq(j:j) = '&'
  109.           old = char(ichar(old).and.177b)
  110.           j = j +1
  111.         else if ((native).and.(old.eq.char(US))) then
  112.           ! we have to convert this to std text EOL sequence
  113.           pktseq(j:j+3) = eolseq
  114.           j = j+3
  115.           go to 120
  116.         end if                           !  if 8th bit prefixing
  117.         !  now encode lo-order 7 bits of the char, if needed
  118.         if ((ichar(old).gt.037b).and.(old.ne.char(177b))
  119.      !   .and.(old.ne.quote)
  120.      !   .and.((old.ne.'&').or.(.not.(quote8)))
  121.      !   .and.((old.ne.'~').or.(.not.(repeat))) )
  122.      !  then                             ! it needs no quoting
  123.           pktseq(j:j) = old
  124.         else
  125.           pktseq(j:j) = quote
  126.           if ((old.ne.quote).and.(old.ne.'&').and.(old.ne.'~'))
  127.      !    then                           !  transform the quoted char
  128.             old = kctl(old)
  129.           end if
  130.           j = j + 1
  131.           pktseq(j:j) = old
  132.         end if
  133.       end if                             !  end of all char cases
  134.  
  135. 120   continue
  136.       do 170 i=1,rpcount
  137.         seqend = pkptr + j - 1
  138.         if (seqend.le.maxpack) then        !  there's room
  139.           packet(px)(pkptr:seqend) = pktseq(1:j)
  140.           pkptr = seqend + 1
  141.         else                             ! coded char wont fit in pkt
  142.           if (savect.ge.cutoff) then    ! it was repeat prefixed
  143.             rpcount = savect - 1
  144.           else if (rpcount.gt.1) then   !  it was a mini-run
  145.             bptr = bptr - (savect-i)     ! index first excluded char
  146.             rpcount = 0                  ! and let it start new scope
  147.           else
  148.             rpcount = 0
  149.           end if
  150.           go to 200
  151.         end if                           !  if room
  152. 170   continue
  153.  
  154.        rpcount = 0
  155.        bptr = bptr + 1
  156.        if(pkptr.le.maxpack) go to 10
  157.  
  158. 200   result = full
  159.  
  160. 400   continue
  161.       packet(px)(2:2) = kchar(pkptr-2)   !  coded count
  162.       packet(px)(3:3) = kchar(mod(seq,64))
  163.       packet(px)(4:4) = 'D'
  164.       packet(px)(pkptr:pkptr) = cksum(packet(px))
  165.  
  166. 900   continue
  167.       return
  168.       end                                !  subroutine makedata
  169.  
  170.  
  171.       subroutine putdata(px,result)
  172.       implicit integer(a-z)
  173.       ! Function : This routine is called in the RECEIVE state to
  174.       !            process a 'D' packet.  It packs the data portion
  175.       !            of a 'D' pkt into the character buffer, replacing
  176.       !            quoted and/or prefixed sequences if necessary.
  177.       !            If file is CTSS native, quoted CR,LF sequences are
  178.       !            stored as the single ctss EOL character, Ascii US.
  179.       !            Evaluation of logical function bufout forces transfer
  180.       !            of contents of character buffer into the sector-sized
  181.       !            word buffer dkbuf which is managed by bufout.
  182.       !  Called Procedures : kctl, unchar, bufout
  183.  
  184.       parameter( CR=015b, LF =012b, US = 037b )
  185.       parameter( buflen = 504 )          !  bufsize = max char string
  186.       parameter( ok=0, error=1 )         !  putdata return codes
  187.  
  188.       character *504 buffer
  189.       character*104 packet(2)
  190.       character*9 myparms, hisparms, defaults
  191.       character  kctl, quote, qchar, pchar
  192.       logical bufout, eofsw, hibit, debug, native, quote8, repeat
  193.      !        ,lastbuf, savedcr
  194.  
  195.       common /runparms/ myparms, hisparms, defaults
  196.       common /packets/ packet
  197.       common /buffers/ buffer
  198.       common /pkstats/  bptr, bufleft, maxpack, lastbuf
  199.      !                , rpcount, savedcr
  200.       common /environ/ debug, native, quote8, repeat
  201.  
  202.       quote = hisparms(6:6)              !  get partner's quote char
  203.       eofsw = .false.
  204.       hibit = .false.
  205.       pkptr = 5                         !  index 1st data char
  206.       pkend = unchar(packet(px)(2:2)) + 1 !  index last data char
  207. 10    continue                           !  top of packing loop
  208.       if (pkptr.gt.pkend) then           !  Reached end of packet
  209.         result = ok
  210.         go to 800
  211.       end if
  212.       pchar = packet(px)(pkptr:pkptr)    !  Get next packet character
  213.       !  Check for repeat prefix
  214.       if ((repeat).and.(pchar.eq.'~')) then
  215.         pkptr = pkptr + 1                !  Index count char
  216.         count = unchar(packet(px)(pkptr:pkptr))
  217.         pkptr = pkptr + 1
  218.         pchar = packet(px)(pkptr:pkptr)
  219.       else
  220.         count = 1
  221.       end if                             !  if repeat
  222.       if ((quote8).and.(pchar.eq.'&')) then
  223.         hibit = .true.
  224.         pkptr = pkptr + 1                !  Index prefixed character
  225.         pchar = packet(px)(pkptr:pkptr)
  226.       else
  227.         hibit = .false.
  228.       end if                             !  If 8th bit quoting
  229.       if (pchar.eq.quote)  then      !  Character is quoted ctl
  230.         pkptr = pkptr + 1            !  Index the quoted character
  231.         pchar = packet(px)(pkptr:pkptr)
  232.         if ((pchar.ne.quote).and.(pchar.ne.'&').and.(pchar.ne.'~'))
  233.      !  then
  234.           pchar = kctl(pchar)            !  Transform quoted character
  235.         end if
  236.       end if                             !  If quoted sequence
  237.       if (hibit) then                    !  Char had an 8th bit prefix
  238.         pchar = char(ichar(pchar).or.200b)
  239.       else if ((native).and.(count.eq.1)) then
  240.         ! Map incoming CR,LF sequences to CTSS end-of-line char
  241.         if ((pchar.eq.char(LF)).and.(savedcr)) then
  242.           pchar = char(US)               !  Replace by native EOL char
  243.           savedcr = .false.
  244.         else if (savedcr) then           !  Previous CR not in a sequence
  245.           pchar = char(CR)
  246.           savedcr = .false.
  247.           pkptr = pkptr - 1              !  Pick up current char nxt time
  248.         else if (pchar.eq.char(CR)) then
  249.           savedcr = .true.
  250.         end if
  251.       end if
  252.       if (.not.(savedcr))  then          !  Put char into buffer
  253.         do 40 i=1,count
  254.           if (bptr.gt.buflen)  then      !  Need to empty buffer first
  255.             if (.not.(bufout(buffer,eofsw))) then
  256.               result = error
  257.               go to 800
  258.             end if
  259.           end if
  260.           buffer(bptr:bptr) = pchar      !  Put pkt char into buffer
  261.           bptr = bptr + 1
  262. 40      continue
  263.       end if
  264.       pkptr = pkptr + 1
  265.       go to 10                           !  Bottom of unpacking loop
  266.  
  267. 800   continue
  268.       return
  269.       end                          !  subroutine putdata
  270.  
  271.  
  272.       logical function puteof(usrfil)
  273.       implicit integer(a-z)
  274.       ! Function : This routine is called in the RECEIVE state to
  275.       !            process a 'Z' packet.  It terminates CTSS native but not
  276.       !            other, files with an Ascii FS character,  and
  277.       !            evaluates the logical function bufout with 2nd arg
  278.       !            set .true. to force a write of the last sector now.
  279.       !            If user's filespace has an old copy of the receive file,
  280.       !            this copy is destroyed before switching receive file's
  281.       !            name from the interim 'kmtfil' to name in 'F' pkt.
  282.       !  Called Procedures : bufout, logline, kfdelete, kfswitch
  283.  
  284.       parameter( buflen = 504 )          !  max length character string
  285.  
  286.       character dum1*4                   ! debuggery
  287.       logical debug, native
  288.       character kchar
  289.       character *504 buffer
  290.       character cmdstr*80
  291.       logical oldfile, bufout, kfdelete, kfswitch
  292.       parameter( NULL = 0, FS = 034b, US = 037b )
  293.  
  294.       common /buffers/ buffer
  295.       common /pkstats/  bptr, bufleft
  296.       common /strings/ cmdstr
  297.       common /environ/ debug, native
  298.  
  299.       dimension beta(4)
  300.  
  301.       if (native) then             !  File needs CTSS EOF terminator
  302.         if (bptr.gt.buflen) then   !  Buffer already full
  303.           if(.not.(bufout(buffer,.false.))) go to 300
  304.         end if                     !  else evaluation emptied buffer
  305.         buffer(bptr:bptr) = char(FS)
  306.         bptr = bptr + 1
  307.       end if
  308.       nx = mod(bptr-1,8)           !  Index last byte used in final word
  309.       if (nx.ne.0)  then           !  Pad out last word with nulls
  310.         wdend = bptr + 7 - nx
  311.         do 200 i=bptr,wdend
  312.           buffer(i:i) = char(NULL)
  313. 200     continue
  314.         bptr = wdend + 1
  315.       end if
  316.       if (bufout(buffer,.true.)) then    !  final write succeeeds
  317.         !  see if we are replacing an existing copy
  318.         inquire(iostat=ios,file=cmdstr(1:8),exist=oldfile)
  319.         if (ios.eq.0)  then
  320.           if (oldfile) then
  321.             call logline('old file copy exists$$')
  322.             if (.not.(kfdelete(usrfil))) go to 300
  323.           end if                         !  if oldfile
  324.           if (kfswitch(usrfil))  then    !  if std file renemed ok
  325.             puteof = .true.
  326.             go to 400
  327.           end if                         !  if kfswitch
  328.         end if                           !  if ios
  329.       end if                             !  if bufout
  330. 300   puteof = .false.
  331. 400   continue
  332.       return
  333.       end                                !  logical fn puteof
  334.  
  335.  
  336.       logical function bufin(string,last)
  337.       implicit integer(a-z)
  338.       ! Function : This is a virtual disk read routine.
  339.       !            It packs 63 words from the sector-sized buffer dkbuf
  340.       !            into the buffer used as caller's first argument.
  341.       !            BUFIN resets the string pointers bptr and bufhold.
  342.       !            When dkbuf is empty, BUFIN evaluates the logical
  343.       !            function KFREAD to force a physical disk sector read.
  344.       !            Upon return from BUFIN, the parameter LAST is true
  345.       !            iff current string is the last of the file.
  346.       ! Called Procedures : kfread.
  347.       !            .
  348.       parameter( fs = 034b )
  349.       dimension string(63)               !  treat 504 char buf as 63 words
  350.       dimension dkbuf(512)               !  sector-sized buffer
  351.       logical dkempty, kfread, last
  352.  
  353.       common /units/ logioc, fioc, dkctr, dkbuf, nsectors
  354.      !              ,fptr, dkptr, dkhold
  355.       common /pkstats/  bptr, bufhold
  356.  
  357.       place = 1                          !  Index 1st word of string
  358. 10    continue
  359.       dkempty = .false.
  360.       do 20 i=place,63
  361.         if (dkptr.gt.dkhold)  then
  362.           dkempty = .true.
  363.           go to 40
  364.         else
  365.           string(i) = dkbuf(dkptr)       !  put a word into string
  366.           dkptr = dkptr + 1              !  Index next sector word
  367.         end if
  368. 20    continue
  369. 40    if (.not.(dkempty))  then          !  String is full
  370.         sx = 63
  371.       else if (dkctr.eq.nsectors) then   !  Exhausted last sector
  372.         sx = i - 1                       !  Index last string word used
  373.       else if (.not.(kfread())) then     !  Forced sector read failed
  374.         bufin = .false.
  375.         go to 800
  376.       else                               !  Sector buffer replenished
  377.         place = i                        !  Index next string word
  378.         go to 10                         !  Go continuing filling string
  379.       end if
  380.       bptr = 1                           !  Point to start of string
  381.       bufhold = sx*8                     ! Num. bytes in string
  382.       !  Is this the last string of the file ?
  383.       if ((sx.eq.63).and.((dkctr.lt.nsectors).or.(dkptr.le.dkhold)))
  384.      !then
  385.         last = .false.
  386.       else
  387.         last = .true.
  388.       end if
  389.       bufin = .true.
  390. 800   continue
  391.       return
  392.       end                                !  logical function bufin
  393.  
  394.       logical function bufout(string,eof)
  395.       implicit integer(a-z)
  396.       ! Function : This is a virtual disk write routine that packs the
  397.       !            contents of the caller's buffer into the 512-word sector
  398.       !            buffer dkbuf.  Caller's buffer is assumed to be at most
  399.       !            504 characters long (the maximum CFT string), with bptr
  400.       !            indexing  past the last position used, and is treated as
  401.       !            an array of 63 words.  When dkbuf is full, or if entered
  402.       !            with eof argument .true., kfwrite is called to do the
  403.       !            physical disk write.
  404.       ! Called Procedures : kfwrite, kfprune, logline, tdisp
  405.       logical eof, dkfull, kfwrite
  406.       parameter( buflen = 504 )          !  max num. chars in string
  407.       parameter( sector = 512 )
  408.       logical debug
  409.  
  410.       common /pkstats/  bptr, bufhold
  411.       common /units/ logioc, fioc, dkctr, dkbuf(sector), nsectors,
  412.      !             fptr, dkptr, dkhold
  413.       common /environ/ debug
  414.  
  415.       character*4 dum1
  416.       dimension string(63)               !  treat 504 chars as 63 words
  417.  
  418.       nchar = bptr - 1                   !  num. chars in string
  419.       nwords = nchar/8                   !  num. words in string
  420.       dkfull = .false.
  421.       do 20 i=1,nwords
  422.         if(dkptr.gt.sector)  then
  423.           dkfull = .true.
  424.           go to 30
  425.         else
  426.           dkbuf(dkptr) = string(i)
  427.           dkptr = dkptr + 1
  428.         end if
  429. 20    continue
  430.       !  see if string fit into dkbuf
  431. 30    if (dkfull)  then                  !  it didn't
  432.         if (kfwrite(sector))  then  !  wrote dkbuf to disk
  433.           do 50 j=i,nwords               !  put string remnant in new buf
  434.             dkbuf(dkptr) = string(j)
  435.             dkptr = dkptr + 1
  436. 50        continue
  437.         else                             !  if write failed
  438.           bufout = .false.
  439.           go to 400
  440.         end if                           !  if kfwrite
  441.       end if                             !  if dkfull
  442.       bufout = .true.                       !  Default evaluation
  443.       if (.not.(eof))  then
  444.         bptr = 1                            !  indicate string empty
  445.         bufhold = buflen
  446.       else                                  !  Write final partial sector
  447.         nsiz = dkptr - 1                !  num. words in last sector.
  448.         if(kfwrite(nsiz)) then
  449.           fwords = (dkctr-1)*sector + nsiz     !  real file size in words
  450.           call kfprune(fwords)              !  make file size exact
  451.           if (debug) then
  452.             call tdisp(fwords,dum1)
  453.             call logline('At EOF - file size is : '//dum1//' words$$')
  454.           end if
  455.         else
  456.          bufout = .false.
  457.         end if                           !  if kfwrite
  458.       end if                             !  if eof
  459. 400   continue
  460.       return
  461.       end                                !  logical fn bufout
  462. !-cr.kermain-!
  463.       !  Kermit-CR  -  LANL Cray Kermit
  464.       !
  465.       !  Author :  Leah Miller,
  466.       !            Computer User Services Group (C-10)
  467.       !            Los Alamos National Laboratory
  468.       !            Los Alamos, New Mexico  87545
  469.       !
  470.       !            Arpanet address :  lfm@lanl
  471.       !
  472.  
  473.       !*******************************************************************
  474.       !  Copyright, 1984, The Regents of the University of California.
  475.       !  This software was produced under a U.S. Government contract
  476.       !  (W-7405-ENG-36)  by the Los Alamos National Laboratory, which is
  477.       !  operated by the University of California for the U.S. Department
  478.       !  of Energy.  The U.S. Government is licensed to use, reproduce and
  479.       !  distribute this software.  Permission is granted to the public to
  480.       !  copy and use this software without charge, provided that this notice
  481.       !  and any statement of authorship are reproduced on all copies.
  482.       !  Neither the Government nor the University makes any warranty,
  483.       !  express or implied, or assumes any liability or responsibility
  484.       !  for the use of this software.
  485.       !*******************************************************************
  486.  
  487.       !  Acknowledgement :  The Kermit Protocol was developed by the
  488.       !                     Columbia University Center for Computing
  489.       !                     Activities (CUCCA),  N.Y., N.Y., USA
  490.  
  491.       !    Kermit-CR runs on the Cray-1 and Cray X-MP computers, under
  492.       !  the CTSS (Cray Time-Sharing System) Operating System.
  493.       !  It is written in CFT, the Cray version of Fortran-77.
  494.       !  All input/output functions are done by invoking CTSS operating
  495.       !  system functions from low level Fortran subroutines.
  496.       !
  497.       !    Kermit-CR is a remote host Kermit.  It has a server
  498.       !  and can time out.  File transfer interrupt  packets from
  499.       !  local Kermits are recognized.  Default file transfer
  500.       !  mode is CTSS native text.  In this mode the single character
  501.       !  CTSS end-of-line indicator (Ascii US) is converted to
  502.       !  the standard quoted CR,LF sequence on sends, and vice-versa
  503.       !  on receives.  If this option is disabled by user's command
  504.       !  "set native off", only the standard Kermit quoting of control
  505.       !  characters is done.  Binary files may be transferred via 8th bit
  506.       !  quoting if the local Kermit also has this capability.
  507.       !  Data compression via repeat prefixing will be done if the other
  508.       !  Kermit agrees.
  509.       !  Wildcard sends are not done, but more than one file may be
  510.       !  specified on a send command (non-server mode).
  511.       !  The Kermit-CR server cannot log itself it, so that a local
  512.       !  Kermit's "finish" or "bye" command will cause exit from
  513.       !  Kermit-CR and return to the CTSS level.
  514.       !
  515.       !    Installers should note that Cray-1 and Cray X-MP, under CTSS,
  516.       !  accept line, not character, input.  Network line concentrator
  517.       !  hardware may impose a maximum message length of less than
  518.       !  the maximum Kermit packet length.  This hardware may also perform
  519.       !  echoback of terminal messages.  If the local Kermit does not
  520.       !  check incoming packet type (and ignore packets of type just sent),
  521.       !  then the local Kermit may use appropriate PAD and EOL characters
  522.       !  to disable concentrator echoback.
  523.       !  Site Dependancy : Some network line concentrators are unable to
  524.       !                    keep up with the data rate of a SENDing local
  525.       !                    Kermit unless echoback is disabled.  [lfm 1/85]
  526.  
  527.       program kermit(input=tty,output=tty)
  528.       implicit integer(a-z)
  529.  
  530.       !  Function :  This is the main Kermit-CR program.
  531.       !              Session initialization is forced via evaluation
  532.       !              of the logical function KINIT, and the programs enters
  533.       !              a command loop:  user's input command is accepted
  534.       !              by subroutine READCMD, validated & parsed into tokens
  535.       !              by KPARSE, and the appropriate command interpreter is
  536.       !              invoked.  Exit from loop occurs when user types the
  537.       !              exit command, or when the Kermit-CR Server enters exit
  538.       !              mode in response to local Kermit's 'finish', 'bye'  or
  539.       !              'logout' packet.
  540.       !  Called Procedures :  kinit, prompt, logline, readcmd, kparse,
  541.       !                       display.  Also these cmd interpreters :
  542.       !                         kserv, ktrans, krecv, kset, kstatus,
  543.       !                         khelp and kclose.
  544.  
  545.       character *80 cmdstr
  546.       character *40 report
  547.  
  548.       logical kparse, kinit
  549.       logical debug, done
  550.  
  551.       common /strings/ cmdstr, report
  552.       common /states/ state, retry, ntries, oldtries, seq
  553.      !              , delay, stdelay,tcpu, tio
  554.       common /globals/ runtype, nargs, args(10,2), thisarg
  555.  
  556.       parameter(send=1, receive = 2, help = 3, exitype = 4, server = 5 )
  557.       parameter(set = 6, status = 7 )
  558.       parameter( init = 1, abort = 6, complete = 7 )
  559.       parameter( wait = 0 )
  560.  
  561.       ! main proc. rtne.
  562.       print *,'  LANL Cray Kermit Release 2.1'
  563.       !  Evaluate initialization function :
  564.       if (.not.(kinit()))  then
  565.         print *,' cant initialize - bye.'
  566.         go to 900       ! can't initialize
  567.       end if                             !  else session initialized
  568.       done = .false.
  569. 120   continue                           !  Top of command loop
  570.       call prompt('Kermit-CR>.')         ! prompt user
  571.       call readcmd(strad(cmdstr),cmdlen) ! get user's cmd & its length
  572.       if (cmdlen.gt.0) then
  573.         call logline(cmdstr(1:cmdlen)//'$$')
  574.       else                               !  it's a bare CR
  575.         go to 120                        !  Ignore it - reissue prompt
  576.       end if                             ! if user typed a command
  577.       if (kparse()) then
  578.         go to 200                        ! valid cmd
  579.       else                               !  kparse provides report
  580.         call logline(report)
  581.         call display(report)
  582.         call display( 'type help for menu.')
  583.         go to 120
  584.       end if
  585. 200   continue     ! kparse has parsed a valid cmd
  586.       if (runtype .eq. server) then
  587.           call kserv                     !  start Server loop
  588.           call kclose                    !  shut log file
  589.           done = .true.                  !  tell Kermit to exit
  590.       else if ( runtype .eq. send ) then
  591.           call ktrans
  592.       else if (runtype .eq. receive) then
  593.           state = init                   !  initialize non-server xfer
  594.           call krecv
  595.       else if (runtype .eq. help) then
  596.           call khelp
  597.       else if (runtype .eq. exitype) then
  598.           call kclose
  599.           done = .true.
  600.       else if (runtype .eq. set) then
  601.         call kset
  602.       else if (runtype .eq. status) then
  603.         call kstatus
  604.       else
  605.           call logline('cmd parse error.$$')
  606.       end if
  607.  
  608.       if (.not.(done)) go to 120         !  Bottom of command loop
  609. 900   continue
  610.       call exit
  611.       end     ! kermit main program
  612.  
  613.  
  614.       logical function kparse()
  615.       ! scans user's input line in cmdstr for valid cmd type;
  616.       ! if cmd = (server, status, receive, help, exit) :
  617.       !                            sets runtype, returns .true.
  618.       ! if cmd = (send, set)     : sets runtype, sets nargs <= num.args.,
  619.       !                            args(i,1) <= index of start ith argument
  620.       !                                        in input command string,
  621.       !                            args(i,2) <= index  last char of ith arg.
  622.       ! else  rturns .false.
  623.       ! Called Procedures : none
  624.  
  625.       implicit integer(a-z)
  626.       character *80 cmdstr
  627.       character *40 report
  628.       common /strings/ cmdstr, report
  629.       common /globals/ runtype, nargs, args(10,2), thisarg
  630.  
  631.       parameter( send=1, receive=2, help=3, exitype=4, server = 5 )
  632.       parameter( set = 6, status = 7 )
  633.       parameter( cr = 13 )
  634.  
  635.       nargs = 0
  636.       ! look for cmd type
  637.       if ( cmdstr (1:6) .eq. 'server' ) then
  638.         runtype = server
  639.         go to 800
  640.       else if (cmdstr(1:3).eq.'set') then
  641.         runtype = set
  642.       else if (cmdstr(1:2).eq.'st') then
  643.         runtype = status
  644.         go to 800
  645.       else if (cmdstr (1:1) .eq. 's' ) then
  646.         runtype = send
  647.       else if ( cmdstr (1:1) .eq. 'r' ) then
  648.         runtype = receive
  649.         go to 800
  650.       else if ( (cmdstr (1:1) .eq. 'h').or.(cmdstr(1:1).eq.'?')) then
  651.         runtype = help
  652.         go to 800   ! no args to scan
  653.       else if ( cmdstr (1:1) .eq. 'e' ) then
  654.         runtype = exitype
  655.         go to 800
  656.       else
  657.         report = 'invalid cmd type:' // cmdstr(1:1) //'.'
  658.         kparse = .false.
  659.         go to 900
  660.       end if
  661.       ! find end of cmd arg
  662.       i = 1
  663. 20    continue
  664.       i = i + 1
  665.       if (cmdstr (i:i) .eq. ' ') go to 30
  666.       if ( i .ge. 8 ) go to 700    ! error : arg too long
  667.       go to 20
  668.       ! find start of next arg : skip past blanks
  669. 30    continue
  670.       if ( i .ge. 80 ) go to 780   ! there are no more args
  671.       i = i + 1
  672.       if ( cmdstr (i:i) .eq. ' ') go to 30   ! loop til nonblank
  673.       ! else current char marks start of nxt argument
  674.       nargs = nargs + 1
  675.       if (nargs .gt. 10) go to 600    ! error : too many args
  676.       args(nargs,1) = i     ! save starting position
  677.       ! find end of current aerg
  678. 40    continue
  679.       i = i + 1
  680.       if ((cmdstr(i:i) .eq. ' ') .or. (cmdstr(i:i) .eq. char(cr)))
  681.      !    go to 50
  682.       if ( (i-args(nargs,1)) .ge. 8 ) go to 700  ! too long
  683.       go to 40             ! loop til term delimiter found
  684. 50    continue
  685.       args(nargs,2) = i - 1
  686.       if (cmdstr (i:i) .eq. ' ') go to 30    ! if blank was delimiter
  687.       go to 880                              ! if  delimiter
  688. 600   continue
  689.       report = 'more than 10 args.'
  690.       kparse = .false.
  691.       go to 900
  692. 700   continue
  693.       report = 'arg length exceeds 8:' // cmdstr(args(nargs,1):i)//'.'
  694.       kparse = .false.
  695.       go to 900
  696. 780   continue
  697.       if (nargs .eq. 0) then
  698.         report = 'no arguments.'
  699.         kparse = .false.
  700.         go to 900
  701.       end if
  702.  
  703. 800   continue
  704. 880   continue
  705.       kparse = .true.
  706. 900   return
  707.       end       ! logical function kparse
  708.  
  709.  
  710.       logical function kinit()
  711.       implicit integer(a-z)
  712.       !  Function : This is the session initialization function.  It sets
  713.       !             session parameters to their default values and creates
  714.       !             a new session logfile, destroying the previous
  715.       !             logfile if one exits.
  716.       !  Called Procedures :  kchar, kctl, initlog.
  717.       logical logging, debug, native, quote8, repeat, echo
  718.       parameter( CR = 13, CTLW = 23, CTLZ = 26,  null = 0 )
  719.       parameter( soh = 01 )
  720.       parameter( ns = 15 )
  721.       parameter( LINEBUF = 86 )          ! current length of kbd input buf
  722.       parameter( SITEMAX = LINEBUF-4)
  723.       character pad, eol, quote, bq8, cktype, repchar
  724.       character bufsize,timout, npad
  725.       character rpkthead
  726.       character *9 myparms, hisparms, dflt
  727.       character kchar, kctl
  728.  
  729.       common /units/ logioc, fioc, dkctr, dkbuf(512), nsectors,
  730.      !            fptr, dkptr, dkhold
  731.       common /states/ state, retry, ntries, oldtries, seq, delay
  732.      !      , stdelay
  733.       common /runparms/ myparms, hisparms, dflt
  734.       common /environ/ debug, native, quote8, repeat, window, echo
  735.  
  736.       equivalence (bufsize,dflt(1:1)),(timout,dflt(2:2)),
  737.      ! (npad,dflt(3:3)),(pad,dflt(4:4)),(eol,dflt(5:5)),
  738.      ! (quote,dflt(6:6)),
  739.      ! (bq8,dflt(7:7)),(cktype,dflt(8:8)),(repchar,dflt(9:9))
  740.  
  741.       ! set default system parameters
  742.       bufsize  = kchar(SITEMAX)    ! His safe max COUNT for pkts
  743.       timout = kchar(ns)    ! I want ns secs. to respond, by his clock
  744.       npad = kchar(0)
  745.       pad = kctl(null)
  746.       eol = kchar(CR)     ! end pkts to me with this kchar
  747.       quote = '#'
  748.       bq8 = 'N'             ! Default filetype is Ascii text
  749.       cktype = '1'          ! Default is single character checksums
  750.       repchar = ' '         ! Default is no data compression
  751.  
  752.  
  753.       myparms(1:9) = dflt(1:9)   ! Initialize to defaults
  754.  
  755.  
  756.       !  Site-dependancy : current line concentrator hardware echoes back
  757.       !                    packets. The following NPAD, PAD and EOL chars
  758.       !                    are used to disable echoback.  If echoback isn't
  759.       !                    disabled, then transmissions will fail (even if
  760.       !                    local Kermit detects and ignores echo) because
  761.       !                    local Kermit's packets swamp the concentrator.
  762.       myparms(3:5) = kchar(1)//kctl(char(CTLZ))//kchar(CTLW)
  763.  
  764.       myparms(7:7) = '&'                 !  My 8th bit prefix char
  765.       myparms(9:9) = '~'                 !  My repeat count prefix
  766.  
  767.       !  Use this default till we get his params :
  768.       hisparms(5:5) = char(CR)           ! store the real character
  769.  
  770.       logioc = 8
  771.       fioc = 9
  772.  
  773.       delay = 5000000        ! default Cray timeout = 5 secs.
  774.       stdelay = delay
  775.       retry = 5              ! I'll retry up to 5 times
  776.  
  777.       ! Establish default session environment :
  778.       debug = .false.
  779.       native = .true.        !  Default filetype is ctss native text
  780.       echo = .true.          !  Assume  echoback must be disabled
  781.       window = 1             !  Default size of floating window
  782.  
  783.       seq = 0
  784.  
  785.       ! initialize session log
  786.       call initlog(logging)
  787.       kinit = logging
  788. 900   continue
  789.  
  790.         return
  791.       end                   !  logical function kinit
  792.  
  793.       subroutine kclose()
  794.       implicit integer(a-z)
  795.       !  Function : This is the EXIT command interpreter,  but is also
  796.       !             invoked upon return to main program from server mode.
  797.       !             It merely closes the session logfile.  All data files
  798.       !             are closed by the appropriate state-switcher when
  799.       !             the current command (SEND/RECEIVE) completes or aborts.
  800.  
  801.  
  802.       call endlog()
  803.       return
  804.       end
  805.  
  806. !-cr.kfutil-!
  807.       !  This module contains a collection of bottom-level Fortran
  808.       !  subroutines, each of which invokes a CTSS operating system
  809.       !  function via a call to the library routine SYCALL.
  810.       !  The first SYCALL parameter is a literal index of the CTSS
  811.       !  function requested.  The second SYCALL parameter names the
  812.       !  array by which request parameters are passed between the
  813.       !  caller and CTSS.  Result codes are returned in the second word
  814.       !  of this array.  Their meaning may be site-dependent.  The
  815.       !  possibility of error recovery is site-dependent.
  816.  
  817.       subroutine readcmd(buffer,cmdlen)
  818.       implicit integer(a-z)
  819.       ! Function : reads user's command from keyboard controller
  820.       !            into buffer used as 1st argument,
  821.       !            returns command length in 2nd argument.
  822.       ! Called Procedures : sycall
  823.  
  824.       parameter (cmdmax=80)
  825.       parameter( wait = 0 )
  826.       dimension alpha(5)
  827.  
  828.       alpha(3) = buffer                  !  Address of caller's buffer
  829.       alpha(4) = cmdmax
  830.       alpha(5) = wait                    !  Wait until something is typed
  831.       call sycall(4l1500,alpha)          !  Read msg from kbd controller
  832.       cmdlen = alpha(4)                  !  Number of chars read
  833.  
  834.       return
  835.       end                                ! subroutine readcmd
  836.  
  837.       logical function kfspace(listadr, listmax, numfiles)
  838.       implicit integer(a-z)
  839.       ! Function : gets list of private files in user's filespace
  840.       !            into buffer addressed by first argument;
  841.       !            if no error and  0 < number_of_files <= 256, then
  842.       !            evaluates TRUE with number of files in second argument,
  843.       !            else evaluates false with numfiles := 0.
  844.       ! Called Procedures : sycall, logline
  845.       dimension beta(5)
  846.  
  847.       beta(3) = listadr
  848.       beta(4) = 2*listmax        ! num. words is 2*(max no. entries)
  849.       beta(5) = 0
  850.       call sycall(4l1001,beta)   ! Get private file list
  851.       if (beta(2).eq.0) then
  852.         numfiles = beta(4)/2
  853.         kfspace = .true.
  854.       else
  855.         numfiles = 0
  856.         kfspace = .false.
  857.       end if
  858.       return
  859.       end                        ! logical function kfspace
  860.  
  861.       logical function kfopen(fname)
  862.       implicit integer(a-z)
  863.       ! Function : opens file fname on kermit std. ioc, returns .true.,
  864.       !            else  returns .false.
  865.       ! Called Procedures : sycall, tdisp, logline
  866.       parameter( readacc = 2 )
  867.  
  868.       dimension dkbuf(512)
  869.       logical debug
  870.  
  871.       common /units/ logioc, fioc, dkctr, dkbuf,nsectors
  872.      !              , fptr, dkptr, dkhold
  873.       common /environ/ debug
  874.  
  875.       dimension beta(12)
  876.       character*4 code, dum1, dum2
  877.  
  878.       beta(3) = fname
  879.       beta(4) = fioc
  880.       beta(7) = readacc
  881.       call sycall(4l0300,beta)
  882.       if (beta(2) .eq. 0) then
  883.         kfopen = .true.
  884.         nx = beta(5)/512                 ! get num. full sectors in file
  885.         if (nx*512.eq.beta(5))  then     ! no remainder
  886.           nsectors = nx
  887.         else
  888.           nsectors = nx + 1
  889.         end if
  890.         fptr = 0                         !  initialize file offset (words)
  891.         dkptr = 1
  892.         dkhold = 0                       !  declare sector buffer empty
  893.         dkctr = 0                        !  initialize sectors-read counter
  894.         if (debug) then                  !  log system info
  895.           call tdisp(nsectors,dum1)
  896.           call tdisp(beta(5),dum2)
  897.           call logline('opened file has  '//dum1//' sectors,'//
  898.      !    dum2 // ' words$$')
  899.         end if                           ! if debug
  900.       else
  901.         kfopen = .false.
  902.         if (debug) then                  ! log the cause of failure
  903.           call tdisp(beta(2),code)       !  make error code printable
  904.           call logline('open fails with code:'//code//'$$')
  905.         end if                           ! if debug
  906.       end if
  907.       return
  908.       end      ! subroutine kfopen
  909.  
  910.       subroutine kfclose()
  911.       implicit integer(a-z)
  912.       ! Function : close  kermit std ioc
  913.       ! Called Procedures : sycall
  914.       parameter( sameacc = 0, samesec = 0, samelen = 0 )
  915.  
  916.       common /units/ logioc, fioc
  917.  
  918.       dimension beta(6)
  919.  
  920.       beta(3) = samesec
  921.       beta(4) = fioc
  922.       beta(5) = sameacc
  923.       beta(6) = samelen
  924.       call sycall(4l0400,beta)
  925.       return
  926.       end
  927.  
  928.       logical function kfcreate()
  929.       implicit integer(a-z)
  930.       ! Function : Destroys old kmt std recv file, if it exists,
  931.       !                and creates a new one.
  932.       common /units/ logioc, fioc, dkctr, dkbuf, nsectors, fptr, dkptr
  933.       parameter(sector=512)
  934.       dimension beta(9)
  935.       dimension dkbuf(sector)
  936.  
  937.       beta(3) = 'kmtfil'                 !  std recv file name
  938.       beta(4) = fioc
  939.       beta(5) = sector                      !  ask for 1 sector initially
  940.       beta(6) = 0
  941.       beta(7) = 3
  942.       call sycall(4l0101,beta)           !  create std file & destroy old
  943.       if (beta(2).eq.0) then
  944.         dkctr = 0                        ! initialize sector write ctr
  945.         dkptr = 1                        !  initialize sector buffer ptr
  946.         fptr = 0                         !  initialize file offset (words)
  947.         kfcreate = .true.
  948.       else
  949.         kfcreate = .false.               !  if error
  950.       end if
  951.       return
  952.       end                                !  logical fn kfcreate
  953.  
  954.       logical function kfdelete(usrfil)
  955.       implicit integer(a-z)
  956.       dimension beta(4)
  957.  
  958.       beta(3) = usrfil                   !  name of file to delete
  959.       call sycall(4l0200,beta)           !  delete it
  960.       if (beta(2).eq.0)  then
  961.         kfdelete = .true.                !  file was deleted
  962.       else
  963.         kfdelete = .false.
  964.       end if
  965.       return
  966.       end                                !  logical fn kfdelete
  967.  
  968.       logical function kfswitch(usrfil)
  969.       implicit integer(a-z)
  970.       dimension beta(4)
  971.  
  972.       call kfclose                       !  close kmt std i/o file
  973.       beta(3) = 'kmtfil'                 !  old name = std file name
  974.       beta(4) = usrfil                   !  new name = caller's arg.
  975.       call sycall(4l0600,beta)           !  rename std file to arg name
  976.       if (beta(2).eq.0) then
  977.         kfswitch = .true.                !  file was renamed ok
  978.       else
  979.         kfswitch = .false.
  980.       end if
  981.       return
  982.       end                                !  logical fn kfswitch
  983.  
  984.       logical function kfwrite(n)
  985.       implicit integer(a-z)
  986.       dimension dkbuf(512)
  987.       common /units/ logioc, fioc, dkctr, dkbuf, nsectors, fptr
  988.      !              , dkptr
  989.       dimension alpha(3), beta(9)
  990.  
  991.       beta(3) = fioc
  992.       beta(6) = loc(dkbuf)               !  Word addr of Sector buffer
  993.       beta(7) = fptr
  994.       beta(8) = n                        !  number of words to write
  995.       beta(9) = 0
  996.       call sycall(4l6000,beta)           !  start disk write
  997.       alpha(3) = fioc
  998.       call sycall(4l4001,alpha)          !  wait for dk write to complete
  999.       if (beta(2).eq.0)  then            !  dk write was successful
  1000.         fptr = fptr + beta(4)
  1001.         dkptr = 1                        !  sector buffer now empty
  1002.         kfwrite = .true.
  1003.         dkctr = dkctr + 1                !  incr disk write count
  1004.         if(n.eq.512) then                !  wrote full sector, need another
  1005.           beta(3) = 'kmtfil'
  1006.           beta(4) = (dkctr+1)*512        !  new file size wanted in wds
  1007.           call sycall(4l0702,beta)       !  request another sector
  1008.           if (beta(2).ne.0)  kfwrite = .false.
  1009.         end if                           !  if we filled our sector
  1010.       else
  1011.         kfwrite = .false.
  1012.       end if
  1013.       return
  1014.       end                                !  logical fn kfwrite
  1015.  
  1016.       logical function kfread()
  1017.       implicit integer(a-z)
  1018.       !  Function :  attempts to read 1 sector from Kermit std file ioc
  1019.       !              into common buffer dkbuf.
  1020.       !  Called Procedures :  sycall, logline
  1021.  
  1022.       dimension dkbuf(512)               !  sector-sized buffer
  1023.       logical debug
  1024.       common /units/ logioc, fioc, dkctr, dkbuf, nsectors, fptr,
  1025.      !             dkptr, dkhold
  1026.       common /environ/ debug
  1027.  
  1028.       dimension alpha(3), beta(9)
  1029.       character wval*4                   !  debuggery
  1030.  
  1031.       beta(3) = fioc                     !  device is std Kermit ioc
  1032.       beta(6) = loc(dkbuf)               !  addr of sector buf in common
  1033.       beta(7) = fptr                     !  current file offset in words
  1034.       beta(8) = 512                      !  request a whole sector
  1035.       beta(9) = 0                        ! no interrupt rtne - we'll wait
  1036.       call sycall(4l5000,beta)           !  start disk read
  1037.       alpha(3) = fioc
  1038.       call sycall(4l4001,alpha)          !  wait for read completion
  1039.       if((beta(2).eq.0).or.(beta(2).eq.020b)) then
  1040.         if (debug) then
  1041.           call tdisp(beta(4),wval)         !  debuggery
  1042.           call logline('# wds read is '//wval//'$$') ! debuggery
  1043.         end if
  1044.         dkhold = beta(4)                 !  num. words read
  1045.         fptr = fptr + beta(4)
  1046.         dkctr = dkctr + 1                !  incr count of no. sectors read
  1047.         dkptr = 1
  1048.         kfread = .true.
  1049.       else                               !  trouble with read
  1050.         kfread = .false.
  1051.       end if
  1052.       return
  1053.       end                                !  logical function kfread
  1054.  
  1055.       subroutine kfprune(fsize)
  1056.       implicit integer(a-z)
  1057.       ! Function : returns unused part of disk allocation
  1058.       !            for std Kermit io file.
  1059.       ! Called Procedures : sycall
  1060.       dimension beta(4)
  1061.  
  1062.       beta(3) = 'kmtfil'
  1063.       beta(4) = fsize
  1064.       call sycall(4l0702,beta)           !  make file size exact
  1065.       return
  1066.       end                                !  subroutine kfprune
  1067.  
  1068.       subroutine kgetime(tcpu,tio)
  1069.       implicit integer(a-z)
  1070.       dimension beta(8)
  1071.  
  1072.       do 10 i=2,8
  1073. 10      beta(i) = 0
  1074.       call sycall(4l1031,beta)           ! get real cpu,io times used.
  1075.       tcpu = beta(3)
  1076.       tio = beta(4)
  1077.       return
  1078.       end                                !  subroutine kgetime
  1079.  
  1080.       subroutine displays
  1081.       implicit integer(a-z)
  1082.  
  1083.       character *40 string
  1084.       parameter( cr=13, lf=10 )
  1085.       logical nl
  1086.  
  1087.       character cmdstr*80, report*40
  1088.       common /strings/ cmdstr, report
  1089.       dimension beta(5)
  1090.  
  1091.       entry display(string)
  1092.  
  1093.       nl = .true.
  1094.       go to 10
  1095.  
  1096.       entry prompt(string)
  1097.  
  1098.       nl = .false.
  1099.  
  1100. 10    continue
  1101.       strep = strad(report)
  1102.       if (strad(string) .ne. strep) then
  1103.         report = string       ! if argument is a literal
  1104.       end if
  1105.       beta(3) = strep
  1106.       k = index(report,'.')
  1107.       if (k.eq.0) k =39
  1108.       if (nl) then
  1109.         report(k:k+1) = char(13) // char(10)    ! cr lf
  1110.         beta(4) = k + 1
  1111.       else
  1112.         beta(4) = k-1
  1113.       end if
  1114.       beta(5) = 1
  1115.       call sycall(4l1400,beta)   ! send msg to tty ctlr
  1116.       return
  1117.       end
  1118.  
  1119. !-cr.kutcmds-!
  1120.       subroutine kserv()
  1121.       implicit integer(a-z)
  1122.       ! Function : This is the Kermit Server cmd interpreter.
  1123.       !            It is a command packet accepting loop, with exit
  1124.       !            to top-level upon receiving a FINISH("GF") or
  1125.       !            BYE/LOGOUT('GL") pkt from other Kermit.
  1126.       !            Note : Cray Kermit does not log itself out.
  1127.       ! Called Procedures :  getpkt, unchar, stdname, ktrans, krecv,
  1128.       !                      sendack, decode, encode, sendpkt,
  1129.       !                      errorpkt, logline.
  1130.  
  1131.       logical done, ok
  1132.       character ptype
  1133.       character *104 packet(2)
  1134.       character cmdstr*80, report*40
  1135.       common /globals/ runtype, nargs, args(10,2), thisarg
  1136.       common /states/ state, retry, ntries, oldtries, seq
  1137.      !               , delay, stdelay
  1138.       common /packets/ packet
  1139.       common /strings/ cmdstr, report
  1140.  
  1141.       parameter( init = 1, hdr = 2, abort = 6 )  ! states
  1142.       parameter(good = 0, bad = 1, timeout = 2, escape = 3)
  1143.       parameter( exitype = 4 )           !  runtype on exit
  1144.  
  1145.       done = .false.
  1146. 10    continue                           !  top of Server loop
  1147.       call getpkt(1,status)              !  look for cmd pkt
  1148.       if (status.eq.good)  then          !  got a good pkt
  1149.         ptype = packet(1)(4:4)
  1150.         if (ptype.eq.'R')  then          !  they want to receive
  1151.           !  get filename from R pkt
  1152.           last = unchar(packet(1)(2:2)) + 1
  1153.           if (last.gt.4)  then
  1154.             nargs = 1
  1155.             lx = last - 4
  1156.             cmdstr(1:8) = packet(1)(5:last)
  1157.             call stdname(cmdstr(1:8))    !  convert name to lower case
  1158.             args(1,1) = 1
  1159.             args(1,2) = lx
  1160.             thisarg = 1
  1161.             call ktrans        !  call send state switcher
  1162.           else
  1163.             report = 'Server - no filename.'
  1164.             done = .true.
  1165.           end if                         !  if good file name
  1166.         else if (ptype.eq.'S') then      !  they want to send
  1167.             call krecv               !  call receive state switcher
  1168.         else if (ptype.eq.'G')  then     !  Generic Server pkt type
  1169.           ptype = packet(1)(5:5)         !  1st Data char tells cmd
  1170.           if ((ptype.ne.'F').and.(ptype.ne.'L')) then
  1171.             report = 'Server - unknown G code:'//ptype//'.'
  1172.           else                           ! It's a valid G pkt code
  1173.             call sendack(2,' ','Y')      !  ACK it
  1174.             report = 'Server - shut down by Partner.'
  1175.           end if                         !  if cmdtype in G pkt
  1176.           done = .true.
  1177.         else if (ptype.eq.'I') then
  1178.           call decode(1,ok)               ! Decode their new initial params
  1179.           if (ok) then                    ! we can comply
  1180.             call encode(2,0,'Y')          ! make a 'Y' pkt with our params
  1181.             call sendpkt(2)               ! reply with our params
  1182.           else
  1183.             report = 'cant comply with params.'
  1184.             done = .true.
  1185.           end if
  1186.         else
  1187.           report = 'Server - unknown pkt type:'//ptype//'.'
  1188.           done = .true.
  1189.         end if                              !  if good status
  1190.       else if (status.ne.escape) then    !  if bad pkt or timeout
  1191.         call sendack(2,' ','N')          !  NAK it
  1192.       else
  1193.         report = 'Server - aborted.'
  1194.         done = .true.
  1195.       end if                             !  if getpkt
  1196.       if (.not.(done))  then
  1197.         go to 10                         !  go get another server pkt
  1198.       else                               !  this is exit from server loop
  1199.         call errorpkt(report)
  1200.         call logline(report)
  1201.         runtype = exitype                !  tell Kermit to shut down
  1202.       end if
  1203.  
  1204.       return
  1205.       end
  1206.  
  1207.  
  1208.       subroutine kstatus()
  1209.       implicit integer(a-z)
  1210.       ! Function : This is the STATUS command interpreter.  It displays
  1211.       !            current Cray settable parameters.
  1212.       ! Called Procedures :  tdisp, unchar
  1213.  
  1214.       character report*40, value*4, kctl
  1215.       character*9 myparms, hisparms, defaults
  1216.        logical debug, native, quote8, repeat, echo
  1217.  
  1218.       common /states/ state, retry, ntries, oldtries, seq
  1219.      !      , delay, stdelay
  1220.       common /runparms/ myparms, hisparms, defaults
  1221.       common /environ/ debug, native, quote8, repeat, window, echo
  1222.  
  1223.       call tdisp(stdelay/1000000,value)  !  convert stdelay to ascii secs.
  1224.       report = 'timeout delay is ' //value //'.'
  1225.       print *,report
  1226.       call tdisp(retry,value)
  1227.       report = 'max num tries is ' //value(3:4) // '.'
  1228.       print *,report
  1229.       if (debug) then
  1230.         value = 'on'
  1231.       else
  1232.         value = 'off'
  1233.       end if
  1234.       report = 'debug '//value//'.'
  1235.       print *,report
  1236.       call tdisp(unchar(myparms(1:1)),value)  ! convert coded char
  1237.       report = 'Cray receiving bufsize is '//value(3:4)//' chars.'
  1238.       print *,report
  1239.       if (native) then
  1240.         value = 'on'
  1241.       else
  1242.         value = 'off'
  1243.       end if
  1244.       report = 'ctss native text mode '//value//'.'
  1245.       print *,report
  1246.  
  1247.       ! Site dependancy: see comments in KSET interpreter.
  1248.       !                  This param is not yet made SETable.
  1249.       !if (echo) then
  1250.       !  value = 'on'
  1251.       !else
  1252.       !  value = 'off'
  1253.       !end if
  1254.       !report = 'echoback disable '//value//'.'
  1255.       !print *, report
  1256.  
  1257.       !  Floating Window option not yet implemented
  1258.       !    call tdisp(window,value)
  1259.       !    report = 'window width is '//value//'.'
  1260.       !    print *, report
  1261.  
  1262.       return
  1263.       end                      ! subroutine kstatus
  1264.  
  1265.       subroutine kset()
  1266.       implicit integer(a-z)
  1267.       ! Function : This is is the SET command interpreter.  It changes
  1268.       !            the  Cray delay time, retry, debug, bufsize or
  1269.       !            filetype parameters for current session.
  1270.       ! Called Procedures :  kchar, kctl, unchar, sethelp
  1271.  
  1272.       parameter( MINPKT = 20, MAXPKT = 94 )
  1273.       parameter( CTLZ = 26, CTLW = 23)
  1274.       parameter( microsec = 1000000 )
  1275.       character *80 cmdstr
  1276.       character *40 report
  1277.       character type*3, opt*2, numstr*2, lim1*4, lim2*4
  1278.       character*9 myparms, hisparms, defaults
  1279.       logical debug, turnon, native, quote8, repeat, echo
  1280.       logical code
  1281.       character kchar, kctl
  1282.  
  1283.       common /strings/ cmdstr, report
  1284.       common /states/ state, retry, ntries, oldtries, seq
  1285.      !               , delay, stdelay
  1286.       common /globals/ runtype, nargs, args(10,2)
  1287.       common /runparms/ myparms, hisparms, defaults
  1288.       common /environ/ debug, native, quote8, repeat, window, echo
  1289.  
  1290.       if (nargs.eq.1) then
  1291.         if ( (cmdstr(args(1,1):args(1,1)).eq.'?')
  1292.      !  .or. (cmdstr(args(1,1):args(1,1)+3).eq.'help')) then
  1293.           call sethelp()
  1294.           return
  1295.         end if                           !  If user requested help
  1296.       end if
  1297.       if (nargs.lt.2) then
  1298.         print *, ' set <option> <value>.'
  1299.       else
  1300.         type = cmdstr(args(1,1):args(1,1)+2)
  1301.         if ((type.eq.'deb').or.(type.eq.'nat').or.(type.eq.'ech'))
  1302.      !  then                            !  These are the ON | OFF options
  1303.           opt = cmdstr(args(2,1):args(2,1)+1)
  1304.           if ((opt.eq.'on').or.(opt.eq.'ON')) then
  1305.             turnon = .true.
  1306.           else if ((opt.eq.'of').or.(opt.eq.'OF')) then
  1307.             turnon = .false.
  1308.           else
  1309.             print *, '     option values:  on | off.'
  1310.             go to 800
  1311.           end if                    !  if option value
  1312.           if (type.eq.'deb') then
  1313.             debug = turnon
  1314.           ! Site dependancy: defer implementation of the SET ECHO <ON|OFF>
  1315.           !                  cmd because current KCC's (network line
  1316.           !                  concentrators) cannot keep up with a SENDing
  1317.           !                  local Kermit's data rate, if echoback is
  1318.           !                  enabled.
  1319.           !else if (type.eq.'ech') then
  1320.              !echo = turnon
  1321.              !if (echo) then
  1322.              !  myparms(3:5) = kchar(1)//kctl(char(CTLZ))//kchar(CTLW)
  1323.              !  myparms(1:1) = kchar(unchar(defaults(1:1))-2)
  1324.              !else
  1325.              !  myparms(3:5) = defaults(3:5)
  1326.              !  myparms(1:1) = defaults(1:1)
  1327.              !end if
  1328.           else
  1329.             native = turnon
  1330.           end if
  1331.         else if ((type.eq.'tim').or.(type.eq.'ret').or.(type.eq.'buf'))
  1332.      !  then
  1333.           vlen = args(2,2) - args(2,1) + 1
  1334.           if (vlen.gt.2) then
  1335.             print *, ': value is 1 or 2 decimal digits.'
  1336.             go to 800
  1337.           else if (vlen.eq.1) then
  1338.             numstr = '0'//cmdstr(args(2,1):args(2,1))
  1339.           else
  1340.             numstr = cmdstr(args(2,1):args(2,2))
  1341.           end if
  1342.           call undisp(numstr,value,code)
  1343.           if (.not.(code)) then
  1344.             print *, ': use decimal characters for value.'
  1345.             go to 800
  1346.           end if
  1347.           if (type.eq.'tim') then
  1348.             stdelay = value * microsec
  1349.           else if (type.eq.'ret') then
  1350.             retry = value
  1351.           else if (type.eq.'buf') then
  1352.             if ((value.ge.MINPKT).and.(value.le.MAXPKT)) then
  1353.               myparms(1:1) = kchar(value)
  1354.             else
  1355.               call tdisp(MINPKT,lim1)
  1356.               call tdisp(MAXPKT,lim2)
  1357.               report = 'Use buffer size between '//lim1
  1358.      !                //' and '//lim2//'.'
  1359.               print *, report
  1360.             end if
  1361.           end if
  1362.         else
  1363.           print *, ':not a valid set option.'
  1364.         end if
  1365.       end if
  1366.  
  1367. 800   continue
  1368.       return
  1369.       end                   ! subroutine kset
  1370.  
  1371.       subroutine sethelp()
  1372.       implicit integer(a-z)
  1373.       ! Function : This subroutine displays the settable parameters.
  1374.       ! Called procedures : none.
  1375.  
  1376.       print *, 'Set options are :'
  1377.       print *,' '
  1378.       print *,'    timeout <decimal value>'
  1379.       print *,'    retry <decimal value>'
  1380.       print *,'    debug <on | off>'
  1381.       print *,'    bufsize <decimal value>'
  1382.       print *,'    native <on | off>'
  1383.       ! Defer implementation of the SET ECHO option  [lfm 1/85]
  1384.       !print *,'    echo <on | off>'
  1385.  
  1386.       return
  1387.       end                                ! subroutine sethelp
  1388.  
  1389.  
  1390.       subroutine khelp()
  1391.       ! Function : This is the HELP command interpreter.
  1392.  
  1393.       print *,' LANL Cray Kermit Commands :'
  1394.       print *,' '
  1395.       print *,' server'
  1396.       print *,'    (Enter Server mode : all transmission info will'
  1397.       print *,'     come from Partner Kermit, as packets.)'
  1398.       print *,' s[end] <list of 1-10 file names>'
  1399.       print *,'    (Send files to a partner in receive mode)'
  1400.       print *,' r[eceive]'
  1401.       print *,'    (receive files from non-server partner)'
  1402.       print *,' e[xit]'
  1403.       print *,'    (exit from non-server Kermit, return to Cray OS)'
  1404.       print *,' st[atus]'
  1405.       print *,'    (display status of settable Cray Kermit parameters)'
  1406.       print *,' set <option> <value>'
  1407.       print *,'    (set value of a parameter)'
  1408.       print *,' h[elp]'
  1409.       print *,'    (display this menu)'
  1410.         return
  1411.       end
  1412.  
  1413. !-cr.pktio-!
  1414.       subroutine sendpkt(pindex)
  1415.       implicit integer(a-z)
  1416.       ! Function : This is the physical packet send routine.  Packets
  1417.       !            are sent as messages to the keyboard controller.
  1418.       !            If pad or EOL characters have been requested by
  1419.       !            the other Kermit,  they are added here.
  1420.       ! Called Procedures : strad, unchar, kctl, sycall, logpkt
  1421.       character kctl, pad
  1422.       character *104 packet(2)
  1423.       character *9 myparms, hisparms
  1424.       logical debug
  1425.       parameter(  wait = 1 )
  1426.       parameter( SOH = 01 )
  1427.  
  1428.       common /packets/ packet
  1429.       common /runparms/ myparms, hisparms
  1430.       common /environ/ debug
  1431.  
  1432.       dimension beta(5)
  1433.  
  1434.       packet(pindex)(1:1) = char(SOH)
  1435.       beta(3) = strad(packet(pindex))
  1436.       beta(4) = unchar(packet(pindex) (2:2)) + 3    ! pt past chksum
  1437.       packet (pindex) (beta(4):beta(4)) = hisparms(5:5)   !append his eol
  1438.       npad = unchar(hisparms(3:3))       !  get num pads if any
  1439.       if (npad.gt.0)  then               !  he wants pad char prefix
  1440.         pad = kctl(hisparms(4:4))        !  uncontrolify - true pad char
  1441.         packet(pindex)(npad+1:beta(4)+npad)
  1442.      !   = packet(pindex)(1:beta(4))     !  shift data right
  1443.         do 10 i=1,npad
  1444.           packet(pindex)(i:i) = pad
  1445. 10      continue
  1446.         beta(4) = beta(4) + npad         !  revise length to include pads
  1447.       end if
  1448.       beta(5) = wait
  1449.       call sycall(4l1400,beta)    ! send packet as msg to kbd controller
  1450.       if (debug) call logpkt(pindex)     !  show the pkt sent
  1451.       !f ( beta(2) .eq. 0 ) then ... what ?
  1452.       return
  1453.       end                 !  subr sendpkt
  1454.  
  1455.       subroutine sendack(pindex,theirseq,ok)
  1456.       implicit integer(a-z)
  1457.       ! Function :  This is a virtual packet send routine called
  1458.       !             in the RECEIVE states.  It invokes SENDPKT and
  1459.       !             if ok = 'Y', ACK's pkt no. theirseq, else NAK's it.
  1460.       ! Called Procedures :  cksum, sendpkt
  1461.  
  1462.       character theirseq, ok, cksum
  1463.       character *104 packet(2)
  1464.       common /packets/ packet
  1465.  
  1466.       packet(pindex)(2:2) = '#'      ! count is coded 3
  1467.       packet(pindex) (3:3) = theirseq
  1468.       packet(pindex) (4:4) = ok
  1469.       packet(pindex)(5:5) = cksum(packet(pindex))
  1470.       call sendpkt(pindex)
  1471.       return
  1472.       end       ! subroutine sendack
  1473.  
  1474.       subroutine getpkt(px,status)
  1475.       implicit integer(a-z)
  1476.       !  Function : This is the packet read routine. Packets are read as
  1477.       !             messages from the Keyboard Controller.  When entered,
  1478.       !             getpkt suspends itself until arrival of a message
  1479.       !             or elapse of timeout interval.  If a message is there
  1480.       !             at entry, suspension does not occur (i.e., an
  1481.       !             immediate return occurs from the delay sycall).
  1482.       !             If awakened by timeout, getpkt returns staus=timeout,
  1483.       !             if by msg arrival then staus=good IFF msg is
  1484.       !             a correctly checksumed packet,  else status=bad.
  1485.       !  Called Procedures :  sycall, logline, unchar, cksum, logpkt,
  1486.       !                      tdisp.
  1487.  
  1488.       character kchar, cksum, nval*4
  1489.       character *9 myparms
  1490.       character *104 packet(2)
  1491.       logical debug
  1492.  
  1493.       common /states/ state, retry, ntries, oldtries, seq,
  1494.      !      delay, stdelay
  1495.       common /runparms/ myparms
  1496.       common /packets/ packet
  1497.       common /environ/ debug
  1498.  
  1499.       parameter( good = 0, bad = 1, timeout = 2, escape = 3 )
  1500.       parameter( abort = 6 )
  1501.       parameter( MAXMSG = 104, MINLEN = 5, wait =0, nowait = 1 )
  1502.       !  MAXMSG 104 allows up to 96 pkt chars + eol(stripped by ctss),
  1503.       !  plus up to 8 pad/noise char prefix.
  1504.       parameter( kccmax = 86 )          ! max len of kcc read, alas.
  1505.       parameter( soh = 1, esc = 033b )
  1506.  
  1507.       dimension alpha(3), beta(5)
  1508.  
  1509.       beta(3) = strad(packet(px))          !  get addr of packet
  1510.       beta(5) = nowait
  1511. 10    continue
  1512.       alpha(3) = delay
  1513.       call sycall(4l3000,alpha)        !  sleep dt or till msg comes
  1514.       beta(4) = MAXMSG
  1515.       call sycall(4l1500,beta)         !  see which event occurred
  1516.       if (beta(2) .ne. 0)  then        !  time elapsed without msg
  1517.         status = timeout
  1518.         if (debug) call logline('timed out$$')
  1519.       else if (beta(4).eq.0) then      !  got lone EOL char - ignore it
  1520.         if (debug) call logline('null pkt$$')
  1521.         go to 10                         !  go back to sleep
  1522.       else if (packet(px)(1:1).eq.char(esc))
  1523.      !then                               !  someone hit ESC key
  1524.         call logline('escaped$$')
  1525.         status = escape
  1526.       else                               !  is msg a real packet ?
  1527.         if (debug) then
  1528.           call tdisp(beta(4),nval)
  1529.           call logline('Got '//nval//' msg chars$$')
  1530.         end if
  1531.         sx = index(packet(px),char(soh)) !  look for SOH in msg
  1532.         if ((sx.eq.0).and.(beta(4).lt.MINLEN))
  1533.      !  then                             ! Headless blip - treat as noise
  1534.           if (debug) call logline('noise pkt ignored$$')
  1535.           go to 10
  1536.         else if ((sx.eq.0).or.(beta(4).lt.MINLEN)) then
  1537.           status = bad                   ! Let it be NAK'ed
  1538.           go to 100
  1539.         else                             !  it looks like a pkt
  1540. 30        continue
  1541.           nx = index(packet(px)(sx+1:sx+1), char(soh))
  1542.           if (nx.ne.0)  then             !  found another SOH
  1543.             sx = sx + nx                 !  get its absolute index
  1544.             if (sx.le.MAXMSG-MINLEN) then
  1545.               go to 30                   !  go see if it's the last one
  1546.             else
  1547.               status = bad
  1548.               go to 100
  1549.             end if
  1550.           end if
  1551.           pklen = unchar(packet(px)(sx+1:sx+1)) + 2
  1552.           if (sx .gt. 1)  then           !  need to left-adjust
  1553.             packet(px) (1:pklen) = packet(px)(sx:sx+pklen-1)
  1554.           end if                         !  if there were pad chars
  1555.         end if                                 !  if sx
  1556.         if (debug) call logpkt(px)       !  Show their packet
  1557.         if (cksum(packet(px)) .eq. packet(px)(pklen:pklen)) then
  1558.           status = good
  1559.         else
  1560.           if (debug) call logline('bad checksum$$')
  1561.           status = bad
  1562.         end if                           !  if checksum
  1563.       end if                             !  if beta(2)
  1564. 100   return
  1565.       end                                     ! subroutine getpkt
  1566.  
  1567.  
  1568.       logical function gotack(px,seq)
  1569.       implicit integer(a-z)
  1570.       !  Function :  This is a virtual packet read routine called from
  1571.       !              the SEND state.  Evaluation of GOTACK forces a
  1572.       !              call to GETPKT, the physical pkt read rtne.
  1573.       !              GOTACK is .true. iff a valid ACK for current pkt
  1574.       !              or valid NAK for next is rec'd.  Receipt of good
  1575.       !              discard-type ACK for current pkt causes signal
  1576.       !              variable to be set to action character in pkt.
  1577.       !  Called Procedures :  getpkt, kchar, unchar, logline
  1578.       parameter( good=0, bad=1, timeout=2 ) ! getpkt return codes
  1579.       character kchar, pseq, ptype, expect, next, signal
  1580.       character *104 packet(2)
  1581.  
  1582.       common /packets/ packet, signal
  1583.  
  1584.       call getpkt(px,status)      !  look for partners response
  1585.       if (status.eq.good)  then   !  got a valid pkt
  1586.         pcount = unchar(packet(px)(2:2))
  1587.         pseq = packet(px)(3:3)
  1588.         ptype = packet(px)(4:4)
  1589.         expect = kchar(mod(seq,64))
  1590.         next = kchar(mod(seq+1,64))
  1591.         if (((ptype.eq.'Y').and.(pseq.eq.expect)) .or.
  1592.      !      ((ptype.eq.'N').and.(pseq.eq.next)))
  1593.      ! then                       !  ACK for this or NAK for next
  1594.           gotack = .true.
  1595.           !  was it a discard-type ACK ?
  1596.           if ((ptype.eq.'Y').and.(pcount.gt.3))  then
  1597.             signal = packet(px)(5:5)  !  save discard action field
  1598.             call logline('Interrupt request, type '//signal//'$$')
  1599.           end if
  1600.         else                      !  Good pkt,  wrong type or seq
  1601.           gotack = .false.
  1602.         end if                    !  If ptype
  1603.       else                        !  Bad pkt or timeout
  1604.         gotack = .false.
  1605.       end if                      !  If getpkt status
  1606.       return
  1607.       end                         !  logical function gotack
  1608.  
  1609. !-cr.receive-!
  1610.       subroutine krecv()
  1611.       implicit integer(a-z)
  1612.       !  Function : RECEIVE state switcher
  1613.       !  Called Procedures :  getinit, gethdr, getfile, logline,
  1614.       !                       kfclose, kgetime, tdisp.
  1615.       parameter( init = 1, hdr = 2, data = 3, feof = 4, complete = 7,
  1616.      !            abort = 6 )
  1617.       parameter( seconds = 1000000, ms = 1000 )
  1618.       character*4 cpr,tpr
  1619.       character cmdstr*80, report*40
  1620.       logical rpcount, savedcr
  1621.  
  1622.       common /states/ state, retry, ntries, oldtries, seq, delay
  1623.      !         , stdelay,  tcpu, tio
  1624.       common /pkstats/   bptr, bufleft, maxpack, lastbuf
  1625.      !                , rpcount, savedcr
  1626.       common /strings/ cmdstr, report
  1627.  
  1628.       ntries = 0
  1629.       delay = stdelay
  1630.       state = init
  1631.       call kgetime(tcpu,tio)              !  Get initial times
  1632.  
  1633. 100   if ( state .ne. complete)  then
  1634.         if (state .eq. init) then
  1635.           call getinit
  1636.         else if (state .eq. hdr) then
  1637.           call gethdr
  1638.         else if (state .eq. data) then
  1639.           call getfile
  1640.         else if (state .eq. abort) then
  1641.           call kfclose                !  make sure recv file closed
  1642.           call logline(report)        !  log reported cause of failure
  1643.           call errorpkt(report)
  1644.           state = complete
  1645.         end if                        !  end of non-complete cases
  1646.         go to 100
  1647.       end if                          !  else state is complete
  1648.       call tdisp(seq,tpr)
  1649.       call logline('num pkts received = '//tpr//'$$')
  1650.       call kgetime(tcx,tix)
  1651.       call tdisp((tcx-tcpu)/ms, cpr)
  1652.       call tdisp((tix-tio)/seconds,tpr) ! get printable io usage in seconds
  1653.       call logline('Transaction time = '//cpr//' cpu ms, '//
  1654.      !  tpr//' io sec$$' )
  1655.       return
  1656.       end                       !  subroutine krecv
  1657.  
  1658.  
  1659.       subroutine getinit()
  1660.       implicit integer(a-z)
  1661.       ! Function :  This routine gets the other Kermit's parameters in
  1662.       !             an 'S' packet, checks them,  and ACK's with ours
  1663.       !             IFF we can comply with other Kermit's requests.
  1664.  
  1665.       parameter( init=1, hdr=2, abort=6)
  1666.       parameter( good=0, bad=1, timeout=2, escape=3 )
  1667.       parameter( thispkt = 1, nxtpkt = 2 )
  1668.       parameter( initry = 20 )           !  allow more tries for S pkt
  1669.  
  1670.       character *104 packet(2)
  1671.       character cmdstr*80, report*40
  1672.  
  1673.       common /states/ state, retry, ntries, oldtries, seq
  1674.      !               , delay, stdelay
  1675.       common /packets/ packet
  1676.       common /strings/ cmdstr, report
  1677.  
  1678.       logical nakit, resolve
  1679.  
  1680.       if (ntries .ge. initry)  then
  1681.         report = 'getinit - too many.'
  1682.         state = abort
  1683.       else
  1684.         ntries = ntries + 1
  1685.         nakit = .false.
  1686.         if (ntries .eq. 1)  delay = stdelay * 2  !  wait longer for S & F
  1687.         call getpkt(thispkt, status)
  1688.         if (status .eq. good)  then
  1689.           if (packet(thispkt)(4:4) .eq. 'S')  then  ! got a good S pkt
  1690.             call decode(thispkt,resolve)         !  decode his parms
  1691.             if (resolve) then
  1692.               seq = unchar(packet(thispkt)(3:3)) !  synchronize seq nos.
  1693.               call encode(nxtpkt,seq,'Y')        !  format our params
  1694.               call sendpkt(nxtpkt)               !  send him ours
  1695.               state = hdr
  1696.               seq = seq + 1
  1697.               oldtries = ntries
  1698.               ntries = 0
  1699.             else
  1700.               report = 'cant resolve params.'
  1701.               state = abort
  1702.             end if                               !  if resolve
  1703.           else                                   !  wrong pkt type
  1704.             nakit = .true.
  1705.           end if
  1706.         else if (status.eq.escape) then
  1707.           state = abort
  1708.           report = 'Host User Escape Request.'
  1709.           nakit = .false.
  1710.         else                                     !  bad pkt or timeout
  1711.           nakit = .true.
  1712.         end if                                   !  if status
  1713.  
  1714.         if (nakit)  call sendack(ack,' ','N')      !  send NAK
  1715.  
  1716.       end if                                     !  if ntries
  1717.       return
  1718.       end                       !  subroutine       GETINIT
  1719.  
  1720.       subroutine gethdr()
  1721.       implicit integer(a-z)
  1722.       ! Function :  This routine gets an 'F' (header) packet from the
  1723.       !             other Kermit, saves file name,  opens a workfile
  1724.       !             'kmtfil' to receive the incoming file,  and ACK's
  1725.       !             the 'F' pkt.  Workfile name will be switched to header
  1726.       !             name when transmission completes.
  1727.  
  1728.       parameter( hdr = 2, data = 3, abort = 6, complete = 7 )
  1729.       parameter( good = 0, bad = 1, timeout = 2 )
  1730.       parameter( thispkt = 1, ack = 2 )
  1731.       parameter( buflen = 504 )
  1732.  
  1733.       character *104 packet(2)
  1734.       character cmdstr*80, report*40
  1735.       dimension dkbuf(512)
  1736.  
  1737.       common /states/ state, retry, ntries, oldtries, seq
  1738.      !              , delay, stdelay
  1739.       common /packets/ packet
  1740.       common /pkstats/  bptr, bufleft,  maxpack, lastbuf, rpcount, savedcr
  1741.       common /strings/ cmdstr, report
  1742.       common /environ/ debug, native
  1743.  
  1744.       logical ackit, oldfile, kfopen, kfcreate, lastbuf, savedcr
  1745.       logical debug, native
  1746.       character ptype, kchar
  1747.       dimension beta(9)
  1748.  
  1749.       if (ntries .ge. retry)  then
  1750.         report = 'gethdr - too many.'
  1751.         state = abort
  1752.       else
  1753.         ntries = ntries + 1
  1754.         call getpkt(thispkt, status)
  1755.         if (status .eq. good)  then
  1756.           ptype = packet(thispkt) (4:4)
  1757.           if (ptype .eq. 'F')  then
  1758.             !  save pkt file name in command string
  1759.             namend = unchar(packet(thispkt)(2:2)) + 1
  1760.             cmdstr(1:8) = packet(thispkt) (5:namend)
  1761.             call stdname(cmdstr(1:8))    !  Convert to std name
  1762.             if (kfcreate())  then        !  if opened std recv file
  1763.               report = 'Opened std file for:'//cmdstr(1:8)
  1764.               call logline(report)
  1765.               bptr = 1                   !  initialize buffer ptr
  1766.               bufleft = buflen
  1767.               savedcr = .false.
  1768.             else
  1769.               report = 'gethdr - cant open std file.'
  1770.               state = abort
  1771.               go to 700
  1772.             end if
  1773.             state = data
  1774.             seq = seq + 1
  1775.             oldtries = ntries
  1776.             ntries = 0
  1777.             ackit = .true.
  1778.           else if (ptype .eq. 'S')  then
  1779.             !  they lost our ACK
  1780.             ackit = .false.                !  not a regular ACK
  1781.             if (oldtries.lt.retry) then
  1782.               call encode(nxtpkt,1,'Y')              !  send it again
  1783.               call sendpkt(ack)            !  ACK it again
  1784.               oldtries =   oldtries + 1
  1785.             else
  1786.               report = 'gethdr - aborting after too many S pkts.'
  1787.               state = abort
  1788.             end if
  1789.           else if (ptype .eq. 'Z')  then
  1790.             !  lost ACK for previous file on list
  1791.             ackit = .true.
  1792.             ntries = 0
  1793.           else if (ptype .eq. 'B')  then
  1794.             state = complete
  1795.             ackit = .true.
  1796.           else
  1797.             report = 'gethdr - aborting on unknown pkt type.'
  1798.             state = abort
  1799.             ackit = .false.
  1800.           end if                                 !  if ptype
  1801.           if (ackit)  call sendack(ack,packet(thispkt)(3:3),'Y')
  1802.         else if (state .ne. abort) then          !  if bad pkt or timeout
  1803.           call sendack(ack,kchar(mod(seq,64)),'N')    ! NAK expected pkt
  1804.         end if                                   !  if status
  1805.       end if                                     !  if ntries
  1806. 700   continue
  1807.       if (state.gt.hdr)  delay = stdelay  ! restore std delay
  1808.       return
  1809.       end                               !  subroutine gethdr
  1810.  
  1811.       subroutine getfile()
  1812.       implicit integer(a-z)
  1813.       ! Function :  This routine gets a 'D' (data) packet from the other
  1814.       !             Kermit, ACK's it,  and invokes the pkt-unpacking
  1815.       !             rtne PUTDATA to buffer received data.  End of file
  1816.       !             is detected in this state when a 'Z' pkt arrives.
  1817.       !             Discard-type 'Z' pkts are recognized.
  1818.  
  1819.       !  send states :
  1820.       parameter( hdr = 2, data = 3, abort = 6 )
  1821.       !  getpkt status codes :
  1822.       parameter( good = 0, bad = 1, timeout = 2 )
  1823.       parameter( px = 1, ack = 2 )
  1824.       parameter( ok= 0, err = 1 )        !  putdata result codes
  1825.  
  1826.       character kchar, ptype, pseq, expect, last
  1827.       character cmdstr*80, report*40
  1828.       logical puteof
  1829.  
  1830.       character *104 packet(2)
  1831.       common /states/ state, retry, ntries, oldtries, seq
  1832.      !               , delay, stdelay
  1833.       common /packets/ packet
  1834.       common /strings/ cmdstr, report
  1835.  
  1836.       if (ntries .ge. retry) then
  1837.         report = 'getfile - too many.'
  1838.         state = abort
  1839.       else
  1840.         ntries = ntries + 1
  1841.         call getpkt(px,status)           !  look for expected data pkt
  1842.         expect = kchar(mod(seq,64))
  1843.         last = kchar(mod(seq-1,64))
  1844.         if (status.eq.good) then         !  got a pkt
  1845.           pseq = packet(px)(3:3)
  1846.           ptype = packet(px)(4:4)
  1847.           if (ptype.eq.'D')  then        !  type is Data
  1848.             if ((pseq.eq.expect).or.(pseq.eq.last)) then
  1849.               call sendack(ack,pseq,'Y')     !  ACK if it's nth or (n-1)st
  1850.             end if                           !  if pseq
  1851.             if (pseq.eq.expect)  then
  1852.               call putdata(px,result)        !  store data from nth pkt
  1853.               if (result.ne.ok)  then
  1854.                 report = 'file write error.'
  1855.                 state = abort
  1856.               else
  1857.                 seq = seq + 1
  1858.                 oldtries = ntries
  1859.                 ntries = 0
  1860.               end if
  1861.             end if                           !  if pseq in 'D' pkt
  1862.           else if (ptype.eq.'Z')  then       !  received eof
  1863.             if(unchar(packet(px)(2:2)).eq.3) then  ! Normal EOF pkt
  1864.               ! evaluate puteof to terminate file, switch name
  1865.               if(.not.(puteof(cmdstr(1:8))))  then
  1866.                 report = 'can''t save file.'
  1867.                 state = abort
  1868.               end if
  1869.             else if (packet(px)(5:5).eq.'D') then
  1870.               call kfclose()            !  This file to be Discarded.
  1871.               call logline('Incoming copy discarded by request$$')
  1872.             end if
  1873.             if (state.ne.abort) then
  1874.               state = hdr
  1875.               seq = seq + 1
  1876.               ntries = 0
  1877.               call sendack(ack,pseq,'Y')
  1878.             end if
  1879.           else if (ptype .eq.'F') then   !  they lost our ACK
  1880.             call sendack(ack,pseq,'Y')   !  ACK again
  1881.             ntries = 0
  1882.           else                           !  probably 'E' or 'B' pkt
  1883.            state = abort
  1884.            if(ptype.eq.'E') call logpkt(px)
  1885.           end if                         !  if ptype
  1886.         else                             !  timeout or bad pkt
  1887.           call sendack(ack,expect,'N')   !  NAK it
  1888.         end if                             !  if status
  1889.       end if                             !  if ntries
  1890.       return
  1891.       end                                        !  subroutine getfile
  1892.  
  1893.  
  1894. !-cr.send-!
  1895.       subroutine ktrans()
  1896.       implicit integer(a-z)
  1897.       ! Function : State-switcher for shipping files out.
  1898.       !            Called Procedures change the state. Complete state
  1899.       !            occurs after sendeof finds arg list empty, or after
  1900.       !            a called procedure signals abort state.
  1901.       ! Called Procedures : sendinit, sendhdr, sendfile, sendeof,
  1902.       !                     sendbrk, errorpkt, logline, kfclose, kgetime,
  1903.       !                     tdisp
  1904.       parameter( init = 1, hdr = 2, data = 3, feof = 4, break = 5,
  1905.      !           abort = 6, complete = 7 )
  1906.       parameter( seconds = 1000000, ms = 1000)
  1907.       character cmdstr*80, report*40
  1908.       logical lastbuf, savedcr
  1909.  
  1910.       common /states/ state, retry, ntries, oldtries, seq
  1911.      !                 , delay, stdelay, tcpu, tio
  1912.       common /pkstats/   bptr, bufhold, maxpack, lastbuf
  1913.      !                 , rpcount, savedcr
  1914.       common /strings/ cmdstr, report
  1915.  
  1916.       character*4 cpr, tpr
  1917.       character *4 dval
  1918.  
  1919.       ntries = 0
  1920.       delay = stdelay
  1921.       call kgetime(tcpu,tio)            !  get initial trans. times
  1922.       state = init
  1923.  
  1924. 100   if ( state .ne. complete ) then
  1925.         if (state .eq. init) then
  1926.           call sendinit
  1927.         else if (state .eq. hdr) then
  1928.           call sendhdr
  1929.         else if (state .eq. data) then
  1930.           call sendfile
  1931.         else if (state .eq. feof) then
  1932.           call sendeof
  1933.         else if (state .eq. break) then
  1934.           call sendbrk
  1935.         else if (state .eq. abort) then
  1936.           call errorpkt(report)
  1937.           call logline(report)
  1938.           call kfclose()         ! close send file
  1939.           state = complete
  1940.         else
  1941.           report = 'unrecognized state.'
  1942.           state = abort
  1943.         end if
  1944.         go to 100
  1945.       end if                      !  if not complete
  1946.  
  1947.       call tdisp(seq+1,tpr)
  1948.       call logline('Number of packets sent = '//tpr//'$$')
  1949.       !  log elapsed times for trans.
  1950.       call kgetime(tcx,tix)            !  get times used till now
  1951.       call tdisp((tcx-tcpu)/ms,cpr)    !  printable cpu time in ms
  1952.       call tdisp((tix-tio)/seconds,tpr)
  1953.       call logline('Tr time : cpu='//cpr
  1954.      !     //' ms, io='//tpr//' sec$$')
  1955.  
  1956.       return
  1957.       end                        ! subroutine ktrans
  1958.  
  1959.  
  1960.       subroutine sendinit()
  1961.       implicit integer(a-z)
  1962.       !  Function :  This routine sends an 'S' pkt with our params
  1963.       !              and looks for partner's params in his ACK.
  1964.       !              If valid ACK is rec'd and we can comply with
  1965.       !              partner's specs., then state <== hdr;  else if
  1966.       !              we cant resolve params or we dont receive ACK in
  1967.       !              requisite num. tries, state <== abort.
  1968.       !  Called Procedures :  encode,sendpkt, getpkt, decode
  1969.  
  1970.       parameter( hdr = 2, break = 5, abort = 6 )
  1971.       parameter( good = 0, bad = 1, timeout = 2, escape = 3 )
  1972.       parameter( thispkt = 1, nxtpkt = 2 )
  1973.       parameter( initry = 20 )           !  allow more tries for S pkt
  1974.  
  1975.       logical resolve
  1976.       character ptype, kchar
  1977.       character cmdstr*80, report*40
  1978.       character *104 packet(2)
  1979.       character *4 dval
  1980.  
  1981.       common /states/ state, retry, ntries, oldtries, seq,
  1982.      !               delay, stdelay
  1983.       common /globals/ runtype, nargs, args(10,2), thisarg
  1984.       common /strings/ cmdstr, report
  1985.       common/packets/packet
  1986.  
  1987.        if (ntries .ge. initry) then
  1988.         delay = stdelay                      !  restore std delay
  1989.         report = 'can''t get ACK for S pkt.'
  1990.         state = abort
  1991.       else
  1992.         ntries = ntries + 1
  1993.         if (ntries .eq. 1)  then             ! if 1st try, prepare
  1994.           delay = delay * 2                  !  allow longer for S & F
  1995.           call encode(thispkt,0,'S')         !  make an S pkt
  1996.         end if
  1997.         call sendpkt(thispkt)                !  send our S pkt
  1998.         call getpkt(nxtpkt,status)           !  look for his ACK
  1999.         if (status .eq. good)  then          !  got a good pkt
  2000.           if ((packet(nxtpkt) (4:4) .eq. 'Y') .and.
  2001.      !     (packet(nxtpkt) (3:3) .eq. ' '))  then
  2002.             call decode(nxtpkt,resolve)      !  decode his params
  2003.             if (resolve) then
  2004.               state = hdr
  2005.             else
  2006.               state = abort
  2007.               report = 'cant resolve initial parameters.'
  2008.             end if
  2009.           else if((packet(nxtpkt)(4:4).eq.'N')
  2010.      !         .and.(packet(nxtpkt)(3:3).eq.'!'))
  2011.      !    then                           !  we lost their previous ACK
  2012.             state = hdr
  2013.           end if
  2014.           if (state.eq.hdr) then
  2015.             seq = 1
  2016.             ntries = 0
  2017.             thisarg = 1
  2018.           end if                         !  if state
  2019.         else if (status.eq.escape) then
  2020.           state = abort
  2021.           report = 'User Escape Request.'
  2022.         end if                           !  if status - else dont change
  2023.       end if           !  if ntries ok
  2024.       return
  2025.       end     ! subroutine sendinit
  2026.  
  2027.       subroutine sendhdr()
  2028.       implicit integer(a-z)
  2029.       !  Function :  This routine sends a 'F' (file header) pkt,
  2030.       !              and accepts its ACK from the other Kermit.
  2031.       !              The send file is opened and buffers initialized
  2032.       !              before the first attempt to send the pkt.
  2033.       !              If a valid ACK is received in the requisite number
  2034.       !              of tries, state <== data, else state <== abort.
  2035.       !              Discard-type ACK's are recognized in this state.
  2036.       !  Called Procedures : logline, kfopen, errorpkt, makehdr,
  2037.       !                      unchar, sendpkt, gotack
  2038.  
  2039.       character *104 packet(2)
  2040.       character cmdstr*80, report*40
  2041.       character *8 fname
  2042.       character *9 myparms,hisparms
  2043.       character kchar, signal
  2044.       logical lastbuf
  2045.  
  2046.       common /runparms/ myparms, hisparms
  2047.       common /states/ state, retry, ntries, oldtries, seq,
  2048.      !               delay, stdelay
  2049.       common /globals/ runtype, nargs, args(10,2), thisarg
  2050.       common /strings/ cmdstr, report
  2051.       common /packets/ packet, signal
  2052.       common /pkstats/ bptr, bufhold,  maxpack, lastbuf, rpcount
  2053.  
  2054.       parameter( hdr = 2, data = 3,  abort = 6 )
  2055.       parameter( thispkt = 1, ack = 2 )
  2056.       logical kfopen, gotack
  2057.  
  2058.       if (ntries .ge. retry) then
  2059.         report = 'can''t get ACK for F pkt.'
  2060.         state = abort
  2061.       else
  2062.         ntries = ntries + 1
  2063.         if (ntries .eq. 1) then
  2064.           !  Do file xfer initialization once,
  2065.           !  before sending 1st 'F' pkt :
  2066.           fname = cmdstr (args(thisarg,1):args(thisarg,2))
  2067.           if (.not.(kfopen(fname)))  then
  2068.             report = 'cant open:' // fname // '.'
  2069.             state = abort
  2070.             go to 800
  2071.           else
  2072.             report = 'Opened send file: '//fname
  2073.             call logline(report)
  2074.             call makehdr(thispkt,seq)    !  prepare the 'F' pkt
  2075.             bufhold = 0                  !  declare char buffer empty
  2076.             bptr = 1
  2077.             maxpack = unchar(hisparms(1:1)) + 1  !  last data pos
  2078.             if (myparms(3:3).ne.' ') then
  2079.                 ! Site Dependency : use pkt length 2 less than Partner's
  2080.                 ! bufsize, lest echoback of his pad & EOL chars overflow
  2081.                 ! his input buffer
  2082.                 maxpack = maxpack - 2
  2083.             end if
  2084.             signal = ' '                 !  set discard signal off
  2085.             lastbuf = .false.               !  set EOF indicator off
  2086.             rpcount = 0                 !  initialize repeat count
  2087.           end if
  2088.         end if                      !  if 1st try
  2089.         call sendpkt(thispkt)                     !  send an F pkt
  2090.         if (gotack(ack,seq)) then       !  if partner acknowledges
  2091.           seq = seq + 1
  2092.           ntries = 0
  2093.           if (signal.eq.' ')  then      !  no complications
  2094.             state = data                !  hdr ACKed, go to data state
  2095.           else                          !  The ACK was a discard signal
  2096.             state = feof                !  Go directly to EOF state
  2097.           end if                          !  If signal
  2098.         end if                            !  If gotack - else no change
  2099.       end if                     !  if ntries
  2100. 800   continue
  2101.       if (state .ne. hdr)  delay = stdelay         !  restore std. delay
  2102.       return
  2103.       end     ! subroutine sendhdr
  2104.  
  2105.       subroutine sendfile()
  2106.       implicit integer(a-z)
  2107.       !  Function :  This routine sends a 'D' (data) packet and
  2108.       !              looks for an ACK.  End of file is detected
  2109.       !              upon report from MAKEDATA, the data packet
  2110.       !              preparation rtne.  Discard-type ACK's are
  2111.       !              recognized in this state.
  2112.       !  Called Procedures : makedata, sendpkt, gotack
  2113.  
  2114.       parameter( thispkt = 1, ack = 2 )
  2115.       parameter( data = 3, feof = 4, abort = 6 )
  2116.       parameter( ok = 0, lastpkt = 1, nopkt=3, err = 4 )
  2117.       logical gotack
  2118.  
  2119.       character *104 packet(2)
  2120.       character signal
  2121.       character kchar, cksum
  2122.       character cmdstr*80, report*40
  2123.  
  2124.       common /states/ state, retry, ntries, oldtries, seq
  2125.      !              , delay, stdelay
  2126.       common /packets/ packet, signal
  2127.       common /strings/ cmdstr, report
  2128.  
  2129.       if (ntries.ge.retry)  then
  2130.         report = 'can''t get ACK for data pkt.'
  2131.         state = abort
  2132.       else
  2133.         ntries = ntries + 1
  2134.         if (ntries.eq.1) then            !  set up packet 1st time
  2135.           call makedata(seq,result)      !  get packetfull
  2136.           if (result.eq.nopkt) then
  2137.             state = feof
  2138.             ntries = 0
  2139.             go to 400
  2140.           else if (result.eq.err) then
  2141.             state = abort
  2142.             go to 400
  2143.           end if                         !  if nthg to send
  2144.         end if                           !  if 1st try
  2145.         call sendpkt(thispkt)            !  send data packet(n)
  2146.         if (gotack(ack,seq))  then       !  if partner acknowledges
  2147.           seq = seq + 1
  2148.           ntries = 0
  2149.           if ((signal.ne.' ').or.(result.eq.lastpkt)) then
  2150.             state = feof
  2151.           end if                          !  if signal - else dont change
  2152.         end if                            !  if gotack - else dont change
  2153.       end if                             !  if ntries
  2154. 400   continue
  2155.       return
  2156.       end    ! subroutine sendfile
  2157.  
  2158.       subroutine sendeof()
  2159.       implicit integer(a-z)
  2160.       !  Function :  Sends a 'Z' pkt indicating end-of-file.
  2161.       !              If this state was entered in response to an
  2162.       !              interrupt-request (other Kermit's discard-type
  2163.       !              ACK for a previous pkt) or if no more files to
  2164.       !              send, then state <== break,  else state <== hdr.
  2165.       !              Discard-type ACK's are recognized in this state.
  2166.       !  Called Procedures :  logline, sendpkt, gotack, kfclose
  2167.  
  2168.       parameter( hdr = 2, break = 5, abort = 6, complete = 7 )
  2169.       parameter( thispkt=1, ack=2 )
  2170.       parameter( good = 0, bad = 1, timeout = 2 )
  2171.  
  2172.       logical gotack, debug
  2173.       character *104 packet(2)
  2174.       character signal
  2175.       character cmdstr*80, report*40
  2176.  
  2177.       common /states/ state, retry, ntries, oldtries, seq
  2178.      !               , delay, stdelay
  2179.  
  2180.       common /globals/ runtype, nargs, args(10,2), thisarg
  2181.       common /packets/ packet, signal
  2182.       common /strings/ cmdstr, report
  2183.       common /environ/ debug
  2184.  
  2185.       if (ntries .ge. retry) then
  2186.         report = 'can''t get ACK for Z pkt.'
  2187.         state = abort
  2188.       else
  2189.         ntries = ntries + 1
  2190.         if (ntries .eq. 1)  call makeof(thispkt,seq)
  2191.         call sendpkt(thispkt)
  2192.         if (gotack(ack,seq))  then
  2193.           ntries = 0
  2194.           call kfclose     !  close the file just sent
  2195.           if (debug)  call logline('close send file$$')
  2196.           seq = seq + 1
  2197.           if ((thisarg .lt. nargs).and.(signal.ne.'Z'))  then
  2198.             thisarg = thisarg + 1    !  index next fname
  2199.             state = hdr
  2200.           else                   !  no more files to send
  2201.             state = break
  2202.           end if
  2203.         end if                   !  if gotack
  2204.       end if
  2205.       return
  2206.       end     ! subroutine sendeof
  2207.  
  2208.       subroutine sendbrk()
  2209.       implicit integer(a-z)
  2210.       !  Function :  Sends a 'B' (break) packet indicating completion
  2211.       !              of current transmission.  If valid ACK is received
  2212.       !              state <== complete, else state <== abort.
  2213.       !  Called Procedures :  kchar, sendpkt, getpkt
  2214.  
  2215.       character kchar, myseq
  2216.       character *104 packet(2)
  2217.       character cmdstr*80, report*40
  2218.  
  2219.       common /states/ state, retry, ntries, oldtries, seq
  2220.      !              , delay, stdelay
  2221.       common /packets/ packet
  2222.       common /strings/ cmdstr, report
  2223.  
  2224.       parameter( abort = 6, complete = 7 )
  2225.       parameter( thispkt = 1, ack = 2)
  2226.       parameter( good = 0, bad = 1, timeout = 2 )
  2227.  
  2228.       if (ntries .eq. retry) then
  2229.         report = 'can''t get ACK for Break pkt.'
  2230.         state = abort
  2231.       else
  2232.         ntries = ntries + 1
  2233.         if (ntries .eq. 1)  call makebrk(thispkt,seq)
  2234.         call sendpkt(thispkt)
  2235.         call getpkt(ack,status)
  2236.         if (status .eq. good)  then
  2237.           myseq = kchar(mod(seq,64))
  2238.           if ((packet(ack) (4:4) .eq. 'Y') .and.
  2239.      !        (packet(ack) (3:3) .eq. myseq))
  2240.      !    then
  2241.             state = complete
  2242.           end if         !  else NAK, wrong ACK - dont change
  2243.         end if           ! if status ...  else dont change state
  2244.       end if
  2245.       return
  2246.       end      ! subroutine sendbrk
  2247.  
  2248.  
  2249.       subroutine encode(pindex, seq,type)
  2250.       implicit integer(a-z)
  2251.       ! Function : puts current cray parameters into an 'S' packet
  2252.       !             (if called in SEND state) or a 'Y' packet
  2253.       !             (if called from RECEIVE state).
  2254.       ! Called Procedures : kchar, cksum
  2255.       character kchar, cksum, type
  2256.       character *104 packet(2)
  2257.       character *9 myparms, hisparms
  2258.  
  2259.       common /packets/ packet
  2260.       common /runparms/ myparms, hisparms
  2261.  
  2262.       parameter( soh = 1, cr = 13, numparm = 9 )
  2263.  
  2264.       packet(pindex) (2:2) = kchar( numparm + 3 )  ! set count
  2265.       packet(pindex) (3:3) = kchar(mod(seq,64))
  2266.       packet(pindex) (4:4) = type               ! set type
  2267.       packet(pindex) (5:13) = myparms(1:9)
  2268.       packet(pindex)(14:14) = cksum(packet(pindex))
  2269.  
  2270.       return
  2271.       end      ! subroutine encode
  2272.  
  2273.       subroutine makehdr(pindex,seq)
  2274.       implicit integer(a-z)
  2275.       ! Function : Makes an 'F' (header) packet,  getting file name
  2276.       !            from user's input line, saved in cmdstr.
  2277.       ! Called Procedures : kchar, cksum
  2278.  
  2279.       character *80 cmdstr
  2280.       character *104 packet(2)
  2281.       common /strings/ cmdstr
  2282.       common /globals/ rtype,n, args(10,2), thisarg
  2283.       common /packets/ packet
  2284.       character kchar,cksum
  2285.  
  2286.       arglen = args(thisarg,2) - args(thisarg,1) + 1
  2287.       packet (pindex) (2:2) = kchar(arglen+3)
  2288.       packet (pindex) (3:3) = kchar(mod(seq,64))
  2289.       packet (pindex) (4:4) = 'F'
  2290.       packet(pindex)(5:4+arglen) =
  2291.      !         cmdstr (args(thisarg,1) : args(thisarg,2))
  2292.       packet(pindex) (5+arglen:5+arglen) = cksum(packet(pindex))
  2293.  
  2294.       return
  2295.       end     ! subroutine makehdr
  2296.  
  2297.       subroutine makeof(pindex,seq)
  2298.       implicit integer(a-z)
  2299.       ! Function : If signal is the normal blank, makes a std
  2300.       !            'Z' pkt indicating normal EOF,  else
  2301.       !            makes a discard-type 'Z' packet.
  2302.       ! Called Procedures : kchar, cksum
  2303.  
  2304.       character *104 packet(2)
  2305.       character signal, cx
  2306.       common /packets/ packet, signal
  2307.       character kchar,cksum
  2308.  
  2309.       if (signal.eq.' ') then           ! Normal EOF - no data field.
  2310.         packet (pindex) (2:2) = kchar(3)
  2311.       else                              ! Interrupt signal - need data fld
  2312.         packet(pindex)(2:2) = kchar(4)
  2313.       end if
  2314.       packet (pindex) (3:3) = kchar(mod(seq,64))
  2315.       packet (pindex) (4:4) = 'Z'
  2316.       if (signal.eq.' ') then           ! It's a normal EOF
  2317.         packet(pindex)(5:5) = cksum(packet(pindex))
  2318.       else                              ! We've received interrupt signal
  2319.         packet(pindex)(5:5) = 'D'       ! Tell them to close and Discard
  2320.         packet(pindex)(6:6) = cksum(packet(pindex))
  2321.       end if
  2322.  
  2323.       return
  2324.       end    ! subroutine makeof
  2325.  
  2326.       subroutine makebrk(pindex,seq)
  2327.       implicit integer(a-z)
  2328.       character *104 packet(2)
  2329.       common /packets/ packet
  2330.       character kchar,cksum
  2331.  
  2332.       packet (pindex) (2:2) = kchar(3)
  2333.       packet (pindex) (3:3) = kchar(mod(seq,64))
  2334.       packet (pindex) (4:4) = 'B'
  2335.       packet(pindex)(5:5) = cksum(packet(pindex))
  2336.  
  2337.       return
  2338.       end     ! subroutine makebrk
  2339.  
  2340.       subroutine decode(pindex,ok)
  2341.       implicit integer(a-z)
  2342.       ! Function : Saves partner's params & resolves with ours.
  2343.       !            Returns ok = .true. iff we can comply with
  2344.       !            partner's parameters, else ok = .false.
  2345.       ! Called Procedures : kchar, unchar, logline
  2346.  
  2347.       logical ok, debug, native, quote8, repeat
  2348.       character kchar
  2349.       character *104 packet(2)
  2350.       character cmdstr*80, report*40
  2351.       character *9 myparms, hisparms, default
  2352.       common /runparms/ myparms, hisparms, default
  2353.       common /environ/ debug, native, quote8, repeat
  2354.       common /packets/ packet
  2355.       common /strings/ cmdstr, report
  2356.  
  2357.       hislast = unchar(packet(pindex)(2:2)) + 1   ! index last data char
  2358.       if (hislast .gt. 4) then
  2359.         if (debug) then
  2360.           report = 'Partner''s params received: '//
  2361.      !    packet(pindex)(5:hislast) //'$$'
  2362.           call logline(report)
  2363.         end if
  2364.         do 50 i=5, hislast
  2365.           j = i-4
  2366.           if (packet(pindex)(i:i) .ne. ' ') then
  2367.             hisparms(j:j) = packet(pindex)(i:i)  ! save char he asks for
  2368.           else
  2369.             hisparms(j:j) = default(j:j)
  2370.           end if
  2371. 50      continue
  2372.       end if
  2373.       !  Use standard defaults for his omissions :
  2374.       if (hislast .lt. 13)  then     ! if he didnt specify all
  2375.         hisparms(hislast-3:9) = default(hislast-3:9)
  2376.       end if
  2377.       ok = .true.                        !  start optimistically
  2378.       !  Treat Partner's BUFSIZE param as max count he wants :
  2379.       hisbuf = unchar(hisparms(1:1)) + 2 ! packet length he wants
  2380.       hisnpad = unchar(hisparms(3:3))    ! no. pad chars he wants
  2381.       ! now make sure we agree on things ..
  2382.       if ((hisparms(7:7).eq.'&').or.(hisparms(7:7).eq.'Y'))
  2383.      !then
  2384.         quote8 = .true.
  2385.       else
  2386.         quote8 = .false.
  2387.       end if
  2388.       hisparms(8:8) = '1'          !  I only do 1-char checks
  2389.       if ((hisparms(9:9).eq.'~').and.(myparms(9:9).eq.'~')) then
  2390.         repeat = .true.            !  We both agree to do 8th bits
  2391.       else
  2392.         repeat = .false.
  2393.       end if
  2394.       if (hisbuf .lt. 6) then       !  call that a packet?
  2395.         ok = .false.
  2396.       else if (hisbuf+hisnpad .gt. 104) then
  2397.         ok = .false.
  2398.       end if
  2399.       ! decode his eol
  2400.       hisparms(5:5) = char(unchar(hisparms(5:5)))  ! save true eol char
  2401.       return
  2402.       end       ! subroutine decode
  2403.  
  2404.       subroutine errorpkt(msg)
  2405.       implicit integer(a-z)
  2406.       ! Function : formats an error packet w/msg arg text
  2407.       ! Called Procedures : kchar, cksum
  2408.       parameter (thispkt = 1, soh=01 )
  2409.       character *40 msg
  2410.       character *104 packet(2)
  2411.       character kchar, cksum
  2412.       common /states/ state, retry, ntries, oldtries, seq
  2413.       common /packets/ packet
  2414.  
  2415.       k = index(msg,'.')      ! look for a delimiter
  2416.       if (k.eq.0)  k = 40        ! if none - xfer max
  2417.       packet(thispkt)(2:2) = kchar(k+3)
  2418.       packet(thispkt)(3:3) = ' '           ! no seq.
  2419.       packet(thispkt)(4:4) = 'E'           ! type is Error
  2420.       packet(thispkt)(5:4+k) = msg(1:k)
  2421.       packet(thispkt)(5+k:5+k) = cksum(packet(thispkt))
  2422.       call sendpkt(thispkt)
  2423.       return
  2424.       end      ! subroutine errorpkt
  2425.  
  2426. !-cr.stdutils-!
  2427.       character function kchar(n)
  2428.       ! maps an integer n=(0,136)octal onto the nth character
  2429.       ! in the ascii printable range : 40,176 octal
  2430.  
  2431.         kchar = char( n + 040b )
  2432.         return
  2433.       end
  2434.  
  2435.       character function kctl(n)
  2436.       ! Function : maps true ctl char (ascii 000 - 037) onto unique
  2437.       !            printable representation.
  2438.       character n
  2439.  
  2440.       kctl = char( ichar(n) .xor. 100b)
  2441.       return
  2442.       end
  2443.  
  2444.       integer function unchar(n)
  2445.       ! Function : maps print char onto decoded octal
  2446.       character n
  2447.  
  2448.         unchar = ichar(n) - 40b
  2449.       return
  2450.       end
  2451.  
  2452.       character function cksum(cpkt)
  2453.       implicit integer(a-z)
  2454.       !Function : computes Type 1 checksum for argument pkt
  2455.       ! Called Rtnes : unchar, kchar
  2456.  
  2457.       character kchar
  2458.       character *104 cpkt
  2459.  
  2460.       count = unchar(cpkt(2:2))       ! decode to true count
  2461.       sum = 0        ! initialize
  2462.       do 100 i=2,count + 1
  2463.         sum = sum + ichar(cpkt(i:i))  ! add coded char value
  2464. 100   continue
  2465.       sum = (sum + shiftr(sum .and. 300b , 6)) .and. 077b
  2466.       cksum = kchar(sum)
  2467.       return
  2468.       end
  2469.  
  2470.       integer function strad(x)
  2471.       ! returns word addr of string argument
  2472.       parameter( strmask = 77700000000000b )
  2473.  
  2474.       itemp = loc(x)
  2475.       strad = ( itemp .and. strmask ) .xor. itemp
  2476.       return
  2477.       end
  2478.  
  2479.       logical function member(word,pattern)
  2480.       implicit integer(a-z)
  2481.       character word*8, pattern*1
  2482.  
  2483.       if (index(word,pattern).eq.0)  then
  2484.         member = .false.
  2485.       else
  2486.         member = .true.
  2487.       end if
  2488.       return
  2489.       end                               !  logical fn member
  2490.  
  2491.       subroutine stdname(string)
  2492.       implicit integer(a-z)
  2493.       !  Function : Converts incoming file name from uppercase to lower,
  2494.       !             and if there is a trailing dot, but no suffix, blanks
  2495.       !             out the dot.
  2496.       character*8 string
  2497.       parameter(dot=056b)
  2498.  
  2499.       do 10 i=1,8
  2500.         cval = ichar(string(i:i))
  2501.         if ((cval.ge.101b).and.(cval.le.132b)) then
  2502.           string(i:i) = char(cval+40b)   !  Convert to lower case
  2503.         end if
  2504. 10    continue
  2505.       dx = index(string(1:8),char(dot))
  2506.       if (dx.gt.0) then                  !  file name has a dot
  2507.         !  See if the dot is followed by a Suffix :
  2508.         if (dx.eq.8) then
  2509.           string(dx:dx) = ' '            !  blank out the dot
  2510.         else if (string(dx+1:dx+1).eq.' ') then
  2511.           string(dx:dx) = ' '
  2512.         end if                           !  if no suffix follows the dot
  2513.         ! else leave dot and suffix in file name
  2514.       end if                             !  if file name has embedded dot
  2515.       return
  2516.       end
  2517.  
  2518.  
  2519.       subroutine tdisp(value,pval)
  2520.       implicit integer(a-z)
  2521.       ! Function : converts integer value to Ascii equivalent
  2522.       character*4 pval
  2523.  
  2524.       if (value.gt.9999)  then
  2525.         pval(1:4) = ' big'
  2526.       else
  2527.         p2 = value/10
  2528.         p3 = p2/10
  2529.         p4 = p3/10
  2530.         pval(1:4) = char(p4+48)//char(mod(p3,10)+48) //
  2531.      !               char(mod(mod(p2,100),10)+48) //
  2532.      !               char(mod(mod(mod(value,1000),100),10)+48)
  2533.       end if
  2534. 70    return
  2535.       end                                !  subroutine tdisp
  2536.  
  2537.       subroutine undisp(str,val,code)
  2538.       implicit integer(a-z)
  2539.       ! Function : converts 2-digit Ascii string to numeric value
  2540.       character *2 str
  2541.       logical code
  2542.  
  2543.       if ((str(1:1).ge.'0').and.(str(1:1).le.'9').and.
  2544.      !    (str(2:2).ge.'0').and.(str(2:2).le.'9')) then
  2545.         val = 10*(ichar(str(1:1))-48) + ichar(str(2:2)) - 48
  2546.         code = .true.
  2547.       else
  2548.         val = 0
  2549.         code = .false.
  2550.       end if
  2551.       return
  2552.       end                                  ! subroutine undisp
  2553.  
  2554.       subroutine logger
  2555.       implicit integer(a-z)
  2556.       character *104 packet(2)
  2557.       character *80 logit
  2558.       logical status, fexist, fopen
  2559.       common /units/ logioc, fioc
  2560.       common /packets/ packet
  2561.  
  2562.       entry initlog(status)
  2563.  
  2564.       inquire(iostat=ios,exist=fexist,opened=fopen,file='kmtlog')
  2565.       if ((ios.ne.0).or.( fexist.and.fopen)) then
  2566.         status = .false.
  2567.         go to 100
  2568.       else
  2569.         if (fexist) then
  2570.           call destroy(logioc,'kmtlog',0,dstat)
  2571.           if (dstat.ne.0) then
  2572.             status = .false.
  2573.             go to 100
  2574.           end if
  2575.         end if
  2576.         open(unit=logioc,iostat=ios,file='kmtlog',status='new')
  2577.         if (ios.ne.0) then
  2578.           status = .false.
  2579.           go to 100
  2580.         else
  2581.           status = .true.
  2582.         end if
  2583.       end if
  2584.       go to 100
  2585.  
  2586.       entry logline(logit)
  2587.       ! Function : writes calling string argument onto std logfile.
  2588.       !            Uses 1st 40 chars if no '$$' terminator in string.
  2589.  
  2590.  
  2591.       k = index(logit,'$')
  2592.       if ((k.eq.0).or.(logit(k+1:k+1).ne.'$'))
  2593.      !then                               ! no terminator, use default
  2594.         k = 40
  2595.       else
  2596.         k = k-1
  2597.       end if
  2598.       write(unit=logioc,fmt=*) logit(1:k)
  2599.       go to 100
  2600.  
  2601.       entry logpkt(px)
  2602.       ! Function : writes the packet indexed in calling argument
  2603.       !            onto std logfile.  This routine is called from
  2604.       !            the SENDPKT and GETPKT routines if the debug
  2605.       !            option is on.
  2606.  
  2607.       k = unchar(packet(px)(2:2)) + 2    ! number of chars. to log
  2608.       write(unit=logioc,fmt=*) packet(px)(1:k)
  2609.       go to 100
  2610.  
  2611.       entry endlog
  2612.  
  2613.       close(unit=logioc,iostat=ios,status='keep')
  2614.  
  2615. 100   continue
  2616.       return
  2617.       end                                !  subroutine logger
  2618.