home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / d / k20mit-262.mac < prev    next >
Text File  |  2020-01-01  |  127KB  |  3,976 lines

  1. ;PS:<TIMREK>KERMIT.MAC.56,  4-May-83 09:01:16, Frank
  2. ;[32] Report bad checksums correctly when debugging.  
  3. ; Report error message from server & "abort" if it can't get a file.
  4. ;PS:<TIMREK>KERMIT.MAC.54, 26-Apr-83 19:08:00, Frank
  5. ;[31] Beep when done with a transfer, if local.
  6. ;PS:<KERMIT>20KERMIT.MAC.8, 15-Apr-83 14:45:36, Frank
  7. ;[30] A NAK for the next packet is *not* the same as an ACK for the current
  8. ; packet if the current packet is Send-Init.
  9. ;PS:<TIMREK>KERMIT.MAC.42, 15-Apr-83 11:39:08, Frank
  10. ;[29] When debugging packets, print checksum of incoming packets, and  
  11. ; print bad packets.
  12. ;PS:<TIMREK>KERMIT.MAC.41,  8-Apr-83 19:31:28, Frank
  13. ;[28] Add FINISH command.  
  14. ;PS:<TIMREK>KERMIT.MAC.29,  8-Apr-83 12:43:02, Frank
  15. ;[27] Fix ^C trap to DEBRK to the right place in all cases.
  16. ;PS:<TIMREK>KERMIT.MAC.28,  8-Apr-83 09:38:49, Frank
  17. ;[26] Save and restore normal send timeout when going in & out of server 
  18. ; command-wait.
  19. ;PS:<TIMREK>KERMIT.MAC.27,  7-Apr-83 20:20:15, Bill C.
  20. ;[25] Neaten up SERVER mode time out changes.
  21. ;PS:<TIMREK>KERMIT.MAC.20,  5-Apr-83 18:14:14, Frank
  22. ;[24] Fix SPAR to account for the actual length of an incoming SEND-INIT.  
  23. ;PS:<TIMREK>KERMIT.MAC.19,  5-Apr-83 17:46:23, Frank
  24. ;[23] Include both send and receieve parameters in SHOW command.  
  25. ;PS:<TIMREK>KERMIT.MAC.4, 3:20pm  Tuesday, 5 April 1983, Frank
  26. ;[22] Add debugging options.  Remove i/o to DIAJFN and just test LOCAL and
  27. ; DEBUG flag values.  Make DEBUG an AC, move RTOT & STOT to memory.
  28. ;PS:<TIMREK>KERMIT.MAC.81,  1-Apr-83 15:59:19, Frank
  29. ;[21] Change SET SEND/RECEIVE QUOTE to parse an octal number.  The hairy
  30. ; .CMUQS/breakmask/.CMTOK parsing tended to hang the program...
  31. ;PS:<TIMREK>KERMIT.MAC.75,  1-Apr-83 15:13:43, Bill C.
  32. ;[20] Make packet time outs longer if in server mode awaiting commands.
  33. ;PS:<TIMREK>KERMIT.MAC.72,  1-Apr-83 12:55:40, Frank
  34. ;[19] Print "[OK]" for each file successfully sent or received, if local.  
  35. ;PS:<TIMREK>KERMIT.MAC.65, 31-Mar-83 16:43:20, Frank
  36. ;[18] Expanded help text, with individual help for each command.
  37. ; Added SET DUPLEX, SET SEND/RECEIVE START-OF-PACKET.
  38. ;PS:<TIMREK>KERMIT.MAC.58, 31-Mar-83 13:35:57, Bill C.
  39. ;[17] Restore CFIBFs of yore.  Clears up packet echoing and stacking.
  40. ;PS:<TIMREK>KERMIT.MAC.52, 31-Mar-83 10:58:12, Frank
  41. ;[16] Add SET ESCAPE (for CONNECT), try to print remote message after BYE.  
  42. ;PS:<TIMREK>KERMIT.MAC.48, 30-Mar-83 19:54:32, Frank
  43. ;[15] Don't bomb if we can't open a file to be sent, just print nice msg.
  44. ;PS:<TIMREK>KERMIT.MAC.47, 30-Mar-83 18:16:53, Frank
  45. ;[14] Add code for ^B interrupts, but don't use it for anything yet.
  46. ;PS:<TIMREK>KERMIT.MAC.45, 30-Mar-83 15:06:42, Frank
  47. ;[13] Don't delay before send if local.  
  48. ;PS:<TIMREK>KERMIT.MAC.41, 30-Mar-83 13:52:57, Frank
  49. ;[12] When local, print name of file being sent or received.
  50. ;PS:<TIMREK>KERMIT.MAC.33, 29-Mar-83 17:59:47, Frank
  51. ;[11] Talk to Kermit server.  Added BYE and GET commands.  
  52. ;************* Version 3 ****************
  53. ;PS:<TIMREK>KERMIT.MAC.22, 28-Mar-83 14:56:39, Frank
  54. ;[10] Enable ^C capability if not on already (reported by Willis Dair, SCU).
  55. ; If we can't enable it, don't go on unless we're running under batch.
  56. ;PS:<TIMREK>KERMIT.MAC.21, 20-Mar-83 17:55:27, Bill C.
  57. ;[9] Fixed SHOW command to print number of blips correctly.
  58. ;PS:<TIMREK>KERMIT.MAC.17, 18-Mar-83 20:31:00, Frank
  59. ;[8] Added some help to the help text.
  60. ;PS:<TIMREK>KERMIT.MAC.15, 18-Mar-83 19:03:51, Frank
  61. ;[7] Assign & deassign line if not already assigned.  This prevents
  62. ; "?Line is not active" and similar errors if Kermit is run on top of TTLINK
  63. ; rather than vice versa, and not under DIAL (both TTLINK and DIAL will do
  64. ; their own assigning, if necessary).  Thanks to Willis Dair, Santa Clara
  65. ; University, for pointing out the bug.
  66. ;PS:<TIMREK>KERMIT.MAC.14, 18-Mar-83 18:44:39, Frank
  67. ;[6] Differentiate between remote & local timeouts in SHOW command.  
  68. ; Add version #, date/time, etc, to SHOW.
  69. ; Replace a zillion NOUTs with NUMOUT macro.
  70. ;PS:<TIMREK>KERMIT.MAC.12, 17-Mar-83 18:47:21, Frank
  71. ;[5] Give error message when initial connection can't be made, if local.
  72. ;PS:<TIMREK>KERMIT.MAC.7, 17-Mar-83 15:54:33, Frank
  73. ;[4] When acting as local Kermit, show packet traffic by typing blips.
  74. ;PS:<TIMREK>KERMIT.MAC.6, 17-Mar-83 15:31:30, Frank
  75. ;[3] When comparing packet numbers, allow for wraparound.
  76. ;PS:<TIMREK>KERMIT.MAC.3, 17-Mar-83 10:53:03, Frank
  77. ;[2] Cont'd... Show range of timeouts in SHOW command.
  78. ;PS:<TIMREK>KERMIT.MAC.2, 15-Mar-83 12:51:12, Frank
  79. ;[2] Make timeouts load-dependent.  Fix spelling of "interrupt" everywhere.
  80. ;PS:<KERMIT>20KERMIT.MAC.22, 20-Feb-83 14:13:19, Bill C.
  81. ;[1] Put in a CFIBF% in the INILIN code to clear the line at the beginning
  82. ; of each send or receive of backed up NAKs.  This may not be just right.  This
  83. ; can lose a Send Init packet some times.  This will work til the problem can
  84. ; be looked at more closely.
  85. ;*************************** Major Version 2 ********************************
  86. ;PS:<SY.WBC3>KERMIT.MAC.20,  8-Feb-83 14:43:48, Bill C.
  87. ; Put in (FINALLY!) the SHOW command.
  88. ;PS:<SY.WBC3>KERMIT.MAC.11,  8-Feb-83 10:04:10, Bill C.
  89. ; Add SET PARITY command.  Eliminate IGNORE-PARITY as its functionality is
  90. ; replaced by SET PARITY SPACE.
  91. ;PS:<KERMIT>20KERMIT.MAC.3,  4-Feb-83 11:04:08, Bill C.
  92. ; Change TELNET to TTLINK (by FdC) and remove TELNET command.
  93. ;PS:<SY.WBC3>KERMIT.MAC.38, 26-Jan-83 15:35:37, Bill C.
  94. ; Make Kermit able to act as a SERVER.
  95. ;PS:<KERMIT>20-KERMIT.MAC.29, 18-Jan-83 14:08:45, Bill C.
  96. ; Take care of the case where user set terminal pause char to ^A.
  97. ;PS:<KERMIT>20-KERMIT.MAC.27, 11-Jan-83 13:19:06, Bill C.
  98. ; Fix ^C trap bug that caused illegal instruction.
  99. ;PS:<KERMIT>20-KERMIT.MAC.22, 11-Jan-83 11:40:01, Bill C.
  100. ; Fix bug in SET IGNORE-PARITY COMMAND.
  101. ;PS:<KERMIT>20-KERMIT.MAC.11, 10-Jan-83 16:52:03, Bill C.
  102. ; Add turn around char for the IBM running VM/CMS.
  103. ;PS:<KERMIT>20-KERMIT.MAC.8,  7-Jan-83 17:59:01, Bill C.
  104. ; Fix numerous mispellings of received.
  105. ;PS:<KERMIT>20-KERMIT.MAC.3,  7-Jan-83 16:06:04, Bill C.
  106. ; Clean up the diagnostic and error message code.
  107. ;PS:<KERMIT>20-KERMIT.MAC.2,  7-Jan-83 15:06:02, Bill C.
  108. ; Add the TELNET command (thanks to Bill Schilit.)  Change EXIT/CONT
  109. ;    sequence to not throw away JFN.
  110. ;PS:<KERMIT>KERMIT-20.MAC.2, 14-Dec-82 15:25:40, Bill C.
  111. ; Be scrupulous in PMAP use after errors.  Don't make files with holes.
  112. ;PS:<KERMIT>KERMIT.MAC.44, 28-Sep-82 09:47:32, Bill C.
  113. ; Add ignore parity option for some UNIX systems.
  114. ;PS:<KERMIT>KERMIT.MAC.19, 28-Apr-82 16:00:31, Bill C.
  115. ; Big clean up.  Consolidate duplicate sections of code.  Also,
  116. ;    no longer die on bad packet type, just NAK or retransmit.
  117. ;    Removed empty show command.
  118. ;PS:<KERMIT>KERMIT.MAC.18, 21-Apr-82 16:31:04, Bill C.
  119. ; Clean up line on ^C from transfer. 
  120. ;PS:<KERMIT>KERMIT.MAC.17, 17-Feb-82 16:16:10, Bill C.
  121. ; Add eight bit file mode.
  122. ;PS:<KERMIT>KERMIT.MAC.16, 28-Jan-82 12:31:09, Bill C.
  123. ; Clean up better on some error conditions.
  124. ;PS:<KERMIT>KERMIT.MAC.15,  6-Jan-82 12:18:06, Bill C.
  125. ; Fill out some of the SET command options.
  126.  
  127. ; THINGS TO DO...
  128. ;
  129. ; * Add new server functions: directory, type, delete, etc, and user commands
  130. ;   to invoke them.  Must first implement "X" packet handling.
  131. ;
  132. ; * Add host commands.  Fork an Exec, pass commands to it in rescan, somehow
  133. ;   pipe the Exec's typeout back, packetized.  Too bad this isn't UNIX...
  134. ;
  135. ; * Show incoming as well as outgoing packets when in debug mode?
  136. ;
  137. ; * Terminal interrupt for local Kermit to report status.
  138. ;
  139. ; * Terminal interrupt to "abort" transmission of current file.  Stopping
  140. ;   transmission of an outgoing file can be done easily by sending an error
  141. ;   packet.  The side receiving a file, upon receipt of an error packet should
  142. ;   know to discard the file rather than simply close it. (?)
  143. ;
  144. ; * It would be even better to have a one way to quit the current file
  145. ;   and go on to the next in a wildcard group, and another way to quit a whole
  146. ;   file group.
  147. ;
  148. ; * Terminal interrupts to switch debugging modes during a transfer.
  149. ;
  150. ; * 2-character checksum option: parse, put it in the packet routines, add
  151. ;   to SHOW command, etc.
  152. ;
  153. ; * Do 8th-bit quoting.  There's code for this laying around somewhere.  First
  154. ;   get it working 20-to-20, then add it to Kermit-80 &/or -86.
  155. ;
  156. ; * Data compression using repeat count for repeated characters -- best savings
  157. ;   realized in binary files.
  158. ;
  159. ; * Try this (make sure it doesn't break the other KERMITs) -- When receiving
  160. ;   a file, put the name I open the file under in the data field of the ACK to
  161. ;   the File Header.  When receiving File Headers in local mode, print the
  162. ;   contents of the data field instead of doing a JFNS if the data field is not
  163. ;   empty.  If this works OK, then try it out in some other KERMITs that
  164. ;   actually have to change the file name to avoid conflicts.
  165. ;
  166. ; * Investigate complaint about server mode versus autobyte after output of
  167. ;   an 8-bit file...
  168. ;
  169. ; * PUSH command.
  170. ;
  171. ; * TAKE command.
  172. ;
  173. ; * Automatic take of KERMIT.INIT or KERMIT.CMD?
  174. ;
  175. ; * Think a little more carefully about the load-dependent timeouts.  If the
  176. ;   timeout interval is set very long, maybe upon timing out we should check to
  177. ;   see if a packet has partially arrived before NAKing it...  Also, we should
  178. ;   do some experimentation to adjust the timeout function & its parameters
  179. ;   optimally -- right now, they're just rough stabs based on guesses.  Also,
  180. ;   take class scheduling into account when getting load average.
  181.  
  182.     Title Kermit -- That's Celtic for "free".
  183.  
  184. ; Needs only standard DEC-distributed external files MONSYM, MACSYM, CMD.
  185.  
  186.     search monsym,macsym,cmd
  187.     .require sys:macrel,sys:cmd
  188.     SALL            ; SHUT YOUR FACE
  189.     .DIRECTIVE FLBLST
  190.  
  191. $verno==^d3            ; Major version number.
  192. $mnver==^d0            ; Minor version number.
  193. $edno==^d32            ; Edit number.
  194. $who==^d0            ; Who edited.
  195.  
  196. ; Written by Bill Catchings, April 1981.
  197. ;
  198. ; This program is the DEC-20 implementation of a file transfer protocol for
  199. ; use over serial asynchronous communication lines.  See the KERMIT user and
  200. ; protocol manuals for the specifications.
  201. ;
  202. ; Version 1, 1981-82:  Basic service.
  203. ;
  204. ; Version 2, Feb 83:   Server service.
  205. ;
  206. ; Version 3, March 83: Talk to server.
  207.  
  208.     subttl Help Text.    ;[18] All of this is edit 18.
  209.  
  210. hkermi:    asciz |
  211. KERMIT is a file transfer protocol for use over an asynchronous serial
  212. telecommunication line.  Files are broken up into "packets" with checksums and
  213. other control information to ensure (with high probability) error-free and
  214. complete transmission.
  215.  
  216. KERMIT-20 is the KERMIT implementation for the DECSYSTEM-20.  KERMIT-20 can be
  217. run "locally" with a remote Kermit on the other end of an assigned TTY line
  218. (e.g. over an autodialer connection), or "remotely" from another computer
  219. (e.g.  a microcomputer).
  220.  
  221. You can run Kermit interactively by typing repeated commands in response to
  222. its "Kermit-20>" prompt, or you can invoke it from the TOPS-20 Exec with a
  223. command line argument (e.g. "kermit receive"), or you can run it as a remote
  224. server.
  225.  
  226. KERMIT-20 commands -- optional parts are in [brackets]:
  227.  
  228. * For exchanging files:        SEND file(s) [(INITIAL) file]
  229.                 RECEIVE [file]
  230.                 GET remote-file(s)
  231.  
  232. * For acting as local Kermit:    SET LINE, SET PARITY, DUPLEX, ESCAPE
  233.                 CONNECT [line]
  234.  
  235. * For acting as a server:    SERVER
  236.  
  237. * For talking to a server:    BYE, GET remote-file(s), SEND file(s)
  238.  
  239. * For running interactively:    PROMPT
  240.  
  241. * Setting nonstandard transmission and file parameters:
  242.     SET DEBUG, DELAY, FILE-BYTE-SIZE, PARITY
  243.     SET SEND (or RECEIVE) END-OF-LINE, START-OF-PACKET, PACKET-LENGTH,
  244.         TIMEOUT, PADDING.
  245.  
  246. * Getting information:        HELP [topic], STATUS, SHOW
  247.  
  248. * Leaving the program:        EXIT, QUIT, BYE
  249.  
  250.  
  251. For further information, type "help" for any of the above, e.g. "help set",
  252. or see the "Kermit Users Guide" and the "Kermit Protocol Manual" for complete
  253. details.
  254. |
  255.  
  256. hsend:    asciz |
  257. SEND filespec1 [(INITIAL) filespec2]
  258.  
  259. Send a file or file group from the DEC-20 to the other host.  If filespec1
  260. contains wildcard characters (* or %) then all matching files will be sent, in
  261. alphabetical order by name.  The name of each file is passed to the other host
  262. in a file header packet, so that the file can be stored there with the same
  263. name.
  264.  
  265. The INITIAL file in a wildcard group can be specified with the optional
  266. filespec2.  This is handy to continue a previously interrupted wildcard
  267. transfer from where it left off, or to skip some files that would be
  268. transmitted first.
  269.  
  270. If running as a local Kermit, the name of each file will be displayed on your
  271. screen as the transfer begins, a "." will be printed for every 5 data packets
  272. sucessfully sent, and a "%" for every retransmission or timeout that occurs.
  273. If you see many "%" characters, you are probably suffering from a noisy
  274. connection.
  275.  
  276. If running as a remote Kermit, you should escape back to your local Kermit and
  277. give the RECEIVE command.  If you don't do this fast enough, several
  278. "send-init" packets may arrive prematurely; don't worry, KERMIT-20 will keep
  279. sending them until it gets a response.
  280. |
  281.  
  282. hrecei:    asciz |
  283. RECEIVE    [filespec]
  284.  
  285. Receive a file or file group from the other host.  If only one file is being
  286. received, you may include the optional filespec as the name to store it under
  287. when it arrives; otherwise, the name is taken from the incoming file header
  288. packet.  Even if the name in the header packet is not a legal TOPS-20 file
  289. name, KERMIT-20 will store it under that name, in which case you can refer to
  290. it later only by quoting the illegal characters (spaces, lower case letters,
  291. control characters, etc) with ^V.
  292.  
  293. If a file with the same name already exists, KERMIT-20 just creates a new
  294. generation.
  295.  
  296. If running as a local Kermit, the names of the incoming files will be
  297. displayed on your screen, along with "." and "%" characters to indicate the
  298. packet traffic.  If running as a remote Kermit, you should escape back to your
  299. local Kermit and give the SEND command.
  300. |
  301.  
  302. hset:    asciz |
  303. SET
  304.   Establish system-dependent parameters.  You can examine their values with the
  305.   SHOW command.  The following may be SET:
  306.  
  307.  DEBUG option
  308.    Show packet traffic explicitly.  Only use when local.  Options are:
  309.      OFF      Don't show debugging information (OFF by default).
  310.      STATES   Show Kermit state transitions and packet numbers (brief).
  311.      PACKETS  Display each incoming and outgoing packet (verbose).
  312.  
  313.  DELAY number
  314.    How many seconds to wait before sending the first packet.  Use when remote
  315.    and SENDing files back to your local Kermit.  This gives you time to
  316.    "escape" back and issue a RECEIVE command.
  317.  
  318.  FILE-BYTE-SIZE keyword
  319.    Byte size for DEC-20 file input/output.  The choices are SEVEN, EIGHT, and
  320.    AUTO.  If SEVEN, do normal ASCII character i/o.  EIGHT is necessary for
  321.    transmission of non-DEC-20 binary files, like .COM files from
  322.    microcomputers.  AUTO is equivalent to SEVEN for incoming files, and for
  323.    outgoing files means to use EIGHT if the DEC-20 file bytsize (as shown by
  324.    the Exec VDIR command) is 8, otherwise use SEVEN.  The default is AUTO.
  325.  
  326.  PARITY keyword
  327.    If the other computer is using parity on the communication line, you must
  328.    inform KERMIT-20, so it can send the desired parity on outgoing characters,
  329.    and strip it from incoming ones.  The DEC-20 does not use parity on
  330.    communication lines.  The choices are NONE (the default), ODD, EVEN, MARK,
  331.    and SPACE.  NONE means no parity processing is done, and the 8th bit of
  332.    each character can be used for data when transmitting binary files.
  333.    The specified parity is used both for terminal connection (CONNECT) and
  334.    file transfer (SEND, RECEIVE, GET).
  335.  
  336.  DUPLEX keyword
  337.    For use when CONNECTed to a remote system.  The choices are FULL and HALF.
  338.    Full means the remote system echoes the characters you type, HALF means
  339.    the local system echoes them.  FULL is the default, and is used by most
  340.    hosts.  HALF is necessary when connecting to IBM mainframes.
  341.  
  342.  IBM-FLAG
  343.    Equivalent to SET PARITY MARK and SET DUPLEX HALF, plus it instructs
  344.    KERMIT-20 to look for the IBM system's "line turnaround" character before
  345.    sending packets.
  346.  
  347.  LINE number
  348.    Specify the octal TTY number to use for file transfer or CONNECT.
  349.    If you issue this command, you will be running as a local Kermit, and you
  350.    must log in to the remote system and run Kermit on that side in order to
  351.    transfer a file.  If you don't issue this command, KERMIT-20 assumes it is
  352.    running remotely, and does file transfer over its job's controlling
  353.    terminal line.
  354.  
  355.  ESCAPE number
  356.    Tell what control character you want to use to "escape" from remote
  357.    connections.  31 (Control-Y) by default.  The number is the octal value of
  358.    the ASCII control character, 1 to 37.
  359.  
  360.  SEND parameter
  361.    Parameters for outgoing packets, as follows:
  362.  
  363.    END-OF-LINE number 
  364.      The octal value of the ASCII character to be used as a line terminator
  365.      for packets, if one is required by the other system.  Carriage return
  366.      (15) by default. 
  367.  
  368.    PACKET-LENGTH number
  369.      Maximum packet length to send, decimal number, between 10 and 94, 80 by
  370.      default. 
  371.  
  372.    TIMEOUT number
  373.      How many seconds to wait for a packet before trying again.
  374.  
  375.    PADDING number, PADCHAR number
  376.      How much padding to send before a packet, if the other side needs padding,
  377.      and what character to use for padding.  Defaults are no padding, and NUL
  378.      (0) for the padding character.  No cases are presently known where this
  379.      is necessary.
  380.  
  381.    QUOTE number
  382.      What printable character to use for quoting of control characters.
  383.      Specify an octal ASCII value.  "#" (43) by default.  There should be no
  384.      reason to change this. 
  385.  
  386.    START-OF-PACKET number
  387.      The control character that marks the beginning of a packet.  Normally
  388.      SOH (Control-A, ASCII 1).  There should be no reason to change this.
  389.  
  390.  RECEIVE parameter
  391.    Parameters to request or expect for incoming packets, as follows:
  392.  
  393.    END-OF-LINE number 
  394.      Carriage return (15) by default.  The DEC-20 does not actually need any
  395.      line terminator for incoming packets.
  396.  
  397.    PACKET-LENGTH number
  398.      Maximum packet length packet for the other side to send, decimal number,
  399.      between 10 and 94, 80 by default. 
  400.  
  401.    TIMEOUT number
  402.      How many seconds the other Kermit should wait for a packet before asking
  403.      for retransmission.
  404.  
  405.    PADDING number, PADCHAR number
  406.      Never necessary; the DEC-20 needs no padding.
  407.  
  408.    QUOTE number
  409.      What printable character to use for quoting of control characters.
  410.      Specify the octal ASCII value.  "#" (43) by default.  There should be no
  411.      reason to change this. 
  412.  
  413.    START-OF-PACKET number
  414.      The control character to mark the beginning of incoming packets.  Normally
  415.      SOH (Control-A, ASCII 1).  There should be no reason to change this.
  416. |
  417.  
  418. hshow:    asciz |
  419. SHOW
  420.  
  421. Display current SET parameters, version of KERMIT-20, and other info.
  422. Items under RECEIVE column show parameters for packets KERMIT-20 expects
  423. to receive, under SEND shows parameters for outgoing packets.
  424. |
  425.  
  426. hstatu:    asciz |
  427. STATUS
  428.  
  429. Give statistics about the most recent file transfer.
  430. |
  431.  
  432. hconne:    asciz |
  433. CONNECT [number]
  434.  
  435. Establish a terminal connection to the system connected to the octal TTY
  436. number specified here or in the most recent SET LINE command, using full
  437. duplex echoing and no parity unless otherwise specified in previous SET
  438. commands.  Get back to KERMIT-20 by typing the escape character followed by
  439. the letter C.  The escape character is Control-Y by default.  When you type
  440. the escape character, several single-character commands are possible:
  441.  
  442. C -- Close the connection and return to KERMIT-20.
  443. S -- Show status of the connection.
  444. P -- Push to a new Exec.  POP from the Exec to get back to the connection.
  445. ^Y (or whatever you have set the escape character to be) -- Typing the escape
  446.  character twice sends one copy of it to the connected host.
  447.  
  448. You can use the SET ESCAPE command to define a different escape character.
  449.  
  450. KERMIT-20 accomplishes the connection by running the TTLINK program in a lower
  451. fork.  If all you want to do connect to a remote host over a TTY line, without
  452. file transfer, you can run TTLINK itself.  TTLINK also provides other options,
  453. like logging of the remote session to provide "unguarded" capturing of files
  454. or typescripts from systems that do not have KERMIT.
  455. |
  456.  
  457. hserve:    asciz |
  458. SERVER
  459.  
  460. Act as a server for another Kermit.  Take all further commands only from the
  461. other Kermit.  Only works when running remotely.  After issuing this command,
  462. escape back to your local system and issue SEND, RECEIVE or GET, BYE, or other
  463. server-oriented commands from there.  If your local KERMIT does not have a BYE
  464. command, it does not have the full ability to communicate with a KERMIT server
  465. (in which case you can only use the SEND command).  If your local KERMIT does
  466. have a BYE command, use it to shut down and log out the KERMIT server when you
  467. are done with it; otherwise, connect back to the DEC-20, type several
  468. Control-C's to stop the server, and logout.
  469.  
  470. For doing nonstandard kinds of file transfer (for instance to send binary
  471. files from a microcomputer), you should issue the appropriate SET commands
  472. before the SERVER command.
  473. |
  474.  
  475. hfinis:    asciz |
  476. FINISH
  477.  
  478. When running as a local Kermit, talking to a KERMIT server over a TTY line
  479. specified in a SET LINE command, use the FINISH command to shut down the
  480. server without logging out the remote job, so that you can CONNECT back to it.
  481. |
  482. hbye:    asciz |
  483. BYE     
  484.  
  485. When running as a local Kermit, talking to a KERMIT server over a TTY line
  486. specified in a SET LINE command, use the BYE command to shut down and log out
  487. the server.  This will also exit from the local KERMIT.
  488. |
  489.  
  490. hhelp:    asciz |
  491. HELP [topic]
  492.  
  493. Typing HELP alone prints a brief summary of KERMIT-20 and its commands.
  494. You can also type
  495.  
  496.    HELP command
  497.  
  498. for any Kermit-20 command, e.g. "help send", to get more detailed information
  499. about a specific command.  Type
  500.  
  501.    HELP ?
  502.  
  503. to see a list of all the available help commands, or consult the Kermit
  504. Users Guide.
  505. |
  506.  
  507. hexit:    asciz |
  508. EXIT
  509.  
  510. Exit from KERMIT-20.  You can CONTINUE the program from the TOPS-20 Exec,
  511. provided you haven't run another program on top of it.
  512. |
  513.  
  514. hquit:    asciz |
  515. QUIT
  516.  
  517. Synonym for EXIT.
  518. |
  519.  
  520. hpromp:    asciz |
  521. PROMPT
  522.  
  523. If KERMIT-20 runs in server mode by default, typing the following command
  524. to the TOPS-20 Exec
  525.  
  526.    kermit prompt
  527.  
  528. will start it up in interactive mode, and leave you at the "Kermit-20>" prompt.
  529. |
  530.  
  531. hget:    asciz |
  532. GET remote-filespec
  533.  
  534. For use only when talking to a KERMIT server.
  535.  
  536. When running as a local KERMIT (i.e. when communicating with a remote KERMIT
  537. over an assigned TTY line, which you have specified with the SET LINE
  538. command), you may use the GET command to request the remote KERMIT server to
  539. send you the specified files.  The filespec is any string that can be a legal
  540. file specification for the remote system; it is not parsed or validated
  541. locally.  As files arrive, their names will be displayed on your screen, along
  542. with "." and "%" characters to indicate the packet traffic.
  543.  
  544. If the remote KERMIT is not capable of server functions, then you will
  545. probably get an error message back from it like "Illegal packet type".
  546. In this case, you must connect to the other Kermit, give a SEND command, 
  547. escape back, and give a RECEIVE command.
  548.  
  549. The GET command has no effect when running as a remote KERMIT.
  550. |
  551.  
  552.     subttl Definitions
  553.  
  554. pdlsiz==^d100            ; Stack size.
  555.  
  556. f=0                ; AC defs:  flag AC,
  557. t4=<t3=<t2=<t1=1>+1>+1>+1    ;  temporary AC's,
  558. q4=<q3=<q2=<q1=t4+1>+1>+1>+1    ;  and preserved AC's.
  559. state=q4+1            ; State of the automaton.
  560. rchr=state+1            ; Total data chars received.
  561. schr=rchr+1            ; Total data chars sent.
  562. debug=schr+1            ;[22] Debugging status (none, some, verbose)
  563.  
  564. mappag==200            ; Where to map things in.
  565.  
  566. SOH==^o001            ; Start of header char.
  567. XON==^o021            ; Control-Q.
  568.  
  569. maxpkt=="~"-" "+2        ; Maximum size of a packet.
  570. dmxtry==5            ; Default number of retries on a packet.
  571. dimxtr==20            ; Default number of retries send initiate.
  572. drpsiz==^d80            ; Default receive packet size.
  573. dspsiz==^d80            ; Default send packet size.
  574. dstim==^d10            ; Default send time out interval.
  575. drtim==^d8            ; Default receive time out interval.
  576. dsrvtm==^d30            ;[20] Def timout when awaiting server commands.
  577. dspad==^o000            ; Default send padding char.
  578. drpad==^o000            ; Default receive padding char.
  579. dspadn==^d0            ; Default number of send padding chars.
  580. drpadn==^d0            ; Default number of receive padding chars.
  581. dseol==.chcrt            ; Default send EOL char.
  582. dreol==.chcrt            ; Default receive EOL char.
  583. dsquot=="#"            ; Default send quote char.
  584. drquot=="#"            ; Default receive quote char.
  585. ddelay==^d5            ; Default delay before the first packet, secs.
  586. dtrnrn==XON            ; Default half duplex turnaround character.
  587. dxfull==0            ;[18] Full duplex.
  588. dxhalf==1            ;[18] Half duplex.
  589. ibmdpx==dxhalf            ;[18] Duplex for IBM host.
  590. defpar==none            ; Default parity.
  591. ibmpar==mark            ; Parity for IBM host.
  592. maxtim=^d94            ;[2] Maximum timeout interval to set, secs.
  593. minlod=4.0            ;[2] Minimum ldav to consider for timeout.
  594. maxlod=50.0            ;[2] Maximum ldav to consider for timeout.
  595. blip=^d5            ;[4] Every this many packets, print a blip.
  596. diasw==0            ; Default is diagnostics off.
  597.  
  598.  
  599.     subttl Macros
  600.  
  601.  
  602. define    diamsg (msg) <        ;;[22] Print state if normal debugging.
  603.     call [    skipe local    ;;[22] If not local, forget it.
  604.          caie debug, 1    ;;[22] Only do this in normal debugging mode.
  605.          ret        ;;[22]
  606.         saveac <t1>    ;;[22]
  607.         hrroi t1, [asciz/'msg/] ;;[22]
  608.         PSOUT        ;;[22]
  609.         ret ]        ;;[22]
  610. > ;[22] diamsg
  611.  
  612. define ermsg (msg) <
  613.      call [    tmsg <
  614. >
  615.         hrroi t1, [asciz/?Kermit:  'msg/]
  616.         movem t1, errptr ;; Save pointer to error mess for status.
  617.         PSOUT%
  618.         tmsg <
  619. >
  620.         ret ]
  621. >
  622.  
  623. ; Change the order to increase the likelyhood of the micro seeing
  624. ;  the error packet.
  625.  
  626. define kermsg (msg) <
  627.     $count=0
  628.     irpc msg, <$count=$count+1>
  629.      call [    movei t1, "E"    ;; Send an error packet to the other side.
  630.         move t2, pktnum    ;; Packet number.
  631.         movei t3, $count+^d13 ;; The count.
  632.         move t4, [point 7, [asciz/?Kermit-20:  'msg/]] ;; Error mess.
  633.         movem t4, errptr ;; Save pointer to error mess for status.
  634.         call spack    ;; Send the error packet.
  635.          nop
  636.         tmsg <
  637. ?Kermit:  'msg
  638. >
  639.         ret ]
  640. >
  641.  
  642. ; Error handling macros.
  643.  
  644. define %jserr (msg, label) <    ;; Use this immediately following a JSYS.
  645.     erjmp [    tmsg <
  646. ?Kermit:  'msg>            ;; Type given msg with our prefix,
  647. ifnb <msg>,<    call jserr0>    ;;  if given, put JSYS error after dash,
  648. ifb <msg>,<    call jsmsg0>    ;;  else right after "?Kermit:  "
  649. ifb <label>,<    HALTF%        ;; then if no label was specified, halt,
  650.         jrst .+1    ;; continuably,
  651. >;ifb
  652. ifnb <label>,<    jrst label>    ;; or if there was, go there.
  653.           ]
  654. >;%jserr
  655.  
  656. jserr0:    movei t1,.priin
  657.     CFIBF%            ; Clear typeahead.
  658.     movei t1,.priou
  659.     DOBE%            ; Wait for previous output to finish.
  660.     tmsg < - >
  661. jsmsg0:    movei t1,.priou
  662.     hrloi t2,.fhslf        ; Say:  this fork ,, last error.
  663.     setz t3,
  664.     ERSTR%
  665.      jfcl
  666.      jfcl
  667.     tmsg <
  668. >
  669.     ret
  670.  
  671. ; Improve order to facilitate error packets.
  672.  
  673. define %jsker (msg, label) <    ;; Use this immediately following a JSYS.
  674.     erjmp [    move t1, [point 7, [asciz/?Kermit-20:  'msg   /]] ;; Error.
  675.         movem t1, errptr ;; Save pointer to error mess for status.
  676.         call %%krms
  677.         tmsg <
  678. ?Kermit:  'msg>            ;; Type given msg with our prefix,
  679. ifnb <msg>,<    call jserr0>    ;;  if given, put JSYS error after dash,
  680. ifb <msg>,<    call jsmsg0>    ;;  else right after "?Kermit:  "
  681. ifb <label>,<    HALTF%        ;; then if no label was specified, halt,
  682.         jrst .+1    ;; continuably,
  683. >;ifb
  684. ifnb <label>,<    jrst label>    ;; or if there was, go there.
  685.           ]
  686. >;%jsKer
  687.  
  688. %%krms:    move t3, [point 7, %%krbf] ;; Get a pointer to the buffer.
  689.     setz t4,        ;; Zero the counter.
  690. %%krm1:    ildb t2, t1        ;; Get the byte.
  691.     jumpe t2, %%krm2    ;; Is it a null?
  692.     addi t4, 1        ;; Increment the counter.
  693.     idpb t2, t3        ;; Deposit the byte.
  694.     jrst %%krm1
  695. %%krm2:    move t1, t3        ;; Put the information into the buffer.
  696.     hrloi t2, .fhslf    ;; Say:  this fork ,, last error.
  697.     movei t3, ^d80        ;; Eighty chars minus the number so far.
  698.     sub t3, t4
  699.     ERSTR%
  700.      trn
  701.      trn
  702.     move t2, t1        ;; Put in the correct AC.
  703.     move t1, [point 7, %%krbf] ;; Find the length of the string.
  704.     call subbp        ;; Subtract byte pointers.
  705.      movei t3, ^d80        ;; If there is an error assume this count.
  706.     movei t1, "E"        ;; An error packet.
  707.     move t2, pktnum        ;; Packet number.
  708.     move t4, [point 7, %%krbf] ;; Pointer to string.
  709.     call spack        ;; Send the error packet.
  710.      trn
  711.     ret
  712.  
  713. ; %Clear
  714. ;
  715. ;    This macro takes three args, two of which are optional.  The first,
  716. ; non-optional, argument is the starting address of the area to be cleared.
  717. ; The next is the number of locations to clear, which defaults to one.
  718. ; The last argument is the desired filler, which defaults to zero.
  719.  
  720. define %clear (area, length, fill) <
  721.    ifb <fill>, <setzm area>
  722.    ifnb<fill>, <
  723.     movx .sac, <fill>
  724.     movem .sac, area
  725.    >
  726.    if1, <ifnb <length>, <exp 0, 0, 0>>
  727.    if2, <
  728.       ifb <length>, <%%%clr==1>
  729.       ifnb<length>, <%%%clr==<length>>
  730.       ifg <%%%clr-1>, <
  731.        hrli .sac, area
  732.        hrri .sac, <1>+area
  733.        blt .sac, <%%%clr-1>+area
  734.       >
  735.    >
  736. >
  737.  
  738.  
  739. define numout(num,base<^d10>) <    ;; Type number in desired base, free format.
  740.     call [    move b, num
  741.         movei a, .PRIOU
  742.         movei c, base
  743.         NOUT%
  744.          nop
  745.         ret ]    
  746. >;numout
  747.  
  748. define    OUTCHR(char) <
  749.     jrst [    push p,1
  750.         move 1,char
  751.         PBOUT%
  752.         pop p,1
  753.         jrst .+1 ]
  754. >;OUTCHR
  755.  
  756. ; Parsing aids
  757.  
  758. defstr %prsadr,0,17,18        ; Parse routine address
  759. defstr %evladr,0,35,18        ; Evaluation routine address
  760.  
  761. ; %Table
  762. ;
  763. ;    This macro is used to start a keyword table definition.
  764.  
  765. define %table <
  766.     %%tbst== .        ;; Plant start of table
  767.     exp 0            ;;  and leave a hole for %tbend to fill
  768. >
  769.  
  770. ; %TBend 
  771. ;
  772. ;    This macro is the compliment of %Table; it ends a keyword table.
  773.  
  774. define %tbend <
  775.     %%tbnd==.-1        ;; Get address of last entry in table
  776.     .org %%tbst        ;; Move back to start
  777.     xwd %%tbnd-%%tbst, %%tbnd-%%tbst;;  and build table header
  778.     .org            ;; Finally, get back to the way we were
  779. >
  780.  
  781. ; %Key
  782. ;
  783. ;    This macro takes three arguments: an (alphanumerics only!) keyword, the
  784. ; data to be associated with the keywod, and an (optional) flag value.  It
  785. ; creates either a flagless keyword (the normal case), or, if flags are
  786. ; given, a keyword with flags in the first word (and CM%FW set).  Thus,
  787. ; the result is a TBLUK table entry, suitable for use by the .CMKEY COMND
  788. ; JSYS function.  Note that all %Key words in a table must be bracketed
  789. ; by %Table and %TbEnd macros (see above).
  790.  
  791. define %key (name, data, flags) < ;; Flags are optional
  792.    ifb <flags>, <
  793.     xwd [asciz\name\],data    ;; No-flags case
  794.    >
  795.    ifnb<flags>, <
  796.     xwd [<flags>!cm%fw    ;; Flags: first word holds them,
  797.          asciz\name\], data    ;;  second is start of name
  798.    >
  799. >
  800.  
  801.     subttl Check rescan line
  802.  
  803. rescan:    saveac <t2,q4>        ; Save the used AC's.
  804.     move q4, t1        ; Save AC1.
  805.  
  806.     movx t1, .rsini        ; Any rescan arguments?
  807.     RSCAN%            ;  ...
  808.      erjmp rskp        ;  If not return.
  809.  
  810.     movx t1, .rscnt        ; Get the size of the rescan.
  811.     RSCAN%            ;  ...
  812.      erjmp rskp        ;  Return if unsucessful.
  813.     jumpe t1, rskp        ; If the size is zero return.
  814.  
  815.     prompt <>        ; Null prompt.
  816.  
  817.     movei t1, r+1        ; Get the address we want to go to on reparse.
  818.     movem t1, repara    ; Fudge it.  This is to prevent looping back
  819.                 ;  to prompt <> for ever on an error on the 
  820.                 ;  rescan line.
  821.     move t1, q4        ; Parse for the "keyword" in q4.
  822.     call rflde        ; Parse it, returning +2 on success.
  823.      retskp            ;  If we don't find it return.
  824.     movei t1, [flddb. (.cmcfm,cm%sdh)] ; See if we can parse a confirm.
  825.     call rflde
  826.      ret            ;  If not, we have a rescan argument.
  827.     retskp            ; Say we haven't got one.
  828.  
  829.  
  830. Kermit:    jrst start        ; Start entry.
  831.     jrst reen        ; Re-entry.
  832. versio:    byte (3)$who(9)$verno(6)$mnver(18)$edno    ; Program version.
  833.  
  834. reen:    jrst start
  835.  
  836. start:    RESET%            ; Normal startup: reset everything
  837.     move p, [iowd pdlsiz,pdl] ;  and set up a stack.
  838.     setzm telfrk        ; 
  839.     setzm netjfn
  840.     setzm f$exit
  841.     call main        ; The actual program.
  842. halt:    HALTF%            ; Stop.
  843.     jrst cont        ; Go around again.
  844.  
  845. cont:    setzm f$exit        ; Turn off the exit flag.
  846.     call prsint
  847.     jrst halt
  848.  
  849. main:    call pinit        ; Initialize interrupt system.
  850.     GJINF%            ; Get the our terminal number.
  851.     movem t4, pars3        ; Make believe we parsed it.
  852.     movem t3, myjob        ;[7] Job number of my job.
  853.     movem t4, mytty        ;[4] Remember this is my controlling terminal.
  854.     setzm local        ;[4] Assume we're running remotely.
  855.     setz debug,        ;[22] And no debugging
  856.     call $setln        ; Set the line to our own.
  857.     call cmdini        ; Initialize the command package.
  858.     movei t1, [flddb. (.cmkey,,<[exp <1,,1>,<[asciz/Kermit/],,0>]>)]
  859.     call rescan        ; Check rescan buffer.
  860.      jrst [    skipe f$exit    ;  Is the exit flag already on?
  861.          jrst prsint    ;   Yes, then we have parsed an error on the
  862.                 ;    rescan line.  Go handle it.
  863.         setom f$exit    ;  Turn on the exit flag.
  864.         jrst parse]    ;  Parse the rescan line
  865.  
  866.     jrst @dfstrt        ; No rescan go to default: PROMPT or SERVER.
  867.  
  868. server:    jrst getcom
  869.  
  870. promp:    setzm f$exit        ; They don't really want to exit yet.
  871.     jrst prsint        ; Where we go for experts.
  872.  
  873. prsint:    skipe f$exit        ; Exit?
  874.      ret            ;  If so, return.
  875.     prompt (Kermit-20>)
  876. parse:    %clear pars1, parsnm    ; Clear parse values.
  877.     setzm cjfnbk+.gjgen    ; Clear the JFN bits.
  878.     movei t1, [flddb. (.cmkey,,cmdtab,,,)]
  879.     call rfield        ; Parse a keyword.
  880.     hrrz t2, (t2)        ; Get the command routine addresses.
  881.     movem t2, pars1        ; Save into pars1.
  882.     load t1, %prsad, (t2)    ; Get the next level routine.
  883.     call (t1)        ; Call it.
  884. eval:    move t2, pars1        ; Get back data value.
  885.     load t1, %evlad, (t2)    ; Get evaluation routine.
  886.     call (t1)        ; Call it.
  887.     jrst prsint        ; Do it again.
  888.  
  889.     subttl    EXIT command
  890.  
  891. .exit:    noise <from Kermit>
  892.     confrm            ; Confirm.
  893.     ret
  894.  
  895. $exit:    setom f$exit        ; Set exit flag.
  896.     skipn assflg        ;[7] Did I assign a TTY?
  897.      ret            ;[7]  No.
  898.     move t1, ttynum        ;[7] Yes, so I should deassign it.
  899.     movei t1, .ttdes(t1)    ;[7]
  900.     RELD%            ;[7]
  901.      %jserr (,r)        ;[7]
  902.     ret
  903.  
  904.     subttl    HELP command
  905.  
  906. .help:    noise <about>        ;[18] HELP
  907.     movei t1, [flddb. .cmkey,,hlptab,,<kermit>]
  908.     call cfield    
  909.     move t2, (t2)        ; Get help text address.
  910.     movem t2, pars3
  911.     ret
  912.  
  913. hlptab:    %table            ;[18] Table of help commands.
  914.     %key <bye>,hbye
  915.     %key <connect>,hconne
  916.     %key <exit>,hexit
  917.     %key <finish>,hfinis
  918.     %key <get>,hget
  919.     %key <help>,hhelp
  920.     %key <kermit>,hkermi
  921.     %key <prompt>,hpromp
  922.     %key <quit>,hquit
  923.     %key <receive>,hrecei
  924.     %key <send>,hsend
  925.     %key <server>,hserve
  926.     %key <set>,hset
  927.     %key <show>,hshow
  928.     %key <status>,hstatu
  929.     %tbend
  930.  
  931. $help:    hrro t1, pars3        ;[18] Print the desired help text.
  932.     PSOUT
  933.     hrroi t1, crlf
  934.     PSOUT
  935.     ret
  936.  
  937.     subttl    SET command
  938.  
  939. .set:    movei t1, [flddb. .cmkey,,setabl,,,]
  940.     call rfield        ; Parse a keyword.
  941.     hrrz t2, (t2)        ; Get the command routine addresses.
  942.     movem t2, pars2        ; Save into pars2.
  943.     load t1, %prsad, (t2)    ; Get the next level routine.
  944.     call (t1)        ; Call it.
  945.     ret
  946.  
  947. .setdb:    noise <protocol mode>
  948.     movei t1, [flddb. .cmkey,,dbgtab,,states]
  949.     call rfield        ; Parse a keyword.
  950.     hrrz t2, (t2)        ; Get the value for the keyword (0 or 1).
  951.     movem t2, pars3        ; Save into pars3.
  952.     confrm
  953.     ret
  954.  
  955. dbgtab:    %table
  956.     %key    <off>, 0
  957.     %key    <packets>, 2    ;[22]
  958.     %key    <states>, 1    ;[22]
  959.     %tbend
  960.  
  961. .setf8:    noise <to>
  962.     movei t1, [flddb. (.cmkey,,sftab,<DEC-20 file byte size,>,auto-byte,)]
  963.     call rfield        ; Parse a keyword.
  964.     hrrz t2, (t2)        ; Get the value for the keyword (0 or 1).
  965.     movem t2, pars3        ; Save into pars3.
  966.     confrm
  967.     ret
  968.  
  969. .setpa:    noise <to>
  970.     movei t1, [flddb. .cmkey,,partab,,none,]
  971.     call rfield        ; Parse a keyword.
  972.     hrrz t2, (t2)        ; Get the value for the keyword.
  973.     movem t2, pars3        ; Save into pars3.
  974.     confrm
  975.     ret
  976.  
  977. .setib:    movei t1, [flddb. .cmkey,,offon,,on,]
  978.     call rfield        ; Parse a keyword.
  979.     hrrz t2, (t2)        ; Get the value for the keyword (0 or 1).
  980.     movem t2, pars3        ; Save into pars3.
  981.     confrm
  982.     ret
  983.  
  984. offon:    %table
  985.     %key    <off>, 0
  986.     %key    <on>, 1
  987.     %tbend
  988.  
  989. .setln:    noise <to tty>
  990.     movei t1, [flddb. (.cmnum,cm%sdh,^d8,<octal tty to transfer files over>,,[
  991.            flddb. (.cmcfm,cm%sdh,,<confirm to reset>)])]
  992.     call rfield        ; Parse a tty number.
  993.     ldb t3, [pointr (.cmfnp(t3),cm%fnc)] ; Get function code.
  994.     caie t3, .cmnum        ; Is it a TTY number?
  995.      jrst .setl1        ;  If not it must be a confirm.
  996.     movem t2, pars3        ; Save the tty number.
  997.     confrm
  998.     ret
  999.  
  1000. .setl1:    move t4, mytty        ; Get the our terminal number.
  1001.     movem t4, pars3        ; Make believe we parsed it.
  1002.     ret
  1003.  
  1004.     ;...
  1005.  
  1006. .setdl:    noise <to>        ; DELAY
  1007.     movei t1, [flddb. (.cmnum,cm%sdh,^d10,<decimal number of seconds>,)]
  1008.     call cfield        ; Parse a number.
  1009.     movem t2, pars3        ; Save the number.
  1010.     ret
  1011.  
  1012. .setdu:    noise <to>        ;[18] DUPLEX
  1013.     movei t1, [flddb. .cmkey,,duptab,,<full>]
  1014.     call cfield
  1015.     hrrz t2, (t2)
  1016.     movem t2, pars3
  1017.     ret
  1018.  
  1019. duptab:    %table            ;[18] legal duplexes
  1020.     %key <full>,dxfull
  1021.     %key <half>,dxhalf
  1022.     %tbend
  1023.  
  1024. .setes:    noise <character for connect to> ;[16] ESCAPE
  1025.     movei t1, [flddb. (.cmnum,cm%sdh,^d8,<Octal value of ASCII control character>,<31>)]
  1026.     call cfield
  1027.     movem t2, pars3
  1028.     ret
  1029.  
  1030. .setrc:    movei t1, [flddb. (.cmkey,,srtabl,,)] ; SET SEND ...
  1031.     call rfield        ; Parse a keyword.
  1032.     hrrz t2, (t2)        ; Get the command routine addresses.
  1033.     movem t2, pars3        ; Save into pars3.
  1034.     load t1, %prsad, (t2)    ; Get the next level routine.
  1035.     call (t1)        ; Call it.
  1036.     ret
  1037.  
  1038. .setsn:    movei t1, [flddb. (.cmkey,,sstabl,,)] ; SET RECEIVE ...
  1039.     call rfield        ; Parse a keyword.
  1040.     hrrz t2, (t2)        ; Get the command routine addresses.
  1041.     movem t2, pars3        ; Save into pars3.
  1042.     load t1, %prsad, (t2)    ; Get the next level routine.
  1043.     call (t1)        ; Call it.
  1044.     ret
  1045.  
  1046. .setpk:    noise <to>        ; SET SEND/RECEIVE PACKET-LENGTH
  1047.     movei t1, [flddb. (.cmnum,cm%sdh,^d10,<Decimal number between 10 and 94>,)]
  1048.     call rfield        ; Parse the packet size.
  1049.     movem t2, pars4        ; Save the packet size.
  1050.     confrm
  1051.     move t2, pars4        ; Get the packet size we parsed.
  1052.     cail t2, ^d10        ; Is the number in the right range?
  1053.      caile t2, ^d94
  1054.       jrst [tmsg <?Illegal packet size>
  1055.         jrst cmder1 ]
  1056.     ret
  1057.  
  1058.     ;...
  1059.  
  1060. .setpd:    noise <to>        ; SET SEND/RECEIVE PADDING
  1061.     movei t1, [flddb. (.cmnum,cm%sdh,^d10,<positive decimal number of padding characters>,)]
  1062.     call rfield        ; Parse the number of padding chars.
  1063.     movem t2, pars4        ; Save the number.
  1064.     confrm
  1065.     move t2, pars4        ; Get the amount of padding we parsed.
  1066.     skipge t2        ; Is the number in the right range?
  1067.      jrst [    tmsg <?Must be a positive number>
  1068.         jrst cmder1 ]
  1069.     ret
  1070.  
  1071. .setpc:    noise <to>        ; SET SEND/RECEIVE PADCHAR
  1072.     movei t1, [flddb. (.cmnum,cm%sdh,^o10,<octal number of character between 0 and 37 or 177>,)]
  1073.     call rfield        ; Parse the padding character.
  1074.     movem t2, pars4        ; Save the padding char.
  1075.     confrm
  1076.     move t2, pars4        ; Get the padding char we parsed.
  1077.     skipl t2        ; Is the number in the right range?
  1078.      caile t2, ^o37        ;  Fix to compare correctly.
  1079.       jrst [caie t2, ^o177
  1080.         tmsg <?Illegal padding character>
  1081.         jrst cmder1 ]
  1082.     ret
  1083.  
  1084. .seteo:    noise <to>        ; END-OF-LINE
  1085.     movei t1, [flddb. .cmnum,cm%sdh,^o10,<octal value of ASCII control character>,<15>]
  1086.     call cfield        ; Parse the EOL char.
  1087.     skipl t2        ; Is the number in the right range?
  1088.      caile t2, ^o37        ;  Fix to compare correctly.
  1089.       jrst [tmsg <?Illegal EOL character>
  1090.         jrst cmder1 ]
  1091.     movem t2, pars4        ; Get the EOL char we parsed.
  1092.     ret
  1093.  
  1094.  
  1095. .setsp:    noise <to>        ;[18] START-OF-PACKET
  1096.     movei t1, [flddb. .cmnum,cm%sdh,^d8,<Octal value of ASCII control character>,<1>]
  1097.     call cfield
  1098.     skipl t2        ; Is the number in the right range?
  1099.      caile t2, ^o37        ;  Fix to compare correctly.
  1100.       jrst [tmsg <?Illegal start-of-packet character>
  1101.         jrst cmder1 ]
  1102.     movem t2, pars4
  1103.     ret
  1104.  
  1105.     ;...
  1106.  
  1107. .setqu:    noise <to>        ; SET SEND/RECEIVE QUOTE
  1108.     movei t1, [flddb. .cmnum,cm%sdh,^d8,<Octal value of printable ASCII character>,<43>] ;[21] 
  1109.     call cfield        ;[21]
  1110.     caile t2," "        ;[21] Printable?
  1111.      caile t2, "~"        ;[21]
  1112.      jrst [    tmsg <?Must be printable character, range 41-176>
  1113.         jrst cmder1 ]    ;[21]
  1114.     movem t2, pars4        ;[21] OK, stash it.
  1115.     ret
  1116.  
  1117. .setim:    noise <to>        ; SET TIMEOUT
  1118.     movei t1, [flddb. (.cmnum,cm%sdh,^d10,<Number of seconds before timing out, 1 to 94>,)]
  1119.     call rfield        ; Parse the number.
  1120.     movem t2, pars4        ; Save the number.
  1121.     confrm
  1122.     move t2, pars4        ; Get the number we parsed.
  1123.     cail t2, 1        ; Is the number in the right range?
  1124.      caile t2, ^d94        ;  Fix to compare correctly.
  1125.       jrst [tmsg <?Illegal number of seconds>
  1126.         jrst cmder1 ]
  1127.     ret
  1128.  
  1129. $set:    move t2, pars2        ; Get back data value.
  1130.     load t1, %evlad, (t2)    ; Get evaluation routine.
  1131.     call (t1)        ; Call it.
  1132.     ret
  1133.  
  1134. $setdb:    skipl debug, pars3    ; DEBUG. Get the value we parsed.
  1135.      caile debug, 2        ;[22] Make sure it's 0, 1, or 2.
  1136.      movei debug, 1        ;[22] ...
  1137.     ret
  1138.  
  1139. $setrs:    move t1, @pars3        ; SEND/RECEIVE.  Address of variable to set.
  1140.     move t2, pars4        ; The value that was parsed.
  1141.     movem t2, (t1)        ; Save the value.
  1142.     ret
  1143.  
  1144. $setdl:    move t1, pars3        ; DELAY. Get the number of seconds to delay.
  1145.     movem t1, delay        ; Save the delay time.
  1146.     movem t1, odelay    ;[27] Here too, for saving & restoring.
  1147.     ret
  1148.  
  1149. $setdu:    move t1, pars3        ;[18] DUPLEX.  Get what was parsed.
  1150.     movem t1, duplex
  1151.     ret
  1152.  
  1153. $setes:    move t1, pars3        ;[16] ESCAPE.  Get what we parsed.
  1154.     cail t1, 1
  1155.     cail t1, " "
  1156.      skipa
  1157.      jrst [    movem t1, escape
  1158.         ret ]
  1159.     tmsg <
  1160. ?Escape character must be between 1 (CTRL-A) and 37 (CTRL-_)>
  1161.     setzm escape
  1162.     ret
  1163.  
  1164. $setf8:    move t1, pars3        ; FILE-BYTE... Get the value of the flag.
  1165.     cain t1, 2        ; Is it autobyte?
  1166.      jrst [ setom autbyt    ;  If so, say so.
  1167.         ret ]
  1168.     setzm autbyt        ; Say no auto-byte.
  1169.     movem t1, ebtflg    ; Set the flag.
  1170.     ret
  1171.  
  1172. $setpa:    move t1, pars3        ; SET PARITY
  1173.     movem t1, parity
  1174.     ret
  1175.  
  1176. $setib:    move t1, pars3        ; SET IBM-FLAG
  1177.     movem t1, ibmflg    ; Say whether we want to talk to IBM host.
  1178.     skipe ibmflg        ; If we turned IBM flag ON,
  1179.      jrst [    movei t1, ibmpar ; then set IBM parity,
  1180.         movem t1, parity ; ...
  1181.         movei t1, ibmdpx ;[18] and IBM duplex.
  1182.         movem t1, duplex ;[18]
  1183.         ret ]        ; 
  1184.     movei t1, defpar    ; else we turned it OFF, so
  1185.     movem t1, parity    ; put back default parity
  1186.     movei t1, dxfull    ;[18] and default duplex, which is FULL
  1187.     movem t1, duplex    ;[18]
  1188.     ret
  1189.  
  1190. $setln:    stkvar <oldjfn>        ; SET LINE
  1191.     move t1, ttynum        ;[7] Previous line number, if any.
  1192.     movem t1, oldnum    ;[7] Remember it.
  1193.     move t1, pars3        ;[7] Now get new one.
  1194.     movem t1, ttynum    ;[7]
  1195.     setzm local        ;[4] Assume we're a remote Kermit.
  1196.     came t1, mytty        ;[4] Lines the same?
  1197.      setom local        ;[4] No, so we're local.
  1198.     movei t1, .ttdes(t1)    ;[7] Form device designator.
  1199.     DVCHR            ;[7] 
  1200.      erjmp asser1        ;[7]
  1201.     hlre t1, t3        ;[7] Who has it?
  1202.     movem t1, job        ;[7] Job number of who has it, or -1 (or -2).
  1203.     move t1, assflg        ;[7] Remember in case we already had another...
  1204.     movem t1, oasflg    ;[7] 
  1205.     setzm assflg        ;[7] Assume I don't have to assign it.
  1206.     skipn local        ;[7] If it's my own controlling TTY I don't
  1207.      jrst $stln2        ;[7]  have to assign it.
  1208.     move t3, myjob        ;[7] My job number.
  1209.     camn t3, job        ;[7] If I had it assigned already,
  1210.      jrst $stln2        ;[7]  just go get a JFN on it.
  1211.     move t1, ttynum        ;[7] Form device designator again,
  1212.     movei t1, .ttdes(t1)    ;[7]  and...
  1213.     ASND            ;[7]  give it a try.
  1214.      erjmp asser1        ;[7] Uh oh, can't assign it.
  1215.     setom assflg        ;[7] Assigned it.  Set this flag to remember.
  1216.  
  1217. $stln2:    move t1, netjfn        ; Get the present JFN.
  1218.     movem t1, oldjfn    ; Save it so we can close it up.
  1219.     move t1, [170700,,filbuf] ; Pointer to file name buffer.
  1220.     move t2, [ascii/TTY/]    ; Build TTY: filename.
  1221.     movem t2, filbuf    ; Into filbuf.
  1222.     move t2, ttynum        ; TTY number.
  1223.     movei t3, ^d8        ; Octal.
  1224.     NOUT%
  1225.      erjmp [ermsg <Can't NOUT TTY number>
  1226.         ret ]
  1227.     movei t2, ":"        ; Add a colon.
  1228.     idpb t2, t1
  1229.     setz t2,
  1230.     idpb t2, t1
  1231.     movx t1, gj%sht        ; Now try to get a JFN on the TTY:.
  1232.     hrroi t2, filbuf
  1233.     GTJFN%
  1234.      erjmp [ermsg <Can't get JFN on TTY> ;  Probably no such device.
  1235.         ret ]
  1236.     hrrzm t1, netjfn    ; Save it as the net JFN.
  1237.     movx t2, fld(8,of%bsz)!of%wr!of%rd ; 8-bit bytes, read & write access.
  1238.     OPENF%            ; Assign the TTY.
  1239.      erjmp asserr        ;[7] Can't, print informative error message.
  1240.     move t1, oldjfn        ; OK, get the old tty jfn.
  1241.     jumpe t1, $stlnx
  1242.     skipe oasflg        ;[7] Had I assigned the old one?
  1243.      jrst [    skipn t1, oldnum ;[7] Yes,
  1244.          jrst .+1
  1245.         movei t1, .ttdes(t1) ;[7] deassign it. 
  1246.         RELD%        ;[7]
  1247.          %jserr (,.+1)    ;[7]
  1248.         setzm oldnum    ;[7] Set these to zero...
  1249.         setzm oasflg    ;[7]
  1250.         jrst .+1 ]    ;[7]
  1251.     CLOSF%            ; Close it.
  1252.      %jserr (,.+1)
  1253. $stlnx:    move t1, netjfn
  1254.     movei t2, .chcrt    ; Send a CR down the line to get things going.
  1255.     BOUT%
  1256.      %jserr (,r)
  1257.     ret
  1258.  
  1259. ;[7] (this whole section...) Get here if error assigning link tty.
  1260.  
  1261.  
  1262. asserr:    movei t1, .fhslf        ; Got error trying to open link tty.
  1263.     GETER%
  1264.     hrrzs t2
  1265.     caie t2, opnx7        ; Somebody else has it?
  1266.      jrst [    ermsg <Can't assign or open TTY>
  1267.         move t2, oldjfn    ; No, something else.  Restore old JFN.
  1268.         movem t2, netjfn
  1269.         ret ]
  1270. asser1:    tmsg <
  1271. ?Line >
  1272.     numout ttynum, 8
  1273.     tmsg < in use by job >
  1274.     numout job
  1275.     tmsg <, user >
  1276.     move t1, job
  1277.     hrroi t2, t3
  1278.     movei t3, .jiuno
  1279.     GETJI
  1280.       erjmp asserx
  1281.     movei t1, .priou
  1282.     move t2, t3        ; User...
  1283.     DIRST
  1284.       erjmp asserx
  1285.     ret
  1286.  
  1287. asserx:    tmsg <???
  1288. >
  1289.     ret
  1290.  
  1291.     subttl    STATUS command
  1292.  
  1293. .stat:    noise <of Kermit>    ; STATUS
  1294.     confrm
  1295.     ret
  1296.  
  1297. $stat:    stkvar <sec>
  1298.     tmsg <
  1299.  Maximum number of characters in packet:  >
  1300.     numout rpsiz
  1301.     tmsg < received; >
  1302.     numout  spsiz
  1303.     tmsg < sent
  1304.  Number of characters transmitted in >
  1305.     move t2, stdat        ; Get the number of thirds of seconds.
  1306.     idivi t2, ^d3        ; Get the number of seconds.
  1307.     movem t2, sec        ; Save the number of seconds.
  1308.     idivi t2, ^d60        ; Divide to get minutes.
  1309.     move t4, t3        ; Save the remainder.
  1310.     jumpe t2, $stat2    ; If no minutes then don't print them.
  1311.     numout t2
  1312.     tmsg < minutes and >
  1313. $stat2:    move t2, t4        ; Get the remainder.
  1314.     jumpe t2, $stat3    ; If no seconds then don't print them.
  1315.     numout t2
  1316.     tmsg < seconds>
  1317. $stat3:    tmsg <
  1318.     Sent:      >
  1319.     numout stot
  1320.     tmsg <        Overhead:    >
  1321.     movei t1, .priou    ; Output the number of chars in decimal.
  1322.     move t2, stot
  1323.     sub t2, stchr
  1324.     numout t2
  1325.     tmsg <
  1326.     Received:  >
  1327.     numout rtot
  1328.     tmsg <        Overhead:    >
  1329.     movei t1, .priou    ; Output the number of chars in decimal.
  1330.     move t2, rtot
  1331.     sub t2, rtchr
  1332.     numout t2
  1333.     tmsg <
  1334.   Total received:  >
  1335.     movei t1, .priou    ; Output the number of chars in decimal.
  1336.     move t2, rtot
  1337.     add t2, stot
  1338.     move t4, t2        ; Save the total number of chars.
  1339.     numout t2
  1340.     tmsg <        Overhead:    >
  1341.     movei t1, .priou    ; Output the number of chars in decimal.
  1342.     move t2, t4        ; Get total chars.
  1343.     sub t2, rtchr
  1344.     numout t2
  1345.     tmsg <
  1346.  Total characters transmitted per second:    >
  1347.     move t2, t4        ; Total chars transmitted.
  1348.     idiv t2, sec        ; Divided by the number of seconds.
  1349.     numout t2
  1350.     tmsg <
  1351.  Effective data rate:    >
  1352.     skipn t2, stchr        ; Is the number of chars sent zero?
  1353.      move t2, rtchr        ;  If so we were receiving.
  1354.     idiv t2, sec        ; Divided by the number of seconds.
  1355.     imuli t2, ^d10        ; Multiply chars/sec by 10 to get bits/sec.
  1356.     numout t2
  1357.     tmsg < Baud
  1358. >
  1359.     skipn errptr        ; Was there an error?
  1360.      jrst $statx        ;  If not, done.
  1361.     tmsg < Aborted by error:  >
  1362.     move t1, errptr
  1363.     PSOUT%            ; If so output it.
  1364. $statx:    tmsg <
  1365.  
  1366. >
  1367.     ret
  1368.  
  1369. .show:    noise <Kermit parameters>
  1370.     confrm
  1371.     ret
  1372.  
  1373. $show:    tmsg <
  1374. TOPS-20 KERMIT version >
  1375.     ldb t2, [301100,,versio] ; major version
  1376.     numout t2, 8
  1377.     ldb t1, [220600,,versio]
  1378.     skipe t1        ; minor version
  1379.      call [    addi t1, "A"-1    ; make it a letter (A=1)
  1380.         PBOUT
  1381.         ret ]
  1382.     hrrz t3, versio        ; edit
  1383.     skipe t3
  1384.      call [    movei t1, "("
  1385.         PBOUT
  1386.         numout t3, 8
  1387.         movei t1, ")"
  1388.         PBOUT
  1389.         ret ]
  1390.     ldb t4, [410300,,versio] ; who
  1391.     skipe t4
  1392.      call [    movei t1, "-"
  1393.         PBOUT
  1394.         numout t4, 8
  1395.         ret ]
  1396.  
  1397. time:    hrroi t1, crlf
  1398.     PSOUT
  1399.     movx t1, .priou        ; Current date and time.
  1400.     seto t2,        ; 
  1401.     movx t3, ot%day!ot%fdy!ot%fmn!ot%4yr!ot%dam!ot%spa!ot%scl
  1402.     ODTIM%
  1403.      erjmp .+1
  1404.     call moon        ; Phase of the moon.
  1405.  
  1406.     tmsg <
  1407. TTY for file transfer:  >
  1408.     numout ttynum, 8
  1409.     move t4, mytty        ; See whether we're local or remote...
  1410.     hrroi t1, [asciz/ (job's controlling terminal, KERMIT-20 is REMOTE)/]
  1411.     came t4, ttynum
  1412.      hrroi t1, [asciz/ (assigned TTY line, KERMIT-20 is LOCAL)/]
  1413.     PSOUT%
  1414.  
  1415. $show2:    tmsg <
  1416.  
  1417.   Byte size for file I/O:  >
  1418.     hrroi t1, [ASCIZ/"Auto-Byte"/]
  1419.     skipn autbyt
  1420.      jrst [    hrroi t1, [ASCIZ/Seven-Bit/]
  1421.         skipe ebtflg
  1422.          hrroi t1, [ASCIZ/Eight-Bit/]
  1423.         jrst .+1 ]
  1424.     PSOUT%
  1425. $show3:    tmsg <
  1426.   IBM-Flag:  >
  1427.     hrroi t1, [ASCIZ/On/]
  1428.     skipn ibmflg
  1429.      hrroi t1, [ASCIZ/Off/]
  1430.     PSOUT%
  1431.     skipe ibmflg
  1432.      jrst [    tmsg <, Handshake: >
  1433.         move t1, trnrnd
  1434.         call putc
  1435.         jrst .+1 ]
  1436. $show4:    tmsg <
  1437.   Parity:    >
  1438.     move t2, parity
  1439.     hrroi t1, [ASCIZ/None/]
  1440.     cain t2, space
  1441.      hrroi t1, [ASCIZ/Space/]
  1442.     cain t2, mark
  1443.      hrroi t1, [ASCIZ/Mark/]
  1444.     cain t2, odd
  1445.      hrroi t1, [ASCIZ/Odd/]
  1446.     cain t2, even
  1447.      hrroi t1, [ASCIZ/Even/]
  1448.     PSOUT%
  1449.  
  1450. $sho4a:    tmsg <
  1451.   Duplex:    >            ;[18]
  1452.     move t2, duplex
  1453.     hrroi t1, [asciz/Full/]
  1454.     caie t2, dxfull
  1455.      hrroi t1, [asciz/Half/]
  1456.     PSOUT
  1457.  
  1458. $sho4b:    tmsg <
  1459.   Escape:    >
  1460.     move t1, escape
  1461.     call putc
  1462.  
  1463. $show5:    tmsg <
  1464.   Debugging: >
  1465.     hrro t1, [
  1466.         [asciz/Off/]
  1467.         [asciz/States/]
  1468.         [asciz/Packets/]
  1469.         ](debug)
  1470.     PSOUT%
  1471. $show6:    tmsg <
  1472.  
  1473. Packet parameters:
  1474.  
  1475.               Receive         Send
  1476.   Size:            >
  1477.     numout rpsiz,^d10
  1478.     tmsg <        >
  1479.     numout spsiz,^d10
  1480.  
  1481.     tmsg <
  1482.   Timeout:         >
  1483.     numout rtimou
  1484.     tmsg <        >
  1485.     numout stimou
  1486.     movei t1, "-"        ;[6]
  1487.     PBOUT%            ;[6]
  1488.     numout [maxtim]        ;[6]
  1489.     tmsg < sec>
  1490.  
  1491. $show7:    tmsg <
  1492.   Padding:         >
  1493.     numout rpadnm
  1494.     tmsg <        >
  1495.     numout spadnm
  1496.     tmsg <
  1497.   Pad Character:   >
  1498.     move t1, rpadch
  1499.     call putc
  1500.     tmsg <        >
  1501.     move t1, spadch
  1502.     call putc
  1503.  
  1504. $show8:    tmsg <
  1505.   End-Of-Line:     >
  1506.     move t1, reolch
  1507.     call putc
  1508.     tmsg <        >
  1509.     move t1, seolch
  1510.     call putc
  1511.  
  1512.     tmsg <
  1513.   Control Quote:   >
  1514.     move t1, rquote
  1515.     call putc
  1516.     tmsg <        >
  1517.     move t1, squote
  1518.     call putc
  1519.     
  1520. $showa: tmsg <
  1521.   Start-Of-Packet: >
  1522.     move t1, ssthdr        ;[18]
  1523.     call putc
  1524.     tmsg <        >
  1525.     move t1, rsthdr        ;[18]
  1526.     call putc
  1527.  
  1528. $show9:    tmsg <
  1529.  
  1530. Delay before sending first packet:  >
  1531.     numout delay
  1532.     tmsg < sec>
  1533. $showb:    tmsg <
  1534. Packet retries before timeout:      >
  1535.     numout maxtry
  1536. $showc:    tmsg <
  1537. Number of retries for init packet:  >
  1538.     numout imxtry
  1539.  
  1540.     tmsg <
  1541. Server sends NAKs every >
  1542.     numout [dsrvtm]
  1543.     tmsg < sec while waiting for command.>
  1544.  
  1545.     skipn debug        ; No blips if debugging.
  1546.     skipn local        ; Or if not local.
  1547.      jrst $showx        ;  ...
  1548.  
  1549. $showd:    tmsg <
  1550.  
  1551. "." for every >            ;[4]
  1552.     numout [blip]        ;[9]
  1553.     tmsg < packets, "%" for each NAK.>
  1554.  
  1555. $showx:    tmsg <
  1556.  
  1557. >                ;[4]
  1558.     ret
  1559.  
  1560. putc:    caile t1, "~"        ; Rubout?
  1561.      jrst [ tmsg <DEL>    ;  Yes, type this?
  1562.         ret ]
  1563.     caige t1, " "        ; Is it a control char?
  1564.      jrst [ push p, t1    ;  Save the char.
  1565.         movei t1, "^"    ;  Get the control quote.
  1566.         PBOUT%
  1567.         pop p, t1
  1568.         ori t1, ^o100    ;  Turn on the non-control bit.
  1569.         jrst .+1 ]
  1570.     PBOUT%
  1571.     ret
  1572.  
  1573.     subttl    BYE command
  1574.  
  1575.  ;[11] The BYE command is part of edit 11.
  1576.  
  1577. .bye:    noise (to remote server) ; Parse rest of BYE command.
  1578.     confrm
  1579.     ret
  1580.  
  1581. $bye:    skipn local        ; Local Kermit?
  1582.      jrst [    ermsg <BYE command has no effect without prior SET LINE>
  1583.         ret ]
  1584.     setzm numtry        ; OK, try to do it.
  1585.  
  1586. $bye2:    move q1, numtry        ; Make sure we haven't tried too much.
  1587.     caml q1, maxtry
  1588.      jrst [ ermsg <Can't send BYE, max tries exceeded>
  1589.         ret ]
  1590.     aos numtry        ; Count this try.
  1591.     move t1, [byte (8)"L",0] ; Put a Logout command in the data block.
  1592.     movem t1, data
  1593.     diamsg <GL >        ; Say we're sending generic logout command.
  1594.     movei t1, "G"        ; Generic command.
  1595.     setz t2,        ; Make the packet number zero.
  1596.     movei t3, 1        ; Data is one character.
  1597.     move t4, [point 8, data] ; Point to data block.
  1598.     call spack        ; Send it off.
  1599.      jrst [    ermsg <Can't send BYE packet>
  1600.         ret ]
  1601.     call rpack        ; Look for acknowledgment.
  1602.      jrst [    ermsg <Can't get reply to BYE packet>
  1603.         ret ]
  1604.     cain t1, "Y"        ; Got reply.  Is it an ACK?
  1605.      jrst [    setom f$exit    ; Turn on the exit flag.
  1606.         jrst $byex ]
  1607.     cain t1, "E"        ; Error packet?
  1608.      jrst [    hrroi t1, [asciz/?Remote error -- /] ; Yes, print it.
  1609.         PSOUT%
  1610.         move t1, t4    ; Get pointer to it,
  1611.         PSOUT%        ; and print it.
  1612.         setzm f$exit    ; Don't exit, since the command failed.
  1613.         ret ]
  1614.     caie t1, "N"        ; NAK?
  1615.      cain t1, "T"        ; Or Timeout?
  1616.      jrst $bye2        ;  One of those, go try again.
  1617.  
  1618.     ermsg <Can't send BYE, don't know why>
  1619.     ret
  1620.  
  1621. ;[16] From here to end is part of edit 16.
  1622.  
  1623. $byex:    movei q1, 5        ; Try this 5 times
  1624.     movei t1, ^d750        ; Sleep a second.
  1625.     DISMS%
  1626. $byex2:    movei t1, ^d250        ; Sleep a little bit
  1627.     DISMS%
  1628.     move t1, netjfn        ; Any messages?
  1629.     SIBE%
  1630.      skipa t3, t2        ; Yes, this many characters.
  1631.      jrst $byexx        ;  No, try again.
  1632.     hrroi t2, buffer    ; Get whatever is there.
  1633.     movei t4, .chlfd
  1634.     SIN%
  1635.     setz t3,
  1636.     idpb t3, t2
  1637.     hrroi t1, buffer    ; And print it.
  1638.     PSOUT%
  1639. $byexx: sojg q1, $byex2        ; See if we want to type some more.
  1640.  
  1641.     setzm buffer        ; Zero this out, just in case.
  1642.     tmsg <...>        ; No. Maybe there's more, but...
  1643.     move t1, netjfn        ;  can't wait forever for it,
  1644.     CFIBF%            ;  throw the rest away.
  1645.     ret
  1646.  
  1647.     subttl    FINISH command
  1648.  
  1649.  ;[28] The FINISH command is edit 28.
  1650.  
  1651. .finis:    noise (remote server operation) ; Parse rest of FINISH command.
  1652.     confrm
  1653.     ret
  1654.  
  1655. $finis:    skipn local        ; Local Kermit?
  1656.      jrst [    ermsg <FINISH command has no effect without prior SET LINE>
  1657.         ret ]
  1658.     setzm numtry        ; OK, try to do it.
  1659.  
  1660. $fini2:    move q1, numtry        ; Too many tries?
  1661.     caml q1, maxtry
  1662.      jrst [ ermsg <Can't send FINISH, max tries exceeded>
  1663.         ret ]
  1664.     aos numtry        ; Count this try.
  1665.     move t1, [byte (8)"F",0] ; Put a Finish command in the data block.
  1666.     movem t1, data
  1667.     diamsg <GF >        ; Say we're sending generic logout command.
  1668.     movei t1, "G"        ; Generic command.
  1669.     setz t2,        ; Make the packet number zero.
  1670.     movei t3, 1        ; Data is one character.
  1671.     move t4, [point 8, data] ; Point to data block.
  1672.     call spack        ; Send it off.
  1673.      jrst [    ermsg <Can't send FINISH packet>
  1674.         ret ]
  1675.     call rpack        ; Look for acknowledgment.
  1676.      jrst [    ermsg <Can't get reply to FINISH packet>
  1677.         ret ]
  1678.     cain t1, "Y"        ; Got reply.  Is it an ACK?
  1679.      jrst [     tmsg <[OK]>    ;  Yes, good.
  1680.          ret ]
  1681.     cain t1, "E"        ; Error packet?
  1682.      jrst [    hrroi t1, [asciz/?Remote error -- /] ; Yes, print it.
  1683.         PSOUT%
  1684.         move t1, t4    ; Get pointer to it,
  1685.         PSOUT%        ; and print it.
  1686.         ret ]
  1687.     caie t1, "N"        ; NAK?
  1688.      cain t1, "T"        ; Or Timeout?
  1689.      jrst $fini2        ;  One of those, go try again.
  1690.  
  1691.     ermsg <Can't send FINISH, don't know why>
  1692.     ret
  1693.  
  1694.     subttl    CONNECT command
  1695.  
  1696. .conne:    noise <to tty>
  1697.     movei t1, [flddb. (.cmnum,cm%sdh,^d8,<octal tty number to connect to>,,[
  1698.            flddb. (.cmcfm,cm%sdh,,<confirm to connect to selected line>)])]
  1699.     call rfield        ; Parse a tty number.
  1700.     ldb t3, [pointr (.cmfnp(t3),cm%fnc)] ; Get function code.
  1701.     caie t3, .cmnum        ; Is it a number?
  1702.      ret            ;  If not it must be a confirm.
  1703.     movem t2, pars3        ; Save the tty number.
  1704.     confrm
  1705.     ret
  1706.  
  1707. $conne:    stkvar <tjfn,<trscn,20>>
  1708.     skipe pars3        ; Did we parse a TTY number?
  1709.      call $setln        ;  If so, use that one.
  1710.     skipe telfrk        ; Have a ttlink fork?
  1711.      jrst $conn1        ; Yes, continue.
  1712.     move t4, mytty        ; Find our terminal number.
  1713.     camn t4, ttynum        ; Is this number the same as the TTLINK tty?
  1714.      jrst [    ermsg <Can't CONNECT to your own line.  Use the SET LINE n command first.>
  1715.         ret ]
  1716.     movx t1, gj%sht+gj%old    ; Find the TTLINK program.
  1717.     hrroi t2, [asciz/SYS:TTLINK.EXE/]
  1718.     GTJFN%
  1719.      %jserr (Can't find SYS:TTLINK.EXE,r)
  1720.     movem t1, tjfn        ; Save the JFN.
  1721.     movx t1, cr%cap        ; Needs Control-C capability.
  1722.     setzm t2
  1723.     CFORK%
  1724.      %jserr <Can't create TTLINK fork>,r
  1725.     movem t1, telfrk    ; Remember the fork.
  1726.     hrlzs t1        ; Move handle into left half.
  1727.     hrr t1, tjfn        ; JFN in right half.
  1728.     setzm t2        ; Nothing special.
  1729.     GET%            ; Do the get.
  1730.      %jserr <Can't GET TTLINK fork>,r
  1731.  
  1732.     ;...
  1733.  
  1734. $conn1:    hrroi t1, trscn        ; Now set up the rescan buffer for TTLINK.
  1735.     hrroi t2, [asciz/TTLINK CONNECT /]
  1736.     setzb t3, t4
  1737.     SOUT%
  1738.      %jserr (,.+1)
  1739.  
  1740. $conn2:    move t2, ttynum        ; Get the tty number.
  1741.     movei t3, ^d8        ; Octal.
  1742.     NOUT%
  1743.      %jserr (,.+1)
  1744.     skipe escape        ;[16] Escape character specified?
  1745.      jrst [    hrroi t2, [asciz\/ESC:\] ;[16] Yes, make TTLINK switch for it.
  1746.         setzb t3, t4    ;[16] 
  1747.         SOUT%        ;[16]
  1748.          %jserr (,.+1)    ;[16]
  1749.         move t2, escape    ;[16] Octal value of escape character.
  1750.         movei t3, ^d8    ;[16]
  1751.         NOUT%        ;[16]
  1752.          %jserr (,.+1)    ;[16]
  1753.         jrst .+1 ]
  1754.     move t3, duplex        ;[18] Duplex.
  1755.     caie t3, dxfull        ;[18] Full is the default.
  1756.      jrst [    hrroi t2, [asciz\/DUP:HALF\] ;[18] Want half, include switch.
  1757.         setzb t3, t4    ;[18]
  1758.         SOUT%        ;[18]
  1759.          %jserr (,.+1)    ;[18]
  1760.         jrst .+1 ]    ;[18]
  1761.  
  1762. $conn3:    hrroi t2, [asciz\/PARITY:\] ; Parity switch
  1763.     setzb t3, t4
  1764.     SOUT%
  1765.      %jserr (,.+1)
  1766.     move t3, parity
  1767.     hrroi t2, [ASCIZ/NONE/]
  1768.     cain t3, space
  1769.      hrroi t2, [ASCIZ/SPACE/]
  1770.     cain t3, mark
  1771.      hrroi t2, [ASCIZ/MARK/]
  1772.     cain t3, odd
  1773.      hrroi t2, [ASCIZ/ODD/]
  1774.     cain t3, even
  1775.      hrroi t2, [ASCIZ/EVEN/]
  1776.     setzb t3, t4
  1777.     SOUT%
  1778.      %jserr (,.+1)
  1779.  
  1780. $conn5:    hrroi t2, crlf        ; End with a CRLF.
  1781.     setzb t3, t4
  1782.     SOUT%
  1783.      %jserr (,.+1)
  1784. $conn6:    hrroi t1, trscn        ; Here is the pointer.
  1785.     RSCAN%            ; Make it readable.
  1786.      %jserr (,r)
  1787. $conn7:    move t1, telfrk        ; Here is the fork.
  1788.     setz t2,        ; Primary start address.
  1789.     SFRKV%            ;  Start it up.
  1790.      %jserr <Can't start TTLINK fork>,r
  1791. $conn8:    WFORK%            ; wait for the fork
  1792.      %jserr <Can't wait for TTLINK fork>,r
  1793.     ret            ; Fork done, just return.
  1794.  
  1795.     subttl    PROMPT command
  1796.  
  1797. .promp:    confrm            ; Confirm.
  1798.     ret
  1799.  
  1800. $promp:    setzm f$exit        ; Set exit flag.
  1801.     ret
  1802.  
  1803.     subttl    SERVER command
  1804.  
  1805. .serve:    confrm            ; Confirm.
  1806.     ret
  1807.  
  1808. $serve:    setom f$exit        ; Set exit flag.
  1809.     call getcom        ; Go serve.
  1810.     ret
  1811.  
  1812.     subttl    GET remote files
  1813.  
  1814. ;[11] This whole command is part of edit 11
  1815.  
  1816. .get:    noise <remote files>
  1817.     movei t1, [flddb. .cmtxt,cm%sdh,,<remote file specification>]
  1818.     call cfield
  1819.     ret
  1820.  
  1821. $get:    skipe local        ; This only works if local Kermit.
  1822.      jrst $get2
  1823.     ermsg <Can't GET without prior SET LINE>
  1824.     ret
  1825.  
  1826. $get2:    move t1, [point 7, atmbuf] ; Copy the string out of the atom buffer.
  1827.     move t2, [point 8, data]
  1828.     seto t3,        ; Counter, started at -1.
  1829.  
  1830. $get3:    ildb t4, t1        ; Get a character.
  1831.     idpb t4, t2        ; Copy it.
  1832.     aos t3            ; Count it.
  1833.     jumpn t4, $get3        ; Everything up to & including the first null.
  1834.  
  1835.     jumpe t3, [ermsg <No remote filespec given>
  1836.         ret ]
  1837.     movei t1, "R"        ; Send a Receive-Init packet.
  1838.     setz t2,        ; Number 0.
  1839.     move t4, [point 8, data] ; Point to remote filespec.
  1840.     call spack
  1841.      jrst [    ermsg <Can't send Receive-Init>
  1842.         ret ]
  1843.     callret $recv        ; Go into receive state.
  1844.  
  1845.     subttl    RECEIVE command
  1846.  
  1847. .recv:    noise <into file>
  1848.     movei t1, [flddb. (.cmofi,cm%sdh,,<output file specification>,,[
  1849.            flddb. (.cmcfm,cm%sdh,,<confirm to use micro's filespec>,,)])]
  1850.     call rfield        ; Parse a file spec or a confirm.
  1851.     ldb t3, [pointr (.cmfnp(t3),cm%fnc)] ; Get function code.
  1852.     caie t3, .cmofi        ; Is it an input file spec?
  1853.      jrst .recv2        ;  If not it must be a confirm.
  1854.     movem t2, filjfn    ; Save the JFN.
  1855.     movei t1, [flddb. .cmcfm]
  1856.     call rflde
  1857.      jrst [ move t1, filjfn    ;  Get the JFN.
  1858.         RLJFN%        ;  Release it.
  1859.          erjmp .recv1    ;   Ignore.
  1860. .recv1:        setzm filjfn    ;  Set the JFN to zero.
  1861.         tmsg <?Not confirmed>
  1862.         jrst cmder1 ]
  1863. .recv2:    ret
  1864.  
  1865. $recv:    setzm stot        ; Initialize character counters.
  1866.     setzm rtot
  1867.     setzb schr, stchr
  1868.     setzb rchr, rtchr
  1869.     setom rptot        ;[4] Init received-packet counter to -1.
  1870.     setzm errptr        ; Zero the error message pointer.
  1871.     skipe autbyt        ; Using autobyte?
  1872.      setzm ebtflg        ;  If so reset eight bit flag.
  1873.     call inilin        ; Initialize the line.
  1874.     call ccon        ; Turn on the ^C trap so line is restored.
  1875.      jrst reslin        ;[27] On ^C, go reset line & return from there.
  1876.     setzm pktnum        ; Inititial the packet sequence number.
  1877.     movei state, "R"    ; Set the state to receive initiate.
  1878.     setzm numtry        ; Set the number of tries to zero.
  1879.  
  1880. $recv2:    skipe local        ;[22] Local?
  1881.      caie debug, 1        ;[22] Normal debugging?
  1882.      skipa            ;[22]  No.
  1883.      jrst [    movei t1, .priou ;[22]  Yes, output the packet number.
  1884.         move t2, pktnum    ; 
  1885.         movei t3, ^d10    ; In decimal.
  1886.         NOUT%        ; 
  1887.          jrst .+1    ;  Can't, but it's not the end of the world...
  1888.         jrst .+1 ]
  1889.     cain state, "D"        ; Are we in the data send state?
  1890.      jrst [ diamsg <D >
  1891.         call rdata
  1892.         jrst $recv2 ]
  1893.     cain state, "F"        ; Are we in the file receive state?
  1894.      jrst [ diamsg <F >
  1895.         move t1, filjfn    ;  Get the file's JFN.
  1896.         call rfile    ;  Call receive file.
  1897.         jrst $recv2 ]
  1898.     cain state, "R"        ; Are we in the receive initiate state?
  1899.      jrst [    diamsg <R >
  1900.         call rinit    ;  Call receive initiate.
  1901.         jrst $recv2 ]
  1902.     cain state, "C"        ; Are we in the receive complete state?
  1903.      jrst [    diamsg <C >
  1904.         call reslin    ;  Restore the line.
  1905.         GTAD%        ;  Get the time we ended.
  1906.         subm t1, stdat    ;  Figure how long it all took.
  1907.         call ccoff    ;  Turn off ^C trap.
  1908.         movei t1, .chbel ;[31] Give a beep
  1909.         skipe local    ;[31] if local
  1910.          PBOUT        ;[31]
  1911.         ret ]
  1912.     cain state, "A"        ; Are we in the receive abort state?
  1913.      jrst [    diamsg <A >
  1914.         call reslin    ;  Restore the line.
  1915.         GTAD%        ;  Get the time we ended.
  1916.         subm t1, stdat    ;  Figure how long it all took.
  1917.         call ccoff    ;  Turn off ^C trap.
  1918.         ret ]
  1919.     diamsg <U >        ; Something else...
  1920.     call ccoff        ; Turn off ^C trap.
  1921.     ret
  1922.  
  1923.  
  1924.     subttl receive routines
  1925.  
  1926. rinit:    saveac <q1>
  1927.     move q1, numtry        ; Get the number of tries.
  1928.     caml q1, imxtry        ; Have we reached the maximum number of tries?
  1929.      jrst [ ermsg <Unable to receive initiate>
  1930.         movei state, "A" ;  Change the state to abort.
  1931.         ret ]
  1932.     aos numtry        ; Increment the number of tries.
  1933.     call rpack        ; Get a packet.
  1934.      ret            ;  Trashed packet don't change state, retry.
  1935.     cain t1, "E"        ;[32] Error packet?
  1936.      jrst [    hrroi t1, [asciz/?Remote error -- /] ;[32] Yes, print it.
  1937.         PSOUT%        ;[32]
  1938.         move t1, t4    ;[32] Get pointer to it,
  1939.         PSOUT%        ;[32] and print it.
  1940.         movei state, "A" ;[32] "Abort" the transfer.
  1941.         ret ]        ;[32]  Return gracefully.
  1942.     move q1, t1        ; Not error, save the packet type.
  1943.     GTAD%            ; Get the time we start.
  1944.     movem t1, stdat        ; Save it.
  1945.     caie q1, "S"        ; Got a send-init?
  1946.      jrst [    move t2, pktnum    ;  No, something else, or timed out.
  1947.         call NAK    ;  Just NAK the packet we wanted.
  1948.         ret ]
  1949.     movem t2, pktnum    ; Yes, synchronize packet numbers.
  1950.     call spar        ; Get the information
  1951.     move t4, [point 8, data] ; Get a pointer to our data block.
  1952.     call rpar        ; Set the information.
  1953.     movei t1, "Y"        ; Acknowledge packet.
  1954.     move t2, pktnum        ; Packet number.
  1955.     move t4, [point 8, data] ; The address of the data.
  1956.     call spack        ; Send the packet.
  1957.      jrst [    movei state, "A" ; Failed, set state to "abort".
  1958.         ret ]
  1959.     move t2, numtry        ; Get the number of tries.
  1960.     movem t2, oldtry    ; Save it.
  1961.     setzm numtry        ; Reset the number of tries.
  1962.     move t2, pktnum        ; Get the packet number.
  1963.     addi t2, 1        ; Increment it.
  1964.     dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  1965.     movei state, "F"    ; Set the state to file send.
  1966.     ret 
  1967.  
  1968. rfile:    saveac <q1,q2>
  1969.     move q1, numtry        ; Get the number of tries.
  1970.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  1971.      jrst [ ermsg <Unable to receive file header
  1972. >
  1973.         movei state, "A" ;  Change the state to abort.
  1974.         ret ]
  1975.     aos numtry        ; Increment number of tries.
  1976.     move q1, t1        ; Save the arguments.
  1977.     move q2, t2
  1978.     call rpack        ; Get a packet.
  1979.      ret            ;  Trashed packet, don't change state, retry.
  1980.  
  1981. rfile1:    caie t1, "S"        ; Check the packet.
  1982.      jrst rfile2
  1983.     move q1, oldtry        ; Get the number of tries.
  1984.     caml q1, imxtry        ; Have we reached the maximum number of tries?
  1985.      jrst [ ermsg <Unable to receive initiate>
  1986.         movei state, "A" ; Change the state to abort.
  1987.         ret ]
  1988.     aos oldtry        ; Save the updated number of tries.
  1989.     skipg q1, pktnum    ;[3] Get the present packet number.
  1990.      movei q1, 100        ;[3]  If it just wrapped around, do this.
  1991.     caie t2, -1(q1)        ; Is the packet's number one less than now?
  1992.      jrst [ ermsg <Error receiving initiate>
  1993.         movei state, "A" ; Change the state to "abort".
  1994.         ret ]
  1995.     setzm numtry         ; Start count over.
  1996.     move t4, [point 8, data] ; Get a pointer to our data block.
  1997.     call rpar         ; Set the information.
  1998.     movei t1, "Y"         ; Acknowledge packet.
  1999.     move t4, [point 8, data] ; The address of the data.
  2000.     call spack         ; Send the packet.
  2001.      movei state, "A" ;  Can't, set state to "abort".
  2002.     ret
  2003.  
  2004. rfile2:    caie t1, "Z"        ; Check the packet.
  2005.      jrst rfile3
  2006.     move q1, oldtry        ; Get the number of tries.
  2007.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  2008.      jrst [ ermsg <Maximum retries exceeded, unable to receive EOF>
  2009.         movei state, "A" ; Change the state to abort.
  2010.         ret ]
  2011.     aos oldtry        ; Save the updated number of tries.
  2012.     skipg q1, pktnum    ;[3] Get the present packet number.
  2013.      movei q1, 100        ;[3] If it just wrapped around, do this.
  2014.     caie t2, -1(q1)        ; Is the packet's number one less than now?
  2015.      jrst [ ermsg <Invalid EOF packet received>
  2016.         movei state, "A" ; Change the state to abort.
  2017.         ret ]
  2018.     setzm numtry        ; Start count over.
  2019.     movei t1, "Y"        ; Acknowledge packet.
  2020.     setzb t3, t4        ; No data.
  2021.     call spack        ; Send the packet.
  2022.      movei state, "A"    ; Can't, set state to abort.
  2023.     ret
  2024.  
  2025. rfile3:    caie t1, "F"        ; Start of file?
  2026.      jrst rfile4
  2027.     came t2, pktnum        ; Is it the right packet number?
  2028.      jrst [ ermsg <Incorrect packet number on start of file packet>
  2029.             movei state, "A" ; Change the state to abort.
  2030.             ret ]
  2031.     move t1, t4        ; Get a pointer to the data.
  2032.     move t2, t3        ; Get the length of the data.
  2033.     call gofil        ; Get a file to write to.
  2034.      jrst [    movei state, "A" ;  Set state to abort.
  2035.         ret ]
  2036.     movem t1, filjfn    ; Save the JFN.
  2037.     movei t1, "Y"        ; Acknowledge packet.
  2038.     move t2, pktnum
  2039.     setzb t3, t4        ; No data.
  2040.     call spack        ; Send the packet.
  2041.      jrst [    movei state, "A" ; Can't, "abort".
  2042.         ret ]
  2043.     move t1, filjfn
  2044.     movx t2, fld(7,of%bsz)!of%wr ;  7-bit bytes, write access.
  2045.     skipe ebtflg        ;  Eight bit access?
  2046.      movx t2, fld(8,of%bsz)!of%wr ;  8-bit bytes, write access.
  2047.     OPENF%            ; Open the file.
  2048.      erjmp [kermsg <Unable to open file
  2049. >
  2050.         move t1, filjfn    ; Get the output JFN.
  2051.         RLJFN%        ; Release the JFN.
  2052.          erjmp .+1    ;  Ignore the error.
  2053.         setzm filjfn    ; Clear the JFN.
  2054.         movei state, "A" ; Change state to EOF
  2055.         ret ]
  2056.     skipe local        ;[12] Local Kermit?
  2057.      jrst [    movei t1, .priou ;[12] Yes, print the file name.
  2058.         RFPOS%        ;[12] First see if we need to start a new line.
  2059.         hrroi t1, crlf    ;[12]  ...
  2060.         trne t2, -1    ;[12]  ...
  2061.          PSOUT%        ;[12]
  2062.         movei t1, .priou ;[12] Now print the file name.
  2063.         hrrz t2, filjfn ;[12]
  2064.         setz t3,    ;[12]
  2065.         JFNS%        ;[12]
  2066.          erjmp .+1    ;[12]
  2067.         movei t1, " "    ;[12]
  2068.         PBOUT%        ;[12]
  2069.         jrst .+1 ]    ;[12]
  2070.  
  2071.     setzm mapflg        ; Say no pages mapped in yet.
  2072.     move t2, numtry        ; Get the number of tries.
  2073.     movem t2, oldtry    ; Save it.
  2074.     setzm numtry        ; Reset the number of tries.
  2075.     move t2, pktnum        ; Get the packet number.
  2076.     addi t2, 1        ; Increment it.
  2077.     dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2078.     movei state, "D"    ; Set the state to file send.
  2079.     ret
  2080.  
  2081. rfile4:    caie t1, "B"        ; End of transmission?
  2082.      jrst rfile5        ;  No.
  2083.     came t2, pktnum        ; Is it the right packet number?
  2084.      jrst [ ermsg <Incorrect packet number on EOT packet
  2085. >
  2086.         movei state, "A" ; Change the state to abort.
  2087.         ret ]
  2088.     movei t1, "Y"        ; Acknowledge packet.
  2089.     setzb t3, t4        ; No data.
  2090.     call spack        ; Send the packet.
  2091.      skipa state, "A"    ; Can't, abort.
  2092.     movei state, "C"    ; Set state to complete.
  2093.     ret
  2094.  
  2095. rfile5:    cain t1, "T"        ; Timer interrupt pseudo packet?
  2096.      jrst [    movei t1, "N"    ; Yes, send a NAK
  2097.         move t2, pktnum    ; for the expected packet.
  2098.         setzb t3, t4    ; No data.
  2099.         call spack    ; Send the packet.
  2100.          movei state, "A" ; Can't, "abort".
  2101.         ret ]
  2102.  
  2103. rfilex:    movei state, "A"    ; Anything else: "abort".
  2104.     ret
  2105.  
  2106.  
  2107. rdata:    saveac <q1,q2>
  2108.     move q1, numtry        ; Get the number of tries.
  2109.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  2110.      jrst [ ermsg <Unable to receive data
  2111. >
  2112.         jrst rdterr]
  2113.     addi q1, 1        ; Increment it.
  2114.     movem q1, numtry    ; Save the updated number of tries.
  2115.     move q1, t1        ; Save the arguments.
  2116.     move q2, t2
  2117.     call rpack        ; Get a packet.
  2118.      ret            ;  Trashed packet don't change state, retry.
  2119.     cain t1, "D"        ; Data packet?
  2120.      jrst [    came t2, pktnum    ;  Is it the right packet?
  2121.          jrst .+1
  2122.         move t1, t4    ;  Get the pointer to the data.
  2123.         move t2, t3    ;  Get the length of the data.
  2124.         call ptchr    ;  Write the chars to a file.
  2125.          jrst rdterr    ;   Die cleanly.
  2126.         movei t1, "Y"    ;  Acknowledge packet.
  2127.         move t2, pktnum    ;  Get the sequence number.
  2128.         setzb t3, t4    ;  No data.
  2129.         call spack    ;  Send the packet.
  2130.          jrst rdterr    ;   Die cleanly.
  2131.         move t2, numtry ;  Get the number of tries.
  2132.         movem t2, oldtry ;  Save it.
  2133.         setzm numtry    ;  Reset the number of tries.
  2134.         move t2, pktnum ;  Get the packet number.
  2135.         addi t2, 1    ;  Increment it.
  2136.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2137.         ret ]
  2138.     cain t1, "D"        ; Is it a previous data packet?
  2139.      jrst [    move q1, oldtry    ;  Get the number of tries.
  2140.         caml q1, maxtry    ;  Have we reached the maximum number of tries?
  2141.          jrst [ ermsg <Unable to receive data
  2142. >
  2143.             jrst rdterr ] ; Die cleanly.
  2144.         aos oldtry    ; Updated number of tries.
  2145.         skipg q1, pktnum ;[3]  Get the present packet number.
  2146.          movei q1, 100    ;[3]  If it just wrapped around, do this.
  2147.         caie t2, -1(q1)    ;  Is the packet's number one less than now?
  2148.          jrst [ ermsg <Error receiving data
  2149. >
  2150.              jrst rdterr] ;  Die cleanly
  2151.         setzm numtry    ;  Start count over.
  2152.         movei t1, "Y"    ;  Acknowledge packet.
  2153.         setzb t3, t4    ;  No data.
  2154.         call spack    ;  Send the packet.
  2155.          movei state, "A" ;   Set state to abort.
  2156.         ret ]
  2157.  
  2158.     cain t1, "F"        ; Check the packet.
  2159.      jrst [    move q1, oldtry    ;  Get the number of tries.
  2160.         caml q1, maxtry    ;  Have we reached the maximum number of tries?
  2161.          jrst [ ermsg <Unable to acknowledge file header
  2162. >
  2163.              jrst rdterr] ;  Die cleanly
  2164.         aos oldtry    ;  Save the updated number of tries.
  2165.         skipg q1, pktnum ;[3]  Get the present packet number.
  2166.          movei q1, 100    ;[3]  If it just wrapped around, do this.
  2167.         caie t2, -1(q1)    ;  Is the packet's number one less than now?
  2168.          jrst [ ermsg <Error receiving file header
  2169. >
  2170.              jrst rdterr] ;  Die cleanly
  2171.         setzm numtry    ;  Start count over.
  2172.         movei t1, "Y"    ;  Acknowledge packet.
  2173.         setzb t3, t4    ;  No data.
  2174.         call spack    ;  Send the packet.
  2175.          jrst rdterr    ;   Die cleanly
  2176.         ret ]
  2177.     cain t1, "Z"        ; Is it an EOF?
  2178.      jrst [    came t2, pktnum    ;  Yes, is the packet number correct?
  2179.          jrst [ ermsg <Invalid EOF packet received
  2180. >
  2181.             movei state, "A" ; Change the state to "abort".
  2182.             ret ]
  2183.         movei t1, "Y"    ; OK, acknowledge the packet.
  2184.         setzb t3, t4    ; (no data)
  2185.         call spack    ; Send the ACK.
  2186.          jrst [    movei state, "A" ; Can't, set state to "abort".
  2187.             ret ]
  2188.         skipe mapflg    ;  Any pages mapped in?
  2189.          jrst [    movx t1, <.fhslf,,mappag> ;   <our fork,,mapping page>
  2190.             hrl t2, filjfn ;  <file JFN,, page #>
  2191.             hrr t2, prepag
  2192.             movx t3, pm%rd!pm%wr ;   Read and write.
  2193.             PMAP%    ;   Map it out.
  2194.               %jsker (,r)
  2195.             setzm mapflg ;   Say no page mapped in.
  2196.             jrst rd1 ]
  2197.  
  2198. rd1:        movx t1, co%nrj
  2199.         hrr t1, filjfn    ;  Get the JFN.
  2200.         CLOSF%        ;  Close it.
  2201.          erjmp rd2
  2202.         movx cf%nud
  2203.         hrli t1, .fbsiz    ;  Set the number of bytes
  2204.         ior t1, [cf%nud]
  2205.         hrr t1, filjfn    ;  Get the JFN.
  2206.         seto t2,    ;  Change all bits.
  2207.         move t3, rchr    ;  Get the number of bytes.
  2208.         CHFDB%
  2209.          erjmp rd12
  2210. rd12:        hrli t1, .fbbyv    ;  Set the byte size.
  2211.         hrr t1, filjfn
  2212.         move t2, [007700,,0] ;  Just the correct six bits.
  2213.         move t3, [000700,,0] ;  Seven bit.
  2214.         skipe ebtflg    ;  Eight bit mode?
  2215.          move t3, [001000,,0] ;  Set it as such.
  2216.         CHFDB%
  2217.          erjmp rd2
  2218. rd2:        hrr t1, filjfn    ;  Get the JFN.
  2219.         RLJFN%        ;  Release the JFN.
  2220.          nop
  2221.         hrroi t1, [asciz/[OK]/]    ;[19] Comforting message.
  2222.         skipe local    ;[19]  Print it if local.
  2223.          PSOUT%        ;[19]
  2224.         setzm filjfn    ;  Say we have no file.
  2225.         addm rchr, rtchr ;  Add to the total.
  2226.         setz rchr,
  2227.         move t2, numtry ;  Get the number of tries.
  2228.         movem t2, oldtry ;  Save it.
  2229.         setzm numtry    ;  Reset the number of tries.
  2230.         move t2, pktnum ;  Get the packet number.
  2231.         addi t2, 1    ;  Increment it.
  2232.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2233.         movei state, "F"
  2234.         ret ]
  2235.     cain t1, "T"        ; Timer interrupt pseudo packet?
  2236.      jrst [    movei t1, "N"    ;  Send a NAK.
  2237.         move t2, pktnum
  2238.         setzb t3, t4    ;  No data.
  2239.         call spack    ;  Send the packet.
  2240.          movei state, "A" ; Can't, set state to "abort".
  2241.         ret ]
  2242. rdterr:    movx t1, cz%abt        ; Abort the file.
  2243.     hrr t1, filjfn        ; Get the JFN.
  2244.     CLOSF%            ; Close it.
  2245.      erjmp .+1
  2246.     setzm filjfn        ; Say we have no file.
  2247.     movei state, "A"    ; Change the state to abort.
  2248.     ret
  2249.  
  2250.     subttl    Utility protocol routines
  2251.  
  2252. ; Send a NAK.  Expects to find the packet number to NAK in AC2.
  2253.  
  2254. nak:    movei t1, "N"        ; Send a NAK.
  2255.     setzb t3, t4        ; No data.
  2256.     call spack        ; Send the packet.
  2257.      jrst [    movei state, "A" ;  Set state to abort.
  2258.         ret ]
  2259.     ret
  2260.  
  2261. ; Get the arguments from a Send_Init packet.
  2262. ;
  2263. ; The length of the data (i.e. the number of fields) should be in t3.
  2264.  
  2265. spar:    sojl t3, r        ;[24] Make sure the field is there.
  2266.     ildb t2, t4        ; Get the first argument.
  2267.     subi t2, " "        ; Convert it to a number.
  2268.     movem t2, spsiz        ; Set the maximum packet size to send.
  2269.  
  2270. spar2:    sojl t3, r        ;[24] Make sure the field is there.
  2271.     ildb t2, t4        ; Get the second argument.
  2272.     subi t2, " "        ; Convert it to a real number.
  2273.     movem t2, stimou    ; Set the time out interval.
  2274.     movem t2, otimou    ;[26] Here too, in case we want to change it.
  2275.  
  2276. spar3:    sojl t3, r        ;[24] Make sure the field is there.
  2277.     ildb t2, t4        ; Get the second argument.
  2278.     subi t2, " "        ; Convert it to a number.
  2279.     movem t2, spadnm    ; Set the padding.
  2280.  
  2281. spar4:    sojl t3, r        ;[24] Make sure the field is there.
  2282.     ildb t2, t4        ; Get the second argument.
  2283.     addi t2, ^o100
  2284.     andi t2, ^o177
  2285.     movem t2, spadch    ; Set the padding char.
  2286.  
  2287. spar5:    sojl t3, r        ;[24] Make sure the field is there.
  2288.     ildb t2, t4        ; Get the second argument.
  2289.     subi t2, " "        ; Convert it to a number.
  2290.     movem t2, seolch    ; Set the EOL char.
  2291.  
  2292. spar6:    sojl t3, r        ;[24] Make sure the field is there.
  2293.     ildb t2, t4        ; Get the second argument.
  2294.     movem t2, squote    ; Set the quote char.
  2295.  
  2296. ; Add additional fields here.
  2297.  
  2298. sparx:    ret
  2299.  
  2300. ; Sets up the init packet.  Returns number of elements in T3.
  2301.  
  2302. rpar:    saveac <q1>
  2303.     move q1, rpsiz        ; Get the packet size.
  2304.     addi q1, " "        ; Make the char printable.
  2305.     idpb q1, t4        ; Put it in the data block.
  2306.     move q1, rtimou        ; Get the time out interval.
  2307.     addi q1, " "        ; Make the char printable.
  2308.     idpb q1, t4        ; Put it in the data block.
  2309.     move q1, rpadnm        ; Get the padding.
  2310.     addi q1, " "        ; Make the char printable.
  2311.     idpb q1, t4        ; Put it in the data block.
  2312.     move q1, rpadch        ; Get the padding char.
  2313.     addi q1, ^o100        ; De-controlify it.
  2314.     andi q1, ^o177
  2315.     idpb q1, t4        ; Put it in the data block.
  2316.     move q1, reolch        ; Get the EOL char.
  2317.     addi q1, " "        ; Make the char printable.
  2318.     idpb q1, t4        ; Put it in the data block.
  2319.     move q1, rquote        ; Get the quote char.
  2320.     idpb q1, t4        ; Put it in the data block.
  2321.     movei t3, 6        ; Six pieces of data.
  2322.     ret
  2323.  
  2324.  
  2325.     subttl    SEND command
  2326.  
  2327. .send:    noise <from files>
  2328.     move t2, cjfnbk+.gjgen    ; Get the JFN flag bits.
  2329.     txo t2, gj%ifg!gj%old    ; Turn on wild carding for old files only.
  2330.     movem t2, cjfnbk+.gjgen    ; Return the JFN flag bits.
  2331.     movei t1, [flddb. (.cmfil,cm%sdh,,<input file spec (possibly wild)>,,)]
  2332.     call rfield        ; Parse a file spec or a confirm.
  2333.     movem t2, ndxjfn    ; Save the indexable JFN.
  2334.     hrrm t2, filjfn        ; Save the JFN.
  2335.     noise <initial>
  2336.     movei t1, [flddb. (.cmcfm,cm%sdh,,<Carriage return to send them all>,,[
  2337.            flddb. (.cmfil,cm%sdh,,<Initial filespec>)])]
  2338.     call rflde
  2339.      jrst [ move t1, filjfn    ;  Get the JFN.
  2340.         RLJFN%        ;  Release it.
  2341.          erjmp .snd2    ;   Ignore.
  2342. .snd1:        setzm filjfn    ;  Set the JFN to zero.
  2343.         tmsg <?Not confirmed>
  2344.         jrst cmder1 ]
  2345.     ldb t3, [pointr (.cmfnp(t3),cm%fnc)] ; Get function code.
  2346.     cain t3, .cmcfm        ; Confirmation?
  2347.      ret            ;  Yes, just return.
  2348.     hrrm t2, ndxjfn        ; No, initial filespec - substitute it.
  2349.     hrrm t2, filjfn
  2350.     movei t1, [flddb. .cmcfm]
  2351.     call rflde
  2352.      jrst [ move t1, filjfn    ; Get the JFN.
  2353.         RLJFN%        ; Release it.
  2354.          erjmp .snd2    ;  Ignore.
  2355. .snd2:        setzm filjfn    ; Set the JFN to zero.
  2356.         tmsg <?Not confirmed>
  2357.         jrst cmder1 ]
  2358.     ret
  2359.  
  2360. $send:    setzm stot        ; Initialize character counters.
  2361.     setzm rtot
  2362.     setzb schr, stchr
  2363.     setzb rchr, rtchr
  2364.     setom sptot        ;[4] Init the sent-packet counter to -1.
  2365.     setzm errptr        ; Zero the error message pointer.
  2366.     GTAD%            ; Get the time we start.
  2367.     movem t1, stdat        ; Save it for statistics.
  2368.     skipn srvflg        ; In server mode?
  2369.      jrst [    call inilin    ; No, need to initialize the line
  2370.         call ccon    ;  and turn on ^C trap so we can restore line.
  2371.          jrst reslin    ;[10] Don't go on if this fails.
  2372.         jrst .+1 ]
  2373.  
  2374.     move t1, delay        ; The specified delay in seconds,
  2375.         imuli t1, ^d1000    ;  converted to milliseconds.
  2376.     skipn local        ;[13] If acting as remote Kermit,
  2377.      DISMS%            ;  sleep to let them set up other side.
  2378.  
  2379. $send1:    setzm pktnum        ; Inititial the packet sequence number.
  2380.     movei state, "S"    ; Set the state to send initiate.
  2381.     setzm numtry        ; Set the number of tries to zero.
  2382.  
  2383.     ;...cont'd
  2384.  
  2385. $send2:    skipe local        ;[22] If local
  2386.      caie debug, 1        ;[22] and doing "state" debugging,
  2387.      skipa            ;[22]
  2388.      jrst [    movei t1, .priou ;[22]
  2389.         move t2, pktnum    ; type the packet number,
  2390.         movei t3, ^d10    ; in decimal.
  2391.         NOUT%
  2392.          jrst .+1
  2393.         jrst .+1 ]
  2394.  
  2395.     cain state, "D"        ; Are we in the data send state?
  2396.      jrst [ diamsg <D >
  2397.         call sdata
  2398.         jrst $send2 ]
  2399.     cain state, "F"        ; Are we in the file send state?
  2400.      jrst [    diamsg <F >
  2401.         move t1, filjfn    ;  Get the file's JFN.
  2402.         call sfile    ;  Call send file.
  2403.         jrst $send2 ]
  2404.     cain state, "Z"        ; Are we in the end of file state?
  2405.      jrst [    diamsg <Z >
  2406.         call seof
  2407.         jrst $send2 ]
  2408.     cain state, "S"        ; Are we in the send initiate state?
  2409.      jrst [    diamsg <S >
  2410.         call sinit    ;  Call send initiate.
  2411.         jrst $send2 ]
  2412.     cain state, "B"        ; Are we in the end of send state?
  2413.      jrst [    diamsg <B >
  2414.         call seot
  2415.         jrst $send2 ]
  2416.     cain state, "C"        ; Are we in the send complete state?
  2417.      jrst [    diamsg <C >
  2418.         call reslin    ;  Restore the line.
  2419.         GTAD%        ;  Get the time we ended.
  2420.         subm t1, stdat    ;  Figure how long it all took.
  2421.         call ccoff    ;  Turn off ^C trap.
  2422.         movei t1, .chbel ;[31] Give a beep
  2423.         skipe local    ;[31] if local
  2424.          PBOUT        ;[31]
  2425.         ret ]
  2426.     cain state, "A"        ; Are we in the send abort state?
  2427.      jrst [    diamsg <A >
  2428.         call reslin    ;  Restore the line.
  2429.         GTAD%        ;  Get the time we ended.
  2430.         subm t1, stdat    ;  Figure how long it all took.
  2431.         call ccoff    ;  Turn off ^C trap.
  2432.         ret ]
  2433.     diamsg <U >
  2434.     call ccoff        ; Turn off ^C trap.
  2435.     ret
  2436.  
  2437.  
  2438.     subttl Send routines
  2439.  
  2440. sinit:    saveac <q1>
  2441.     move q1, numtry        ; Get the number of tries.
  2442.     caml q1, imxtry        ; Have we reached the maximum number of tries?
  2443.      jrst [    skipe local    ;[5]
  2444.          ermsg <Send-Init not ACK'd> ;[5]
  2445.         movei state, "A" ;  Change the state to abort.
  2446.         ret ]
  2447.     aos numtry        ; Save updated number of tries.
  2448.     move t4, [point 8, data] ; Get a pointer to our data block.
  2449.     call rpar        ; Set the information.
  2450.     movei t1, "S"        ; Send initiate packet.
  2451.     move t2, pktnum        ; Packet number.
  2452.     move t4, [point 8, data] ; The address of the data.
  2453.     call spack        ; Send the packet.
  2454.      jrst [    movei state, "A" ; Can't, set state to "abort".
  2455.         ret ]
  2456.     call rpack        ; Get a packet.
  2457.      ret            ;  Trashed packet don't change state, retry.
  2458.     cain t1, "Y"        ; Check the packet.
  2459.      jrst [    came t2, pktnum    ; Is it the right ACK?
  2460.          ret        ;  No, don't settle, hold out for right one.
  2461.         call spar    ; Get the information
  2462.         setzm numtry    ; Reset the number of tries.
  2463.         move t2, pktnum ; Get the packet number.
  2464.         aos t2        ; Increment it.
  2465.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2466.         movei state, "F" ; Set the state to file send.
  2467.         ret ]
  2468.     caie t1, "N"        ;[30] NAK?
  2469.     cain t1, "T"        ; Timer interrupt pseudo packet?
  2470.      ret            ;[30] One of those, just keep trying.
  2471.     movei state, "A"    ; Anything else, just "abort".
  2472.     cain t1, "E"        ; But also print message if error packet.
  2473.      jrst [    hrroi t1, [asciz/?Remote error -- /] ; Yes, print it.
  2474.         PSOUT%
  2475.         move t1, t4    ; Get pointer to it,
  2476.         PSOUT%        ; and print it.
  2477.         ret ]
  2478.     ret
  2479.  
  2480. sfile:    saveac <q1>
  2481.     move q1, numtry        ; Get the number of tries.
  2482.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  2483.      jrst [ ermsg <Unable to send file name
  2484. >
  2485.         movei state, "A" ;  Change the state to abort.
  2486.         ret ]
  2487.     addi q1, 1        ; Increment it.
  2488.     movem q1, numtry    ; Save the updated number of tries.
  2489.  
  2490. sfilea:    skipe local        ;[12] Local Kermit?
  2491.      jrst [    movei t1, .priou ;[12] Yes, print the file name.
  2492.         RFPOS%        ;[12] First see if we need to start a new line.
  2493.         hrroi t1, crlf    ;[12]  ...
  2494.         trne t2, -1    ;[12]  ...
  2495.          PSOUT%        ;[12]
  2496.         movei t1, .priou ;[12] Now print the file name.
  2497.         hrrz t2, filjfn ;[12]
  2498.         setz t3,    ;[12]
  2499.         JFNS%        ;[12]
  2500.          erjmp .+1    ;[12]
  2501.         movei t1, " "    ;[12] and a space.
  2502.         PBOUT%        ;[12]
  2503.         jrst .+1 ]    ;[12]
  2504.  
  2505.     move t1, filjfn        ;[15] Try to open the file.
  2506.     movx t2, fld(7,of%bsz)+of%rd ;[15]
  2507.     skipe ebtflg        ;[15] 8-bit access?
  2508.      movx t2, fld(8,of%bsz)+of%rd ;[15]
  2509.     OPENF%            ;[15]
  2510.      erjmp [skipe local    ;[15]
  2511.          call [    movei t1, " " ;[15]
  2512.             PBOUT%    ;[15]
  2513.             movei t1, .priou ;[15]
  2514.             move t2, [.fhslf,,-1] ;[15] Print OPENF error msg.
  2515.             setz t3, ;[15]
  2516.             ERSTR%    ;[15]
  2517.              nop    ;[15]
  2518.              nop    ;[15]
  2519.             tmsg < (not sent)> ;[15]
  2520.             ret ]    ;[15]
  2521.         call gtnfil    ;[15] Try to get the next file.
  2522.          jrst [    setzm filjfn ;[15]
  2523.             movei state, "B" ;[15] No more, break transmission.
  2524.             ret ]    ;[15]
  2525.         jrst sfilea ]    ;[15] Got one, go try to open it.
  2526.  
  2527.     move t2, filjfn        ; Get the JFN.
  2528.     move t1, [point 8, data] ; Get a pointer to the data buffer.
  2529.     movx t3, js%nam+js%typ+js%paf ; Just the file name and type.
  2530.     setz t4,
  2531.     JFNS%            ; Get the file name.
  2532.     move t2, t1        ; Set up to subtract the byte pointers.
  2533.     move t1, [point 8, data] ; Get a pointer to our data block.
  2534.     call subbp        ; Subtract the byte pointers.
  2535.      ret
  2536.     movei t1, "F"        ; File send packet.
  2537.     move t2, pktnum        ; Packet number.
  2538.     move t4, [point 8, data] ; Get a pointer to our data block.
  2539.     call spack        ; Send the packet.
  2540.      jrst [    movei state, "A" ;  Set state to abort.
  2541.         ret ]
  2542.     call rpack        ; Get a packet.
  2543.      ret            ;  Trashed packet don't change state, retry.
  2544.     caie t1, "Y"        ; Check the packet, is it an ACK?
  2545.      jrst sfile3        ;  No.
  2546. sfile2:    came t2, pktnum        ; Yes, but is it the right ACK?
  2547.      ret            ;   No, don't settle, hold out for right one.
  2548.     setzm numtry        ;  Reset the number of tries.
  2549.     move t2, pktnum        ;  Get the packet number.
  2550.     addi t2, 1        ;  Increment it.
  2551.     dpb t2, [point 6, pktnum, 35] ;  Save modulo 64 of the number.
  2552.     setzm mapflg        ; Say no pages mapped in yet.
  2553.     move t1, spsiz        ; Get the send packet size.
  2554.     subi t1, 5        ; Subtract the overhead.
  2555.     call gtchr        ; Get the chars.
  2556.      jrst [    movei state, "Z" ; Assume end of file
  2557.         skipe t1    ; Was it?
  2558.          movei state, "A" ; No, "abort".
  2559.         ret ]
  2560.     movei state, "D"    ;  Set the state to file send.
  2561.     movem t1, size        ;  Save the length of the data.
  2562.     ret
  2563.  
  2564. sfile3:    caie t1, "N"        ; NAK?
  2565.      jrst sfile4
  2566.     ldb t1, [point 6, pktnum, 35] ;[3] Get expected packet number.
  2567.     caie t2, 1(t1)        ;  Is the NAK for the next packet?
  2568.      ret            ;   Assume its for this packet.
  2569.     setzm numtry        ;  Yes, means the same as ACK.  
  2570.     addi t1, 1        ;  Increment it.
  2571.     dpb t1, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2572.     setzm mapflg        ; Say no pages mapped in yet.
  2573.     move t1, spsiz        ; Get the send packet size.
  2574.     subi t1, 5        ; Subtract the overhead.
  2575.     call gtchr        ; Get the chars.
  2576.      jrst [    movei state, "Z" ; Assume end of file
  2577.         skipe t1    ; Was it?
  2578.          movei state, "A" ; No, "abort".
  2579.         ret ]
  2580.     movei state, "D"    ;  Set the state to file send.
  2581.     movem t1, size        ;  Save the length of the data.
  2582.     ret
  2583.  
  2584. sfile4:    cain t1, "T"        ; Timer interrupt pseudo packet?
  2585.      ret
  2586.     movei state, "A"    ; Otherwise abort.
  2587.     ret
  2588.  
  2589. sdata:    saveac <q1>
  2590.     move q1, numtry        ; Get the number of tries.
  2591.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  2592.      jrst [ ermsg <Unable to send data
  2593. >
  2594.         movei state, "A" ;  Change the state to abort.
  2595.         ret ]
  2596.     aos numtry        ; Increment number of tries.
  2597.     movei t1, "D"        ; File send packet.
  2598.     move t2, pktnum        ; Packet number.
  2599.     move t3, size        ; Get the data length.
  2600.     move t4, [point 8, data] ; Get a pointer to our data block.
  2601.     call spack        ; Send the packet.
  2602.      skipa state, "A"    ;  Can't, "abort".
  2603.     call rpack        ; Get a packet.
  2604.      ret            ;  Trashed packet don't change state, retry.
  2605.     cain t1, "Y"        ; Check the packet.
  2606.      jrst [    came t2, pktnum    ;  Is it the right ACK?
  2607.          ret        ;   No, don't settle, hold out for right one.
  2608.         setzm numtry    ;  Reset the number of tries.
  2609.         move t2, pktnum ;  Get the packet number.
  2610.         addi t2, 1    ;  Increment it.
  2611.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2612.         move t1, spsiz    ;  Get the send packet size.
  2613.         subi t1, 5    ;  Subtract the overhead.
  2614.         call gtchr
  2615.          jrst [    skipe t1 ; Is it end of file?
  2616.              skipa state, "A" ; No, change state to abort.
  2617.              movei state, "Z" ; Yes, set state to end of file.
  2618.             ret ]
  2619.         movem t1, size    ;  Save the length of the data.
  2620.         ret ]
  2621.  
  2622.     cain t1, "N"        ; NAK?
  2623.      jrst [    ldb t1, [point 6, pktnum, 35] ;[3] Get expected packet number.
  2624.         caie t2, 1(t1)    ;  Is the NAK for the next packet?
  2625.          ret        ;   Assume its for this packet.
  2626.         setzm numtry    ;  Yes, means the same as ACK.  
  2627.         addi t1, 1    ;  Increment it.
  2628.         dpb t1, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2629.         move t1, spsiz    ;  Get the send packet size.
  2630.         subi t1, 5    ;  Subtract the overhead.
  2631.         call gtchr
  2632.          jrst [    skipe t1 ; Is it end of file?
  2633.                      skipa state, "A" ; No, change state to abort.
  2634.              movei state, "Z" ; Set state to end of file.
  2635.             ret ]
  2636.         movem t1, size    ;  Save the length of the data.
  2637.         ret ]
  2638.  
  2639.     cain t1, "T"        ; Timer interrupt pseudo packet?
  2640.      ret
  2641.     movei state, "A"    ; Otherwise abort.
  2642.     ret
  2643.  
  2644. seof:    saveac <q1>
  2645.     move q1, numtry        ; Get the number of tries.
  2646.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  2647.      jrst [ ermsg <Unable to send end of file>
  2648.         movei state, "A" ;  Change the state to abort.
  2649.         ret ]
  2650.     aos numtry        ; Increment number of tries.
  2651.     movei t1, "Z"
  2652.     move t2, pktnum        ; Packet number.
  2653.     setzb t3, t4        ; No data.
  2654.     call spack        ; Send the packet.
  2655.      skipa state, "A"    ;  Can't, "abort".
  2656.     call rpack        ; Get a packet.
  2657.      ret            ;  Trashed packet don't change state, retry.
  2658.     cain t1, "Y"        ; Check the packet.
  2659.      jrst [    came t2, pktnum    ;  Is it the right ACK?
  2660.          ret        ;   No, don't settle, hold out for right one.
  2661.         setzm numtry    ;  Reset the number of tries.
  2662.         move t2, pktnum ;  Get the packet number.
  2663.         addi t2, 1    ;  Increment it.
  2664.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2665.         move t1, filjfn    ;  Get the file JFN.
  2666.         txo t1, co%nrj    ;  Don't release the JFN (for GNJFN%).
  2667.         CLOSF%
  2668.          erjmp gt3
  2669.         hrroi t1, [asciz/[OK]/]    ;[19] Comforting message.
  2670.         skipe local    ;[19]  Print it if local.
  2671.          PSOUT%        ;[19]
  2672.         addm schr, stchr ;  Add the last file's size to the total.
  2673.         setz schr,    ;  Zero the present count.
  2674. gt3:        call gtnfil    ;  Get the next file.
  2675.          jrst [    setzm filjfn ;   Zero the JFN.
  2676.             movei state, "B" ;   No more, set state to complete.
  2677.             ret ]
  2678.         movei state, "F" ;  File send state.
  2679.         ret ]
  2680.     cain t1, "N"        ; NAK?
  2681.      jrst [    ldb t1, [point 6, pktnum, 35] ;[3] Get expected packet number.
  2682.         caie t2, 1(t1)    ;  Is the NAK for the next packet?
  2683.          ret        ;   Assume its for this packet.
  2684.         setzm numtry    ;  Reset the number of tries.
  2685.         move t2, pktnum ;  Get the packet number.
  2686.         addi t2, 1    ;  Increment it.
  2687.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2688.         move t1, filjfn    ;  Get the file JFN.
  2689.         txo t1, co%nrj    ;  Don't release the JFN (for GNJFN%).
  2690.         CLOSF%
  2691.          erjmp gt3
  2692.         hrroi t1, [asciz/[OK]/]    ;[19] Comforting message.
  2693.         skipe local    ;[19]  Print it if local.
  2694.          PSOUT%        ;[19]
  2695.         addm schr, stchr ;  Add the last file's size to the total.
  2696.         setz schr,    ;  Zero the present count.
  2697.         call gtnfil    ;  Get the next file.
  2698.          jrst [    setzm filjfn ;   Zero the JFN.
  2699.             movei state, "B" ; No more, set state to complete.
  2700.             ret ]
  2701.         movei state, "F" ;  File send state.
  2702.         ret ]
  2703.     cain t1, "T"        ; Timer interrupt pseudo packet?
  2704.      ret
  2705.     movei state, "A"    ; Otherwise "abort".
  2706.     ret
  2707.  
  2708.  
  2709. seot:    saveac <q1>
  2710.     move q1, numtry        ; Get the number of tries.
  2711.     caml q1, maxtry        ; Have we reached the maximum number of tries?
  2712.      jrst [ ermsg <Unable to send end of file
  2713. >
  2714.         movei state, "A" ;  Change the state to abort.
  2715.         ret ]
  2716.     aos numtry        ; Increment number of tries.
  2717.     movei t1, "B"
  2718.     move t2, pktnum        ; Packet number.
  2719.     setzb t3, t4        ; No data.
  2720.     call spack        ; Send the packet.
  2721.      skipa state, "A"    ;  Can't...
  2722.     call rpack        ; Get a packet.
  2723.      ret            ;  Trashed packet don't change state, retry.
  2724.     cain t1, "Y"        ; Check the packet.
  2725.      jrst [    came t2, pktnum    ;  Is it the right ACK?
  2726.          ret        ;   No, don't settle, hold out for right one.
  2727.         setzm numtry    ;  Reset the number of tries.
  2728.         move t2, pktnum ;  Get the packet number.
  2729.         addi t2, 1    ;  Increment it.
  2730.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2731.         movei state, "C" ;  Complete state.
  2732.         ret ]
  2733.     cain t1, "N"        ; NAK?
  2734.      jrst [    ldb t1, [point 6, pktnum, 35] ;[3] Get expected packet number.
  2735.         caie t2, 1(t1)    ;  Is the NAK for the next packet?
  2736.          ret        ;   Assume its for this packet.
  2737.         setzm numtry    ;  Reset the number of tries.
  2738.         move t2, pktnum ;  Get the packet number.
  2739.         addi t2, 1    ;  Increment it.
  2740.         dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  2741.         movei state, "C" ;  Complete state.
  2742.         ret ]
  2743.     cain t1, "T"        ; Timer interrupt pseudo packet?
  2744.      ret
  2745.     movei state, "A"    ; Otherwise abort.
  2746.     ret
  2747.  
  2748.     subttl File routines
  2749.  
  2750. gtchr:    saveac <q1,q2,q3,q4>
  2751.     stkvar <len,tmpac>
  2752.     subi t1, 1        ; So we don't mess up on quoting.
  2753.     movem t1, len        ; Save the length.
  2754.     skipe eoflag        ; Is the end of file flag set?
  2755.      jrst [    setz t1,    ;  Indicate EOF.
  2756.         setzm eoflag
  2757.         ret ]
  2758.     skipe mapflg        ; Do we have any thing mapped in?
  2759.      jrst gtchr1        ;  If so don't map anything in.
  2760.     move t1, filjfn        ; Get the JFN.
  2761.     movx t2, <2,,.fbbyv>    ; Get number of pages and bytes
  2762.     movei t3, filpag    ;  into filpag and filbyt.
  2763.     GTFDB%            ; Get the file descriptor block.
  2764.      %jsker <Can't get file length>,r ;  Error close up.
  2765.     skipn filbyt        ; Any bytes in the file?
  2766.      jrst [    setom eoflag    ;  No, set end of file flag.
  2767.         setz t1,    ;  Say no chars.
  2768.         retskp]
  2769.     ldb t2, [point 6, filpag, 11] ; Get the byte size.
  2770.     movem t2, filbsz    ; Save the file byte size.
  2771.     skipe autbyt        ; Are we using autobyte?
  2772.      jrst [    setzm ebtflg    ;  Probably seven bit.
  2773.         cain t2, ^d8    ;  Is the file eight bit?
  2774.          setom ebtflg    ;   If so, act like user requested 8-bit.
  2775.         jrst .+1 ]
  2776.     skipe ebtflg        ; Eight bit mode?
  2777.      jrst [    cain t2, ^d8    ;  Is the byte size 8?
  2778.          jrst gtchr0    ;  If so nothing to do.
  2779.         movei t3, ^d36    ;  If so, get the size of a word.
  2780.         idiv t3, t2    ;  Divide by the byte size.
  2781.         move q1, filbyt    ;  Get the number of bytes in file.
  2782.         idiv q1, t3    ;  Divide by the bytes/word to get words.
  2783.         imuli q1, 4    ;  Multilply by 4 (as if 8bit bytes).
  2784.         movem q1, filbyt ;  Save the new byte size.
  2785.         jrst gtchr0 ]
  2786.     caie t2, 7        ; Is the byte size seven?
  2787.      jrst [    movei t3, ^d36    ;  If not, get the size of a word.
  2788.         idiv t3, t2    ;  Divide by the byte size.
  2789.         move q1, filbyt    ;  Get the number of bytes in file.
  2790.         idiv q1, t3    ;  Divide by the bytes/word to get words.
  2791.         imuli q1, 5    ;  Multiply by 5 (as if 7bit bytes).
  2792.         movem q1, filbyt ;  Save the new byte size.
  2793.         jrst gtchr0 ]
  2794.  
  2795.     ;... (cont'd)
  2796.  
  2797. gtchr0:    hrlzs t1        ; If so continue.  <file JFN,, page 0>
  2798.     hrlm t1, filpag        ; Zero the left half of filpag.
  2799.     movx t2, <.fhslf,,mappag> ; <our fork,,mapping page>
  2800.     movx t3, pm%rd        ; Just want to read it.
  2801.     PMAP%            ; Map it in.
  2802.      %jsker <Can't map in file page>,r ;  Error close up.
  2803.     move q4, [point 7, mappag*1000]    ; Get a pointer to it.
  2804.     skipe ebtflg        ; Eight bit access?
  2805.      move q4, [point 8, mappag*1000] ; Get a pointer to it.
  2806.     setzm prepag        ; Present page is zero.
  2807.     setom mapflg        ; Say we've got a page mapped in.
  2808.     skipa            ; Skip the next.
  2809. gtchr1:     move q4, mapptr    ; Get the PMAP buffer pointer.
  2810.     setz q1,        ; Initialize the character count.
  2811.     move q2, [point 8, data] ; Get a pointer to where to put the chars.
  2812. gtchr2:    caml q1, len        ; Have we exceeded the length?
  2813.      jrst [    move t1, q1    ;  Return the length.
  2814.         movem q4, mapptr ;  Save the pointer.
  2815.         retskp ]
  2816.     caml schr, filbyt    ; Any more chars?
  2817.      jrst [    setom eoflag    ; Set the end of file flag.
  2818.         seto t1,    ; Indicate unmap.
  2819.         movx t2, <.fhslf,,mappag> ; This process.
  2820.         setz t3,
  2821.         PMAP%        ; Unmap the page.
  2822.          %jsker <Error unmapping page>,r
  2823.         setzm mapflg    ;  Say nothing mapped in.
  2824.         move t1, q1    ;  Return the size in the right AC.
  2825.         retskp ]
  2826.     ildb t2, q4        ; Get the next byte.
  2827.     movei t1, <mappag+1>*1000 ; Are we at the end yet
  2828.     caig t1, (q4)
  2829.      jrst [    seto t1,    ;  Indicate unmap.
  2830.         movx t2, <.fhslf,,mappag> ;  This process.
  2831.         setz t3,
  2832.         PMAP%        ;  Unmap the page.
  2833.          %jsker <Error unmapping page>,r
  2834.         move t1, prepag    ;  Get the present page number.
  2835.         addi t1, 1    ;  Increment it.
  2836.         caml t1, filpag    ;  Any more pages?
  2837.          jrst [    setom eoflag ;   Set the end of file flag.
  2838.             move t1, q1 ;   Return the size in the right AC.
  2839.             setzm mapflg ;   Say nothing mapped in.
  2840.             retskp ]
  2841.         movem t1, prepag ;  Save the new number.
  2842.         hrl t1, filjfn    ;  <file JFN,, page 0>
  2843.         movx t2, <.fhslf,,mappag> ;  <our fork,,mapping page>
  2844.         movx t3, pm%rd    ;  Just want to read it.
  2845.         PMAP%        ;  Map it in.
  2846.           %jsker <Can't map in file>,r ;   Error close up.
  2847.         move q4, [point 7, mappag*1000]    ; Get a pointer to it.        
  2848.         skipe ebtflg    ;  Eight bit access?
  2849.          move q4, [point 8, mappag*1000] ;  Get a pointer to it.
  2850.         ildb t2, q4    ;  Get the next byte.
  2851.         jrst .+1 ]
  2852.     ;...
  2853.  
  2854. gtch2a:    aos schr        ; Increment the file chars sent total.
  2855.     aos q1            ; Increment char count.
  2856.     movem t2, tmpac        ; Save the char.
  2857.     andi t2, ^o177        ; Turn off the 8th bit.
  2858.     cail t2, " "        ; Is it a control char?
  2859.      cain t2, .chdel    ;  Or a delete?
  2860.       jrst [move q3, squote    ;   Get the quote character.
  2861.         addi q1, 1    ;   Increment char count.
  2862.         idpb q3, q2    ;   Put in the quote character.
  2863.         move t2, tmpac    ;   Restore the char.
  2864.         xori t2, ^o100    ;   Make the char noncontrol.
  2865.         jrst gtchr3 ]
  2866.     camn t2, squote        ; Is it the quote character?
  2867.      jrst [    addi q1, 1    ;  Increment char count.
  2868.         idpb t2, q2    ;  Put in the quote character.
  2869.         jrst .+1 ]
  2870.     move t2, tmpac        ; Restore the char.
  2871.  
  2872. gtchr3:    move q3, schr        ; Get the char count.
  2873.     skipe ebtflg        ; Eight bit mode?
  2874.      jrst gtchr4        ;  If so don't fool with this hack.
  2875.     movem q4, tmpac        ; Save the AC.
  2876.     idivi q3, 5
  2877.     skipn q4        ; Is this the last char in the word?
  2878.      jrst [    hrr q4, tmpac    ;  Get the address of the word.
  2879.         move q4, (q4)    ;  Get its contents.
  2880.         andi q4, 1    ;  Get just bit 35.
  2881.         lsh q4, 7    ;  Shift it over into bit 8.
  2882.         ior t2, q4    ;  Or in that bit to the char.
  2883.         jrst .+1 ]
  2884.     move q4, tmpac        ; Restore the AC.
  2885. gtchr4:    idpb t2, q2        ; Put in the character.
  2886.     jrst gtchr2        ; Loop way back...
  2887.  
  2888. ptchr:    saveac <q1,q2,q3,q4>
  2889.     stkvar <siz,tmp>
  2890.     movem t2, siz        ; Save the size.
  2891.     move q1, t1        ; Save the arguments.
  2892.     move q2, t2
  2893.     skipn mapflg        ; Is there a page mapped in?
  2894.      jrst [    move q3, [point 7, mappag*1000]    ;  Get a pointer to it.
  2895.         skipe ebtflg    ;  Eight bit access?
  2896.          move q3, [point 8, mappag*1000] ;  Get a pointer to it.
  2897.         setzm prepag    ;  Present page is zero.
  2898.         setom mapflg    ;  Say we've got a page mapped in.
  2899.         jrst ptchr1 ]
  2900.     move q3, mapptr        ; Get a pointer to the buffer.
  2901. ptchr1:    setz q4,        ; Zero quote char count.
  2902. ptchr2:    skipg q2        ; Are we done?
  2903.      jrst [    movem q3, mapptr ;  Save the byte pointer.
  2904.         retskp ]
  2905.     addi rchr, 1        ; Add to the character count.
  2906.     subi q2, 1        ; Decrement char count.
  2907.     ildb t2, q1        ; Get the char.
  2908.     camn t2, rquote        ; Is it the quote character?
  2909.      jrst [    subi q2, 1    ;  Decrement char count.
  2910.         addi q4, 1    ;  Increment quote char count.
  2911.         ildb t2, q1    ;  Get the quoted character.
  2912.         move t1, t2    ;  Save the parity bit.
  2913.         andi t1, ^o177    ;  Save modulo 200 of the number.
  2914.         camn t1, rquote    ;  Is it the quote character?
  2915.          jrst .+1    ;   Yes, don't convert it.
  2916.         xori t2, ^o100    ;  Make the char noncontrol.
  2917.         jrst .+1 ]
  2918.     idpb t2, q3        ; Put it in the page.
  2919.     skipn ebtflg        ; Eight bit mode?
  2920.      caige t2, ^o200    ; Is the parity bit on?
  2921.      skipa
  2922.      jrst [    move t3, rchr    ;  If so, get the char count.
  2923.         idivi t3, 5
  2924.         skipn t4    ;  Is this the last char in the word?
  2925.          jrst [    move t4, (q3) ;   If so, get its contents.
  2926.             iori t4, 1 ;   Turn on bit 35.
  2927.             movem t4, (q3)
  2928.             jrst .+1 ]
  2929.         jrst .+1 ]
  2930.     ;...
  2931.  
  2932. ptchr3:    movei t1, <mappag+1>*1000 ; Are we at the end yet?
  2933.     caig t1, (q3)
  2934.      jrst [    movem t2, tmp    ;  Save char we just put in the wrong place.
  2935.         movx t1, <.fhslf,,mappag> ;  <our fork,,mapping page>
  2936.         hrl t2, filjfn ;  <file JFN,, page #>
  2937.         hrr t2, prepag
  2938.         movx t3, pm%rd!pm%wr ;  Read and write.
  2939.         PMAP%        ;  Map it out.
  2940.           %jsker (Unable to map out file page,r) ;   Error close.
  2941.         move t1, prepag    ;  Get the present page number.
  2942.         addi t1, 1    ;  Increment it.
  2943.         movem t1, prepag ;  Save the new number.
  2944.         move q3, [point 7, mappag*1000]    ;  Get a pointer to it.        
  2945.         skipe ebtflg    ;  Eight bit access?
  2946.          move q3, [point 8, mappag*1000] ;  Get a pointer to it.
  2947.         move t2, tmp    ;  Get back our char.
  2948.         idpb t2, q3    ;  Put it into the new page.
  2949.         jrst .+1 ]
  2950.     jrst ptchr2        ; Loop.
  2951.  
  2952. ; Get next file from wild file specification.
  2953.  
  2954. gtnfil:    move t1, ndxjfn        ; Get the indexable JFN.
  2955.     GNJFN%            ; Get the next JFN.
  2956.      ret            ;  No more files, so give up.
  2957.     hrrm t1, ndxjfn        ; Save the new JFN.
  2958.     hrrm t1, filjfn        ; Save the new JFN.
  2959.     retskp
  2960.  
  2961.  
  2962. ; Get an output file spec.
  2963. ;  AC1 - Pointer to a file name from the micro.
  2964. ;  AC2 - Number of characters.
  2965.  
  2966. gofil:    saveac <q1>
  2967.     move q1, t1        ; Save the pointer to the file name.
  2968.     skipe t1, filjfn    ; Do we have a file yet?
  2969.      retskp            ;  If so just return its JFN.
  2970.     skipg t2        ; Are there at least a few chars?
  2971.      jrst [    kermsg <Micro did not specify file name>
  2972.         ret ]
  2973.     move t1, q1        ; Get the file name pointer.
  2974.     call filfix        ; Go check & fix the filename syntax.
  2975.     movx t1, gj%sht!gj%fou    ; Short form.
  2976.     GTJFN%
  2977.      %jsker <Unable to get a JFN on the file>,r
  2978.     retskp
  2979.  
  2980. filfix:    move t3, [point 7, filbuf]
  2981. filfx2:    ildb t2, t1        ; Get the next char.
  2982.     skipn t2        ; The end?
  2983.      jrst [    idpb t2, t3    ; Put the null in.
  2984.         move t2, [point 7, filbuf] ; Return a pointer to the file.
  2985.         ret ]
  2986.     caile t2, " "        ; Space or less?
  2987.      cain t2, ^o177        ;  Or a delete?
  2988.       jrst filfx2        ;   If so skip it and move on.
  2989.     cain t2, "."
  2990.      jrst filfx4
  2991.     cail t2, "0"        ; Test if it is legal.
  2992.      caile t2, "z"
  2993.       jrst filfx3
  2994.     caige t2, "a"
  2995.      caig t2, "9"
  2996.       jrst filfx4
  2997.     cail t2, "A"
  2998.      caile t2, "Z"
  2999.       jrst filfx3
  3000.     jrst filfx4
  3001. filfx3:    movei t4, ^o26        ; If illegal get a control V.
  3002.     idpb t4, t3        ; Quote the illegal character.
  3003. filfx4:    idpb t2, t3        ; Put the character in.
  3004.     jrst filfx2
  3005.  
  3006.  
  3007.  
  3008.     subttl    Line routines
  3009.  
  3010. inilin:    move t1, netjfn        ; Get the line.
  3011.     movei t2, .morxo    ; Get the terminal pause characters.
  3012.     MTOPR%
  3013.      %jserr (,r)
  3014.     movem t3, oldpau    ; Save the old pause mode.
  3015.     movei t2, .moxof    ; Set the terminal pause characters.
  3016.     movei t3, .mooff    ; Set no pause on end.
  3017.     MTOPR%
  3018.      %jserr (,r)
  3019.     RFMOD%            ; Get current mode for this line.
  3020.      %jserr (,r)
  3021.     movem t2, oldmod    ; Save the present mode.
  3022.     movx t2, tt%mff+tt%tab+tt%lca+tt%dum+tt%pgm ; No conversion, half
  3023.                 ; .. duplex, pause on com and no echo.
  3024.     skipe ibmflg        ; Are we talking to the IBM?
  3025.      movx t2, tt%mff+tt%tab+tt%lca+tt%dum ; If so, same minus XON/XOFF.
  3026.     SFMOD%
  3027.      %jserr (,.+1)
  3028.     STPAR%
  3029.      %jserr (,.+1)
  3030.     CFIBF%            ;[1] Clear the line in case a bunch of NAKs
  3031.      %jserr (,.+1)        ;[1]  have piled up.
  3032.     ret
  3033.  
  3034. reslin:    move t1, netjfn        ; Get the line.
  3035.     movei t2, .moxof    ; Set the terminal pause on end mode.
  3036.     move t3, oldpau        ; Get the old pause mode.
  3037.     MTOPR%
  3038.      %jserr (,r)
  3039.     move t2, oldmod        ; Get the previous mode.
  3040.     SFMOD%
  3041.      %jserr (,.+1)
  3042.     STPAR%
  3043.      %jserr (,.+1)
  3044.     ret
  3045.  
  3046.  
  3047.     subttl Packet routines
  3048.  
  3049. ; Send_Packet
  3050. ; This routine assembles a packet from the arguments given and sends it
  3051. ; to the micro.
  3052. ;
  3053. ; Expects the following:
  3054. ;    AC1 - Type of packet (D,Y,N,S,R,E,F,Z,T)
  3055. ;    AC2 - Packet sequence number
  3056. ;    AC3 - Number of data characters
  3057. ;    AC4 - Byte pointer to data characters
  3058. ; Returns: +1 on failure
  3059. ;       +2 on success
  3060.  
  3061. spack:    saveac <q1,q2,q3>
  3062.     stkvar <type>        ; Local storage.
  3063.     movem t1, type        ; Save the type.
  3064.     setz q2,        ; Zero the checksum AC.
  3065.     move q1, [point 8, sndpkt] ; Get a byte pointer to the send packet.
  3066.     move t1, ssthdr        ;[18] Get the start of header char.
  3067.     call @parity        ; Call the appropriate parity routine.
  3068.     idpb t1, q1        ; Put in the packet.
  3069.     move t1, spsiz        ; Get the send packet size.
  3070.     caml t3, [-3]        ; Does the packet have some length?
  3071.      caile t3, -5(t1)    ;  Is this packet small enough?
  3072.       jrst [ermsg <Invalid data field of message>
  3073.         ret ]
  3074.     movei t1, 5(t3)        ;[22] We need the count for later.
  3075.     addm t1, stot        ;[22]
  3076.     addi t1, <" "-2>    ;[22] Real packet character count, printable.
  3077.     add q2, t1        ; Add the count to the checksum.
  3078.     call @parity        ; Call the appropriate parity routine.
  3079.     idpb t1, q1        ; Put the count into the packet.
  3080.     skipl t1, t2        ; Is the sequence number valid? (0-64)?
  3081.      cail t2, ^o100
  3082.       jrst [ermsg <Invalid message sequence number>
  3083.         ret ]
  3084.     addi t1, " "        ; Add a space so the number is printable.
  3085.     add q2, t1        ; Add the number to the checksum.
  3086.     call @parity        ; Call the appropriate parity routine.
  3087.     idpb t1, q1        ; Put the sequence number into the packet.
  3088.     move t1, type        ; Get the type.
  3089.     cail t1, "A"        ; Check if the type is a capital letter.
  3090.      caile t1, "Z"
  3091.       jrst [ermsg <Illegal message type>
  3092.         ret ]
  3093.     add q2, t1        ; Add in the message type to the checksum.
  3094.     call @parity        ; Call the appropriate parity routine.
  3095.     idpb t1, q1        ; Put the type into the packet.
  3096.     skipg t3        ; Are there any chars of data?
  3097.      jrst spack3        ;  No, finish up.
  3098.  
  3099.     ;...
  3100.  
  3101. spack2:    ildb t1, t4        ; Get the next char.
  3102.     add q2, t1        ; Add the char to the checksum.
  3103.     call @parity        ; Call the appropriate parity routine.
  3104.     idpb t1, q1        ; Put it into the packet.
  3105.     subi t3, 1        ; Decrement the char count.
  3106.     skiple t3        ; Are there any chars of data left?
  3107.      jrst spack2        ;  Yes, go get another.
  3108. spack3:    move t3, q2        ; Save the character total.
  3109.     andi q2, ^o300        ; And out all but 2 bits.
  3110.     lsh q2, -6        ; Shift them to the far right.
  3111.     add q2, t3        ; Add in the original value.
  3112.     ldb t1, [point 6, q2, 35] ; Get the modulo 64 of the char total.
  3113.     addi t1, " "        ; Add a space so the number is printable.
  3114.     call @parity        ; Call the appropriate parity routine.
  3115.     idpb t1, q1        ; Put the checksum into the packet.
  3116.     move t1, seolch        ; Get the requested EOL char.
  3117.     call @parity        ; Call the appropriate parity routine.
  3118.     idpb t1, q1        ; Add it to the packet.
  3119.     setz t1,        ; Get a null.
  3120.     idpb t1, q1        ; Put it at the end.
  3121.     skipn ibmflg        ; Are we talking to the IBM?
  3122.      jrst spack5        ;  No, proceed.
  3123.     cain state, "S"        ; Is this the send init packet?
  3124.      jrst spack5        ; If so don't wait for the turn around.
  3125.     movei t1, spack6    ; Where to go on time out.
  3126.     call timeit        ; Time the wait for the turn around.
  3127.     move t1, netjfn
  3128. spack4:    BIN%            ; Get a character from the host.
  3129.      %jserr(Error inputing character from micro,r)
  3130.     andi t2, ^o177        ; Turn off the parity.
  3131.     came t2, trnrnd        ; Is it the turn around char?
  3132.      jrst spack4        ;  If not go til it is.
  3133.     call timoff        ; Turn off the timer.
  3134. spack5:    move t1, netjfn        ; Output to the tty (micro).
  3135.     move t2, [point 8, sndpkt] ; The address of the packet.
  3136.     setzb t3, t4        ; End on a null.
  3137.     SOUT%            ; Send the string.
  3138.      %jserr <Send packet SOUT% failed>,r
  3139.     aos sptot        ;[4] Count the packet we sent.
  3140.     skipe debug        ;[4] Debugging?
  3141.      jrst [    move t2, [point 8, sndpkt] ;[22] Point to packet.
  3142.         call typpkt    ;[22] Yes, skip blips but maybe type packet.
  3143.         retskp ]    ;[22]
  3144.     skipn local        ;[4] Not debugging, but still local?
  3145.      retskp            ;[4]  Remote, don't make blips.
  3146.     move t3, type        ;[4] Local, am I sending a NAK packet?
  3147.     movei t1, "%"        ;[4] Print a "%" for each one I send.
  3148.     move t2, numtry        ;[4] Or each resend I have to do.
  3149.     caig t2, 1        ;[4]
  3150.     cain t3, "N"        ;[4]
  3151.      jrst spackx        ;[4]
  3152.     setz t3,        ;[4] Not a NAK, is it time to blip?
  3153.     move t4, sptot        ;[4] Check the absolute packet number.
  3154.     divi t3, blip        ;[4] We do it every "blip" packets.
  3155.     jumpn t4, rskp        ;[4] Not time for a blip.
  3156.     movei t1, "."        ;[4] It's time, here's the blip.
  3157. spackx:    PBOUT%            ;[4] .
  3158.     retskp
  3159.  
  3160. spack6: diamsg <T>        ; Time out returns here.
  3161.     jrst spack5        ; Join the regular code.
  3162.  
  3163.  
  3164. ; Receive_Packet
  3165. ; This routine waits for a packet to arrive from the micro.  It reads
  3166. ; characters until it finds a SOH.  It then reads the packet into recpkt.
  3167. ;
  3168. ; Returns:  +1 failure (if the checksum is wrong or the packet trashed)
  3169. ;        +2 success with AC1:  message type
  3170. ;                AC2:  message number
  3171. ;                           AC3:  length of data
  3172. ;                AC4:  byte pointer to data
  3173.  
  3174. rpack:    saveac <q1,q2,q3>
  3175.     stkvar <type,num>
  3176.     movei t1, tmout        ; Place to go on time out.
  3177.     call timeit        ; Time out if it takes too long.
  3178.     move t1, netjfn        ; Get the chars from the net.
  3179. rpack0:    call inchar        ; Get a character from the micro.
  3180.      jrst rperr
  3181.     came t2, rsthdr        ;[18] Is the char the start of header char?
  3182.      jrst rpack0        ;  No, go until it is (or we are timed out).
  3183. rpack1:    move q1, [point 8, recpkt] ; Get a pointer to the packet buffer.
  3184.     idpb t2, q1        ; Put the char into the packet.
  3185.     call inchar        ; Get a character from the micro.
  3186.      jrst rperr
  3187.     camn t2, rsthdr        ;[18] Is the char the start of header char?
  3188.      jrst rpack1        ;  Yes, then go start over.
  3189.     idpb t2, q1        ; Put the char into the packet.
  3190.     move q2, t2        ; Start the checksum.
  3191.     subi t2, " "+3        ; Get the real data count.
  3192.     skipge t2        ; Make sure the number makes sense.
  3193.      jrst [    ermsg <Bad character count
  3194. >
  3195.         jrst rperr ]
  3196.     move t3, t2        ; Prepare it for returning.
  3197.     call inchar        ; Get a character from the micro.
  3198.      jrst rperr
  3199.     camn t2, rsthdr        ;[18] Is the char the start of header char?
  3200.      jrst rpack1        ;  Yes, then go start over.
  3201.     idpb t2, q1        ; Put the char into the packet.
  3202.     add q2, t2        ; Add it to the checksum.
  3203.     subi t2, " "        ; Get the real packet number.
  3204.     movem t2, num        ; Save it for later.
  3205.     call inchar        ; Get a character from the micro.
  3206.      jrst rperr
  3207.     camn t2, rsthdr        ;[18] Is the char the start of header char?
  3208.      jrst rpack1        ;  Yes, then go start over.
  3209.     idpb t2, q1        ; Put the char into the packet.
  3210.     add q2, t2        ; Add it to the checksum.
  3211.     movem t2, type        ; Save the message type.
  3212.     move q3, t3        ; Get the number of data characters.
  3213.     move t4, q1        ; For returning the data pointer.
  3214.     skipg q3        ; Any data characters?
  3215.      jrst rpack3        ;  If not go get the checksum.
  3216.     ;...
  3217.  
  3218. rpack2:    call inchar        ; Get a character from the other side.
  3219.      jrst rperr        ;  Oops, can't.
  3220.     camn t2, rsthdr        ;[18] Is the char the start of header char?
  3221.      jrst rpack1        ;  Yes, then go start over.
  3222.     idpb t2, q1        ; Put the char into the packet.
  3223.     add q2, t2        ; Add it to the checksum.
  3224.     sojg q3, rpack2        ; Get next character, if any.
  3225.  
  3226. ; Count exhausted, next character will be the checksum.
  3227.  
  3228. rpack3:    call inchar        ; Get a character.
  3229.      jrst rperr
  3230.     camn t2, rsthdr        ;[18] Is the char the start of header char?
  3231.      jrst rpack1        ;  Yes, then go start over.
  3232.     skipe local        ;[29] If remote, skip next little part.
  3233.     call [    saveac <t2,q1>    ;[29] Preserve the current environment.
  3234.         idpb t2, q1    ;[29] Deposit the checksum after the data.
  3235.         setz t1,    ;[29] Terminate the string after the checksum.
  3236.         idpb t1, q1    ;[29]
  3237.         move t2, [point 8, recpkt] ;[29] Point at start of packet,
  3238.         call typpkt    ;[29] and type it if debugging packets.
  3239.         ret ]        ;[29] Back to previous environment.
  3240.     setz t1,        ; Terminate the data string, nullifying
  3241.     idpb t1, q1        ;  the checksum character if it's there.
  3242.     move q3, q2        ; Save the character total.
  3243.     andi q2, ^o300        ; And out all but 2 bits.
  3244.     lsh q2, -6        ; Shift them to the far right.
  3245.     add q2, q3        ; Add in the original value.
  3246.     ldb q2, [point 6, q2, 35] ; Get the modulo 64 of the char total.
  3247.     subi t2, " "        ; Get the numeric received checksum.
  3248.     came t2, q2        ; Are they equal?
  3249.      jrst [    skipn local    ;[22] No, local Kermit?
  3250.          jrst rperr    ;[29] No, skip messages.
  3251.         jumpe debug, rperr ;[29] Yes, but skip msg if not debugging.
  3252.         tmsg <
  3253. %Bad checksum >            ;[29] Local and debugging, say what we got.
  3254.         movei t1, " "(t2) ;[32]
  3255.         PBOUT        ;[29]
  3256.         tmsg <, I get >    ;[29] And what we expected to get.
  3257.         movei t1, " "(q2) ;[32]
  3258.         PBOUT        ;[29]
  3259.         movei t1, " "    ;[29]
  3260.         PBOUT        ;[29]
  3261.         jrst rperr ]
  3262.     call timoff        ; It's OK, turn the timer interrupt off.
  3263.     move t1, netjfn        ;[17]
  3264.     CFIBF%            ;[17] Prevent stacked packets.
  3265.      erjmp .+1        ;[17]
  3266.     aos rptot        ;[4] Count the packet we got.
  3267.  
  3268. rpackx:    move t1, type        ; Return the type in T1
  3269.     move t2, num        ; and the sequence number in T2.
  3270.     retskp
  3271.  
  3272. inchar:    saveac <q1>
  3273.     BIN%            ; Get a character from the micro.
  3274.      %jserr<Can't get character in INCHAR>,r
  3275.     aos rtot        ; Increment total count.
  3276.     move q1, parity        ; What type of parity?
  3277.     caie q1, none        ; If none, don't touch the parity.
  3278.      andi t2, ^o177        ;  Else, take out parity.
  3279.     retskp
  3280.  
  3281. rperr:    call timoff        ; Cancel the time out.
  3282.     move t1, netjfn        ;[17] Prevent stacked-up packets.
  3283.     CFIBF%            ;[17]
  3284.      erjmp .+1        ;[17]
  3285.     hrroi t1, [asciz/ (bad)/] ;[29] And say it was bad,
  3286.     jumpe debug, r        ;[29] if we're debugging,
  3287.     skipe local        ;[29] and local.
  3288.      PSOUT            ;[29]
  3289.     ret
  3290.  
  3291. ;[22] Type out a packet pointed to by t2, if verbose debugging.
  3292.  
  3293. typpkt:    skipe local        ; Local?
  3294.      caie debug, 2        ;  And verbose debugging?
  3295.      ret            ;  Not both, don't do this.
  3296.     saveac <t3,t4>        ; It's verbose debugging.  Save these,
  3297.     hrroi t1, crlf        ; and print the packet preceded by crlf.
  3298.     PSOUT            ;
  3299.     movei t1, .priou    ;
  3300.     setzb t3, t4        ;
  3301.     SOUT            ;
  3302.      erjmp .+1        ;
  3303.     ret
  3304.  
  3305.     subttl    Parity routines
  3306.  
  3307. ; Default, don't touch the eighth bit.
  3308.  
  3309. none:    ret
  3310.  
  3311. ; Mark, bit 8 is always 1.
  3312.  
  3313. mark:    ori t1, ^o200        ; Turn on the parity bit.
  3314.     ret
  3315.  
  3316. ; Space, opposite of mark, bit 8 is always zero.
  3317.  
  3318. space:    andi t1, ^o177        ; Turn off the parity bit.
  3319.     ret
  3320.  
  3321. ; Even, the total number of on bits should be even.
  3322.  
  3323. even:    saveac <t2>
  3324.     andi t1, ^o177        ; Start off with bit 8 = 0.
  3325.     move t2, t1
  3326.     jrst evnodd
  3327.  
  3328. ; Odd, the total number of on bits should be odd.
  3329.  
  3330. odd:    saveac <t2>
  3331.     andi t1, ^o177        ; Turn off the parity bit.
  3332.     movei t2, ^o200(t1)    ; Start off with bit 8 = 1.
  3333.  
  3334. evnodd:    lsh t2, -4        ; Get high order 4 bits of character
  3335.     xori t2, (t1)        ; Fold into 4 bits.
  3336.     trce t2, 14        ; Left two bits both 0 or 1?
  3337.      trnn t2, 14        ;  or both 1?
  3338.      xori t1, 200        ; Yes, set parity
  3339.     trce t2, 3        ; Right two bits both 0?
  3340.      trnn t2, 3        ;  or both 1?
  3341.      xori t1, 200        ; Yes, set parity.
  3342.     ret
  3343.  
  3344. ; We come here if we are in server mode.  This just waits for a
  3345. ; packet of one of the following types:
  3346. ;
  3347. ;    S    Send init - just follow the normal path from here
  3348. ;    R    Receive init - fake like we parsed a send <file-spec>
  3349. ;    G    Generic command
  3350. ;        L    Logout - the micro is done, log out this job
  3351. ;        F    Finish - exit from Kermit
  3352.  
  3353. getcom:    tmsg <
  3354. [Kermit Server running on DEC-20 host.  Please type your escape sequence to
  3355.  return to your local machine.  Shut down the server by typing the Kermit BYE
  3356.  command on your local machine.]
  3357. >
  3358.     setom srvflg        ; Say we are serving.
  3359.     call inilin        ; Initialize the line.
  3360.     call ccon        ; Don't let someone ^C without reseting line.
  3361.      jrst [    move t1, otimou ;[26]  What to do on ^C:
  3362.         movem t1, stimou ;[20] Restore normal timeout interval.
  3363.         move t1, odelay ;[27]  And normal delay
  3364.         movem t1, delay    ;[20]  ...
  3365.         setzm srvflg    ;[27]  Not a server any more.
  3366.         jrst reslin ]    ;[27]  Go reset line & return from there.
  3367.     setzm delay        ; No delay in server mode.
  3368.  
  3369. gtcmlp:    movei t1, dsrvtm    ;[25] Get the default server packet time out.
  3370.     movem t1, stimou    ;[25] Set it so we don't time out as often.
  3371. getcm1:                ;[25]
  3372.     setzm pktnum        ; Inititial packet sequence number.
  3373.     call rpack        ; Get a packet.
  3374.      jrst [    move t2, pktnum    ;  Timed out or something.
  3375.         call nak    ;  NAK that pack.
  3376.          jrst getcm1    ;[25]
  3377.         jrst getcm1 ]    ;[25]  Go round again.
  3378.  
  3379.     cain t1, "T"        ; Timer interrupt pseudo packet?
  3380.      jrst [    move t2, pktnum
  3381.         call nak    ; NAK that "packet".
  3382.          jrst getcm1    ;[25]
  3383.         jrst getcm1 ]    ;[25] Go round again.
  3384.  
  3385. ; Got a real command.  Restore the normal timeout interval and do the command.
  3386.  
  3387.     push p, t1        ;[26] We can't use any normal AC's here...
  3388.     move t1, otimou        ;[26] Put normal timeout back.
  3389.     movem t1, stimou    ;[26] 
  3390.     pop p, t1        ;[26]
  3391.  
  3392.     cain t1, "S"        ; Send command.
  3393.      jrst xsend        ; 
  3394.     cain t1, "R"        ; Receive (get) command.
  3395.      jrst xrecv        ; 
  3396.     cain t1, "G"        ; Generic command.
  3397.      jrst xgen
  3398.     cain t1, "H"        ; Host command.
  3399.      jrst xhost
  3400.  
  3401. ; (add new commands here...)
  3402.  
  3403. getcm2:    kermsg <Unimplemented server command> ; Something else.
  3404.  
  3405.     move t2, pktnum        ; Don't know what it is, just NAK it.
  3406.     call nak
  3407.      jrst .+1
  3408.     jrst gtcmlp        ; Listen again.
  3409.  
  3410.     subttl Server commands.
  3411.  
  3412. ; Server SEND command (i.e. send to server)
  3413.  
  3414. xsend:    setzm stot        ; Initialize character counters.
  3415.     setzm rtot
  3416.     setzb schr, stchr
  3417.     setzb rchr, rtchr
  3418.     setzm errptr        ; Zero the error message pointer.
  3419.     setzm numtry        ; Set the number of tries to zero.
  3420.     GTAD%            ; Get the time.
  3421.     movem t1, stdat        ; Hang on to the time for statistics.
  3422.     movem t2, pktnum    ; Synchronize packet numbers.
  3423.     call spar        ; Get the information
  3424.     move t4, [point 8, data] ; Get a pointer to our data block.
  3425.     call rpar        ; Set the information.
  3426.     movei t1, "Y"        ; Acknowledge packet.
  3427.     move t2, pktnum        ; Packet number.
  3428.     move t4, [point 8, data] ; The address of the data.
  3429.     call spack        ; Send the packet.
  3430.      jrst gtcmlp        ; Give up.
  3431.     move t2, numtry        ; Get the number of tries.
  3432.     movem t2, oldtry    ; Save it.
  3433.     setzm numtry        ; Reset the number of tries.
  3434.     move t2, pktnum        ; Get the packet number.
  3435.     addi t2, 1        ; Increment it.
  3436.     dpb t2, [point 6, pktnum, 35] ; Save modulo 64 of the number.
  3437.     movei state, "F"    ; Set the state to file send.
  3438.     call $recv2        ; Go look like we're receiving.
  3439.     jrst gtcmlp        ; Get another command when done.
  3440.  
  3441.  
  3442. ; Server RECEIVE (or GET) command -- Server sends files.
  3443.  
  3444. xrecv:    movem t2, pktnum    ; Save the packet number.
  3445.     move t2, t4        ;  Get a pointer to the file spec.
  3446.     movx t1, gj%sht!gj%old!gj%ifg ; Old file and allow wildcarding.
  3447.     GTJFN%
  3448.      %jsker (,gtcmlp)    ; Can't, say forget it and loop.
  3449.     movem t1, ndxjfn    ; OK, Save the indexable JFN.
  3450.     hrrm t1, filjfn        ; Save the JFN of the first file.
  3451.     call $send        ; Go send the file(s).
  3452.     jrst gtcmlp
  3453.  
  3454. ; HOST command.
  3455.  
  3456. xhost:    kermsg <Host commands not implemented in KERMIT-20>
  3457.     jrst gtcmlp
  3458.  
  3459.  
  3460. ; Server GENERIC command.  See which one.
  3461.  
  3462. xgen:    ildb t1, t4        ; Get the data char.
  3463.     cain t1, "F"        ; Finish.
  3464.      jrst xgfin        ;  
  3465.     cain t1, "L"        ; Logout.
  3466.      jrst xglogo         ;   
  3467.  
  3468. ; (add new generic commands here...)
  3469.  
  3470.     kermsg <Unimplemented generic command>
  3471.     jrst gtcmlp
  3472.  
  3473.  
  3474. ; Generic commands...
  3475.  
  3476. ; FINISH.  Shut down the server, but don't log out.
  3477.  
  3478. xgfin:    movei t1, "Y"        ;  Acknowledge packet.
  3479.     setzb t3, t4        ;  No data.
  3480.     call spack        ;  Send the packet.
  3481.     call ccoff        ;  Turn off the ^C trap.
  3482.     call reslin        ;  Set the line back to a nice state.
  3483.     move t1, odelay        ;[27] Restore normal delay
  3484.     movem t1, delay        ;[27]
  3485.     move t1, otimou        ;[27] and timout interval
  3486.     movem t1, stimou    ;[27]
  3487.     setzm srvflg        ;[27] and reset the server flag 
  3488.     ret            ; in case we're continued...
  3489.  
  3490. ; LOGOUT (or BYE) -- Shut down the server and log out.
  3491.  
  3492. xglogo:    movei t1, "Y"        ; Acknowledge the command.
  3493.     setzb t3, t4        ; No data.
  3494.     call spack        ; Send the packet.
  3495.     call ccoff        ; Turn off the ^C trap.
  3496.     call reslin        ; Set the line back to a nice state.
  3497.     move t1, odelay        ;[27] Restore normal delay
  3498.     movem t1, delay        ;[27]
  3499.     move t1, otimou        ;[27] and timout interval
  3500.     movem t1, stimou    ;[27]
  3501.     setzm srvflg        ;[27] and reset the server flag.
  3502.     seto t1,        ; Myself.
  3503.     LGOUT%            ; Log me out.
  3504.     %jserr (,r)        ;[27] If this fails, print msg & go back.
  3505.  
  3506.     Remark - Initialize the Priority Interrupt system.
  3507.  
  3508. pinit:    movei t1, .FHSLF    ; This fork.
  3509.     move t2, [levtab,,chntab] ; Say where our tables are.
  3510.     SIR%
  3511.     EIR%            ; Enable the interrupt system.
  3512.     ret
  3513.  
  3514.     Remark - Set timer.
  3515.  
  3516. timeit:    pop p, t2        ; Get the return address off the stack.
  3517.     movem p, intstk        ; Save the stack.
  3518.     push p, t2        ; Restore stack.
  3519.     hrr t2, t1        ; Make interrupt PC point to time out addr.
  3520.     movem t2, intpc        ; Save the PC.
  3521.     movei t1, .fhslf
  3522.     movx t2, 1b0        ; Turn on channel 0.
  3523.     AIC%
  3524.  
  3525. ;[2] Adjust timeout based on load average, LDAV.
  3526. ;[2] Calculate T = STIMOU + (LDAV-MINLOD)*((MAXTIM-STIMOU)/MAXLOD)
  3527. ;[2] If the load is low, this gives the requested timeout, STIMOU.
  3528. ;[2] If the load is very high, this gives the maximum timeout, MAXTIM.
  3529. ;[2] In between, the timeout goes up linearly with load average.
  3530.  
  3531. timei2:    move t1, [14,,.systa]    ;[2] Get load average.
  3532.     setz t2,        ;[2] Assume zero in case GETAB fails.
  3533.     GETAB%            ;[2] Not bothering with class scheduler...
  3534.      erjmp timei3        ;[2]  Can't get it, assume zero.
  3535.     fsb t1, [minlod]    ;[2] Adjust by subtracting the minimum.
  3536.     skipg t1        ;[2] If negative, make it zero.
  3537.      setz t1,        ;[2]
  3538.     caml t1, [maxlod]    ;[2] If too big, cut it off.
  3539.      move t1, [maxlod]    ;[2]
  3540.     movei t2, maxtim    ;[2] Maximum timeout, seconds.
  3541.     sub t2, stimou        ;[2] Less specified timeout interval.
  3542.     fltr t2, t2        ;[2] Floated.
  3543.     fdv t2, [maxlod]    ;[2] Divided by maximum load.
  3544.     fmp t1, t2        ;[2] Multiplied by actual (adjusted) load.
  3545.     fixr t2, t1        ;[2] Fixed & rounded.
  3546. timei3:    add t2, stimou        ;[2] Add in requested timeout.
  3547.  
  3548.     move t1, [.fhslf,,.timel] ; Our process and time from now.
  3549.     imuli t2, ^d1000    ; Make time into milliseconds.
  3550.     setz t3,        ; Channel zero.
  3551.     TIMER%
  3552.      kermsg <Unable to set timer interrupt>
  3553.     ret
  3554.  
  3555.     Remark - Turn off timer.
  3556.  
  3557. timoff:    saveac <t1,t2>
  3558.     move t1, [.fhslf,,.timbf]
  3559.     move t2, [377777,,-1]    ; Time way out in the boonies (won't
  3560.                 ; clobber any runtime limit setting).
  3561.     TIMER%
  3562.      jrst .+1        ; Ignore errors.
  3563.     movx t1, .fhslf        ; Turn off ^O trap.
  3564.     movx t2, 1b0
  3565.     DIC%            ; Deactivate the channel.
  3566.     ret
  3567.  
  3568.     Remark - Time out trap.    
  3569.  
  3570. tmtrp:    push p, t1        ; Get a work AC.
  3571.     move t1, intpc        ; Get the PC we want.
  3572.     movem t1, pc1        ; Restore as if we came from there.
  3573.     pop p, t1
  3574.     move p, intstk        ; Restore the stack.
  3575.     DEBRK%
  3576.  
  3577.     Remark - Return time out packet.
  3578.  
  3579. tmout:    diamsg <T>        ;* Temporary.
  3580.     movei t1, "T"        ; Say we timed out on the packet.
  3581.     move t2, pktnum        ; Tell which packet num.
  3582.     setzb t3, t4        ; No data.
  3583.     retskp
  3584.  
  3585.  
  3586.     subttl subbp - Subtract two arbitrary byte pointers
  3587.  
  3588. ; Subroutine to subtract two byte pointers in current section.
  3589. ; The two byte pointers must point to bytes of the same size.
  3590. ;
  3591. ; Call with:
  3592. ;   t1/ First byte pointer.
  3593. ;   t2/ Second byte pointer.
  3594. ;    CALL SUBBP
  3595. ;
  3596. ; Returns:
  3597. ;   +1 if the byte sizes are different, with t1-t3 unchanged, or else
  3598. ;   +2 with:
  3599. ;   t1,t2/ Unchanged.
  3600. ;   t3/ The number of bytes of the specified bytesize in the string pointed to
  3601. ;       by the first byte pointer (in t1) up to, but not including, the byte
  3602. ;       pointed to by the second byte pointer (in t2).
  3603.  
  3604. subbp:    saveac    <q1,q2,q3,q4>    ; Save permanent regs for work below.
  3605.     ldb q1, [point 6, t1, 11] ; q1 := bytesize 1.
  3606.     ldb q2, [point 6, t2, 11] ; q2 := bytesize 2.
  3607.     came q1, q2        ; Are they equal?
  3608.      ret            ; No, failure
  3609.  
  3610. ; Byte sizes are equal, can do arithmetic.
  3611.  
  3612.     movei q2, @t1        ; Do address calculation for t1
  3613.     movei q4, @t2        ;  and t2.
  3614.     sub q4, q2        ; q4 := (A1 - A2) = N words.
  3615.     movei q2, ^d36        ; q2 := bits/word.
  3616.     idiv q2, q1        ; q2 := bytes/word.
  3617.     imul q4, q2        ; q4 := bytes in N words.
  3618.     move q2, q4        ; (to leave q3-q4 free for IDIV)
  3619.     ldb q3, [point 6, t2, 5] ; q3 := Q2
  3620.     ldb t3, [point 6, t1, 5] ; t3 := Q1
  3621.     sub t3, q3        ; t3 := (Q1 - Q2)
  3622.     idiv t3, q1        ; t3 := (Q1 - Q2) / S
  3623.     add t3, q2        ; Adjust previous count.
  3624.     retskp            ; And return, with success.
  3625.  
  3626.     subttl Interrupt routines.
  3627.  
  3628. ; Turn Control-C trap on.
  3629.  
  3630. $ccn==2                ; Number of ^C's to get out of ^C trap.
  3631.  
  3632. ccon:    movei t1, .fhslf    ; Read current process capabilities.
  3633.     RPCAP%
  3634.     tloe t3, (sc%ctc)    ;[10] Do we have Control-C capas?
  3635.      jrst ccon2        ;[10]  Yes, go on.
  3636.     EPCAP%            ;[10] Nope, try to get them.
  3637.     RPCAP%            ;[10] Did we?
  3638.     tloe t3, (sc%ctc)    ;[10] Check the ^C bit.
  3639.      jrst ccon2        ;[10]  We got them.
  3640.     seto t1,        ;[10] We don't have them.
  3641.     hrroi t2, t4        ;[10] Let's see if we're running under batch,
  3642.     movei t3, .jibat    ;[10] in which case we don't need them anyway.
  3643.     setz t4,        ;[10]
  3644.     GETJI%            ;[10]
  3645.      nop            ;[10]
  3646.     skipe t4        ;[10]
  3647.      jrst ccon2        ;[10] Under batch, can proceed.
  3648.     ermsg <Can't enable ^C capability> ;[10] Not under batch.
  3649.     ret             ;[10] Give up.
  3650.  
  3651. ccon2:    movem t3, capas        ; Save them.
  3652.     movei t1, $ccn         ; Initialize ^C count to this.
  3653.     movem t1, ccn
  3654. ;[27]    move t1, p        ; Save stack pointer of our caller.
  3655. ;[27]    sub t1, [1,,1]
  3656. ;[27]    movem t1, psave
  3657.     movem p, psave        ;[27] Save stack pointer.
  3658.     move t1, (p)        ;[27] And what it points to...
  3659.     movem t1, psave2    ;[27]
  3660.     movx t1, .fhslf        ; Now, for this fork,
  3661.     movx t2, 1b1        ;  activate channel 1
  3662.     AIC%            ;  ...
  3663.      erjmp .+1        ;[10]
  3664.     move t1, [.ticcc,,1]    ;  for ^C.
  3665.     ATI%            ; 
  3666.      erjmp .+1        ;[10]
  3667.     retskp
  3668.  
  3669.  
  3670. ; Turn Control-C trap off.
  3671.  
  3672. ccoff:    setzm ccn        ; Put ^C count back to 0.
  3673.     movx t1, .fhslf        ; This fork.
  3674.     movx t2, 1b1        ; Deactivate channel 1.
  3675.     DIC%
  3676.     RTIW%            ; Fix up the interrupt mask
  3677.     tlz t2, 040000        ;  for ^C... (^C = ASCII 3 = bit 3)
  3678.     STIW%            ;  ...
  3679.     move t3, capas        ; Restore capabilities.
  3680.     EPCAP%
  3681.      erjmp .+1
  3682.     ret
  3683.  
  3684.  
  3685. cctrap:    sosle ccn        ; Count the ^C's.
  3686.      DEBRK%            ; If they haven't typed enough, just resume.
  3687.     call timoff        ; Time to go... turn off the timer.
  3688. ;[27]    move t1, [1b5+reslin]    ; Put clean-up line address
  3689. ;[27]    movem t1, pc1        ;  in PC for level 1, 1b5 means user space.
  3690.     hrroi t1, [asciz/^C
  3691. /]
  3692.     PSOUT%            ; Echo the ^C.
  3693.  
  3694.     move p, psave        ;[27] Make sure stack pointer is right.
  3695.     move t1, psave2        ;[27] And stack top.
  3696.     movem t1, (p)        ;[27]
  3697.     hrli t1, (1b5)        ;[27] Get into user mode.
  3698.     movem t1, pc1        ; Put this place into our PC.
  3699.     setom f$exit        ; Say we want to exit.
  3700.     DEBRK%            ; Resume at clean up line code.
  3701.  
  3702. ;[14] Control-B trap handler.
  3703.  
  3704. cbtrap:    push p, t1        ; Save this.
  3705.     setom cbseen        ; Set flag saying ^B was typed.
  3706.     skipn t1, cbloc        ; Do we have someplace special to go?
  3707.      move t1, pc2        ;  No, just use this to escape from JSYS.
  3708.     txo t1, 1b5        ; Set user mode bit.
  3709.     movem t1, pc2        ; Where to go.
  3710.     pop p, t1        ; Restore the AC.
  3711.     DEBRK%            ; Resume.
  3712.  
  3713. ;[6] (this whole routine, just for fun...)
  3714.  
  3715. moon:    saveac <5,6>
  3716.  
  3717. ; This code stolen from MOON.MAC (anybody know who wrote it?).
  3718. ; Just changed OUTCHR's to PBOUT%'s via a macro.  - Frank.
  3719. ;
  3720.     setzb 3,4
  3721.     seto 2,
  3722.     ODCNV%
  3723.      erjmp r
  3724.     tlz 4,77
  3725.     IDCNV%
  3726.      erjmp r        ; Return upon any error.
  3727.     tmsg <, Moon: >        ; OK so far, say what we're doing.
  3728.  
  3729. ; AC2= Universal time adjusted for time zone.
  3730.  
  3731.     move 1,2        ; Right place.
  3732.     sub 1,newmn        ; Sub off base new moon
  3733.     idiv 1,period        ; Divide by the period
  3734.     idiv 2,perio4        ; Get fractions of a period
  3735.     camg 3,perio8        ; Check for pahse + or -
  3736.      jrst moon1        ; Not more than 3+ days
  3737.  
  3738.     sub 3,perio4        ; Make it next phase -n days
  3739.     cain 2,3        ; Is it LQ+3D+?
  3740.      tdza 2,2        ; It is
  3741.      aoj 2,            ; Increment phase
  3742.  
  3743. moon1:    hllz 1,table(2)        ; Get SIXBIT phase
  3744.     skipge 3        ; 3 < 0 then minus phase output
  3745.      tloa 1,'-'        ; -
  3746.      tloa 1,'+'        ; +
  3747.      movms 3        ; Fix mag of 3
  3748.     move 2,[point 6,1]    ; Byte pointer
  3749.     movei 5,2        ; Loop 3 times
  3750.  
  3751. moon2:    ildb 4,2        ; Get a character
  3752.     addi 4," "        ; Make ASCII
  3753.     OUTCHR 4        ; Type it
  3754.     sojge 5,moon2        ; Loop
  3755.  
  3756.     movsi 4,-4        ; Make aobjn pointer
  3757.     ;...
  3758.  
  3759. moon3:    hrrz 2,table(4)        ; Get a multiplier
  3760.     trz 2,774000        ; Strip off ascii character
  3761.     imuli 3,(2)        ; Get the value decoded
  3762.     hlrz 1,3        ; Get value
  3763.     tlz 3,-1        ; Zap old LH
  3764.     move 5,1        ; Use 5 & 6 here
  3765.     idivi 5,12        ; Radix 10
  3766.     addi 5,60        ; Make ASCII
  3767.     caile 5,60        ; Check for leading zero
  3768.      OUTCHR 5        ;  Type it.
  3769.     addi 6,60        ; Make ASCII
  3770.     OUTCHR 6
  3771.     ldb 5,[point 7,table(4),24] ; Get d/h/m/s
  3772.     OUTCHR 5        ; Type it.
  3773.     OUTCHR ["."]        ; Follow with a dot.
  3774.     aobjn 4,moon3        ; Loop.
  3775.  
  3776.     tmsg <
  3777. >                ; A CRLF at the end.
  3778.     ret            ; Done, return.
  3779.  
  3780. ; Pure data for moon.
  3781.  
  3782. newmn:    125575,,34343        ; 28-jan-79 0120 est
  3783. per==35,,422752            ; 29d.12h.53m.19s
  3784. period:    per
  3785. perio4:    per/4
  3786. perio8:    per/10
  3787.  
  3788. table:    byte(18)'NM '(7)"d"(11)^D1 ; New moon - days - 1
  3789.     byte(18)'FQ '(7)"h"(11)^D24 ; First quarter - hours - 24
  3790.     byte(18)'FM '(7)"m"(11)^D60 ; Full moon - minutes - 60
  3791.     byte(18)'LQ '(7)"s"(11)^D60 ; Last quarter - seconds - 60
  3792.  
  3793.     subttl    Comnd tables
  3794.  
  3795. cmdtab:    %table
  3796.     %key    <bye>, [xwd .bye,$bye] ;[11]
  3797.     %key    <connect>, [xwd .conne,$conne]
  3798.     %key    <exit>, [xwd .exit,$exit]
  3799.     %key    <finish>, [xwd .finis,$finis] ;[28]
  3800.     %key    <get>,  [xwd .get,$get]    ;[11]
  3801.     %key    <help>, [xwd .help,$help]
  3802.     %key    <prompt>, [xwd .promp,$promp], cm%inv
  3803.     %key    <quit>, [xwd .exit,$exit]
  3804.     %key    <receive>, [xwd .recv,$recv]
  3805.     %key    <s>, send, cm%inv+cm%abr
  3806. send:    %key    <send>, [xwd .send,$send]
  3807.     %key    <server>, [xwd .serve,$serve]
  3808.     %key    <set>, [xwd .set,$set]
  3809.     %key    <show>, [xwd .show,$show]
  3810.     %key    <status>, [xwd .stat,$stat]
  3811.     %tbend
  3812.  
  3813. setabl:    %table
  3814.     %key    <debugging>, [xwd .setdb,$setdb]
  3815.     %key    <delay>, [xwd .setdl,$setdl]
  3816.     %key    <duplex>, [xwd .setdu,$setdu]
  3817.     %key    <escape>, [xwd .setes,$setes]
  3818.     %key    <file-byte-size>, [xwd .setf8,$setf8]
  3819.     %key    <IBM-flag>, [xwd .setib,$setib]
  3820.     %key    <line>, [xwd .setln,$setln]
  3821.     %key    <parity>, [xwd .setpa,$setpa]
  3822.     %key    <receive>, [xwd .setrc,$setrs]
  3823.     %key    <send>, [xwd .setsn,$setrs]
  3824.     %tbend
  3825.  
  3826. sftab:    %table
  3827.     %key    <7-bit>, 0
  3828.     %key    <8-bit>, 1
  3829.     %key    <auto-byte>, 2
  3830.     %key    <eight-bit>, 1
  3831.     %key    <seven-bit>, 0
  3832.     %tbend
  3833.  
  3834. partab:    %table
  3835.     %key    <even>, even
  3836.     %key    <mark>, mark
  3837.     %key    <none>, none
  3838.     %key    <odd>, odd
  3839.     %key    <space>, space
  3840.     %tbend
  3841.  
  3842. srtabl:    %table
  3843.     %key    <end-of-line>, [xwd .seteo,reolch]
  3844.     %key    <packet-length>, [xwd .setpk,rpsiz]
  3845.     %key    <padchar>, [xwd .setpc,rpadch]
  3846.     %key    <padding>, [xwd .setpd,rpadnm]
  3847.     %key    <quote>, [xwd .setqu,rquote]
  3848.     %key    <start-of-packet>, [xwd .setsp,rsthdr] ;[18]
  3849.     %key    <timeout>,[xwd .setim,rtimou]
  3850.     %tbend
  3851.  
  3852. sstabl:    %table
  3853.     %key    <end-of-line>, [xwd .seteo,seolch]
  3854.     %key    <packet-length>, [xwd .setpk,spsiz]
  3855.     %key    <padchar>, [xwd .setpc,spadch]
  3856.     %key    <padding>, [xwd .setpd,spadnm]
  3857.     %key    <quote>, [xwd .setqu,squote]
  3858.     %key    <start-of-packet>, [xwd .setsp,ssthdr] ;[18] 
  3859.     %key    <timeout>,[xwd .setim,stimou]
  3860.     %tbend
  3861.  
  3862.     Remark    Pure storage
  3863.  
  3864. levtab:    pc1
  3865.     pc2
  3866.     pc3
  3867. chntab:    1,,tmtrp        ; Timer trap on channel 0, priority 1.
  3868.     1,,cctrap        ; ^C trap on channel 1, same priority.
  3869.     2,,cbtrap        ; ^B trap on channel 0, lower priority.
  3870.     repeat <^d34>,<0>    ; Nothing on other channels.
  3871.  
  3872. lits:    lit            ; Assemble literals here.
  3873.  
  3874.  
  3875.     subttl    Impure data storage
  3876.  
  3877. CMDSTG                ; Allocate COMND JSYS storage
  3878. pdl:    block pdlsiz        ;  and stack.
  3879. pc1:    0            ; Interrupt PC storage, levels 1,
  3880. pc2:    0            ;  2,
  3881. pc3:    0            ;  and 3.
  3882. intpc:    z            ; PC to restore on timer interrupt.
  3883. intstk:    z            ; Stack pointer to restore on timer interrupt.
  3884. ccn:    z            ; Number of ^C's typed.
  3885. cbseen:    z            ; Flag for ^B trap.
  3886. psave:    z            ; Stack pointer for ^C interrupt.
  3887. psave2:    z            ; Stack top for ^C interrupt.
  3888. cbloc:    z            ; Where to go on ^B interrupt.
  3889. capas:    z            ; Process capabilities.
  3890.  
  3891. pars1:    z            ; Data from first parse.
  3892. pars2:    z            ; Data from second parse.
  3893. pars3:    z            ; Data from third parse (flags to turn on).
  3894. pars4:    z            ; Data from fourth parse.
  3895. jbdlm:    z            ; Delimiter character for job command
  3896. srvflg:    z            ; Are we serving?  Erase if we go for command.
  3897. parsnm==.-pars1
  3898.  
  3899. dfstrt:    promp            ; Are we to be a SERVER or go to the PROMPT?
  3900.                 ;  (Use PROMP not PROMPT to avoid collision
  3901.                 ;  with CMD PROMPT macro.)
  3902. f$exit:    z            ; Exit flag.
  3903. filjfn:    z            ; File JFN.
  3904. ndxjfn:    z            ; Indexable JFN.
  3905. netjfn:    z            ; Where to transmit the information.
  3906. oldmod:    z            ; Previous mode of the line.
  3907. oldpau:    z            ; Previous terminal pause on end mode.
  3908. ttynum:    z            ; Number of the TTY being used.
  3909. oldnum:    0            ;[7] Number of previous TTY in case of change.
  3910. mytty:    0            ;[4] TTY number of job's controlling terminal.
  3911. myjob:    0            ;[7] My job number.
  3912. job:    0            ;[7] Number of job that has TTY I want.
  3913. telfrk:    z            ; Fork number of the ttlink fork.
  3914. errptr:    z            ; Storage for previous error.
  3915. ebtflg:    0            ; One if file is to be used in 8-bit mode.
  3916. autbyt:    1            ; One if auto-byte is to be used.
  3917. ibmflg:    0            ; One if we are talking to the IBM.
  3918. assflg:    0            ;[7] -1 if I asg'd the TTY, 0 if already asg'd.
  3919. oasflg:    0            ;[7] Same, but for previous TTY.
  3920. parity:    defpar            ; Type of parity to use.
  3921. trnrnd:    dtrnrn            ; Turn around character.
  3922. mapflg:    0            ; One if a page is mapped in.  (Init to 0.)
  3923. local:    0            ; -1 = local Kermit, 0 = remote.
  3924. mapptr:    z            ; Pointer into the page.
  3925. filpag:    z            ; Number of pages in the file.
  3926. filbyt:    z            ; Number of bytes in the file.
  3927. filbsz:    z            ; Byte size of file.
  3928. prepag:    z            ; Present page number.
  3929. stdat:    z            ; Time taken in transmitting.
  3930. size:    z            ; Size of the present data.
  3931. spsiz:    dspsiz            ; Maximum size packet to send.
  3932. rpsiz:    drpsiz            ; Maximum size packet to receive.
  3933. stimou:    dstim            ; Interval for my own timer.
  3934. otimou:    dstim            ;[26] Place to save old timout interval.
  3935. rtimou:    drtim            ; Time out interval I need.
  3936. spadch:    dspad            ; Pad char micro wants.
  3937. rpadch:    drpad            ; Pad char I want.
  3938. spadnm:    dspadn            ; Number of pad chars for micro.
  3939. rpadnm:    drpadn            ; Number for me.
  3940. seolch:    dseol            ; EOL char micro needs.
  3941. reolch:    dreol            ; EOL I need.
  3942. squote:    dsquot            ; Quote character micro wants.
  3943. rquote:    drquot            ; Quote character I want.
  3944. delay:    ddelay            ; How long before I send the first packet.
  3945. odelay:    ddelay            ;[27] For saving & restoring delay.
  3946. escape:    31            ; Escape character for connecting (default ^Y).
  3947. duplex:    dxfull            ; Duplex for connecting.
  3948. ssthdr:    SOH            ; Start of header character to send.
  3949. rsthdr:    SOH            ; Start of header character to receive.
  3950. rtchr:    z            ; Total characters received.
  3951. stchr:    z            ;  ... sent.
  3952. rtot:    z            ; Some more counters..
  3953. stot:    z            ; 
  3954. numtry:    z            ; Number of tries on a packet.
  3955. oldtry:    z            ; Number of tries for previous packet.
  3956. maxtry:    dmxtry            ; Maximum number of times to try.
  3957. imxtry: dimxtr            ; Maximum retries in send initiate.
  3958. pktnum:    z            ; Packet sequence number.
  3959. rptot:    0            ;[4] Counter for received packets.
  3960. sptot:    0            ;[4] Counter for sent packets.
  3961. eoflag:    z            ; End of file flag.
  3962. crlf:    asciz/
  3963. /                ; A carriage-return-linefeed.
  3964. filbuf:    block ^d20        ; File name building buffer.
  3965. buffer:    block maxpkt/4        ; Buffer for file I/O.
  3966. data:    block maxpkt/4        ; Temp data storage.
  3967. sndpkt:    byte (7) SOH,0        ; Start with the start of header char.
  3968.     block maxpkt/4
  3969. recpkt:    byte (7) SOH,0        ; Start with the start of header char.    
  3970.     block maxpkt/4
  3971. %%krbf:    asciz/                                                                                /        ; Storage for error packet.
  3972.  
  3973.  
  3974.     end    <3,,Kermit>
  3975.  
  3976.