home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / hp3000 / hp3000spl.txt < prev    next >
Text File  |  2020-01-01  |  206KB  |  5,949 lines

  1. $PAGE  
  2. $CONTROL MAIN=KERMIT, NOLIST
  3. $TITLE "KERMIT"
  4. BEGIN
  5.  
  6. define    VERS = ("HP 3000 KERMIT   ",
  7.                   "VERSION: 12 JULY 1994",
  8.                   %(16)0D, %(16)0A,
  9.                   "Works best with PC Kermit V2.31 or newer.",
  10.                   %(16)0D, %(16)0A,
  11.                   "You can now use PARM= on RUN stmt ",
  12.                   "to specify TAKE file.")#;
  13.  
  14. <<*****************************************************************>>
  15. <<                                                                 >>
  16. <<     Version 1.0 : Ed Eldridge                                   >>
  17. <<                   Polaris, Inc.                                 >>
  18. <<                   1400 Wilson Blvd                              >>
  19. <<                     suite 1100                                  >>
  20. <<                   Arlington, Virginia   22209                   >>
  21. <<                   (703) 527-7333                                >>
  22. <<                                                                 >>
  23. <<     Version 2.0 : Tony Appelget                                 >>
  24. <<                   General Mills, Inc.                           >>
  25. <<                   P.O. Box 1113                                 >>
  26. <<                   Minneapolis, MN 55440                         >>
  27. <<                   (612) 540-7703                                >>
  28. <<                                                                 >>
  29. <<    * * * * * * * * * * * * * * * * * * * * * * * * * * * * *    >>
  30. <<                                                                 >>
  31. <<        I have left General Mills, and will no longer be able    >>
  32. <<        to maintain the HP3000 Kermits unless, by chance or good >>
  33. <<        fortune, I wind up in another HP3000 shop.  I will be    >>
  34. <<        available to answer questions on a call-at-your-own risk >>
  35. <<        basis.  My home phone is (612) 559-3764.                 >>
  36. <<                                        Tony Appelget            >>
  37. <<                                        13 July 1994             >>
  38. <<                                                                 >>
  39. <<    * * * * * * * * * * * * * * * * * * * * * * * * * * * * *    >>
  40. <<                                                                 >>
  41. <<        Added HELP function.                                     >>
  42. <<                                                                 >>
  43. <<        Reworked input scanner.  In particular, got rid of       >>
  44. <<        IF-THEN-ELSE structure that went for pages and pages     >>
  45. <<        and was confusing and not particularly maintainable.     >>
  46. <<        Allow a certain amount of abbreviation for input         >>
  47. <<        commands.  This implementation could use improvement.    >>
  48. <<                                                                 >>
  49. <<        Added SET SOH keyin and made default SOH to be octal     >>
  50. <<        02 (STX).                                                >>
  51. <<                                                                 >>
  52. <<        Added file presence tests to RECEIVE and SET LOG         >>
  53. <<        functions so that user will know of a duplicate file     >>
  54. <<        situation before a file is opened rather than when       >>
  55. <<        the attempt is made to close the file, possibly after    >>
  56. <<        a long transmission.                                     >>
  57. <<                                                                 >>
  58. <<                                                                 >>
  59. <<        SSR 91-417  FEB 85   TONY APPELGET                       >>
  60. <<        Added rudimentary file validation check.  Users will be  >>
  61. <<        restricted as to which files or groups of files they     >>
  62. <<        will be permitted to access, and how the files may be    >>
  63. <<        accessed.  The implementation philosophy is identical    >>
  64. <<        to that devised for LINK/125.  Indeed, KERMIT and LINK/  >>
  65. <<        125 use the same file.  Added SPACE, DELETE, and VERIFY  >>
  66. <<        commands.  Fixed assorted bugs.                          >>
  67. <<                                                                 >>
  68. <<        SSR 91-???   SUMMER 1985       TONY APPELGET             >>
  69. <<        1) Made STATUS command SYNONYMOUS with the VERIFY        >>
  70. <<           command.                                              >>
  71. <<                                                                 >>
  72. <<        2) If multiple files were were received from the remote, >>
  73. <<           only the first was saved.  This problem has been      >>
  74. <<           fixed.                                                >>
  75. <<                                                                 >>
  76. <<        3) Changed the abbreviation algorithm to allow shorter   >>
  77. <<           user input.                                           >>
  78. <<                                                                 >>
  79. <<        4) After a file was sent, there was an annoying pause    >>
  80. <<           before the user could enter a new command at the      >>
  81. <<           remote computer.  This Kermit was closing the file    >>
  82. <<           it had just received and was not seeing the EOT packet>>
  83. <<           transmitted by the remote.  This problem has been     >>
  84. <<           fixed.                                                >>
  85. <<                                                                 >>
  86. <<        5) Lockwords may be specified for any filespec including >>
  87. <<           log files.                                            >>
  88. <<                                                                 >>
  89. <<        6) When '?' is entered for help, the command is redis-   >>
  90. <<           played so the user may continue without having to     >>
  91. <<           retype the entire command.                            >>
  92. <<                                                                 >>
  93. <<        8) Any command may be aborted with ctrl-y.               >>
  94. <<                                                                 >>
  95. <<        9) The TYPE command has been implemented.                >>
  96. <<                                                                 >>
  97. <<       10) If the session job control word JCW is non-zero,      >>
  98. <<           Kermit will attempt to access the take file F599KMnn, >>
  99. <<           where nn is the value contained in JCW.               >>
  100. <<                                                                 >>
  101. <<       11) Changed the error message produced when a file does   >>
  102. <<           not pass the validation check.                        >>
  103. <<                                                                 >>
  104. <<       12) If, when receiving a file, the same packet was        >>
  105. <<           received twice, Kermit could not handle the situation >>
  106. <<           and stopped receiving.  Now the duplicate packet is   >>
  107. <<           acked and discarded.                                  >>
  108. <<                                                                 >>
  109. <<       13) Added the equivalent of SET RECEIVE MAXEXT 1 to the   >>
  110. <<           SET RECEIVE PROG command.  Large code files could     >>
  111. <<           occupy more than one extent and hence be nonexe-      >>
  112. <<           cutable.                                              >>
  113. <<                                                                 >>
  114. <<       14) A new receive option, SET RECEIVE EXPTAB, was         >>
  115. <<           implemented.  When set, it expands horizontal tabs    >>
  116. <<           encountered in the data.                              >>
  117. <<                                                                 >>
  118. <<       15) When in server mode and a FINISH packet was received  >>
  119. <<           from the remote, Kermit would EOJ.  Now Kermit drops  >>
  120. <<           out of server mode and continues execution.           >>
  121.  
  122. <<       16) Groups of files may be downloaded to the micro by     >>
  123. <<           the use of the wildcard character in the GET statement>>
  124. <<           on the micro, eg GET MS@.  Kermit3000 must be in      >>
  125. <<           server mode.
  126. <<                                                                 >>
  127. <<*****************************************************************>>
  128. <<                                                                 >>
  129. <<       UNSCHEDULED FIX   12 FEB 86     TONY APPELGET             >>
  130. <<       HELP function in the vicinity of SET RECEIVE PROG through >>
  131. <<       SET RECEIVE EXPTAB was not displaying properly and would  >>
  132. <<       take the program down on occasion.  Fixed it.             >>
  133. <<                                                                 >>
  134. <<       UNSCHEDULED  MODS   FEB/MAR 87     TONY APPELGET         >>
  135. <<       1. Added capability to generate and check 3-byte CRC      >>
  136. <<          block checking in anticipation of being able to handle >>
  137. <<          long packets.  This Kermit will always attempt to use  >>
  138. <<          the 3-byte CRC unless negotiated down to 1-byte simple >>
  139. <<          checksum by the other end.  Capability to handle 2-byte>>
  140. <<          checksum will be deferred forever or until necessary,  >>
  141. <<          whichever comes first.                                 >>
  142. <<                                                                 >>
  143. <<       2) Fixed another bug that a casual user might never       >>
  144. <<          encounter.  If a file had been sent, received, or      >>
  145. <<          typed in non-server mode, and then the user attempted  >>
  146. <<          to upload a file in server mode, the previously speci- >>
  147. <<          fied title, not the currently specified title, was     >>
  148. <<          used to store the file.                                >>
  149. <<                                                                 >>
  150. <<       3) If this Kermit was in server mode, and the user keyed  >>
  151. <<          'GET filename1 filename2', the protocol became very    >>
  152. <<          confused and died a nasty death.  I fixed the problem. >>
  153. <<                                                                 >>
  154. <<       UNSCHEDULED FIX    10 SEPT 87     TONY APPELGET           >>
  155. <<        SENDSW always seemed to complain about a SEND failure    >>
  156. <<        regardless of the success or failure of a file trans-    >>
  157. <<        mission.  STATE was never being set to 'send complete    >>
  158. <<        state' ("C").  Fixed it.                                 >>
  159. <<                                                                 >>
  160. <<       UNSCHEDULED FIX     4 APRIL 88    TONY APPELGET           >>
  161. <<        A failure to complete a handshake by SINIT caused        >>
  162. <<        subsequent attempts of send initiate to fail.  This      >>
  163. <<        fix sets the retry counter to zero before attempting     >>
  164. <<        a send initiate.                                         >>
  165.  
  166. <<   The above unscheduled fixes made legal via SSR 91-557         >>
  167. <<                            29 APRIL 88   TONY APPELGET          >>
  168.  
  169. <<*****************************************************************>>
  170. <<       UNSCHEDULED FIX     8 SEPT 88    TONY APPELGET            >>
  171. <<        An attempt to communicate with a Kermit that did not     >>
  172. <<        specify any block check as part of SINIT caused this     >>
  173. <<        Kermit to use its default 3-byte CRC block check, causing>>
  174. <<        the other Kermit to go bonkers over all packets.  This   >>
  175. <<        fix causes this Kermit to default to 1-byte block check  >>
  176. <<        when the other Kermit does not specify any block check.  >>
  177.  
  178. <<***************************************************************  >>
  179. <<                                                                 >>
  180. <<      GENERAL UPGRADE   APRIL - OCT  89  TONY APPELGET  (91-608) >>
  181. <<                                                                 >>
  182. <<       Bring program up to snuff with newer releases of PC and   >>
  183. <<       IBM Kermits.                                              >>
  184. <<                                                                 >>
  185. <<       1.  Add QUIT as synonym for EXIT.                         >>
  186. <<                                                                 >>
  187. <<       2.  Changed 3-byte CRC calculation from table-lookup      >>
  188. <<           to strictly computational. (Purloined from PC module  >>
  189. <<           MSSCOM.ASM.)                                          >>
  190. <<                                                                 >>
  191. <<       2.  Kermit now sets a JCW, KRMJCWnn where nn is the comm  >>
  192. <<           ldev, to indicate what he is doing or how an xfer was >>
  193. <<           completed.                                            >>
  194. <<                                                                 >>
  195. <<       3.  Procedure WRITE'LOG was added to manage the writing   >>
  196. <<           of packets to the log file.  The time is given for    >>
  197. <<           each packet and long packets are broken up into line- >>
  198. <<           sized hunks.                                          >>
  199. <<                                                                 >>
  200. <<       4.  Long packets are implemented.  Maximum size now is    >>
  201. <<           2048 bytes.  See "Kermit Protocol Manual" for the     >>
  202. <<           long packet format, especially as to how packet length>>
  203. <<           is handled.                                           >>
  204. <<                                                                 >>
  205. <<       5.  STATUS displays of logical values has been changed    >>
  206. <<           from TRUE/FALSE to ON/OFF to correspond with keyins.  >>
  207. <<                                                                 >>
  208. <<       6.  A statement:  LOGNUM:=CONUM   was deleted from proce- >>
  209. <<           dure KINIT.  Presence of that statement caused the log>>
  210. <<           output to be written to STDLIST when Kermit was run   >>
  211. <<           from a job.                                           >>
  212. <<                                                                 >>
  213. <<       7.  SET LOG PURGE will now cause an open log file to be   >>
  214. <<           closed and purged if the user has changed his mind    >>
  215. <<           about retaining a log file.                           >>
  216. <<                                                                 >>
  217. <<       8.  A brief PAUSE was inserted as part of the DELETE      >>
  218. <<           command.  Apparently the COMMAND intrinsic returns    >>
  219. <<           before a PURGE is completed, and a subsequent LISTF,  >>
  220. <<           if initiated very rapidly from a TAKE file, finds the >>
  221. <<           file still present.  Easy, but PAUSEs are kludges.    >>
  222. <<                                                                 >>
  223. <<                                                                 >>
  224. <<*****************************************************************>>
  225. <<                                                                 >>
  226. <<  UNSCHEDULED FIX       TONY APPELGET         8 DEC 89           >>
  227. <<                                                                 >>
  228. <<      After receiving a file, an SINIT packet to send a file     >>
  229. <<      had the packet number of the BREAK packet from the previous>>
  230. <<      file reception.  Many PC Kermits will apparently pick up   >>
  231. <<      this packet number and procede.  I encountered one that    >>
  232. <<      didn't, though.  Since the protocol manual says SINIT      >>
  233. <<      packets be numbered zero, this Kermit now does it.         >>
  234. <<                                                                 >>
  235. <<*****************************************************************>>
  236. <<                                                                 >>
  237. << SSR 91-634           Tony Appelget           July-August 1990   >>
  238. <<                                                                 >>
  239. <<      Imagine a situation where this Kermit is running as a son  >>
  240. <<      process along with other programs.  Suppose that while     >>
  241. <<      this Kermit is interrogating JCW to determine if a TAKE    >>
  242. <<      file is to be opened, one of the other processes blows up  >>
  243. <<      and sets JCW via a QUIT(n).  Well, it happened and Kermit  >>
  244. <<      picked up a bad value which caused the whole process struc->>
  245. <<      ture to grind to a halt.  This patch causes this Kermit to >>
  246. <<      check the PARAM value first, and if it is non-zero, use it >>
  247. <<      to set up the TAKE file title.  If PARAM=0, and JCW<>0,    >>
  248. <<      the JCW value will be used to set the TAKE file title. This>>
  249. <<      procedure maintains compatability with previous versions.  >>
  250. <<                                                                 >>
  251. <<      Packet receives are now nearly transparent, eg NULs may    >>
  252. <<      be received and even used as start-of-packet chars.  The   >>
  253. <<      reason for the change is to troubleshoot the WMS link at   >>
  254. <<      WCA.                                                       >>
  255. <<                                                                 >>
  256. <<*****************************************************************>>
  257. <<                                                                 >>
  258. <<  UNSCHEDULED FIX     Tony Appelget                 15 Oct 90    >>
  259. <<                                                                 >>
  260. <<       Modified procedure RPACK to indicate what sort of error   >>
  261. <<       occurred:  1=Timeout      3=No SOH found     5=Length bad >>
  262. <<       7=Bad checksum            9=Long packet not data type     >>
  263. <<       The only routine using the results is RINIT, and it only  >>
  264. <<       checks for lack of SOH(3).  Perhaps that junky Unix Kermit>>
  265. <<       on the Compaq at West Chicago will quit giving us fits.   >>
  266. <<                                                                 >>
  267. <<*****************************************************************>>
  268. <<                                                                 >>
  269. <<  UNSCHEDULED FIX    Tony Appelget                   13 Nov 90   >>
  270. <<                                                                 >>
  271. <<     Implemented the server command BYE to make this Kermit      >>
  272. <<     compatible with IBM Kermit.  The BYE command blows away the >>
  273. <<     program, session, connection, everything. It is devastating.>>
  274. <<                                                                 >>
  275. <<     Also fixed up the FCLOSEs on LOGNUM so that the log files   >>
  276. <<     can be deleted by other than the creator.                   >>
  277. <<                                                                 >>
  278. <<*****************************************************************>>
  279. <<                                                                 >>
  280. <<  UNSCHEDULED FIX   Tony Appelget                     27 Dec 90  >>
  281. <<                                                                 >>
  282. <<     The West Chicago WMS system bombed trying to purge a file   >>
  283. <<     that had just been sent.  This program still had the file   >>
  284. <<     open.  Juggled code so that file is closed before xfer com- >>
  285. <<     plete JCW is set.                                           >>
  286. <<                                                                 >>
  287. <<*****************************************************************>>
  288. <<  SSR 91-652        Tony Appelget                     15 Feb 91  >>
  289. <<     Added a new SET option, FAST.  It's syntax and operation    >>
  290. <<     are described in the HELP function.  It was implemented due >>
  291. <<     to compaints by users of the Warehouse Management System    >>
  292. <<     that transaction transmissions were slow and transactions   >>
  293. <<     were backing up badly.  Only INIT and FHEADER packets are   >>
  294. <<     affected, both send and receive.                            >>
  295. <<                                                                 >>
  296. <<     While I had my fingers in the works, I added a PAUSE before >>
  297. <<     the ABORTSESS in server's bye function so that the ack to   >>
  298. <<     the bye could make it out of the machine and to the remote  >>
  299. <<     Kermit (on PC) before the session was blown away.           >>
  300. <<                                                                 >>
  301. <<     I also noticed that, with 2000-byte packets, that a full-   >>
  302. <<     sized data packet could not be received at 1800 baud or     >>
  303. <<     less.  It got caught in the 10-second timeout.  Made the    >>
  304. <<     timeout for data packet reception dependent on the line     >>
  305. <<     speed.                                                      >>
  306. <<                                                                 >>
  307. <<***************************************************************  >>
  308. <<                                                                 >>
  309. << UNSCHEDULED FIX          TONY APPELGET               MAY 1991   >>
  310. <<                                                                 >>
  311. <<     Changed RFILE of RECSW to echo the assigned HP file title   >>
  312. <<     rather than the PC file title.  Purely a cosmetic change    >>
  313. <<     since PC Kermit 3.01 displays what it found in the ACK to   >>
  314. <<     file header.                                                >>
  315. <<                                                                 >>
  316. <<**************************************************************** >>
  317. << UNSCHEDULED FIX          TONY APPELGET              JULY 1991   >>
  318. <<                                                                 >>
  319. <<     Changed the method of line speed determination from         >>
  320. <<     FCONTROL 10 to FCONTROL 40.  FCONTROL 10 had problems on    >>
  321. <<     XL machine.  Put in sensor to determine which type of       >>
  322. <<     machine the program is running so that default termtype     >>
  323. <<     would be 10 on XL machine and 13 on classic machine.  Moved >>
  324. <<     FCONTROL 13 (disable echo) from preceding the termtype set  >>
  325. <<     statement to after it so that termtype 18, if used, does    >>
  326. <<     echo.                                                       >>
  327. <<                                                                 >>
  328. << UNSCHEDULED FIX          TONY APPELGET             FEB 1992     >>
  329. <<                                                                 >>
  330. <<     SET RECEIVE FIXREC ? (help) did not allow subsequent setting>>
  331. <<     of ON or OFF.  I uncovered this problem while working on the>>
  332. <<     C translation and suspect it has been in place for 7 years. >>
  333. <<     Fixed it both here and in the C translation.                >>
  334. <<                                                                 >>
  335.  
  336. equate    DBUF'WORDSIZE = 1024,
  337.           DBUF'BYTESIZE = DBUF'WORDSIZE*2,
  338.           LBUF'WORDSIZE = 1024,
  339.           LBUF'BYTESIZE = LBUF'WORDSIZE*2,
  340.           MAX'RCV'SIZE  = 94,
  341.           MAX'LONGPACK'SIZE=2047,
  342.           DFLT'MAXTRY = 10,   << Normal retry count >>
  343.           DFLT'TO     = 10,   << Normal timeout >>
  344.           FAST'MAXTRY = 5,
  345.           FAST'TO     = 2,
  346.  
  347.           CR  =  %15,
  348.           LF  =  %12,
  349.           XON =  %21,
  350.           EOT =   %4,
  351.           SP  =  %40,
  352.           HTAB=  %11,
  353.         A'DEL =  %177;
  354.  
  355. << Configurable Parameters >>
  356.  
  357. equate  P'Q'8    = %46,  << Prefered 8 Bit Quote >>
  358.         P'RPT'CHR = %176; << Prefered Repeat Prefix >>
  359.  
  360. define  LONGP'F   = 14:15:1#,
  361.         WINDOWS'F = 13:15:1#,
  362.         ATTRS'F   = 12:15:1#;
  363.  
  364.  
  365. logical USE'DC1    := true,
  366.         QUOTE'8    := false,
  367.         USE'REPEAT := false,
  368.         EXP'TABS   := false,
  369.         IMAGE      := false;
  370.  
  371. integer PAUSE'CNT     := 0,
  372.         YOUR'PAD      := 0,
  373.         YOUR'PAD'COUNT := 0,
  374.         MAX'SND'SIZE   := MAX'RCV'SIZE,
  375.         MAX'SND'DATA   := MAX'RCV'SIZE,
  376.         LONGPACK'SIZE,
  377.         YOUR'EOL       := CR,
  378.         MY'EOL         := CR,
  379.         MY'Q'CTL       := %43,
  380.         YOUR'Q'CTL     := %43,
  381.         Q'8            := P'Q'8,
  382.         RPT'CHR        := P'RPT'CHR,
  383.         MY'TO          := DFLT'TO,
  384.         YOUR'TO        := 10,
  385.         MAXTRY         := DFLT'MAXTRY;
  386.  
  387. byte    MY'CAPS,
  388.         YOUR'CAPS;
  389.  
  390. DEFINE <<FOR USER INPUT SCANNER>>
  391.        << FIRST WORD OF USER COMMAND STUFF >>
  392.        NULLV      = 0#,
  393.        TAKEV      = 1#,    TAKESZ      = 4#,   TAKESZSZ         = 7#,
  394.        SENDV      = 2#,    SENDSZ      = 4#,   SENDSZSZ         = 7#,
  395.        RECEIVEV   = 3#,    RECEIVESZ   = 7#,   RECEIVESZSZ      = 10#,
  396.        SERVEV     = 4#,    SERVESZ     = 6#,   SERVESZSZ        = 9#,
  397.        SETV       = 5#,    SETSZ       = 3#,   SETSZSZ          = 6#,
  398.        EXITV      = 6#,    EXITSZ      = 4#,   EXITSZSZ         = 7#,
  399.        QUITV      = 6#,    QUITSZ      = 4#,   QUITSZSZ         = 7#,
  400.        DIRV       = 7#,    DIRSZ       = 3#,   DIRSZSZ          = 6#,
  401.        SPACEV     = 8#,    SPACESZ     = 5#,   SPACESZSZ        = 8#,
  402.        DELETEV    = 9#,    DELETESZ    = 6#,   DELETESZSZ       = 9#,
  403.        TYPEV      = 10#,   TYPESZ      = 4#,   TYPESZSZ         = 7#,
  404.        VERIFYV    = 11#,   VERIFYSZ    = 6#,   VERIFYSZSZ       = 9#,
  405.        STATUSV    = 11#,   STATUSSZ    = 6#,   STATUSSZSZ       = 9#,
  406.        << SECOND WORD OF USER COMMAND STUFF >>
  407.        DEBUGV     = 20#,   DEBUGSZ     = 5#,   DEBUGSZSZ        = 8#,
  408.        DELAYV     = 21#,   DELAYSZ     = 5#,   DELAYSZSZ        = 8#,
  409.        LINEV      = 22#,   LINESZ      = 4#,   LINESZSZ         = 7#,
  410.        SENDV'1    = 23#,
  411.        SPEEDV     = 24#,   SPEEDSZ     = 5#,   SPEEDSZSZ        = 8#,
  412.        HANDSHAKEV = 25#,   HANDSHAKESZ = 9#,   HANDSHAKESZSZ    = 12#,
  413.        RECEIVEV'1 = 26#,
  414.        LOGV       = 27#,   LOGSZ       = 3#,   LOGSZSZ          = 6#,
  415.        SOHV       = 28#,   SOHSZ       = 3#,   SOHSZSZ          = 6#,
  416.        FASTV      = 29#,   FASTSZ      = 4#,   FASTSZSZ         = 7#,
  417.        << THIRD WORD OF USER COMMAND STUFF >>
  418.        PAUSEV     = 30#,   PAUSESZ     = 5#,   PAUSESZSZ        = 8#,
  419.        BINARYV    = 31#,   BINARYSZ    = 6#,   BINARYSZSZ       = 9#,
  420.        DEVICEV    = 32#,   DEVICESZ    = 6#,   DEVICESZSZ       = 9#,
  421.        FCODEV     = 33#,   FCODESZ     = 5#,   FCODESZSZ        = 8#,
  422.        RECLENV    = 34#,   RECLENSZ    = 6#,   RECLENSZSZ       = 9#,
  423.        BLOCKFV    = 35#,   BLOCKFSZ    = 6#,   BLOCKFSZSZ       = 9#,
  424.        FIXRECV    = 36#,   FIXRECSZ    = 6#,   FIXRECSZSZ       = 9#,
  425.        MAXRECV    = 37#,   MAXRECSZ    = 6#,   MAXRECSZSZ       = 9#,
  426.        MAXEXTV    = 38#,   MAXEXTSZ    = 6#,   MAXEXTSZSZ       = 9#,
  427.        SAVESPV    = 39#,   SAVESPSZ    = 6#,   SAVESPSZSZ       = 9#,
  428.        PROGV      = 40#,   PROGSZ      = 4#,   PROGSZSZ         = 7#,
  429.        BIN128V    = 41#,   BIN128SZ    = 6#,   BIN128SZSZ       = 9#,
  430.        TEXTV      = 42#,   TEXTSZ      = 4#,   TEXTSZSZ         = 7#,
  431.        TXT80V     = 43#,   TXT80SZ     = 5#,   TXT80SZSZ        = 8#,
  432.        EXPTABV    = 44#,   EXPTABSZ    = 6#,   EXPTABSZSZ       = 9#,
  433.        PURGEV     = 45#,   PURGESZ     = 5#,   PURGESZSZ        = 8#,
  434.        AUTOV      = 50#,   AUTOSZ      = 4#,   AUTOSZSZ         = 7#,
  435.        << FOURTH WORD OF USER COMMAND STUFF >>
  436.        ONV        = 51#,   ONSZ        = 2#,   ONSZSZ           = 5#,
  437.        OFFV       = 52#,   OFFSZ       = 3#,   OFFSZSZ          = 6#,
  438.        NONEV      = 53#,   NONESZ      = 4#,   NONESZSZ         = 7#,
  439.        XONV       = 54#,   XONSZ       = 3#,   XONSZSZ          = 6#,
  440.        XON2V      = 55#,   XON2SZ      = 4#,   XON2SZSZ         = 7#,
  441.        YESV       = 56#,   YESSZ       = 3#,   YESSZSZ          = 6#,
  442.        << QUESTION MARK ANYWHERE FOR HELP >>
  443.        QMARKV     = 60#,   QMARKSZ     = 1#,   QMARKSZSZ        = 4#,
  444.        NUMBERV    = 61#,
  445.        NOMORE     = NUTTIN#;
  446. BYTE ARRAY RESWDS(0:379):= << Should be sum of SZSZ stuff above >>
  447.     1( TAKESZSZ,      TAKESZ,      "TAKE",      TAKEV,
  448.        SERVESZSZ,     SERVESZ,     "SERVER",    SERVEV,
  449.        SENDSZSZ,      SENDSZ,      "SEND",      SENDV,
  450.        RECEIVESZSZ,   RECEIVESZ,   "RECEIVE",   RECEIVEV,
  451.        SETSZSZ,       SETSZ,       "SET",       SETV,
  452.        EXITSZSZ,      EXITSZ,      "EXIT",      EXITV,
  453.        QUITSZSZ,      QUITSZ,      "QUIT",      EXITV,
  454.        DIRSZSZ,       DIRSZ,       "DIR",       DIRV,
  455.        SPACESZSZ,     SPACESZ,     "SPACE",     SPACEV,
  456.        DELETESZSZ,    DELETESZ,    "DELETE",    DELETEV,
  457.        TYPESZSZ,      TYPESZ,      "TYPE",      TYPEV,
  458.        VERIFYSZSZ,    VERIFYSZ,    "VERIFY",    VERIFYV,
  459.        STATUSSZSZ,    STATUSSZ,    "STATUS",    STATUSV,
  460.  
  461.        DEBUGSZSZ,     DEBUGSZ,     "DEBUG",     DEBUGV,
  462.        LOGSZSZ,       LOGSZ,       "LOG",       LOGV,
  463.        HANDSHAKESZSZ, HANDSHAKESZ, "HANDSHAKE", HANDSHAKEV,
  464.        LINESZSZ,      LINESZ,      "LINE",      LINEV,
  465.        SPEEDSZSZ,     SPEEDSZ,     "SPEED",     SPEEDV,
  466.        DELAYSZSZ,     DELAYSZ,     "DELAY",     DELAYV,
  467.        SOHSZSZ,       SOHSZ,       "SOH",       SOHV,
  468.        SENDSZSZ,      SENDSZ,      "SEND",      SENDV'1,
  469.        RECEIVESZSZ,   RECEIVESZ,   "RECEIVE",   RECEIVEV'1,
  470.        FASTSZSZ,      FASTSZ,      "FAST",      FASTV,
  471.  
  472.        PAUSESZSZ,     PAUSESZ,     "PAUSE",     PAUSEV,
  473.        BINARYSZSZ,    BINARYSZ,    "BINARY",    BINARYV,
  474.        DEVICESZSZ,    DEVICESZ,    "DEVICE",    DEVICEV,
  475.        FCODESZSZ,     FCODESZ,     "FCODE",     FCODEV,
  476.        RECLENSZSZ,    RECLENSZ,    "RECLEN",    RECLENV,
  477.        BLOCKFSZSZ,    BLOCKFSZ,    "BLOCKF",    BLOCKFV,
  478.        FIXRECSZSZ,    FIXRECSZ,    "FIXREC",    FIXRECV,
  479.        MAXRECSZSZ,    MAXRECSZ,    "MAXREC",    MAXRECV,
  480.        MAXEXTSZSZ,    MAXEXTSZ,    "MAXEXT",    MAXEXTV,
  481.        SAVESPSZSZ,    SAVESPSZ,    "SAVESP",    SAVESPV,
  482.        PROGSZSZ,      PROGSZ,      "PROG",      PROGV,
  483.        BIN128SZSZ,    BIN128SZ,    "BIN128",    BIN128V,
  484.        TEXTSZSZ,      TEXTSZ,      "TEXT",      TEXTV,
  485.        TXT80SZSZ,     TXT80SZ,     "TXT80",     TXT80V,
  486.        EXPTABSZSZ,    EXPTABSZ,    "EXPTAB",    EXPTABV,
  487.        PURGESZSZ,     PURGESZ,    "PURGE",   PURGEV,
  488.        AUTOSZSZ,      AUTOSZ,      "AUTO",      AUTOV,
  489.  
  490.        ONSZSZ,        ONSZ,        "ON",        ONV,
  491.        OFFSZSZ,       OFFSZ,       "OFF",       OFFV,
  492.        NONESZSZ,      NONESZ,      "NONE",      NONEV,
  493.        XONSZSZ,       XONSZ,       "XON",       XONV,
  494.        XON2SZSZ,      XON2SZ,      "XON2",      XON2V,
  495.        YESSZSZ,       YESSZ,       "YES",       YESV,
  496.        QMARKSZSZ,     QMARKSZ,     "?",         QMARKV,
  497.        0, 0, 0, 0 );
  498. <<*****************************************************************>>
  499. <<                                                                 >>
  500. <<     Parameters that are changed via the SET command             >>
  501. <<                                                                 >>
  502. <<*****************************************************************>>
  503.  
  504. logical        RCV'BINARY := false,     << Binary if true         >>
  505.                RCV'FIXREC := true,      << Fixed records if true  >>
  506.                RCV'SAVESP := true,      << Release unused space   >>
  507.                IMPATIENT  := false;     << Short timeouts         >>
  508.  
  509. integer        RCV'FCODE  := 0,         << File code              >>
  510.                RCV'RECLEN := -80,       << Record Length          >>
  511.                RCV'BLOCKF := 16,        << Blocking Factor        >>
  512.                RCV'MAXEXT := 32;        << Max Extents            >>
  513.  
  514. double         RCV'MAXREC := 5000d;     << Max Records            >>
  515.  
  516. byte array     RCV'DEV(0:15) :=         << Device Type            >>
  517.                                 "DISC            ";
  518.  
  519. integer        SND'BINARY := 0;         << Send Mode: 0 = Auto    >>
  520.                                         <<            1 = Binary  >>
  521.                                         <<            2 = ASCII   >>
  522.  
  523. integer        HNDSHK := 1,             << Handshake: 0 = None    >>
  524.                                         <<            1 = XON     >>
  525.                                         <<            2 = XON2    >>
  526.                DEBUG'MODE := 0,         << Debug Mode             >>
  527.                TSPEED := 0,             << Line Speed (CPS)       >>
  528.                LDEV'LINE := 0;          << Line LDEV              >>
  529.  
  530. byte           SOH          := %1,      << Begin-packet character >>
  531.                MY'BLK'CK    := "3",
  532.                YOUR'BLK'CK  := "3";
  533.  
  534. integer array  MIN'SIZE(0:59):=60(32767);<< Used by input scanner to
  535.                                             ensure unique abbreviated
  536.                                             keywords              >>
  537.  
  538. <<*****************************************************************>>
  539.  
  540.  
  541. << Buffers and etc. >>
  542.  
  543.      integer   LNUM   := 0, << Line File number >>
  544.                DNUM   := 0, << Disc file number >>
  545.                CINUM  := 0, << CI Input         >>
  546.                CONUM  := 0, << CI Output        >>
  547.                VNUM   := 0, << Validation file >>
  548.                TAKENUM:= 0, << TAKE File Number >>
  549.                LOGNUM := 0; << Log Output       >>
  550.  
  551.      logical array  W'DBUF(0:DBUF'WORDSIZE),
  552.                     W'LBUF(0:LBUF'WORDSIZE);
  553.  
  554.      byte array     DBUF(*) = W'DBUF,
  555.                     LBUF(*) = W'LBUF;
  556.  
  557.      integer        DBUFCNT,   << Disc buffer byte count >>
  558.                     DBUF'RMAX, << Receive Max Buf size   >>
  559.                     DBUFINX,   << Disc buffer index >>
  560.                     LBUFCNT;   << Line buffer count >>
  561.  
  562.      byte array     PDATA(0:MAX'LONGPACK'SIZE); << Outgoing pkt data >>
  563.      integer        PDATACNT;
  564.  
  565.      byte array     RP'DATA(0:MAX'LONGPACK'SIZE); << Rcv (data) buf>>
  566.      byte           RP; << Response type >>
  567.      integer        RP'LEN,  << Length of response data >>
  568.                     RP'NUM;  << Packet number of response >>
  569.  
  570.      logical array  PBUF'W(0:79); << PRINT buffer >>
  571.      byte array     PBUF(*) = PBUF'W;
  572.      integer        PLEN;
  573.  
  574.      byte array     L'FNAME(0:37),  << Local file name  >>
  575.                     R'FNAME(0:37),  << Remote file name >>
  576.                     LOGNAME(0:35);  << Current log file name >>
  577.  
  578.      integer        L'FNAME'LEN,  << Length of Name    >>
  579.                     R'FNAME'LEN,  << Length of Name    >>
  580.                     LOGNAME'LEN;  << Length of log file name >>
  581.  
  582.      logical array       IB'W(0:39);    << Input Buffer >>
  583.      byte array          IB(*) = IB'W;
  584.      integer             ILEN;          << Length of Current IB >>
  585.  
  586. << Misc >>
  587.  
  588.      byte      STATE,  << Current state >>
  589.                Q8'IND; << Receive Q8 flag >>
  590.  
  591.      integer   N := 0,  << Current packet number >>
  592.                NUMTRY,  << Current "try" number  >>
  593.                OLDTRY;  << Previous "try" number >>
  594.  
  595.      byte array     KT'NAME(0:31);  << Temp file name >>
  596.  
  597.      integer        KTN'LEN;        << Length of KT'NAME >>
  598.  
  599.      logical        HAVE'KTEMP,     << True if temp file exists >>
  600.                     DBUF'WRITTEN:=false, << Prevent LF from forcing
  601.                                             disc write after write
  602.                                             from full buffer >>
  603.                     CTLY := false;  << True if CONTROL-Y        >>
  604.      array          VALID'TITLE'W(0:11) :=
  605.                       17973, 14649, 22092, 18756, 12118, 16716,
  606.                       18756, 16724, 17710, 20565, 16928, 0;
  607.      byte array     VALID'TITLE(*) = VALID'TITLE'W;
  608.      byte array     MYSELF(0:7);
  609.  
  610.      integer        ERROR,   << For COMMAND int >>
  611.                     PARM;    <<      ditto      >>
  612.  
  613.      byte array     KERM'JCW(0:9) := 1("KRMJCW00", 0,0);
  614.  
  615.      integer        MY'JCW'VAL,
  616.                     JCW'ERR;
  617.  
  618.      define         IDLING  = 0#,
  619.                     SENDING = 1#,
  620.                     RECVING = 2#,
  621.                     SEND'OK = 16+SENDING#,
  622.                     RECV'OK = 16+RECVING#,
  623.                     SEND'NG = 256+SENDING#,
  624.                     RECV'NG = 256+RECVING#;
  625.  
  626. define E'ST = if LOGNUM <> 0 then begin move PBUF := #,
  627.        E'EN = ,2; PLEN := TOS - @PBUF;
  628.                   FWRITE(LOGNUM,PBUF'W,-PLEN,0); end #,
  629.        M'ST = move PBUF := #,
  630.        M'EN = ,2; PLEN := TOS - @PBUF;
  631.                   FWRITE(CONUM,PBUF'W,-PLEN,0) #,
  632.        FLUSH'DBUF = begin
  633.                          FWRITE(DNUM,W'DBUF,-DBUFINX,0);
  634.                          DBUFINX := 0;
  635.                     end #,
  636.        KTEMP'NAME = "KMTTEMP" #,
  637.        RPACK'PACK = 1#,
  638.        SPACK'PACK = 2#;
  639.  
  640. equate IN    = 0,
  641.        OUT   = 1,
  642.        IO    = 2;
  643.  
  644.  
  645. <<****************************************************************>>
  646.      byte pointer   INFO'STR = Q - 5;
  647.      integer        INFO'LEN = Q - 6,
  648.                     PARM'VAL = Q - 4,
  649.                     TAKE'VAL;
  650.  
  651.      integer        TTYPE := 13,  << Terminal type >>
  652.                     LDEV'CI := 0,   << Command ldev >>
  653.                     ORGL'TTYPE,     << Orig TTYPE   >>
  654.                     ORGL'TISPEED,   << Orig I speed >>
  655.                     ORGL'TOSPEED,   << Orig O speed >>
  656.                     ORGL'ECHO,      << 0=off, 1=on  >>
  657.                     DFLT'TTYPE;     << 10=HPPA, 13=Classic machines >>
  658.  
  659.      integer        I'DELAY := 10;    << Initial Pause Duration >>
  660.  
  661. <<****************************************************************>>
  662.  
  663.      intrinsic      FOPEN,
  664.                     FCLOSE,
  665.                     FSETMODE,
  666.                     FREAD,
  667.                     FWRITE,
  668.                     FCONTROL,
  669.                     FGETINFO,
  670.                     PRINT, FCHECK, FERRMSG, << For debugging only >>
  671.                     PRINTFILEINFO, PRINT'FILE'INFO, << ditto >>
  672.                     FPOINT,
  673.                     GETJCW,
  674.                     PUTJCW,
  675.                     BINARY,
  676.                     DBINARY,
  677.                     ASCII,
  678.                     DASCII,
  679.                     WHO,
  680.                     JOBINFO,
  681.                     PAUSE,
  682.                     CLOCK,
  683.                     COMMAND,
  684.                     XCONTRAP,
  685.                     RESETCONTROL,
  686.                     QUIT,
  687.                     ABORTSESS;
  688. $PAGE "Low Level Procedures"
  689. $control segment=WORKER
  690.  
  691. byte procedure TOCHAR(CHR);
  692. value                 CHR ;
  693. integer               CHR ;
  694. begin
  695.      TOCHAR := byte(CHR + SP);
  696. end;
  697.  
  698. <<****************************************************************>>
  699.  
  700. integer procedure UNCHAR(CHR);
  701. value                    CHR ;
  702. byte                     CHR ;
  703. begin
  704.      UNCHAR := integer(CHR) - SP;
  705. end;
  706.  
  707. <<****************************************************************>>
  708.  
  709. integer procedure CTL(CHR);
  710. value                 CHR ;
  711. integer               CHR ;
  712. begin
  713.      CTL := integer(logical(CHR) xor %100);
  714. end;
  715.  
  716. <<****************************************************************>>
  717.  
  718. integer procedure NPNO(PNO);
  719. value                  PNO ;
  720. integer                PNO ;
  721. begin
  722.      NPNO := (PNO + 1) mod 64;
  723. end;
  724.  
  725. <<*****************************************************************>>
  726.  
  727. integer procedure PPNO(PNO);
  728. value                  PNO ;
  729. integer                PNO ;
  730. begin
  731.      if PNO = 0 then
  732.           PPNO := 63
  733.      else
  734.           PPNO := PNO - 1;
  735. end;
  736.  
  737. <<*****************************************************************>>
  738.  
  739. $control segment=CONTROLY'S
  740. procedure CONTROLY;
  741. begin
  742.  
  743.      logical   N = Q + 1;
  744.  
  745.      CTLY := true;
  746.      TOS := %31400 lor (N land %377);
  747.      RESETCONTROL;
  748.      assemble(XEQ 0);
  749. end;
  750.  
  751. <<*****************************************************************>>
  752. $control segment=WORKER
  753. $PAGE "CALCULATE'CRC - Three-byte checksum"
  754. logical procedure CALCULATE'CRC(PKT, LEN);
  755. value                                LEN;
  756. integer                              LEN;
  757. byte array                      PKT;
  758. begin
  759.  
  760.   << Copied from the IBM-PC CRC calulator in module MSSCOM.ASM   >>
  761.   << and modified for better efficiency in this environment.  AX >>
  762.   << and BX were the original PC registers and the nomenclature  >>
  763.   << was retained for want of better identifiers.                >>
  764.  
  765.      logical AX, DX:=0;
  766.      define  AH = AX.(0:8)#,
  767.              AL = AX.(8:8)#,
  768.              DH = DX.(0:8)#,
  769.              DL = DX.(8:8)#;
  770.      integer I := 1;
  771.  
  772.      do begin
  773.           AH := PKT(I);
  774.           DL := DL XOR AH;
  775.           AH := (DL & LSL(4)) XOR DL;
  776.           AL := 0;
  777.           DX := DH LOR AX;
  778.           DL := DL XOR ((AX:= AX & LSR(4)).(0:8));
  779.           DX := DX XOR (AX & LSR(1));
  780.      end
  781.      until ( I := I+1 ) > LEN;
  782.  
  783.      CALCULATE'CRC := DX;
  784.  
  785. END;
  786.  
  787. <<**************************************************************>>
  788.  
  789. $PAGE "Write packets to log file"
  790.  
  791. $control segment=LOGGER
  792. procedure WRITE'LOG(PACKET, LEN, WHO);
  793. value                       LEN, WHO;
  794. integer                     LEN, WHO;
  795. byte array          PACKET;
  796. begin
  797.      double         HH'MM'SS'TT;
  798.  
  799.      logical        HH'MM = HH'MM'SS'TT,
  800.                     SS'TT = HH'MM'SS'TT+1;
  801.  
  802.      define         HH = HH'MM.(0:8)#,
  803.                     MM = HH'MM.(8:8)#,
  804.                     SS = SS'TT.(0:8)#,
  805.                     TT = SS'TT.(8:8)#;
  806.  
  807.      byte pointer   PB;
  808.  
  809.      integer        PB'L;    << So we don't clobber PLEN >>
  810.  
  811.      if WHO = RPACK'PACK  then
  812.           MOVE PBUF := "RPACK: ", 2
  813.      else
  814.      if WHO = SPACK'PACK  then
  815.           MOVE PBUF := "SPACK: ", 2
  816.      else
  817.           MOVE PBUF := "?????? ", 2;
  818.      @PB := TOS;
  819.  
  820.      HH'MM'SS'TT := CLOCK;
  821.  
  822.      @PB := @PB( ASCII(HH, 10, PB) );
  823.      PB := ":";
  824.      @PB := @PB( 1+ASCII(MM, 10, PB(1)) );
  825.      PB := ":";
  826.      @PB := @PB( 1+ASCII(SS, 10, PB(1)) );
  827.      PB := ".";
  828.      @PB := @PB( 1+ASCII(TT, 10, PB(1)) );
  829.      MOVE PB := "   (", 2;
  830.      @PB := TOS;
  831.      @PB := @PB( ASCII(LEN, 10, PB) );
  832.      PB := ")";
  833.      PB'L := @PB-@PBUF;
  834.      FWRITE(LOGNUM, PBUF'W, -(PB'L+1), 0);
  835.  
  836.      move PBUF := "       ";
  837.      @PB := @PACKET;
  838.  
  839.      while LEN > 72  do
  840.      begin
  841.           move PBUF(7) := PB, (72);
  842.           @PB := @PB(72);
  843.           FWRITE(LOGNUM, PBUF'W, -79, 0);
  844.           LEN := LEN-72;
  845.      end;
  846.  
  847.      if LEN > 0  then
  848.      begin
  849.           move PBUF(7) := PB, (LEN);
  850.           FWRITE(LOGNUM, PBUF'W, -(LEN+7), 0);
  851.      end;
  852.  
  853. end;
  854. <<*****************************************************************>>
  855.  
  856. $PAGE "VALID'FILE - File access validator"
  857. $Control segment = VALID'FILE'S
  858. logical procedure VALID'FILE(VNAME, VNAME'LEN, ACCESS);
  859. value                               VNAME'LEN, ACCESS;
  860. byte array                   VNAME;
  861. integer                             VNAME'LEN, ACCESS;
  862. begin
  863.  
  864.      array          LEGAL'FILE'W(0:39);
  865.      byte array     LEGAL'FILE(*) = LEGAL'FILE'W;
  866.  
  867.      define         FILE'NAME     = LEGAL'FILE#,
  868.                     IOPART        = LEGAL'FILE(28)#,
  869.                     USERNAME      = LEGAL'FILE(32)#;
  870.  
  871.      integer        I:=0, J;
  872.  
  873.      label          NEXT'READ,
  874.                     NEXT'CHAR,
  875.                     TITLE'OK;
  876.  
  877.      VALID'FILE := false;  << Prepare for the worst >>
  878.  
  879.      VNAME(VNAME'LEN):=" ";<< In case caller didnt do it >>
  880.  
  881.      do begin  << Upshift so we can use caps only in validation file >>
  882.           move VNAME(I) := VNAME(I) while ANS, 1;
  883.           I := TOS-@VNAME+1;
  884.      end until I >= VNAME'LEN;
  885.  
  886.      if VNUM = 0 then
  887.      begin
  888.           VNUM := FOPEN(VALID'TITLE, 1, 0);
  889.           if VNUM = 0 then
  890.           begin
  891.                VALID'FILE:=true; << no file says all files are legal >>
  892.                return;
  893.           end;
  894.      end;
  895.  
  896.      do begin
  897.      NEXT'READ:
  898.           FREAD(VNUM, LEGAL'FILE'W, -80);
  899.           if <> then
  900.           begin
  901.                FPOINT(VNUM, 0d);  << Ready for next time >>
  902.                return;
  903.           end;
  904.           if not (MYSELF = USERNAME, (8)) then
  905.                go to NEXT'READ;
  906.  
  907.           if not (IOPART = "IO" lor
  908.                   ACCESS = IN  land  IOPART = "I "  lor
  909.                   ACCESS = OUT land  IOPART = "O ") then
  910.                go to NEXT'READ;
  911.  
  912.           I:=J:=0;
  913.      NEXT'CHAR:
  914.           if VNAME(I) = "@" then
  915.           begin             << No wild chars permitted in title >>
  916.                FPOINT(VNUM, 0d);
  917.                return;
  918.           end;
  919.           if VNAME(I) = FILE'NAME(J) then
  920.           begin
  921.                if VNAME(I) = " " then
  922.                     go to TITLE'OK;
  923.                I := I+1;
  924.                J := J+1;
  925.                if I >= VNAME'LEN then
  926.                     go to TITLE'OK;
  927.                go to NEXT'CHAR;
  928.           end
  929.                else
  930.           if FILE'NAME(J) = "@" then
  931.           begin
  932.                J := J+1;      << Skip '@' in legal name >>
  933.                do I := I+1    << Skip chars in test name >>
  934.                until VNAME(I) = " "
  935.                   or VNAME(I) = "."
  936.                   or VNAME(I) = FILE'NAME(J)
  937.                   or I >= VNAME'LEN;
  938.                go to NEXT'CHAR;
  939.           end;
  940.      end
  941.      until false;
  942.  
  943.      FPOINT(VNUM, 0d);  << I bet this is never executed >>
  944.      return;
  945.  
  946.      TITLE'OK:
  947.  
  948.      FPOINT(VNUM, 0d);
  949.      VALID'FILE := true;
  950. end;
  951. $PAGE "SPACK - Send A Packet"
  952. $control segment=WORKER
  953. procedure SPACK(TYP,NUM,LEN,DATA);
  954. value           TYP,NUM,LEN      ;
  955. byte            TYP              ;
  956. integer             NUM,LEN      ;
  957. byte array                  DATA ;
  958. begin
  959.  
  960.      logical   R'ERROR := false,
  961.                CHKSUM  := 0;
  962.  
  963.      integer   IX,
  964.                OX := 1;
  965.  
  966.      real      P'INT;
  967.  
  968.      <<----------------------------------------------------------->>
  969.  
  970.      subroutine XCK(CHR);
  971.      value          CHR ;
  972.      byte           CHR ;
  973.      begin
  974.           CHKSUM := (CHKSUM + logical(CHR)).(1:15);  <<No overflows>>
  975.           LBUF(OX) := CHR;
  976.           OX := OX + 1;
  977.      end;
  978.  
  979.      <<----------------------------------------------------------->>
  980.      subroutine REGULAR'PACK;
  981.      begin
  982.           LBUF(0) := SOH;        << Start with SOH >>
  983.           OX := 1;
  984.           if (STATE = "S") or      << Then length    >>
  985.              (STATE = "R") or
  986.              (YOUR'BLK'CK = "1")  then
  987.           XCK(TOCHAR(LEN+3))
  988.                else
  989.           XCK(TOCHAR(LEN+5));
  990.           XCK(TOCHAR(NUM));        << Block number   >>
  991.           XCK(TYP);              << Block type     >>
  992.  
  993.           if LEN <> 0 then       << Data if needed >>
  994.                for IX := 0 step 1 until LEN -1 do
  995.                     XCK(DATA(IX));
  996.  
  997.           if STATE = "S"  or
  998.              STATE = "R"  or
  999.              YOUR'BLK'CK = "1"  then
  1000.           begin  <<  Kermit primative checksum  >>
  1001.                CHKSUM := (CHKSUM.(8:2) + CHKSUM.(10:6)).(10:6);
  1002.                LBUF(OX) := TOCHAR(CHKSUM);  << Insert checksum >>
  1003.                OX := OX + 1;
  1004.           end
  1005.                else
  1006.           begin  <<  Fancy 3-byte CRC  >>
  1007.                CHKSUM := CALCULATE'CRC(LBUF, OX-1);
  1008.                LBUF(OX) := TOCHAR(CHKSUM.(0:4)); << First byte >>
  1009.                LBUF(OX:=OX+1) := TOCHAR(CHKSUM.(4:6)); << Second byte >>
  1010.                LBUF(OX:=OX+1) := TOCHAR(CHKSUM.(10:6)); << Third byte >>
  1011.                OX := OX + 1;
  1012.           end;
  1013.      end;
  1014.      <<------------------------------------------------------------->>
  1015.      subroutine LONG'PACK;
  1016.      begin
  1017.           LBUF(0) := SOH;
  1018.           XCK(TOCHAR(0));   <<Length=0 says this is long data packet>>
  1019.           XCK(TOCHAR(NUM)); <<Packet number>>
  1020.           XCK(TYP);         <<Should be "D" only>>
  1021.           IX := LEN + integer(YOUR'BLK'CK-"0");
  1022.           XCK(TOCHAR(IX / 95));   <<Length, most significant part>>
  1023.           XCK(TOCHAR(IX mod 95)); <<Length, least significant part>>
  1024.           XCK(TOCHAR( (CHKSUM.(8:2)+CHKSUM.(10:6)).(10:6) ));<<HDR BCC>>
  1025.           if YOUR'BLK'CK = "1"  then
  1026.           begin
  1027.                for IX := 0 step 1 until LEN-1  do
  1028.                     XCK(DATA(IX));
  1029.                CHKSUM := (CHKSUM.(8:2)+CHKSUM.(10:6)).(10:6);
  1030.                LBUF(OX) := TOCHAR( CHKSUM );
  1031.           end
  1032.                else
  1033.           begin  <<  Fancy 3-byte CRC  >>
  1034.                move LBUF(OX):=DATA, (LEN);
  1035.                OX := OX+LEN;
  1036.                CHKSUM := CALCULATE'CRC(LBUF, OX-1);
  1037.                LBUF(OX) := TOCHAR(CHKSUM.(0:4)); << First byte >>
  1038.                LBUF(OX:=OX+1) := TOCHAR(CHKSUM.(4:6)); << Second byte >>
  1039.                LBUF(OX:=OX+1) := TOCHAR(CHKSUM.(10:6)); << Third byte >>
  1040.           end;
  1041.  
  1042.           OX := OX+1;
  1043.      end;
  1044.  
  1045.      <<----------------------------------------------------------->>
  1046.  
  1047.      if (LEN > MAX'SND'DATA) and (TYP = "D") then
  1048.           LONG'PACK
  1049.      else
  1050.           REGULAR'PACK;
  1051.  
  1052.      if DEBUG'MODE > 0 and LOGNUM <> 0 then
  1053.      begin
  1054.           WRITE'LOG(LBUF, OX, SPACK'PACK);
  1055.      end;
  1056.  
  1057.      LBUF(OX) := YOUR'EOL; << Set end of line char >>
  1058.      OX := OX + 1;
  1059.  
  1060.      if PAUSE'CNT <> 0 then
  1061.      begin
  1062.           P'INT := real(PAUSE'CNT)/10.;
  1063.           PAUSE(P'INT);  << Pause for turnaround >>
  1064.      end;
  1065.  
  1066.      FWRITE(LNUM,W'LBUF,-OX,%320);  << Write the block >>
  1067.      IF = THEN BEGIN
  1068.        E'ST "SPACK: WRITE OK" E'EN END
  1069.      ELSE IF DEBUG'MODE<>0 AND LOGNUM<>0 THEN BEGIN
  1070.        FCHECK(LNUM, R'ERROR);
  1071.        MOVE PBUF:="WRITE ERROR ", 2;
  1072.        PLEN:=TOS-@PBUF;
  1073.        PLEN:=PLEN+ASCII(R'ERROR, 10, PBUF(PLEN));
  1074.        WRITE'LOG(PBUF, PLEN, SPACK'PACK);
  1075.      END;
  1076.  
  1077. end;
  1078.  
  1079. <<****************************************************************>>
  1080. $PAGE "RPACK - Recieve Packet"
  1081. logical procedure RPACK(TYP,LEN,NUM,DATA);
  1082. byte                    TYP              ;
  1083. integer                     LEN,NUM      ;
  1084. byte array                          DATA ;
  1085. begin
  1086.  
  1087.      integer        IX,              << General Index       >>
  1088.                     PLEN;            << Packet length       >>
  1089.  
  1090.      logical        R'ERROR := false,  << Error Flag >>
  1091.                     CCHKSUM,           << Calculated checksum >>
  1092.                     RCHKSUM,           << Received checksum >>
  1093.                     DONE := false;     << Done Flag  >>
  1094.  
  1095.      byte pointer   PACKET;
  1096.  
  1097.      <<----------------------------------------------------------->>
  1098.  
  1099.      LBUF(0) := 0;
  1100.      move LBUF(1) := LBUF(0),(LBUF'BYTESIZE -1);
  1101.  
  1102.      FCONTROL(LNUM,04,MY'TO);  << Set timeout interval >>
  1103.  
  1104.      LBUFCNT := FREAD(LNUM,W'LBUF,-LBUF'BYTESIZE); << Read buffer >>
  1105.  
  1106.      if <> then
  1107.      begin  << Timeout >>
  1108.           FCHECK(LNUM, R'ERROR);
  1109.  
  1110.           if LOGNUM<>0 then
  1111.           begin
  1112.                move PBUF := "RPACK: FSERROR ", 2; PLEN:=TOS-@PBUF;
  1113.                PLEN:=PLEN+ASCII(R'ERROR, 10, PBUF(PLEN));
  1114.                FWRITE(LOGNUM, PBUF'W, -PLEN, 0);
  1115.           end;
  1116.           R'ERROR:=1;
  1117.      end
  1118.           else
  1119.      begin  << Have a packet >>
  1120.  
  1121.           if DEBUG'MODE > 0 and LOGNUM <> 0 then
  1122.           begin
  1123.                WRITE'LOG(LBUF, LBUFCNT, RPACK'PACK);
  1124.           end;
  1125.  
  1126.           IX := 0;
  1127.           while not (DONE lor R'ERROR) do
  1128.           begin  << Look for SOH >>
  1129.                if LBUF(IX) = SOH then
  1130.                begin
  1131.                     DONE := true;
  1132.                end
  1133.                     else
  1134.                begin
  1135.                     IX := IX + 1;
  1136.                     if IX > (LBUFCNT - 4) then
  1137.                     begin  << SOH not found >>
  1138.                          R'ERROR := 3;
  1139.                          E'ST "RPACK - SOH not found" E'EN;
  1140.                     end; << No SOH >>
  1141.                end; << Not SOH >>
  1142.           end; << while >>
  1143.      end; << Have a packet >>
  1144.  
  1145.  
  1146.      if R'ERROR then
  1147.      begin
  1148.           RPACK := not(R'ERROR);
  1149.           return;
  1150.      end;
  1151.  
  1152.      << Something in the buffer that starts with SOH. >>
  1153.      << Let's see if everything else looks good.      >>
  1154.  
  1155.      @PACKET := @LBUF(IX);   << Address packet >>
  1156.  
  1157.      PLEN := UNCHAR(PACKET(1));
  1158.      if PLEN > 0  then
  1159.      begin      << Regular packets >>
  1160.           PLEN := PLEN+2;
  1161.           if (IX + PLEN > LBUFCNT) or
  1162.              (PLEN > MAX'RCV'SIZE + 2) or
  1163.              (PLEN < 5) then
  1164.           begin << Length is not reasonable >>
  1165.                R'ERROR := 5;
  1166.                E'ST "RPACK - Invalid length" E'EN;
  1167.           end
  1168.                else
  1169.           begin << Length OK >>
  1170.  
  1171.                if STATE = "S"  or
  1172.                   STATE = "R"  or
  1173.                   YOUR'BLK'CK = "1"  then
  1174.                begin  <<  Kermit primative checksum  >>
  1175.                     CCHKSUM := 0;
  1176.                     for IX := PLEN-2 step -1 until 1  do
  1177.                          CCHKSUM := CCHKSUM + logical(PACKET(IX));
  1178.  
  1179.                     CCHKSUM := (CCHKSUM.(8:2) + CCHKSUM.(10:6)).(10:6);
  1180.                     CCHKSUM := logical(TOCHAR(CCHKSUM));
  1181.  
  1182.                     RCHKSUM := logical(PACKET(PLEN-1));
  1183.                end
  1184.                     else
  1185.                begin
  1186.                     CCHKSUM := CALCULATE'CRC(PACKET, PLEN-4);
  1187.  
  1188.                     RCHKSUM := UNCHAR(PACKET(PLEN-1))  << (10:10:6) >>
  1189.                           cat  UNCHAR(PACKET(PLEN-2))  (4:10:6)
  1190.                           cat  UNCHAR(PACKET(PLEN-3))  (0:12:4);
  1191.  
  1192.                     PLEN := PLEN-2;
  1193.                end;
  1194.  
  1195.               if CCHKSUM <> RCHKSUM then
  1196.               begin  << Bad checksum >>
  1197.                     R'ERROR := 7;
  1198.                     E'ST "RPACK - CHKSUM Error" E'EN;
  1199.               end;
  1200.           end;
  1201.      end
  1202.           else
  1203.      begin    << Long packets >>
  1204.           PLEN := 95*UNCHAR(PACKET(4)) + UNCHAR(PACKET(5));
  1205.  
  1206.           if (PLEN > LBUFCNT)  or
  1207.              (PLEN > LONGPACK'SIZE+10)  then
  1208.           begin
  1209.                R'ERROR := 5;
  1210.                E'ST "RPACK - Invalid longpack length" E'EN;
  1211.           end
  1212.                else
  1213.           begin
  1214.                if PACKET(3) <> "D"  then
  1215.                begin
  1216.                     R'ERROR := 9;
  1217.                     E'ST "RPACK - Longpack not data" E'EN;
  1218.                end
  1219.                     else
  1220.                begin     << Calculate header checksum >>
  1221.                     CCHKSUM := 0;
  1222.                     for IX := 1 step 1 until 5  do
  1223.                          CCHKSUM := CCHKSUM + logical(PACKET(IX));
  1224.  
  1225.                     if (CCHKSUM.(8:2)+CCHKSUM.(10:6)).(10:6)
  1226.                               <> logical(UNCHAR(PACKET(6)))  then
  1227.                     begin
  1228.                          R'ERROR := 7;
  1229.                          E'ST "RPACK - Header checksum error" E'EN;
  1230.                     end
  1231.                          else
  1232.                     begin
  1233.                          if YOUR'BLK'CK = "1"  then
  1234.                          begin
  1235.                               for IX := 6 step 1 until PLEN-2+7  do
  1236.                                   CCHKSUM:=CCHKSUM+logical(PACKET(IX));
  1237.                               CCHKSUM :=
  1238.                                  (CCHKSUM.(8:2)+CCHKSUM.(10:6)).(10:6);
  1239.  
  1240.                               RCHKSUM := UNCHAR(PACKET(PLEN-1+7));
  1241.                          end
  1242.                               else
  1243.                          begin
  1244.                               CCHKSUM :=
  1245.                                    CALCULATE'CRC(PACKET, PLEN-4+7);
  1246.  
  1247.                               RCHKSUM :=
  1248.                                    UNCHAR(PACKET(PLEN-1+7))
  1249.                                    cat UNCHAR(PACKET(PLEN-2+7))(4:10:6)
  1250.                                    cat UNCHAR(PACKET(PLEN-3+7))(0:12:4);
  1251.  
  1252.                          !    PLEN := PLEN-2;
  1253.                          end;
  1254.  
  1255.                          if CCHKSUM <> RCHKSUM  then
  1256.                          begin
  1257.                               R'ERROR := 7;
  1258.                               E'ST
  1259.                                   "RPACK - Longpack checksum error"
  1260.                               E'EN;
  1261.                          end;
  1262.                     end;
  1263.                end;
  1264.           end;
  1265.      end;
  1266.  
  1267.      if not R'ERROR then
  1268.      begin  << Packet OK, return the needed info >>
  1269.           TYP := PACKET(3);
  1270.           NUM := UNCHAR(PACKET(2));
  1271.           if UNCHAR( PACKET(1) )  <>  0 then
  1272.           move DATA := PACKET(4),(LEN:=PLEN-5)
  1273.                else
  1274.           move DATA := PACKET(7),
  1275.                            (LEN:=PLEN-integer(YOUR'BLK'CK-"0"));
  1276.           RPACK := true;
  1277.      end
  1278.           else
  1279.      RPACK := not(R'ERROR);
  1280. end;
  1281. $PAGE "BUFILL - Fill Transmit Buffer"
  1282. procedure BUFILL(DATA,CNT,STAT);
  1283. byte array       DATA          ;
  1284. integer               CNT,STAT ;
  1285. begin
  1286.  
  1287.      logical        DONE := false;
  1288.  
  1289.      integer        T,
  1290.                     T7,
  1291.                     INCLEN,
  1292.                     RPT'CNT,
  1293.                     IX,
  1294.                     CLEFT,
  1295.                     BUF'MAX;
  1296.  
  1297.      logical        TRY'REPEAT;
  1298.  
  1299.      byte array     INCBUF(0:5);   << Intermediate Char Buf >>
  1300.  
  1301.      <<----------------------------------------------------------->>
  1302.  
  1303.      logical subroutine GETCHAR(CHR);
  1304.      integer                    CHR ;
  1305.      begin
  1306.           <<  Extract a char from the buffer and do not increment >>
  1307.           <<  the index.  False is returned if EOF or some error  >>
  1308.           <<  condition occurs (STAT is set accordingly).         >>
  1309.           <<                                                      >>
  1310.           <<  If the buffer index (DBUFINX) is equal to the count >>
  1311.           <<  (DBUFCNT) the buffer is empty. If in binary mode,   >>
  1312.           <<  we simply get another record. Otherwise (ASCII)     >>
  1313.           <<  we return EOL. In this case DBUFINX will equal      >>
  1314.           <<  DBUFCNT + 1 the next time thru.                     >>
  1315.  
  1316.           GETCHAR := true;
  1317.  
  1318.           if not (DBUFINX < DBUFCNT) then
  1319.           begin  << No data in buffer >>
  1320.                if IMAGE lor (DBUFINX > DBUFCNT) then
  1321.                begin  << Fill up the buffer >>
  1322.                     DBUFCNT := FREAD(DNUM,W'DBUF,-DBUF'BYTESIZE);
  1323.                     if < then
  1324.                     begin << Read error >>
  1325.                          STAT := -1;
  1326.                          E'ST "BUFILL - Disc read error" E'EN;
  1327.                          GETCHAR := false;
  1328.                     end
  1329.                          else
  1330.                     if > then
  1331.                     begin  <<  End of file >>
  1332.                          GETCHAR := false;
  1333.                          if CNT = 0 then STAT := 1;
  1334.                     end
  1335.                          else
  1336.                     begin  << Read went OK >>
  1337.  
  1338.                          if not IMAGE then
  1339.                          begin << Suppress trailing blanks >>
  1340.                               DBUFINX := DBUFCNT -1;
  1341.                               while DBUFINX > 0 and
  1342.                                     DBUF(DBUFINX) = " " do
  1343.                               begin
  1344.                                    DBUFINX := DBUFINX - 1;
  1345.                               end;
  1346.                               DBUFCNT := DBUFINX + 1;
  1347.                          end;
  1348.  
  1349.                          DBUFINX := 0;
  1350. <<+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>
  1351. <<                                                                 >>
  1352. <<     WARNING: Zero length binary records will not be handled     >>
  1353. <<              properly.                                          >>
  1354. <<                                                                 >>
  1355. <<+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>
  1356.                          if DBUFCNT > 0 then
  1357.                               CHR := integer(DBUF(0))
  1358.                          else
  1359.                               CHR := CR;
  1360.                     end;
  1361.                end
  1362.                     else
  1363.                begin << Return EOL >>
  1364.                     CHR := CR;
  1365.                end;
  1366.           end << No data in buffer >>
  1367.                else
  1368.           begin
  1369.                CHR := integer(DBUF(DBUFINX));
  1370.           end;
  1371.      end;
  1372.  
  1373.      <<----------------------------------------------------------->>
  1374.  
  1375.      subroutine PUTCHR(CHR);
  1376.      value             CHR ;
  1377.      integer           CHR ;
  1378.      begin
  1379.           INCBUF(INCLEN) := byte(CHR);
  1380.           INCLEN := INCLEN + 1;
  1381.      end;
  1382.  
  1383.      <<----------------------------------------------------------->>
  1384.  
  1385.      CNT := 0;
  1386.      STAT := 0;
  1387.      if LONGPACK'SIZE > MAX'SND'DATA  then
  1388.           BUF'MAX := LONGPACK'SIZE
  1389.      else
  1390.           BUF'MAX := MAX'SND'DATA;
  1391.      CLEFT := BUF'MAX;  << Compute room >>
  1392.      while not DONE do
  1393.      begin
  1394.           DONE := not GETCHAR(T);
  1395.           if not DONE then
  1396.           begin
  1397.                << Transfer the character to an intermediate buffer >>
  1398.                << (INCBUF). If a multi-character sequence is       >>
  1399.                << generated, it is placed in INCBUF in reverse     >>
  1400.                << order. The sequence is re-inverted later.        >>
  1401.  
  1402.                T7 := T.(9:7);  << Get low seven bits >>
  1403.  
  1404.                INCLEN := 0;
  1405.                TRY'REPEAT := USE'REPEAT;
  1406.                if (T7 = CR) and (not IMAGE) then
  1407.                begin << Generate end-of-line sequence >>
  1408.                     TRY'REPEAT := false;
  1409.                     PUTCHR(CTL(LF));
  1410.                     PUTCHR(MY'Q'CTL);
  1411.                     PUTCHR(CTL(CR));
  1412.                     PUTCHR(MY'Q'CTL);
  1413.                end
  1414.                     else
  1415.                begin
  1416.                     if T7 < SP or T7 = A'DEL then
  1417.                     begin  << Control char >>
  1418.                          if QUOTE'8 then
  1419.                               PUTCHR(CTL(T7))
  1420.                          else
  1421.                               PUTCHR(CTL(T));
  1422.                          PUTCHR(MY'Q'CTL);
  1423.                     end
  1424.                          else
  1425.                     if (T7 = MY'Q'CTL)                lor
  1426.                        (QUOTE'8 land T7 = Q'8)        lor
  1427.                        (USE'REPEAT land T7 = RPT'CHR)     then
  1428.                     begin << Quote a not-control char >>
  1429.                          if QUOTE'8 then
  1430.                               PUTCHR(T7)
  1431.                          else
  1432.                               PUTCHR(T);
  1433.                          PUTCHR(MY'Q'CTL);
  1434.                     end
  1435.                          else
  1436.                     begin << Regular char >>
  1437.                          if QUOTE'8 then
  1438.                               PUTCHR(T7)
  1439.                          else
  1440.                               PUTCHR(T);
  1441.                     end;
  1442.  
  1443.                     if QUOTE'8 land (T <> T7) then
  1444.                          PUTCHR(Q'8);
  1445.                end;
  1446.  
  1447.                << The single char sequence has been generated. >>
  1448.                << Continue if it will fit in the buffer.       >>
  1449.  
  1450.                if INCLEN > CLEFT then
  1451.                begin << It won't fit >>
  1452.                     DONE := true;
  1453.                end
  1454.                     else
  1455.                begin  << Accepted >>
  1456.                     DBUFINX := DBUFINX +1;
  1457.                     if TRY'REPEAT land (CLEFT - INCLEN >= 2) then
  1458.                     begin
  1459.  
  1460.                          << OK, now we do repeat processing. >>
  1461.                          << Count the adjacent occurences.   >>
  1462.  
  1463.                          IX := DBUFINX;
  1464.                          while (IX < DBUFCNT) and
  1465.                                (integer(DBUF(IX)) = T) do
  1466.                          begin
  1467.                               IX := IX +1;
  1468.                          end;
  1469.  
  1470.                          RPT'CNT := IX - DBUFINX + 1;
  1471.                          if RPT'CNT > 94 then
  1472.                               RPT'CNT := 94;
  1473.  
  1474.                          << Use the repeat count only if it >>
  1475.                          << saves space in the buffer.      >>
  1476.  
  1477.                          if (INCLEN +2) < (INCLEN * RPT'CNT) then
  1478.                          begin << Use repeat >>
  1479.                               PUTCHR(integer(TOCHAR(RPT'CNT)));
  1480.                               PUTCHR(RPT'CHR);
  1481.                               DBUFINX := DBUFINX + RPT'CNT - 1;
  1482.                          end;
  1483.                     end;
  1484.  
  1485.                     << Transfer to the buffer >>
  1486.  
  1487.                     while INCLEN > 0 do
  1488.                     begin
  1489.                          INCLEN := INCLEN - 1;
  1490.                          DATA(CNT) := INCBUF(INCLEN);
  1491.                          CNT := CNT + 1;
  1492.                     end;
  1493.  
  1494.                     CLEFT := BUF'MAX - CNT;
  1495.                     if CLEFT <= 0 then DONE := true;
  1496.                end;
  1497.           end;
  1498.      end;
  1499. end;
  1500. $PAGE "BUFEMP - Empty Line Buffer"
  1501. procedure BUFEMP(DATA,CNT);
  1502. byte array       DATA     ;
  1503. integer               CNT ;
  1504. begin
  1505.  
  1506.      integer        I := 0,
  1507.                     RPT'CNT,
  1508.                     T,
  1509.                     T'HI,
  1510.                     T7;
  1511.  
  1512. <<---------------------------------------------------------------->>
  1513.  
  1514.      subroutine NCHAR;
  1515.      begin
  1516.           T := integer(DATA(I));
  1517.           T7 := T.(9:7);
  1518.           I := I + 1;
  1519.      end;
  1520.  
  1521. <<---------------------------------------------------------------->>
  1522.  
  1523.      while I < CNT do
  1524.      begin
  1525.           T'HI := 0;  << Hold high bit here if quote 8 >>
  1526.  
  1527.           RPT'CNT := 1;
  1528.  
  1529.           NCHAR;
  1530.           if USE'REPEAT land (T7 = RPT'CHR) then
  1531.           begin  << Process repeat >>
  1532.                NCHAR;
  1533.                RPT'CNT := UNCHAR(byte(T7));
  1534.                NCHAR;
  1535.           end;
  1536.  
  1537.           if QUOTE'8 land (T7 = Q'8) then
  1538.           begin
  1539.                T'HI := 128;
  1540.                NCHAR;
  1541.           end;
  1542.  
  1543.           if T7 = YOUR'Q'CTL then
  1544.           begin
  1545.                NCHAR;
  1546.                if T7 >= %77 and T7 <= %137 then
  1547.                     T := CTL(T);
  1548.                     T7 := T.(9:7);
  1549.           end;
  1550.  
  1551.           if QUOTE'8 then
  1552.                T := T'HI + T7; << Got the real character >>
  1553.  
  1554.           if (not IMAGE) land T7 = CR then
  1555.                RPT'CNT := 0; << Throw away CR >>
  1556.  
  1557.           if EXP'TABS and T7=HTAB  then
  1558.           begin
  1559.                RPT'CNT:=8*RPT'CNT - (DBUFINX mod 8);
  1560.                T:="  ";
  1561.           end;
  1562.  
  1563.           << Transfer to disc buffer >>
  1564.  
  1565.           while RPT'CNT > 0 do
  1566.           begin
  1567.                RPT'CNT := RPT'CNT - 1;
  1568.                if (not IMAGE) land (T7 = LF) then
  1569.                begin
  1570.                     if DBUF'WRITTEN then
  1571.                     begin
  1572.                          DBUF'WRITTEN := false;
  1573.                          if DBUFINX > 0 then
  1574.                               FLUSH'DBUF;
  1575.                     end
  1576.                          else
  1577.                     FLUSH'DBUF;
  1578.                end
  1579.                     else
  1580.                begin
  1581.                     DBUF(DBUFINX) := byte(T);
  1582.                     DBUFINX := DBUFINX + 1;
  1583.                     if DBUFINX >= DBUF'RMAX then
  1584.                     begin
  1585.                          FLUSH'DBUF;
  1586.                          DBUF'WRITTEN := true;
  1587.                     end;
  1588.                end;
  1589.           end;
  1590.      end;
  1591. end;
  1592. $PAGE "CBUFXLT - Translate Command Buffer"
  1593. $control segment=CBUFXLT'S
  1594. logical procedure CBUFXLT(IDATA,ICNT,ODATA,OCNT,OMAX);
  1595. value                           ICNT,           OMAX ;
  1596. byte array                IDATA,     ODATA           ;
  1597. integer                         ICNT,      OCNT,OMAX ;
  1598. begin
  1599.  
  1600.      integer        I := 0,
  1601.                     RPT'CNT,
  1602.                     T,
  1603.                     T'HI,
  1604.                     T7;
  1605.  
  1606. <<---------------------------------------------------------------->>
  1607.  
  1608.      subroutine NCHAR;
  1609.      begin
  1610.           T := integer(IDATA(I));
  1611.           T7 := T.(9:7);
  1612.           I := I + 1;
  1613.      end;
  1614.  
  1615. <<---------------------------------------------------------------->>
  1616.  
  1617.      OCNT := 0;
  1618.      CBUFXLT := true;
  1619.  
  1620.      while I < ICNT do
  1621.      begin
  1622.           T'HI := 0;  << Hold high bit here if quote 8 >>
  1623.  
  1624.           RPT'CNT := 1;
  1625.  
  1626.           NCHAR;
  1627.           if USE'REPEAT land (T7 = RPT'CHR) then
  1628.           begin  << Process repeat >>
  1629.                NCHAR;
  1630.                RPT'CNT := UNCHAR(byte(T7));
  1631.                NCHAR;
  1632.           end;
  1633.  
  1634.           if QUOTE'8 land (T7 = Q'8) then
  1635.           begin
  1636.                T'HI := 128;
  1637.                NCHAR;
  1638.           end;
  1639.  
  1640.           if T7 = YOUR'Q'CTL then
  1641.           begin
  1642.                NCHAR;
  1643.                if T7 >= %77 and T7 <= %137 then
  1644.                     T := CTL(T);
  1645.                     T7 := T.(9:7);
  1646.           end;
  1647.  
  1648.           if QUOTE'8 then
  1649.                T := T'HI + T7; << Got the real character >>
  1650.  
  1651.  
  1652.           << Transfer to output buffer >>
  1653.  
  1654.           while RPT'CNT > 0 do
  1655.           begin
  1656.                RPT'CNT := RPT'CNT - 1;
  1657.                ODATA(OCNT) := byte(T);
  1658.                OCNT := OCNT + 1;
  1659.                if OCNT >= OMAX then
  1660.                begin
  1661.                     I := 0;
  1662.                     CBUFXLT := false;
  1663.                end;
  1664.           end;
  1665.      end;
  1666. end;
  1667. $PAGE "UNQFNAME - Check For Unique File Name"
  1668. $control segment=UNQFNAME'S
  1669. logical procedure UNQFNAME(FNAME,LEN);
  1670. value                            LEN ;
  1671. integer                          LEN ;
  1672. byte array                 FNAME     ;
  1673. begin
  1674.  
  1675.      byte array   BA'TEMP(0:37);
  1676.  
  1677.      integer      I'ERR,
  1678.                   I'PARM;
  1679.  
  1680.      <<---------------------------------------------------------->>
  1681.  
  1682.      move BA'TEMP := "listf ";
  1683.      move BA'TEMP(6) := FNAME,(LEN);
  1684.      move BA'TEMP(6+LEN) := ";$NULL";
  1685.      BA'TEMP(12 + LEN) := %15;
  1686.      COMMAND(BA'TEMP,I'ERR,I'PARM);
  1687.      if I'ERR = 907 then
  1688.           UNQFNAME := true
  1689.      else
  1690.           UNQFNAME := false;
  1691. end;
  1692.  
  1693. $PAGE "MAKE'U'FNAME - Make a Unique File Name"
  1694. $control segment=MAKE'U'FNAME'S
  1695.  
  1696. logical procedure MAKE'U'FNAME(FNAME,LEN);
  1697. byte array                     FNAME     ;
  1698. integer                              LEN ;
  1699. begin
  1700.  
  1701.      integer        FIX,   << From Index  >>
  1702.                     TIX,   << To Index    >>
  1703.                     ITEMP, << Scratch     >>
  1704.                     BLEN;  << Base Length >>
  1705.  
  1706.      logical        ALPH,  << Char Alpha  >>
  1707.                     NUM,   << Char is Num >>
  1708.                     DONE;  << Loop Flag   >>
  1709.  
  1710.      <<---------------------------------------------------------->>
  1711.  
  1712.      FIX := 0;
  1713.      TIX := 0;
  1714.  
  1715.      while FIX < LEN do
  1716.      begin
  1717.           ITEMP := integer(FNAME(FIX));
  1718.  
  1719.           if ITEMP >= %141 <<a>> and
  1720.              ITEMP <= %172 <<z>>     then ITEMP := ITEMP - %40;
  1721.  
  1722.           ALPH := false;
  1723.           NUM := false;
  1724.  
  1725.           if ITEMP >= %101 <<A>> and
  1726.              ITEMP <= %132 <<Z>>     then ALPH := true
  1727.                else
  1728.           if ITEMP >= %60 <<0>> and
  1729.              ITEMP <= %71 <<9>>     then NUM := true;
  1730.  
  1731.           if (ALPH land (TIX = 0)) lor
  1732.              ((ALPH lor NUM) land (TIX > 0)) then
  1733.           begin
  1734.                FNAME(TIX) := byte(ITEMP);
  1735.                TIX := TIX + 1;
  1736.           end;
  1737.  
  1738.           FIX := FIX + 1;
  1739.      end;
  1740.  
  1741.      LEN := TIX;
  1742.  
  1743.      <<------------------------------------------------>>
  1744.      << File name now in native format. Adjust length. >>
  1745.      <<------------------------------------------------>>
  1746.  
  1747.      if LEN > 8 then LEN := 8 << Truncate >>
  1748.           else
  1749.      if LEN = 0 then
  1750.      begin << Nothing left, use default >>
  1751.           move FNAME := "KMT";
  1752.           LEN := 3;
  1753.      end;
  1754.  
  1755.      <<---------------------------------------->>
  1756.      << File name is now OK , check uniqueness >>
  1757.      <<---------------------------------------->>
  1758.  
  1759.      if UNQFNAME(FNAME,LEN) then
  1760.      begin << OK, we're done >>
  1761.           MAKE'U'FNAME := true;
  1762.      end
  1763.           else
  1764.      begin
  1765.           << ---------------------------------------------->>
  1766.           << Append two numeric chars (00-99) to the name. >>
  1767.           <<----------------------------------------------->>
  1768.  
  1769.           BLEN := if LEN > 6 then 6 else LEN;
  1770.           ITEMP := 1;
  1771.           DONE := false;
  1772.           while (ITEMP < 99) land not DONE do
  1773.           begin
  1774.                FNAME(BLEN) := byte((ITEMP/10) + %60);
  1775.                FNAME(BLEN+1) := byte((ITEMP mod 10) + %60);
  1776.                LEN := BLEN + 2;
  1777.                if UNQFNAME(FNAME,LEN) then
  1778.                     DONE := true
  1779.                else
  1780.                     ITEMP := ITEMP + 1;
  1781.           end;
  1782.  
  1783.           MAKE'U'FNAME := not DONE;
  1784.      end;
  1785. end;
  1786. $PAGE "P'EPACK Print Error (E) Packet Data"
  1787. $control segment=P'EPACK'S
  1788. procedure P'EPACK(DATA,LEN);
  1789. value                  LEN ;
  1790. integer                LEN ;
  1791. byte array        DATA     ;
  1792. begin
  1793.  
  1794.      logical pointer WUF;
  1795.  
  1796.      @WUF := @DATA & lsr(1);
  1797.  
  1798.      if LOGNUM <> 0 then
  1799.           FWRITE(LOGNUM,WUF,-LEN,0);
  1800. end;
  1801. $PAGE "SENDSW - Send Switch (Definitions)"
  1802. $control segment=WORKER
  1803. <<****************************************************************>>
  1804.  
  1805. $PAGE "SBREAK - Send Break"
  1806. byte procedure SBREAK;
  1807. begin
  1808.  
  1809.      SBREAK := STATE; << Default is no change >>
  1810.      NUMTRY := NUMTRY + 1;
  1811.      if NUMTRY > MAXTRY then
  1812.      begin
  1813.           E'ST "SBREAK - Max retrys exceeded " E'EN;
  1814.           SBREAK := "A";
  1815.      end
  1816.           else
  1817.      begin
  1818.           SPACK("B",N,0,RP'DATA);
  1819.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  1820.           begin
  1821.                if RP = "Y" then
  1822.                begin
  1823.                     if RP'NUM = N then
  1824.                     begin
  1825.                          NUMTRY := 0;
  1826.                          N := NPNO(N);
  1827.                          SBREAK := "C";
  1828.                     end;
  1829.                end
  1830.                     else
  1831.                if RP = "E" then
  1832.                begin
  1833.                     E'ST "SBREAK - E packet recieved" E'EN;
  1834.                     P'EPACK(RP'DATA,RP'LEN);
  1835.                     SBREAK := "A";
  1836.                end
  1837.                     else
  1838.                if RP <> "N" then
  1839.                begin
  1840.                     E'ST "SBREAK - Unknown packet type" E'EN;
  1841.                     SBREAK := "A";
  1842.                end;
  1843.           end;
  1844.      end;
  1845. end;
  1846. $PAGE "SENDSW - Packet Sender"
  1847. logical procedure SENDSW(SFNAME,SFNLEN);
  1848. value                           SFNLEN ;
  1849. byte array               SFNAME        ;
  1850. integer                         SFNLEN ;
  1851. begin
  1852.  
  1853.      logical        DONE := false,
  1854.                     FOPT;
  1855.  
  1856.      integer        BFSTAT,
  1857.                     TEMP;
  1858.  
  1859.  
  1860. $PAGE "SPAR - Set Up Send SI Parameters"
  1861. subroutine SPAR(DATA,LEN);
  1862. byte array      DATA     ;
  1863. integer              LEN ;
  1864. begin
  1865.      DATA(0) := TOCHAR(MAX'RCV'SIZE); << Biggest to send me      >>
  1866.      DATA(1) := TOCHAR(MY'TO);        << When to time me out     >>
  1867.      DATA(2) := TOCHAR(0);            << How many pads I need    >>
  1868.      DATA(3) := byte(CTL(0));         << Pad char to use for me  >>
  1869.      DATA(4) := TOCHAR(CR);           << End-of-line char for me >>
  1870.      DATA(5) := MY'Q'CTL;             << Control quote I send    >>
  1871.      DATA(6) := byte(P'Q'8);          << Prefered 8 bit quote    >>
  1872.      DATA(7) := MY'BLK'CK;            << 3-char CRC default >>
  1873.      DATA(8) := byte(P'RPT'CHR);      << Prefered repeat prefix  >>
  1874.      DATA(9) := TOCHAR(MY'CAPS);      << Extended capabilities   >>
  1875.      DATA(10):= TOCHAR(0);            << Windowing (none here)   >>
  1876.      DATA(11):= TOCHAR(LONGPACK'SIZE / 95);   << MAXL1           >>
  1877.      DATA(12):= TOCHAR(LONGPACK'SIZE MOD 95); << MAXL2           >>
  1878.      LEN := 13;
  1879. end;
  1880.  
  1881. <<----------------------------------------------------------->>
  1882.  
  1883. $PAGE "RPAR - Set Up Send RI Parameters"
  1884. subroutine RPAR(DATA,LEN);
  1885. value                LEN ;
  1886. integer              LEN ;
  1887. byte array      DATA     ;
  1888. begin
  1889.      MAX'SND'SIZE := UNCHAR(DATA(0));  << Max send size          >>
  1890.   !  MAX'SND'DATA := MAX'SND'SIZE -3;  << Max send data size     >>
  1891.      YOUR'TO := UNCHAR(DATA(1));       << When I time you out    >>
  1892.      YOUR'PAD'COUNT := UNCHAR(DATA(2));<< Number of pads to send >>
  1893.      YOUR'PAD := CTL(DATA(3));         << Your Pad char          >>
  1894.      YOUR'EOL := UNCHAR(DATA(4));      << Your end-of-line       >>
  1895.      YOUR'Q'CTL := integer(DATA(5));   << Your control quote     >>
  1896.  
  1897.      QUOTE'8 := false;
  1898.      if LEN > 6 then
  1899.      begin
  1900.           if (DATA(6) = "Y") lor (integer(DATA(6)) = P'Q'8) then
  1901.           begin
  1902.                Q'8 := P'Q'8;
  1903.                QUOTE'8 := true;
  1904.           end;
  1905.      end;
  1906.  
  1907.      if LEN > 7  then
  1908.      YOUR'BLK'CK := DATA(7)
  1909.           else
  1910.      YOUR'BLK'CK := "1";  << No block check -> one-byte check >>
  1911.  
  1912.      if LEN > 8 and integer(DATA(8)) = P'RPT'CHR then
  1913.      begin
  1914.           RPT'CHR := P'RPT'CHR;
  1915.           USE'REPEAT := true;          << OK for repeat prefix   >>
  1916.      end
  1917.           else
  1918.      begin
  1919.           USE'REPEAT := false;         << No repeat processing   >>
  1920.      end;
  1921.  
  1922.      if LEN >= 12  then
  1923.      begin     << Other side agrees to long packets, maybe >>
  1924.           YOUR'CAPS :=
  1925.              byte( logical(UNCHAR(DATA(9))) land logical(MY'CAPS) );
  1926.           << Windowing, DATA(10), is unsupported in this prog >>
  1927.           TEMP := 95*UNCHAR(DATA(11)) + UNCHAR(DATA(12));
  1928.           if TEMP > MAX'SND'SIZE  then
  1929.           begin
  1930.                if TEMP < MAX'LONGPACK'SIZE  then
  1931.                     LONGPACK'SIZE := TEMP-5-integer(YOUR'BLK'CK-"0")
  1932.                else
  1933.                     LONGPACK'SIZE := MAX'LONGPACK'SIZE;
  1934.           end
  1935.                else
  1936.           LONGPACK'SIZE := 0;
  1937.      end
  1938.           else
  1939.      LONGPACK'SIZE := 0;       << Long packets disallowed >>
  1940. end;
  1941. $PAGE "SINIT - Perform Send Init"
  1942. byte subroutine SINIT;
  1943. begin
  1944.  
  1945.      <<----------------------------------------------------------->>
  1946.  
  1947.      SINIT := STATE;  << Default to return current state >>
  1948.      NUMTRY := NUMTRY + 1;
  1949.      if NUMTRY > MAXTRY then
  1950.      begin
  1951.           E'ST "SINIT - Max retrys exceeded" E'EN;
  1952.           SINIT := "A"; << Abort >>
  1953.      end
  1954.           else
  1955.      begin
  1956.           SPAR(RP'DATA,RP'LEN);         << Set up SI data >>
  1957.           N := 0;                       << Start packets at zero >>
  1958.           SPACK("S",N,RP'LEN,RP'DATA);  << And send it    >>
  1959.  
  1960.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  1961.           begin
  1962.                if RP = "Y" then
  1963.                begin
  1964.                     if RP'NUM = N then
  1965.                     begin  << Positive response >>
  1966.                          RPAR(RP'DATA,RP'LEN);  << Get parameters >>
  1967.                          if  YOUR'BLK'CK <> "1"  and
  1968.                              YOUR'BLK'CK <> "3"  then
  1969.                          begin   << Whatever that was, I can't do it >>
  1970.                               MY'BLK'CK := "1";  << Lets try again >>
  1971.                               N := 0;
  1972.                               SINIT := "S";
  1973.                          end
  1974.                               else
  1975.                          begin  <<  OK, let's try it your way  >>
  1976.                               MY'BLK'CK := YOUR'BLK'CK;
  1977.                               MAX'SND'DATA := MAX'SND'SIZE -
  1978.                                              3-integer(YOUR'BLK'CK-"0");
  1979.                               NUMTRY := 0;
  1980.                               N := NPNO(N);
  1981.                               SINIT:= "F";
  1982.                          end;
  1983.                     end;
  1984.                end
  1985.                     else
  1986.                if RP = "E" then
  1987.                begin << Error packet >>
  1988.                     E'ST "SINIT - E packet recieved" E'EN;
  1989.                     P'EPACK(RP'DATA,RP'LEN);
  1990.                     SINIT := "A";
  1991.                end;
  1992.           end;
  1993.      end;
  1994. end;
  1995. $PAGE "SFILE - Send File Header"
  1996. byte subroutine SFILE;
  1997. begin
  1998.  
  1999.  
  2000.      <<----------------------------------------------------------->>
  2001.  
  2002.      SFILE := STATE;  << Default to current state >>
  2003.      NUMTRY := NUMTRY + 1;
  2004.      if NUMTRY > MAXTRY then
  2005.      begin
  2006.           E'ST "SFILE - Max retrys exceeded" E'EN;
  2007.           SFILE := "A"; << Abort >>
  2008.      end
  2009.           else
  2010.      begin
  2011.           if SFNLEN = 0 then
  2012.                SPACK("X",N,0,SFNAME)  << Header only >>
  2013.           else
  2014.                SPACK("F",N,SFNLEN,SFNAME); << Normal file >>
  2015.  
  2016.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  2017.           begin
  2018.                if RP = "Y" then
  2019.                begin
  2020.                     if RP'NUM = N then
  2021.                     begin
  2022.                          DBUFCNT := 0; << Set disc buf empty >>
  2023.                          DBUFINX := 1; << Index=get next     >>
  2024.  
  2025.                          BUFILL(PDATA,PDATACNT,BFSTAT);
  2026.                          if BFSTAT = 0 then
  2027.                          begin
  2028.                               NUMTRY := 0;
  2029.                               N := NPNO(N);
  2030.                               SFILE := "D";
  2031.                          end
  2032.                               else
  2033.                          begin
  2034.                               E'ST "SFILE - BUFILL error" E'EN;
  2035.                               SFILE := "A";
  2036.                          end;
  2037.                     end;
  2038.                end
  2039.                     else
  2040.                if RP = "E" then
  2041.                begin
  2042.                     P'EPACK(RP'DATA,RP'LEN);
  2043.                     SFILE := "A";
  2044.                end
  2045.                     else
  2046.                if RP <> "N" then
  2047.                begin
  2048.                     SFILE := "A";
  2049.                     E'ST "SFILE - Unknown packet type" E'EN;
  2050.                end;
  2051.           end;
  2052.      end;
  2053. end;
  2054. <<****************************************************************>>
  2055. $PAGE "SDATA - Send Data Packet"
  2056. byte subroutine SDATA;
  2057. begin
  2058.  
  2059.      SDATA := STATE; << Default is return current state >>
  2060.  
  2061.      NUMTRY := NUMTRY + 1;
  2062.      if NUMTRY > MAXTRY then
  2063.      begin
  2064.           SDATA := "A";
  2065.           E'ST "SDATA - Retry count exceeded" E'EN;
  2066.      end
  2067.           else
  2068.      begin
  2069.           SPACK("D",N,PDATACNT,PDATA);
  2070.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  2071.           begin
  2072.                if RP = "Y" then
  2073.                begin
  2074.                     if RP'NUM = N then
  2075.                     begin
  2076.                          NUMTRY := 0;
  2077.                          N := NPNO(N);
  2078.                          BUFILL(PDATA,PDATACNT,BFSTAT);
  2079.                          if BFSTAT <> 0 then
  2080.                          begin
  2081.                               SDATA := "Z";
  2082.                               FCLOSE(DNUM,0,0);
  2083.                               DNUM := 0;
  2084.                          end;
  2085.                     end;
  2086.                end
  2087.                     else
  2088.                if RP = "E" then
  2089.                begin
  2090.                     E'ST "SDATA - E packet recieved" E'EN;
  2091.                     P'EPACK(RP'DATA,RP'LEN);
  2092.                     SDATA := "A";
  2093.                end
  2094.                     else
  2095.                if RP <> "N" then
  2096.                begin
  2097.                     SDATA := "A";
  2098.                     E'ST "SDATA - Unknown Packet Type" E'EN;
  2099.                end;
  2100.           end;
  2101.      end;
  2102. end;
  2103. $PAGE "SEOF - Send EOF"
  2104. byte subroutine SEOF;
  2105. begin
  2106.  
  2107.      SEOF := STATE;
  2108.      NUMTRY := NUMTRY + 1;
  2109.      if NUMTRY > MAXTRY then
  2110.      begin
  2111.           E'ST "SEOF - Max retrys exceeded" E'EN;
  2112.           SEOF := "A";
  2113.      end
  2114.           else
  2115.      begin
  2116.           SPACK("Z",N,0,RP'DATA);
  2117.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  2118.           begin
  2119.                if RP = "Y" then
  2120.                begin
  2121.                     if RP'NUM = N then
  2122.                     begin
  2123.                          NUMTRY := 0;
  2124.                          N := NPNO(N);
  2125.                          SEOF := "B";
  2126.                     end;
  2127.                end
  2128.                     else
  2129.                if RP = "E" then
  2130.                begin
  2131.                     E'ST "SEOF - E packet recieved" E'EN;
  2132.                     P'EPACK(RP'DATA,RP'LEN);
  2133.                     SEOF := "A";
  2134.                end
  2135.                     else
  2136.                if RP <> "N" then
  2137.                begin
  2138.                     SEOF := "A";
  2139.                     E'ST "SEOF - Unknown packet type" E'EN;
  2140.                end;
  2141.           end;
  2142.      end;
  2143. end;
  2144.  
  2145. $PAGE "SENDSW - Send Switch (Main Code)"
  2146.  
  2147. <<****************************************************************>>
  2148.  
  2149.      MY'JCW'VAL := SENDING;
  2150.      PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  2151.      if  IMPATIENT  then
  2152.      begin
  2153.           MY'TO := FAST'TO;
  2154.           MAXTRY := FAST'MAXTRY;
  2155.      end
  2156.           else
  2157.      begin
  2158.           MY'TO := DFLT'TO;
  2159.           MAXTRY := DFLT'MAXTRY;
  2160.      end;
  2161.  
  2162.  
  2163.      NUMTRY := 0;
  2164.      if SFNLEN <= 0  then
  2165.      begin
  2166.           STATE := "S"; << Normal file send >>
  2167.           SFNLEN := -SFNLEN;   << Make positive again >>
  2168.      end
  2169.      else
  2170.           STATE := "F"; << Sending text, skip SI >>
  2171.  
  2172.      if SND'BINARY = 1 then
  2173.      begin << Always binary >>
  2174.           IMAGE := true;
  2175.      end
  2176.           else
  2177.      if SND'BINARY = 2 then
  2178.      begin << Always ASCII >>
  2179.           IMAGE := false;
  2180.      end
  2181.           else
  2182.      begin << Auto, check file >>
  2183.           FGETINFO(DNUM,,FOPT);
  2184.           if (FOPT land %4) <> 0 then
  2185.                IMAGE := false
  2186.           else
  2187.                IMAGE := true;
  2188.      end;
  2189.  
  2190.      while not (DONE lor CTLY) do
  2191.      begin
  2192.           if STATE = "S" then STATE := SINIT
  2193.                else
  2194.           if STATE = "F" then STATE := SFILE
  2195.                else
  2196.           if STATE = "D" then STATE := SDATA
  2197.                else
  2198.           if STATE = "Z" then STATE := SEOF
  2199.                else
  2200.           IF STATE="B" then
  2201.           begin
  2202.                STATE := "C";
  2203.                DONE := true;
  2204.           end
  2205.                else
  2206.           begin
  2207.                DONE := true;
  2208.           end;
  2209.      end;
  2210.  
  2211.      if DNUM <> 0 then
  2212.      begin
  2213.           FCLOSE(DNUM,0,0);
  2214.           DNUM := 0;
  2215.      end;
  2216.      if STATE = "C" then
  2217.      begin
  2218.           MY'JCW'VAL:=SEND'OK;
  2219.           SENDSW := true
  2220.      end
  2221.           else
  2222.      begin
  2223.           MY'JCW'VAL:=SEND'NG;
  2224.           SENDSW := false;
  2225.      end;
  2226. end;
  2227. $PAGE "R'RPAR - Receive Read RI Parms"
  2228. $control segment=R'RPAR'S
  2229. procedure R'RPAR(DATA,LEN);
  2230. value                 LEN ;
  2231. integer               LEN ;
  2232. byte array       DATA     ;
  2233. begin
  2234.      integer   TEMP;
  2235.  
  2236.      MAX'SND'SIZE := UNCHAR(DATA(0));  << Max send size          >>
  2237.      MAX'SND'DATA := MAX'SND'SIZE -3;  << Max send data size     >>
  2238.      YOUR'TO := UNCHAR(DATA(1));       << When I time you out    >>
  2239.      YOUR'PAD'COUNT := UNCHAR(DATA(2));<< Number of pads to send >>
  2240.      YOUR'PAD := CTL(DATA(3));         << Your Pad char          >>
  2241.      YOUR'EOL := UNCHAR(DATA(4));      << Your end-of-line       >>
  2242.      YOUR'Q'CTL := integer(DATA(5));   << Your control quote     >>
  2243.      if LEN > 6 and DATA(6) = "Y" then
  2244.      begin << I specify the quote >>
  2245.           Q8'IND := "Y";
  2246.           QUOTE'8 := true;
  2247.      end
  2248.           else
  2249.      if LEN > 6 and DATA(6) <> "N" then
  2250.      begin << Quote specified for me >>
  2251.           Q'8 := DATA(6);
  2252.           Q8'IND := " ";
  2253.           QUOTE'8 := true;
  2254.      end
  2255.           else
  2256.      begin << No 8 bit quoting >>
  2257.           QUOTE'8 := false;
  2258.      end;
  2259.  
  2260.      if LEN > 7  then
  2261.      begin
  2262.           YOUR'BLK'CK := DATA(7);
  2263.           if YOUR'BLK'CK = "1"  or
  2264.              YOUR'BLK'CK = "3"  then
  2265.           MY'BLK'CK := YOUR'BLK'CK  << Will do it your way >>
  2266.                else
  2267.           MY'BLK'CK := YOUR'BLK'CK := "1";  << The old way >>
  2268.      end
  2269.           else
  2270.      MY'BLK'CK := YOUR'BLK'CK := "1"; << No blk ck -> one-byte ck >>
  2271.  
  2272.      if LEN > 8 and DATA(8) <> " " then
  2273.      begin
  2274.           RPT'CHR := DATA(8);
  2275.           USE'REPEAT := true;
  2276.      end
  2277.           else
  2278.      begin
  2279.           USE'REPEAT := false;
  2280.      end;
  2281.      if LEN > 12  then          << Extended packet stuff >>
  2282.      begin
  2283.           YOUR'CAPS :=
  2284.              byte( logical(UNCHAR(DATA(9))) land logical(MY'CAPS) );
  2285.  
  2286.           << Windowing, DATA(10), is unsupported herein >>
  2287.  
  2288.           TEMP := UNCHAR(DATA(11))*95 + UNCHAR(DATA(12));
  2289.           if TEMP > MAX'LONGPACK'SIZE  then
  2290.                TEMP := MAX'LONGPACK'SIZE;
  2291.           LONGPACK'SIZE := TEMP-7-integer(YOUR'BLK'CK-"1");
  2292.      end
  2293.           else
  2294.      LONGPACK'SIZE := MAX'SND'SIZE-6;
  2295. end;
  2296.  
  2297. $PAGE "R'SPAR - Set up SEND Parameters"
  2298. $control segment=R'SPAR'S
  2299.  
  2300. procedure R'SPAR(DATA,LEN);
  2301. byte array       DATA     ;
  2302. integer               LEN ;
  2303. begin
  2304.      DATA(0) := TOCHAR(MAX'RCV'SIZE   << Biggest to send me      >>
  2305.                 + 1 - (MY'BLK'CK-"0"));
  2306.      DATA(1) := TOCHAR(MY'TO);        << When to time me out     >>
  2307.      DATA(2) := TOCHAR(0);            << How many pads I need    >>
  2308.      DATA(3) := byte(CTL(0));         << Pad char to use for me  >>
  2309.      DATA(4) := TOCHAR(CR);           << End-of-line char for me >>
  2310.      DATA(5) := MY'Q'CTL;             << Control quote I send    >>
  2311.      if QUOTE'8 then
  2312.      begin
  2313.           if Q8'IND = "Y" then
  2314.           begin  << I specify the char >>
  2315.                Q'8 := P'Q'8;
  2316.                DATA(6) := byte(P'Q'8);
  2317.           end
  2318.                else
  2319.           begin  << Already specified >>
  2320.                DATA(6) := "Y";
  2321.           end;
  2322.      end
  2323.           else
  2324.      begin
  2325.           DATA(6) := "N"; << No 8 bit quoting >>
  2326.      end;
  2327.  
  2328.      DATA(7) := MY'BLK'CK;
  2329.  
  2330.      if USE'REPEAT then
  2331.           DATA(8) := byte(RPT'CHR)
  2332.      else
  2333.           DATA(8) := " ";
  2334.  
  2335.      DATA(9) := TOCHAR(YOUR'CAPS);    << We negotiated this >>
  2336.  
  2337.      DATA(10):= TOCHAR(0);  << We don't do windows          >>
  2338.  
  2339.      DATA(11):= TOCHAR( (LONGPACK'SIZE / 95) );   << MAXL1 >>
  2340.      DATA(12):= TOCHAR( (LONGPACK'SIZE MOD 95) ); << MAXL2 >>
  2341.  
  2342.      LEN := 13;
  2343. end;
  2344.  
  2345. $PAGE "RECSW - Receive Switch (Definitions)"
  2346. $control segment=WORKER
  2347. logical procedure RECSW(SERVE);
  2348. value                   SERVE ;
  2349. logical                 SERVE ;
  2350. begin
  2351.  
  2352.      logical        DONE := false,
  2353.                     R'ERROR;
  2354.  
  2355.      integer        FOPT,    << File Options (calculated) >>
  2356.                     FN'LEN;  << File Name Length          >>
  2357.  
  2358.      equate         FN'MAX = 35;  << Max File Name Length >>
  2359.  
  2360.      byte array     FNAME(0:FN'MAX);
  2361.  
  2362.      <<----------------------------------------------------------->>
  2363.  
  2364. $PAGE "RINIT - Recieve Initialization"
  2365. byte subroutine RINIT;
  2366. begin
  2367.  
  2368.      <<---------------------------------------------------------->>
  2369.  
  2370.      RINIT := STATE;
  2371.      NUMTRY := NUMTRY + 1;
  2372.      if NUMTRY > MAXTRY then
  2373.      begin
  2374.           E'ST "RINIT - Retry count exceeded" E'EN;
  2375.           RINIT := "A";
  2376.      end
  2377.           else
  2378.      begin
  2379.           if ( R'ERROR := RPACK(RP,RP'LEN,RP'NUM,RP'DATA) )  then
  2380.           begin
  2381.                if RP = "S" then
  2382.                begin
  2383.                     R'RPAR(RP'DATA,RP'LEN);    << Read the others>>
  2384.                     R'SPAR(RP'DATA,RP'LEN);    << Generate ours  >>
  2385.                     SPACK("Y",N,RP'LEN,RP'DATA);  << Send it        >>
  2386.  
  2387.                     OLDTRY := NUMTRY; << Save trys >>
  2388.                     NUMTRY := 0;
  2389.                     N := NPNO(RP'NUM); << Syncronize >>
  2390.                     RINIT := "F"; << Switch to F mode >>
  2391.                end
  2392.                     else
  2393.                if RP = "E" then
  2394.                begin
  2395.                     E'ST "RINIT - E packet recieved" E'EN;
  2396.                     P'EPACK(RP'DATA,RP'LEN);
  2397.                     RINIT := "A";
  2398.                end
  2399.                     else
  2400.                if RP = "N" then
  2401.                begin
  2402.                     E'ST "RINIT - NAK packet recieved" E'EN;
  2403.                     P'EPACK(RP'DATA,RP'LEN);
  2404.                end
  2405.                     else
  2406.                begin
  2407.                     E'ST "RINIT - Unexpected packet type" E'EN;
  2408.                     RINIT := "A";
  2409.                end;
  2410.           end
  2411.                else
  2412.           begin
  2413.                if ( R'ERROR:=not(R'ERROR) ) <> 3 then <<no SOH found>>
  2414.                     SPACK("N",N,0,RP'DATA);
  2415.           end;
  2416.      end;
  2417. end;
  2418.  
  2419. <<****************************************************************>>
  2420.  
  2421. $PAGE "RFILE - Recieve a File Header"
  2422. byte subroutine RFILE;
  2423. begin
  2424.  
  2425.  
  2426.      RFILE := STATE;
  2427.      NUMTRY := NUMTRY + 1;
  2428.      if NUMTRY > MAXTRY then
  2429.      begin
  2430.           E'ST "RFILE - Retry count exceeded" E'EN;
  2431.           RFILE := "A";
  2432.      end
  2433.           else
  2434.      begin
  2435.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  2436.           begin  << Got a packet>>
  2437.                if RP = "S" then
  2438.                begin << Still in SI, perhaps ACK lost>>
  2439.                     OLDTRY := OLDTRY + 1;
  2440.                     if OLDTRY > MAXTRY then
  2441.                     begin
  2442.                          E'ST "RFILE - Pretry (S) exceeded" E'EN;
  2443.                          RFILE := "A";
  2444.                     end
  2445.                          else
  2446.                     if RP'NUM <> PPNO(N) then
  2447.                     begin << Number must match >>
  2448.                          E'ST "RFILE - N mismatch on S packet" E'EN;
  2449.                          RFILE := "A";
  2450.                     end
  2451.                          else
  2452.                     begin << OK, re-ACK the packet >>
  2453.                          R'SPAR(RP'DATA,RP'LEN);
  2454.                          SPACK("Y",RP'NUM,RP'LEN,RP'DATA);
  2455.                          NUMTRY := 0;
  2456.                     end;
  2457.                end
  2458.                     else
  2459.                if RP = "Z" then
  2460.                begin << End of file, previous packet (?) >>
  2461.                     OLDTRY := OLDTRY + 1;
  2462.                     if OLDTRY > MAXTRY then
  2463.                     begin
  2464.                          E'ST "RFILE - Pretry (Z) exceeded" E'EN;
  2465.                          RFILE := "A";
  2466.                     end
  2467.                          else
  2468.                     if RP'NUM <> PPNO(N) then
  2469.                     begin  << N must match >>
  2470.                          E'ST "RFILE - N mismatch on Z packet" E'EN;
  2471.                          RFILE := "A";
  2472.                     end
  2473.                          else
  2474.                     begin  << OK, re-ACK the packet >>
  2475.                          SPACK("Y",RP'NUM,0,RP'DATA);
  2476.                          NUMTRY := 0;
  2477.                     end;
  2478.                end
  2479.                     else
  2480.                if RP = "F" then
  2481.                begin << File header (what we expect) >>
  2482.                     if RP'NUM <> N then
  2483.                     begin  << Oops >>
  2484.                          E'ST "RFILE - N mismatch" E'EN;
  2485.                          RFILE := "A";
  2486.                     end
  2487.                          else
  2488.                     begin << OK, Open the file >>
  2489.  
  2490.                          if L'FNAME'LEN <> 0 then
  2491.                          begin
  2492.                               move FNAME := L'FNAME,(L'FNAME'LEN);
  2493.                               FN'LEN := L'FNAME'LEN;
  2494.                          end
  2495.                               else
  2496.                          begin
  2497.                               CBUFXLT(RP'DATA,RP'LEN,
  2498.                                         FNAME,FN'LEN,FN'MAX);
  2499.  
  2500.                               if not UNQFNAME(FNAME,FN'LEN) then
  2501.                               begin
  2502.                                    MAKE'U'FNAME(FNAME,FN'LEN);
  2503.                               end;
  2504.                          end;
  2505.  
  2506.                          FNAME(FN'LEN) := " ";
  2507.  
  2508.                          if RCV'BINARY then
  2509.                          begin << Binary mode >>
  2510.                               IMAGE := true;
  2511.                               FOPT := 0;
  2512.                          end
  2513.                               else
  2514.                          begin << ASCII mode >>
  2515.                               IMAGE := false;
  2516.                               FOPT := 4;
  2517.                          end;
  2518.  
  2519.                          if not RCV'FIXREC then
  2520.                               FOPT := FOPT + %100; << set variable >>
  2521.  
  2522.                          if RCV'RECLEN < 0 then
  2523.                               DBUF'RMAX := -RCV'RECLEN
  2524.                          else
  2525.                               DBUF'RMAX := RCV'RECLEN * 2;
  2526.  
  2527.                          if not VALID'FILE(FNAME, FN'LEN, IN) then
  2528.                          begin
  2529.                               E'ST "RFILE - file security error" E'EN;
  2530.                               RFILE := "A";
  2531.                               DNUM := 0;
  2532.                          end
  2533.                               else
  2534.                          begin
  2535.                               DNUM := FOPEN(FNAME,FOPT,1,
  2536.                                             RCV'RECLEN,
  2537.                                             RCV'DEV,,,
  2538.                                             RCV'BLOCKF,,
  2539.                                             RCV'MAXREC,
  2540.                                             RCV'MAXEXT,1,
  2541.                                             RCV'FCODE);
  2542.  
  2543.                               if DNUM = 0 then
  2544.                               begin << Can't open file >>
  2545.                                    E'ST "RFILE - Can't open file" E'EN;
  2546.                                    RFILE := "A";
  2547.                               end
  2548.                                    else
  2549.                               begin << OK >>
  2550.                                    MOVE RP'DATA := FNAME, (FN'LEN);
  2551.                                    RP'LEN := FN'LEN;
  2552.                                    SPACK("Y",N,RP'LEN,RP'DATA);
  2553.                                    OLDTRY := NUMTRY;
  2554.                                    NUMTRY := 0;
  2555.                                    N := NPNO(N);
  2556.                                    RFILE := "D";
  2557.                                    DBUFCNT := 0;
  2558.                                    DBUFINX := 0;
  2559.                               end;
  2560.                          end;
  2561.                     end;
  2562.                end
  2563.                     else
  2564.                if RP = "B" then
  2565.                begin << Break transmission >>
  2566.                     if RP'NUM <> N then
  2567.                     begin << Oops >>
  2568.                          E'ST "RFILE - (B) N mismatch" E'EN;
  2569.                          RFILE := "A";
  2570.                     end
  2571.                          else
  2572.                     begin
  2573.                          SPACK("Y",N,0,RP'DATA);
  2574.                          RFILE := "C";
  2575.                     end;
  2576.                end
  2577.                     else
  2578.                if RP = "E" then
  2579.                begin
  2580.                     E'ST "RFILE - E packet recieved" E'EN;
  2581.                     P'EPACK(RP'DATA,RP'LEN);
  2582.                     RFILE := "A";
  2583.                end
  2584.                     else
  2585.                begin
  2586.                     E'ST "RFILE - Unknown packet type" E'EN;
  2587.                     RFILE := "A";
  2588.                end;
  2589.           end << Got a packet >>
  2590.                else
  2591.           begin
  2592.                SPACK("N",N,0,RP'DATA);  << No (readable) packet >>
  2593.           end;
  2594.      end;
  2595. end;
  2596.  
  2597. <<*****************************************************************>>
  2598.  
  2599. $PAGE "RDATA - Recieve Data"
  2600. byte subroutine RDATA;
  2601. begin
  2602.  
  2603.      RDATA := STATE;
  2604.      NUMTRY := NUMTRY + 1;
  2605.      if NUMTRY > MAXTRY then
  2606.      begin
  2607.           E'ST "RDATA - Retry count exceeded" E'EN;
  2608.           RDATA := "A";
  2609.      end
  2610.           else
  2611.      begin
  2612.           MY'TO := 10 + LONGPACK'SIZE/TSPEED; << Rcv timeout >>
  2613.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) then
  2614.           begin
  2615.                if RP = "D" then
  2616.                begin  << Good, what we expect >>
  2617.                     if RP'NUM <> N then
  2618.                     begin  << Oops, not this packet >>
  2619.                          OLDTRY := OLDTRY + 1;
  2620.                          if OLDTRY > MAXTRY then
  2621.                          begin
  2622.                               E'ST "RDATA - Pretry exceeded" E'EN;
  2623.                               RDATA := "A";
  2624.                          end
  2625.                               else
  2626.                          if RP'NUM = PPNO(N) then
  2627.                          begin  << Already have this one >>
  2628.                               SPACK("Y",RP'NUM,0,RP'DATA); << Re-ACK >>
  2629.                               NUMTRY := 0;
  2630.                          end
  2631.                               else
  2632.                          begin
  2633.                               E'ST "RDATA - N (D) mismatch" E'EN;
  2634.                               RDATA := "A";
  2635.                          end;
  2636.                     end << Wrong packet >>
  2637.                          else
  2638.                     begin << Got the one we want >>
  2639.                          BUFEMP(RP'DATA,RP'LEN);  << Process >>
  2640.                          SPACK("Y",N,0,RP'DATA);  << and ACK >>
  2641.                          OLDTRY := NUMTRY;
  2642.                          NUMTRY := 0;
  2643.                          N := NPNO(N);
  2644.                     end;
  2645.                end << RP = "D" >>
  2646.                     else
  2647.                if RP = "F" then
  2648.                begin << File header >>
  2649.                     OLDTRY := OLDTRY + 1;
  2650.                     if OLDTRY > MAXTRY then
  2651.                     begin
  2652.                          E'ST "RDATA - Pretry (F) exceeded" E'EN;
  2653.                          RDATA := "A";
  2654.                     end
  2655.                          else
  2656.                     if RP'NUM <> PPNO(N) then
  2657.                     begin << Oops >>
  2658.                          E'ST "RDATA - N (F) mismatch" E'EN;
  2659.                          RDATA := "A";
  2660.                     end
  2661.                          else
  2662.                     begin << OK >>
  2663.                          SPACK("Y",RP'NUM,0,RP'DATA); << ReACK >>
  2664.                          NUMTRY := 0;
  2665.                     end;
  2666.                end << RP = "F" >>
  2667.                     else
  2668.                if RP = "Z" then
  2669.                begin << End of File >>
  2670.                     if RP'NUM <> N then
  2671.                     begin
  2672.                          E'ST "RDATA - N (Z) mismatch" E'EN;
  2673.                          RDATA := "A";
  2674.                     end
  2675.                          else
  2676.                     begin
  2677.                          if DBUFINX > 0 then
  2678.                               FLUSH'DBUF;
  2679.  
  2680.                          if RCV'SAVESP then
  2681.                               FCLOSE(DNUM,%11,0)
  2682.                          else
  2683.                               FCLOSE(DNUM,1,0);
  2684.  
  2685.                          DNUM := 0;
  2686.                          SPACK("Y",N,0,RP'DATA); << ACK >>
  2687.                          L'FNAME'LEN := 0;
  2688.                          N := NPNO(N);
  2689.                          RDATA := "F";
  2690.                     end;
  2691.                end << RP = "Z" >>
  2692.                     else
  2693.                if RP = "E" then
  2694.                begin
  2695.                     E'ST "RDATA - E packet recieved" E'EN;
  2696.                     P'EPACK(RP'DATA,RP'LEN);
  2697.                     RDATA := "A";
  2698.                end
  2699.                     else
  2700.                begin
  2701.                     E'ST "RDATA - Unknown packet type" E'EN;
  2702.                     RDATA := "A";
  2703.                end;
  2704.           end << Got packet >>
  2705.                else
  2706.           begin
  2707.                SPACK("N",N,0,RP'DATA);  << NAK >>
  2708.           end;
  2709.      end;
  2710. end;
  2711. $PAGE "RECSW - Main Code"
  2712. <<*****************************************************************>>
  2713.  
  2714.      MY'JCW'VAL := RECVING;
  2715.      PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  2716.      if  IMPATIENT  then
  2717.      begin
  2718.           MY'TO := FAST'TO;
  2719.           MAXTRY := FAST'MAXTRY;
  2720.      end
  2721.           else
  2722.      begin
  2723.           MY'TO := DFLT'TO;
  2724.           MAXTRY := DFLT'MAXTRY;
  2725.      end;
  2726.  
  2727.      if not SERVE then
  2728.      begin
  2729.           STATE := "R";
  2730.           N := 0;
  2731.           NUMTRY := 0;
  2732.      end
  2733.           else
  2734.      begin
  2735.           STATE := "F";
  2736.      end;
  2737.  
  2738.      while not (DONE lor CTLY) do
  2739.      begin
  2740.           if STATE = "R" then STATE := RINIT
  2741.                else
  2742.           if STATE = "F" then STATE := RFILE
  2743.                else
  2744.           if STATE = "D" then STATE := RDATA
  2745.                else
  2746.           if STATE = "C" then
  2747.           begin
  2748.                DONE := true;
  2749.                RECSW := true;
  2750.           end
  2751.                else
  2752.           if STATE = "A" then
  2753.           begin
  2754.                DONE := true;
  2755.                RECSW := false;
  2756.           end;
  2757.      end;
  2758.  
  2759.      if DNUM <> 0 then
  2760.      begin
  2761.           FCLOSE(DNUM,0,0);
  2762.           DNUM := 0;
  2763.      end;
  2764.      if STATE="C" then
  2765.           MY'JCW'VAL:=RECV'OK
  2766.      else
  2767.           MY'JCW'VAL:=RECV'NG;
  2768.      MY'TO := DFLT'TO;
  2769. end;
  2770. <<****************************************************************>>
  2771. $control segment=TYPESW'S
  2772. $PAGE "TYPESW - Type a file on the terminal"
  2773. logical procedure TYPESW;
  2774. begin
  2775.      logical        DONE := false;
  2776.  
  2777.      if VALID'FILE(L'FNAME, L'FNAME'LEN, OUT) then
  2778.           else
  2779.      begin
  2780.           M'ST ("Kermit file security error - ",
  2781.                 "see your account manager") M'EN;
  2782.           TYPESW := false;
  2783.           return;
  2784.      end;
  2785.  
  2786.      DNUM := FOPEN(L'FNAME, 5, 0);
  2787.      if DNUM = 0 then
  2788.      begin
  2789.           M'ST "File open failure" M'EN;
  2790.           TYPESW := false;
  2791.           return;
  2792.      end;
  2793.  
  2794.      while not(DONE lor CTLY) do
  2795.      begin
  2796.           DBUFCNT := FREAD(DNUM, W'DBUF, -DBUF'BYTESIZE);
  2797.           if < then
  2798.           begin  << Read error >>
  2799.                M'ST "TYPESW - read error" M'EN;
  2800.                TYPESW := false;
  2801.                DONE := true;
  2802.           end
  2803.                else
  2804.           if > then
  2805.           begin  << EOF >>
  2806.                TYPESW := DONE := true;
  2807.           end
  2808.                else
  2809.                FWRITE(CONUM, W'DBUF, -DBUFCNT, 0);
  2810.      end;
  2811.      FCLOSE(DNUM, 0, 0);
  2812.      DNUM := 0;
  2813.      if CTLY then
  2814.           TYPESW := false;
  2815. end;
  2816.  
  2817. <<*****************************************************************>>
  2818.  
  2819. $PAGE "OPEN'LINE - Open Communications Line"
  2820. $control segment=OPEN'LINE'S
  2821. logical procedure OPEN'LINE;
  2822. begin
  2823.  
  2824.      logical        R'ERROR := false,
  2825.                     TEMP;
  2826.  
  2827.      integer        DEV'L;
  2828.  
  2829.      byte array     A'DEV(0:11);
  2830.  
  2831.      <<************************************************************>>
  2832.  
  2833.      if LNUM = 0 then
  2834.      begin << Line not open >>
  2835.           if LDEV'LINE = 0 then
  2836.           begin
  2837.                E'ST "Line not specified or defaultable" E'EN;
  2838.                R'ERROR := true;
  2839.           end
  2840.                else
  2841.           begin
  2842.                move PBUF := "SETMSG OFF",2;
  2843.                PLEN := TOS - @PBUF;
  2844.                PBUF(PLEN) := CR;
  2845.                COMMAND(PBUF,PLEN,DEV'L);
  2846.  
  2847.                move A'DEV := "000 ";
  2848.                ASCII(LDEV'LINE, -10, A'DEV(2));
  2849. !
  2850.                LNUM := FOPEN( , %500, %4, LBUF'WORDSIZE, A'DEV);
  2851. IF <> THEN IF LOGNUM<>0 THEN
  2852. BEGIN
  2853.      FCHECK(LNUM, R'ERROR);
  2854.      MOVE PBUF:="OPEN'LINE:  FOPEN ERROR ", 2; PLEN:=TOS-@PBUF;
  2855.      PLEN:=PLEN+ASCII(R'ERROR, 10, R'ERROR);
  2856.      WRITE'LOG(PBUF, PLEN, 0);
  2857.      R'ERROR:=TRUE;
  2858. END;
  2859.                if LNUM = 0 then
  2860.                begin
  2861.                     E'ST "FOPEN error on communications port" E'EN;
  2862.                     R'ERROR := true;
  2863.                end
  2864.                     else
  2865.                begin << Set up the line >>
  2866.                     if HNDSHK = 0 then
  2867.                          TTYPE := 18
  2868.                     else
  2869.                          TTYPE := DFLT'TTYPE;
  2870.  
  2871.                     FCONTROL(LNUM,39,ORGL'TTYPE);
  2872.                     IF <> THEN IF LOGNUM>0
  2873.                       THEN BEGIN
  2874.                         FCHECK(LNUM, TEMP);
  2875.                         E'ST  "FCONTROL 39 PROBLEM"  E'EN;
  2876.                         FERRMSG(TEMP, PBUF, PLEN);
  2877.                         WRITE'LOG(PBUF, PLEN, -2);
  2878.                       END;
  2879.                     FCONTROL(LNUM,38,TTYPE);
  2880.                     IF <> THEN IF LOGNUM>0
  2881.                       THEN BEGIN
  2882.                         FCHECK(LNUM, TEMP);
  2883.                         E'ST  "FCONTROL 38 PROBLEM"  E'EN;
  2884.                         FERRMSG(TEMP, PBUF, PLEN);
  2885.                         WRITE'LOG(PBUF, PLEN, -2);
  2886.                       END;
  2887.  
  2888.                     FCONTROL(LNUM,13,ORGL'ECHO);
  2889.                     IF <> THEN IF LOGNUM>0
  2890.                       THEN BEGIN
  2891.                         FCHECK(LNUM, TEMP);
  2892.                         E'ST  "FCONTROL 13 PROBLEM"  E'EN;
  2893.                         FERRMSG(TEMP, PBUF, PLEN);
  2894.                         WRITE'LOG(PBUF, PLEN, -2);
  2895.                       END;
  2896.  
  2897.                     if TSPEED <> 0 then
  2898.                     begin
  2899.                          ORGL'TISPEED := TSPEED;
  2900.                          FCONTROL(LNUM,10,ORGL'TISPEED);
  2901.                          IF <> THEN IF LOGNUM>0
  2902.                            THEN BEGIN
  2903.                              FCHECK(LNUM, TEMP);
  2904.                              E'ST  "FCONTROL 10 PROBLEM"  E'EN;
  2905.                              FERRMSG(TEMP, PBUF, PLEN);
  2906.                              WRITE'LOG(PBUF, PLEN, -2);
  2907.                            END;
  2908.                          ORGL'TOSPEED := TSPEED;
  2909.                          FCONTROL(LNUM,11,ORGL'TOSPEED);
  2910.                          IF <> THEN IF LOGNUM>0
  2911.                            THEN BEGIN
  2912.                              FCHECK(LNUM, TEMP);
  2913.                              E'ST  "FCONTROL 11 PROBLEM"  E'EN;
  2914.                              FERRMSG(TEMP, PBUF, PLEN);
  2915.                              WRITE'LOG(PBUF, PLEN, -2);
  2916.                            END;
  2917.                     end
  2918.                          else
  2919.                     FCONTROL(LNUM,40,TSPEED); << Get speed >>
  2920.                     IF <> THEN IF LOGNUM>0
  2921.                       THEN BEGIN
  2922.                         FCHECK(LNUM, TEMP);
  2923.                         E'ST  "FCONTROL 40 PROBLEM"  E'EN;
  2924.                         FERRMSG(TEMP, PBUF, PLEN);
  2925.                         WRITE'LOG(PBUF, PLEN, -2);
  2926.                       END;
  2927.  
  2928.                     FSETMODE(LNUM,4); << Inhibit LF >>
  2929.                     IF <> THEN IF LOGNUM>0
  2930.                       THEN BEGIN
  2931.                         FCHECK(LNUM, TEMP);
  2932.                         E'ST  "FSETMODE 4 PROBLEM"  E'EN;
  2933.                         FERRMSG(TEMP, PBUF, PLEN);
  2934.                         WRITE'LOG(PBUF, PLEN, -2);
  2935.                       END;
  2936.  
  2937.                     if HNDSHK = 2 then
  2938.                     begin << Set XON as termination char >>
  2939.                          TEMP := XON;
  2940.                          FCONTROL(LNUM,25,TEMP);
  2941.                     IF <> THEN IF LOGNUM>0
  2942.                       THEN BEGIN
  2943.                         FCHECK(LNUM, TEMP);
  2944.                         E'ST  "FCONTROL 25 PROBLEM"  E'EN;
  2945.                         FERRMSG(TEMP, PBUF, PLEN);
  2946.                         WRITE'LOG(PBUF, PLEN, -2);
  2947.                       END;
  2948.                     end;
  2949.  
  2950.  
  2951.                     TEMP:=MY'EOL cat CTL("Y") (0:8:8);
  2952.                     FCONTROL(LNUM, 41, TEMP); <<Almost transparent rx>>
  2953.                     IF <> THEN IF LOGNUM>0
  2954.                       THEN BEGIN
  2955.                         FCHECK(LNUM, TEMP);
  2956.                         E'ST  "FCONTROL 41 PROBLEM"  E'EN;
  2957.                         FERRMSG(TEMP, PBUF, PLEN);
  2958.                         WRITE'LOG(PBUF, PLEN, -2);
  2959.                       END;
  2960.  
  2961.  
  2962.                     if (LDEV'CI = LDEV'LINE) land
  2963.                        (LOGNUM = CONUM)           then LOGNUM := 0;
  2964.                end;
  2965.           end;
  2966.      end;
  2967.  
  2968.      OPEN'LINE := not R'ERROR;
  2969. end;
  2970.  
  2971. $PAGE "SHUT'LINE - Close Communications Line"
  2972. $control segment=SHUT'LINE'S
  2973. procedure SHUT'LINE;
  2974. begin
  2975.  
  2976.      logical   TEMP;
  2977.  
  2978.      <<************************************************************>>
  2979.  
  2980.      if LNUM <> 0 then
  2981.      begin << Line is open >>
  2982.           FSETMODE(LNUM,0);  << Turn on linefeed >>
  2983.  
  2984.           if ORGL'TTYPE <> TTYPE then
  2985.                FCONTROL(LNUM,38,ORGL'TTYPE);
  2986.  
  2987.           if TSPEED <> 0 then
  2988.           begin
  2989.                if ORGL'TISPEED <> TSPEED then
  2990.                begin
  2991.                     TEMP := ORGL'TISPEED;
  2992.                     FCONTROL(LNUM,10,TEMP);
  2993.                end;
  2994.                if ORGL'TOSPEED <> TSPEED then
  2995.                begin
  2996.                     TEMP := ORGL'TOSPEED;
  2997.                     FCONTROL(LNUM,11,TEMP);
  2998.                end;
  2999.           end;
  3000. !        TEMP:=0;  FCONTROL(LNUM, 41, TEMP);
  3001.  
  3002.           if ORGL'ECHO = 0 then
  3003.                FCONTROL(LNUM,12,TEMP);
  3004.  
  3005.           if HNDSHK = 2 then
  3006.           begin
  3007.                TEMP := 0;
  3008.                FCONTROL(LNUM,25,TEMP);
  3009.           end;
  3010.  
  3011.  
  3012.           FCLOSE(LNUM,0,0);
  3013.           LNUM := 0;
  3014.  
  3015.           if LOGNUM = 0 then LOGNUM := CONUM;
  3016.  
  3017.           move PBUF := "SETMSG ON",2;
  3018.           PLEN := TOS - @PBUF;
  3019.           PBUF(PLEN) := CR;
  3020.           COMMAND(PBUF,PLEN,TEMP);
  3021.      end;
  3022. end;
  3023.  
  3024. $PAGE "Temporary File Allocation/Deletion"
  3025. $control segment=KILL'TEMP'S
  3026. procedure KILL'KTEMP;
  3027. begin
  3028.      integer    TNUM,  << Temp file number >>
  3029.                 X;     << Temp variable    >>
  3030.  
  3031.      byte array TBUF(0:79);
  3032.  
  3033.      move TBUF := "RESET ",2;
  3034.      move * := KTEMP'NAME,2;
  3035.      X := TOS - @TBUF;
  3036.      TBUF(X) := CR;
  3037.      COMMAND(TBUF,TNUM,X);  << Reset file equate >>
  3038.  
  3039.      move TBUF := KTEMP'NAME,2;
  3040.      X := TOS - @TBUF;
  3041.      TBUF(X) := " ";
  3042.  
  3043.      TNUM := FOPEN(TBUF,7,4);  << Try to open it >>
  3044.      if TNUM <> 0 then
  3045.           FCLOSE(TNUM,4,0); << Kill it >>
  3046.      HAVE'KTEMP := false;
  3047. end;
  3048.  
  3049. $PAGE
  3050. $control segment=GET'TEMP'S
  3051. procedure GET'KTEMP;
  3052. begin
  3053.      integer   TNUM,  << Temp file number >>
  3054.                X;     << Temp variable    >>
  3055.  
  3056.      byte array TBUF(0:79);
  3057.  
  3058.      KILL'KTEMP; << Delete any old one >>
  3059.      TNUM := FOPEN(KT'NAME,4,4,-80,,,,16,,2048d,8,1); << Open new >>
  3060.      if TNUM <> 0 then
  3061.      begin
  3062.           FCLOSE(TNUM,2,0); << Save as temporary >>
  3063.           if = then
  3064.           begin
  3065.                move TBUF := "FILE ",2;
  3066.                move * := KTEMP'NAME,2;
  3067.                move * := ",OLDTEMP",2;
  3068.                X := TOS - @TBUF;
  3069.                TBUF(X) := CR;
  3070.                COMMAND(TBUF,X,TNUM);
  3071.                if X = 0 then
  3072.                     HAVE'KTEMP := true;
  3073.           end;
  3074.      end;
  3075. end;
  3076. $PAGE "HOST'COMMAND - Process an HP 3000 Command"
  3077. $control segment=HOST'COMMAND'S
  3078. procedure HOST'COMMAND(CMD,CMD'LEN,LONG'REPLY);
  3079. value                      CMD'LEN,LONG'REPLY ;
  3080. byte array             CMD                    ;
  3081. integer                    CMD'LEN            ;
  3082. logical                            LONG'REPLY ;
  3083. begin
  3084.  
  3085.      byte array     CMD'BUF(0:79);
  3086.  
  3087.      logical        CMD'ERR := false;
  3088.  
  3089.      integer        CI'ERNO,
  3090.                     CI'PARM;
  3091.  
  3092.      <<------------------------------------------------------------>>
  3093.  
  3094.      move CMD'BUF := CMD,(CMD'LEN);
  3095.      if LONG'REPLY then
  3096.      begin
  3097.           GET'KTEMP;
  3098.           if not HAVE'KTEMP then
  3099.           begin
  3100.                move CMD'BUF := "Unable to allocate temp file",2;
  3101.                CMD'LEN := TOS - @CMD'BUF;
  3102.                SPACK("E",N,CMD'LEN,CMD'BUF);
  3103.                CMD'ERR := true;
  3104.           end;
  3105.      end;
  3106.  
  3107.      if not CMD'ERR then
  3108.      begin
  3109.           CMD'BUF(CMD'LEN) := CR;
  3110.           COMMAND(CMD'BUF,CI'ERNO,CI'PARM);  << Issue the command >>
  3111.           if CI'ERNO <> 0 then
  3112.           begin  << Command Interpreter error >>
  3113.                move CMD'BUF := "Command Error, CIERROR = ",2;
  3114.                CMD'LEN := TOS - @CMD'BUF;
  3115.                CMD'LEN := CMD'LEN + ASCII(CI'ERNO,10,CMD'BUF(CMD'LEN));
  3116.                SPACK("E",N,CMD'LEN,CMD'BUF);
  3117.                CMD'ERR := true;
  3118.           end
  3119.                else
  3120.           begin << Command OK  >>
  3121.                if LONG'REPLY then
  3122.                begin
  3123.                     DNUM := FOPEN(KT'NAME,6,0);
  3124.                     if DNUM = 0 then
  3125.                     begin << Temp file open error >>
  3126.                          move CMD'BUF := "Temp file open failure",2;
  3127.                          CMD'LEN := TOS - @CMD'BUF;
  3128.                          SPACK("E",N,CMD'LEN,CMD'BUF);
  3129.                          CMD'ERR := true;
  3130.                     end
  3131.                          else
  3132.                     begin
  3133.                          SENDSW(CMD'BUF,0);
  3134.                          STATE := SBREAK;
  3135.                     end;
  3136.                end
  3137.                     else
  3138.                begin << Short reply >>
  3139.                     SPACK("Y",N,0,CMD'BUF);
  3140.                end;
  3141.           end;
  3142.      end;
  3143. end;
  3144. $PAGE "KERMIT'COMMAND - Process Generic KERMIT Command"
  3145. $control segment=KERMIT'COMMAND'S
  3146. procedure KERMIT'COMMAND(KCMD,KCMD'LEN);
  3147. value                         KCMD'LEN ;
  3148. byte array               KCMD          ;
  3149. integer                       KCMD'LEN ;
  3150. begin
  3151.  
  3152.      byte array     KC'BUF(0:79);
  3153.  
  3154.      array          INTRINSIC'STATUS(0:2);
  3155.  
  3156.      integer        KC'LEN,
  3157.                     ERR,
  3158.                     X;
  3159.  
  3160.      double         SESSION := 0D;
  3161.  
  3162.      real           WRITE'FINISH := 2.0;
  3163.  
  3164.      <<------------------------------------------------------------>>
  3165.  
  3166. E'ST "KERMIT COMMAND  KCMD=(", 2;
  3167. PLEN:=(PLEN:=TOS-@PBUF)+ASCII(KCMD'LEN,10,PBUF(PLEN));
  3168. MOVE PBUF(PLEN):=")", 2; MOVE *:=KCMD,(KCMD'LEN) E'EN;
  3169.      if (KCMD = "D") land (KCMD'LEN > 0) then
  3170.      begin  << Directory Command >>
  3171.           move KC'BUF := "LISTF ",2;
  3172.           KC'LEN := TOS - @KC'BUF;
  3173.  
  3174.           if KCMD'LEN > 2 then
  3175.           begin  << Check for filespec >>
  3176.                X := UNCHAR(KCMD(1));
  3177.                if (X > 0) land (X <= (KCMD'LEN -2)) then
  3178.                begin  << Use filespec >>
  3179.                     move KC'BUF(KC'LEN) := KCMD(2),(X);
  3180.                     KC'LEN := KC'LEN + X;
  3181.                end;
  3182.           end;
  3183.  
  3184.           move KC'BUF(KC'LEN) := ",2",2;
  3185.           move * := ";*",2;
  3186.           move * := KTEMP'NAME,2;
  3187.           KC'LEN := TOS - @KC'BUF;
  3188.           HOST'COMMAND(KC'BUF,KC'LEN,true);
  3189.      end
  3190.  
  3191.           else
  3192.      if (KCMD = "U") land (KCMD'LEN > 0) then
  3193.      begin  << File space usage >>
  3194.           move KC'BUF := "REPORT ",2;
  3195.           KC'LEN := TOS - @KC'BUF;
  3196.  
  3197.           if KCMD'LEN > 2 then
  3198.           begin  << Check for groupspec >>
  3199.                X := UNCHAR(KCMD(1));
  3200.                if (X > 0) land (X <= (KCMD'LEN -2)) then
  3201.                begin  << Use groupspec >>
  3202.                     move KC'BUF(KC'LEN) := KCMD(2),(X);
  3203.                     KC'LEN := KC'LEN + X;
  3204.                end;
  3205.           end;
  3206.  
  3207.           move KC'BUF(KC'LEN) := ",*",2;
  3208.           move * := KTEMP'NAME,2;
  3209.           KC'LEN := TOS - @KC'BUF;
  3210.  
  3211.           HOST'COMMAND(KC'BUF,KC'LEN,true);
  3212.      end
  3213.  
  3214.           else
  3215.      if (KCMD = "E") land (KCMD'LEN > 0) then
  3216.      begin  << Erase (delete) command >>
  3217.           move KC'BUF := "PURGE ",2;
  3218.           KC'LEN := TOS - @KC'BUF;
  3219.  
  3220.           if KCMD'LEN > 2 then
  3221.           begin
  3222.                X := UNCHAR(KCMD(1));
  3223.           end
  3224.                else
  3225.           begin
  3226.                X := 0;
  3227.           end;
  3228.  
  3229.           if (X < 1) lor (X > (KCMD'LEN-2))
  3230.           lor not VALID'FILE(KCMD(2), X, IN)  then
  3231.           begin
  3232.                move KC'BUF := "Filespec missing or invalid",2;
  3233.                KC'LEN := TOS - @KC'BUF;
  3234.                SPACK("E",N,KC'LEN,KC'BUF);
  3235.           end
  3236.                else
  3237.           begin
  3238.                move KC'BUF(KC'LEN) := KCMD(2),(X);
  3239.                KC'LEN := KC'LEN + X;
  3240.                HOST'COMMAND(KC'BUF,KC'LEN,false);
  3241.           end;
  3242.      end
  3243.  
  3244.           else
  3245.      if (KCMD = "T") land (KCMD'LEN > 0) then
  3246.      begin  << Type Command >>
  3247.           if KCMD'LEN > 1 then
  3248.           begin
  3249.                X := UNCHAR(KCMD(1));
  3250.           end
  3251.                else
  3252.           begin
  3253.                X := 0;
  3254.           end;
  3255.  
  3256.           if (X < 1) lor (X > (KCMD'LEN -2)) then
  3257.           begin
  3258.                move KC'BUF := "Filespec missing or invalid",2;
  3259.                KC'LEN := TOS - @KC'BUF;
  3260.                SPACK("E",N,KC'LEN,KC'BUF);
  3261.           end
  3262.                else
  3263.           begin
  3264.                move KC'BUF := KCMD(2),(X);
  3265.                KC'BUF(X) := " ";
  3266.  
  3267.                if not VALID'FILE(KC'BUF, X, OUT) then
  3268.                begin
  3269.                     move KC'BUF := ("Kermit file security error -",
  3270.                                     " see your account manager"),2;
  3271.                     KC'LEN := TOS - @KC'BUF;
  3272.                     SPACK("E",N,KC'LEN,KC'BUF);
  3273.                end
  3274.                     else
  3275.                begin
  3276.                     DNUM := FOPEN(KC'BUF,5,0);
  3277.                     if DNUM = 0 then
  3278.                     begin
  3279.                          move KC'BUF := "File open error",2;
  3280.                          KC'LEN := TOS - @KC'BUF;
  3281.                          SPACK("E",N,KC'LEN,KC'BUF);
  3282.                     end
  3283.                          else
  3284.                     begin
  3285.                          SENDSW(KC'BUF,0);
  3286.                          STATE := SBREAK;
  3287.                     end;
  3288.                end;
  3289.           end;
  3290.      end
  3291.  
  3292.           else
  3293.      if KCMD = "L"  then
  3294.      begin     << Bye command >>
  3295.           JOBINFO(1, SESSION, INTRINSIC'STATUS,
  3296.                   15, SESSION, ERR);
  3297.           if  INTRINSIC'STATUS(0) <> 0  then
  3298.           begin
  3299.                move PBUF:="Can't 'BYE'. JOBINFO status=", 2;
  3300.                PLEN:=(PLEN:=TOS-@PBUF)
  3301.                      +ASCII(INTRINSIC'STATUS, 10, PBUF(PLEN));
  3302.                SPACK("E",N,PLEN,PBUF);
  3303.           end
  3304.                else
  3305.           begin
  3306.                move PBUF:="Kermit session aborted by user", 2;
  3307.                PLEN:=TOS-@PBUF;
  3308.                SPACK("Y",N,PLEN,PBUF);
  3309.                if  LOGNUM<>0  then  FCLOSE(LOGNUM, %11, 0);
  3310.                if  HAVE'KTEMP  then  KILL'KTEMP;
  3311.                PAUSE(WRITE'FINISH);   << FWRITE in SPACK >>
  3312.                ABORTSESS(1, SESSION, INTRINSIC'STATUS);
  3313.           end;
  3314.      end
  3315.           else
  3316.      begin
  3317.           move KC'BUF := "Unimplementented Server Command",2;
  3318.           KC'LEN := TOS - @KC'BUF;
  3319.           SPACK("E",N,KC'LEN,KC'BUF);
  3320.      end;
  3321. end;
  3322. $PAGE "SERVER - Driver for Server Mode"
  3323. $control segment=SERVER'S
  3324. procedure SERVER;
  3325. begin
  3326.  
  3327.      equate         CB'MAX = 79;  << Max command size -1 >>
  3328.  
  3329.      byte array     CBUF(0:CB'MAX); << Command Buffer >>
  3330.  
  3331.      logical        DONE := false,
  3332.                     SEARCHED := false;
  3333.  
  3334.      integer        CB'CNT,  << Command size >>
  3335.                     KT'NUM,  << Temp file number >>
  3336.                     IX;
  3337.      <<************************************************************>>
  3338.      logical subroutine DIRSEARCH;
  3339.      begin
  3340.           DIRSEARCH:=false;  << Prepare for the worst >>
  3341.           if not SEARCHED then
  3342.           begin
  3343.                GET'KTEMP;
  3344.                if not HAVE'KTEMP then
  3345.                begin
  3346.                     move PBUF:="Unable to allocate temp file", 2;
  3347.                     PLEN:=TOS-@PBUF;
  3348.                     SPACK("E", N, PLEN, PBUF);
  3349.                     return;
  3350.                end;
  3351.                move PBUF:="LISTF ", 2;
  3352.                move *:=L'FNAME, (L'FNAME'LEN), 2;
  3353.                move *:=("; *", KTEMP'NAME, CR);
  3354.                COMMAND(PBUF, ERROR, PARM);
  3355.                if ERROR <> 0 then
  3356.                begin
  3357.                     move PBUF:="Directory search failed. Error=", 2;
  3358.                     PLEN:=(PLEN:=TOS-@PBUF) +
  3359.                           ASCII(ERROR, 10, PBUF(PLEN));
  3360.                     SPACK("E", N, PLEN, PBUF);
  3361.                     return;
  3362.                end;
  3363.  
  3364.                KT'NUM:=FOPEN(KT'NAME, 6, 0);
  3365.                if KT'NUM = 0 then
  3366.                begin
  3367.                     move PBUF:="Temp file open failure", 2;
  3368.                     PLEN:=TOS-@PBUF;
  3369.                     SPACK("E", N, PLEN, PBUF);
  3370.                     return;
  3371.                end;
  3372.  
  3373.                FREAD(KT'NUM, PBUF'W, -80); <<Hopefully skip over junk >>
  3374.                FREAD(KT'NUM, PBUF'W, -80);
  3375.                FREAD(KT'NUM, PBUF'W, -80);
  3376.                SEARCHED:=true;
  3377.           end;
  3378.  
  3379.           move PBUF:=20(" ");
  3380.           if FREAD(KT'NUM, PBUF'W, -80) <= 1 lor PBUF(0) = special then
  3381.           begin
  3382.                SEARCHED:=false;
  3383.                FCLOSE(KT'NUM, 4, 0);  << Purge >>
  3384.                KT'NUM:=0;
  3385.                KILL'KTEMP;
  3386.                STATE := SBREAK;
  3387.                return;
  3388.           end;
  3389.  
  3390.           << If we survived all of that, we will return one file name >>
  3391.           << which could be denied by the file validator              >>
  3392.  
  3393.           move L'FNAME:=PBUF(0) while an, 1;
  3394.           L'FNAME'LEN := TOS-@L'FNAME;
  3395.           L'FNAME(L'FNAME'LEN) := " ";
  3396.           if SEARCHED.(0:1)  then
  3397.           begin
  3398.                SEARCHED.(0:1) := false;
  3399.                L'FNAME'LEN := -L'FNAME'LEN;
  3400.           end;
  3401.           DIRSEARCH:=true;
  3402.      end;
  3403.  
  3404. <<----------------------------------------------------------->>
  3405.  
  3406.      subroutine  SPLIT'CBUF(BUF, LEN); ! Handle the case where we have
  3407.      value                       LEN;  ! local and remote file names
  3408.      integer                     LEN;  ! specified in a remote GET
  3409.      byte array             BUF;       ! request.
  3410.      begin
  3411.           IX := 0;
  3412.           while BUF(IX) = " "  do  IX:=IX+1;
  3413.  
  3414.           L'FNAME'LEN := 0;
  3415.  
  3416.           while BUF(IX)<>" "  land  IX<LEN  do
  3417.           begin
  3418.                L'FNAME(L'FNAME'LEN) := BUF(IX);
  3419.                L'FNAME'LEN := L'FNAME'LEN+1;
  3420.                IX := IX+1;
  3421.           end;
  3422.           L'FNAME(L'FNAME'LEN) := " ";
  3423.  
  3424.           R'FNAME'LEN := 0;
  3425.  
  3426.           while BUF(IX)=" "  land  IX<LEN  do  IX := IX+1;
  3427.  
  3428.           while BUF(IX)<>" "  land  IX<LEN  do
  3429.           begin
  3430.                R'FNAME(R'FNAME'LEN) := BUF(IX);
  3431.                R'FNAME'LEN := R'FNAME'LEN+1;
  3432.                IX := IX+1;
  3433.           end;
  3434.           R'FNAME(R'FNAME'LEN) := " ";
  3435. E'ST "SPLIT  ",2; MOVE *:=L'FNAME, (L'FNAME'LEN), 2;
  3436. MOVE *:="    ", 2; MOVE *:=R'FNAME, (R'FNAME'LEN) E'EN;
  3437.           R'FNAME'LEN := -R'FNAME'LEN;
  3438.      end;
  3439.  
  3440. <<--------------------------------------------------------------->>
  3441.  
  3442.  
  3443.  
  3444.  
  3445.      << Set default conditions >>
  3446.  
  3447.      MAX'SND'SIZE := 80;
  3448.      MAX'SND'DATA := 77;
  3449.      YOUR'PAD'COUNT := 0;
  3450.      YOUR'PAD := 0;
  3451.      YOUR'EOL := CR;
  3452.      YOUR'Q'CTL := %43;
  3453.      QUOTE'8 := false;
  3454.      USE'REPEAT := false;
  3455.  
  3456.      while not (DONE lor CTLY) do
  3457.      begin
  3458.           N := 0;
  3459.           NUMTRY := 0;
  3460.           STATE := "S";
  3461.  
  3462.           if RPACK(RP,RP'LEN,RP'NUM,RP'DATA) land (RP'NUM = 0) then
  3463.           begin
  3464.                MY'JCW'VAL := IDLING;
  3465.                PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  3466.                if RP = "I" then
  3467.                begin << Exchange Parameters >>
  3468.                     R'RPAR(RP'DATA,RP'LEN);
  3469.                     R'SPAR(RP'DATA,RP'LEN);
  3470.                     SPACK("Y",N,RP'LEN,RP'DATA);
  3471.                     OLDTRY := NUMTRY;
  3472.                     NUMTRY := 0;
  3473.                     N := NPNO(RP'NUM);
  3474.                end
  3475.                     else
  3476.                if RP = "S" then
  3477.                begin << Other side is sending >>
  3478.                     R'RPAR(RP'DATA,RP'LEN);
  3479.                     R'SPAR(RP'DATA,RP'LEN);
  3480.                     SPACK("Y",N,RP'LEN,RP'DATA);
  3481.                     OLDTRY := NUMTRY;
  3482.                     NUMTRY := 0;
  3483.                     N := NPNO(RP'NUM);
  3484.                     RECSW(true);
  3485.                     PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  3486.                end
  3487.                     else
  3488.                if RP = "R" then
  3489.                begin << Other side wants us to send >>
  3490.  
  3491.                     CBUFXLT(RP'DATA,RP'LEN,CBUF,CB'CNT,CB'MAX);
  3492.                     SPLIT'CBUF(CBUF, CB'CNT);
  3493.                     while DIRSEARCH do
  3494.                     begin
  3495.                     if not VALID'FILE(L'FNAME, \L'FNAME'LEN\, OUT) then
  3496.                     begin
  3497.                          move RP'DATA := ("Kermit file security ",
  3498.                                           "error - see your account ",
  3499.                                           "manager");
  3500.                          SPACK("E",N,53,RP'DATA);
  3501.                          MY'JCW'VAL := SEND'NG;
  3502.                     end
  3503.                          else
  3504.                     begin
  3505.                          DNUM := FOPEN(L'FNAME,5,0);
  3506.                          if DNUM = 0 then
  3507.                          begin  << File open error >>
  3508.                               move RP'DATA := "File open error";
  3509.                               SPACK("E",N,15,RP'DATA);
  3510.                          MY'JCW'VAL := SEND'NG;
  3511.                          end
  3512.                               else
  3513.                          if R'FNAME'LEN = 0  then
  3514.                          begin
  3515.                               SENDSW(L'FNAME, L'FNAME'LEN);
  3516.                               L'FNAME'LEN := 0;
  3517.                          end
  3518.                               else
  3519.                          begin
  3520.                               SENDSW(R'FNAME, R'FNAME'LEN);
  3521.                               R'FNAME'LEN := 0;
  3522.                          end;
  3523.                     end;
  3524.                     PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  3525.                     end;
  3526.                end
  3527.                     else
  3528.                if RP = "G" then
  3529.                begin << KERMIT Command >>
  3530.                     if (RP'DATA = "F") land (RP'LEN = 1) then
  3531.                     begin
  3532.                          SPACK("Y",N,0,RP'DATA);
  3533.                          DONE := true;
  3534.                     end
  3535.                          else
  3536.                     begin
  3537.                          if CBUFXLT(RP'DATA,RP'LEN,
  3538.                                     CBUF,CB'CNT,CB'MAX) then
  3539.                          begin
  3540.                               KERMIT'COMMAND(CBUF,CB'CNT);
  3541.                          end
  3542.                               else
  3543.                          begin
  3544.                               move CBUF := "Command too big",2;
  3545.                               CB'CNT := TOS - @CBUF;
  3546.                               SPACK("E",N,CB'CNT,CBUF);
  3547.                          end;
  3548.                     end;
  3549.                end
  3550.                     else
  3551.                begin
  3552.                     SPACK("N",N,0,RP'DATA);
  3553.                end;
  3554.           end
  3555.                else
  3556.           begin
  3557.                SPACK("N",N,0,RP'DATA);
  3558.           end;
  3559.      end;
  3560. end;
  3561.  
  3562. $PAGE "VERIFY - List assorted attributes"
  3563. $control segment=VERIFY'S
  3564. procedure VERIFY;
  3565. begin
  3566.      byte pointer   P;
  3567.      define    SAY       = begin
  3568.                                 move P:=#,     << Better than M'ST >>
  3569.                ENDSAY    =      ,2;            << Better than M'EN >>
  3570.                                 @P:=TOS;
  3571.                            end#,
  3572.                SAYNUM    = @P:=@P+ASCII(#,
  3573.                DECIMAL   = ,10, P)#,
  3574.                SPIT      = begin
  3575.                                 PLEN:=@P-@PBUF;
  3576.                                 FWRITE(CONUM, PBUF'W, -PLEN, 0);
  3577.                                 @P:=@PBUF;
  3578.                                 move P:=80(" ");
  3579.                            end#,
  3580.                MIDLINE   = @P:=@PBUF+30#;
  3581.      subroutine SAYBOOL(TRUTH);
  3582.      value              TRUTH;
  3583.      logical            TRUTH;
  3584.      begin
  3585.           case TRUTH.(15:1) of  <<Who says we must use IF statements?>>
  3586.           begin
  3587.                SAY "OFF" ENDSAY;
  3588.                SAY "ON" ENDSAY;
  3589.           end;
  3590.      end;
  3591.  
  3592.      @P:=@PBUF;
  3593.      SAY 80(" ") ENDSAY;
  3594.      SPIT;
  3595.      SAY "RECEIVE parameters" ENDSAY;
  3596.      MIDLINE;
  3597.      SAY "Other parameters"   ENDSAY;
  3598.      SPIT;
  3599.  
  3600.      SAY "   BINARY:       " ENDSAY;
  3601.      SAYBOOL(RCV'BINARY);
  3602.      MIDLINE;
  3603.      SAY "   SEND BINARY:  " ENDSAY;
  3604.      case SND'BINARY of
  3605.      begin
  3606.           SAY "Auto"   ENDSAY;
  3607.           SAY "Binary" ENDSAY;
  3608.           SAY "ASCII"  ENDSAY;
  3609.      end;
  3610.      SPIT;
  3611.  
  3612.      SAY "   FIXREC:       " ENDSAY;
  3613.      SAYBOOL(RCV'FIXREC);
  3614.      MIDLINE;
  3615.      SAY "   SEND PAUSE:   " ENDSAY;
  3616.      SAYNUM PAUSE'CNT        DECIMAL;
  3617.      SPIT;
  3618.  
  3619.      SAY "   SAVESP:       " ENDSAY;
  3620.      SAYBOOL(RCV'SAVESP);
  3621.      MIDLINE;
  3622.      SAY "   DELAY:        " ENDSAY;
  3623.      SAYNUM I'DELAY          DECIMAL;
  3624.      SPIT;
  3625.  
  3626.      SAY "   FCODE:        " ENDSAY;
  3627.      SAYNUM RCV'FCODE        DECIMAL;
  3628.      MIDLINE;
  3629.      SAY "   HANDSHAKE:    " ENDSAY;
  3630.      case HNDSHK of
  3631.      begin
  3632.           SAY "None" ENDSAY;
  3633.           SAY "XON"  ENDSAY;
  3634.           SAY "XON2" ENDSAY;
  3635.      end;
  3636.      SPIT;
  3637.  
  3638.      SAY "   RECLEN:       " ENDSAY;
  3639.      SAYNUM RCV'RECLEN       DECIMAL;
  3640.      MIDLINE;
  3641.      SAY "   DEBUG:        " ENDSAY;
  3642.      SAYNUM DEBUG'MODE       DECIMAL;
  3643.      SPIT;
  3644.  
  3645.      SAY "   BLOCKF:       " ENDSAY;
  3646.      SAYNUM RCV'BLOCKF       DECIMAL;
  3647.      MIDLINE;
  3648.      SAY "   LOG:          " ENDSAY;
  3649.      if LOGNUM > 0  and  LOGNUM <> CONUM  then
  3650.      begin
  3651.           SAY "TRUE (" ENDSAY;
  3652.           SAY LOGNAME, (LOGNAME'LEN) ENDSAY;
  3653.           SAY ")" ENDSAY;
  3654.      end
  3655.           else
  3656.           SAY "FALSE" ENDSAY;
  3657.  
  3658.      SPIT;
  3659.      SAY "   MAXEXT:       " ENDSAY;
  3660.      SAYNUM RCV'MAXEXT       DECIMAL;
  3661.      MIDLINE;
  3662.      SAY "   LINE LDEV:    " ENDSAY;
  3663.      SAYNUM LDEV'LINE        DECIMAL;
  3664.      SPIT;
  3665.  
  3666.      SAY "   MAXREC:       " ENDSAY;
  3667.      DASCII(RCV'MAXREC, 10, P);
  3668.      MIDLINE;
  3669.      SAY "   LINE SPEED:   " ENDSAY;
  3670.      SAYNUM TSPEED           DECIMAL;
  3671.      SPIT;
  3672.  
  3673.      SAY "   DEVICE:       " ENDSAY;
  3674.      MOVE P:=RCV'DEV while AN, 1;
  3675.      MIDLINE;
  3676.      SAY "   SOH:          " ENDSAY;
  3677.      SAYNUM SOH              DECIMAL;
  3678.      SPIT;
  3679.  
  3680.      SAY "   EXPTAB:       " ENDSAY;
  3681.      SAYBOOL(EXP'TABS);
  3682.      SPIT;
  3683.  
  3684. end;
  3685.  
  3686.  
  3687. $PAGE "KINIT - Perform KERMIT Initialization"
  3688. $control segment=KINIT'S
  3689. logical procedure KINIT;
  3690. begin
  3691.  
  3692.      logical        R'ERROR := false;
  3693.  
  3694.      integer        J'MODE,
  3695.                     J'LDEV,
  3696.                     DUM,
  3697.                     F'LDEV;
  3698.  
  3699.      byte array     TEST'CMD(0:19);
  3700.  
  3701.      <<------------------------------------------------------------>>
  3702.      LNUM := 0;
  3703.  
  3704.      CINUM := FOPEN(,%54,0);   << Open $STDIN   >>
  3705.      CONUM := FOPEN(,%414,1);  << Open $STDLIST >>
  3706.  
  3707.      <<  LOGNUM := CONUM; Equates to non-STDLIST cause confusion  >>
  3708.  
  3709.      if (CINUM <> 0) land (CONUM <> 0) then
  3710.      begin
  3711.           M'ST    VERS    M'EN;   << Output current version #  >>
  3712.           M'ST   "    "   M'EN;
  3713.  
  3714.           XCONTRAP(@CONTROLY,DUM);
  3715.  
  3716.           move KT'NAME := KTEMP'NAME,2;
  3717.           KTN'LEN := TOS - @KT'NAME;
  3718.           KT'NAME(KTN'LEN) := " ";
  3719.  
  3720.           LDEV'CI := 0;
  3721.           LDEV'LINE := 0;
  3722.  
  3723.           WHO(J'MODE,,,MYSELF,,,,J'LDEV);
  3724.           if J'MODE.(12:2) = 1 then
  3725.           begin << Session >>
  3726.                LDEV'LINE := J'LDEV; << Default COM to session dev >>
  3727.                FGETINFO(CINUM,,,,,,F'LDEV); << Get CI ldev >>
  3728.                if F'LDEV = J'LDEV then
  3729.                begin  << Command input uses session device >>
  3730.                     LDEV'CI := J'LDEV;
  3731.                end
  3732.                     else
  3733.                begin
  3734.                     FGETINFO(CONUM,,,,,,F'LDEV); << Get CO ldev >>
  3735.                     if F'LDEV = J'LDEV then
  3736.                          LDEV'CI := J'LDEV; << CO uses session ldev >>
  3737.                end;
  3738.           end;
  3739.           MIN'SIZE(DELETEV)   :=2;  MIN'SIZE(DIRV)       :=2;
  3740.           MIN'SIZE(EXITV)     :=1;  MIN'SIZE(NULLV)      :=1;
  3741.           MIN'SIZE(RECEIVEV)  :=1;  MIN'SIZE(SENDV)      :=3;
  3742.           MIN'SIZE(SERVEV)    :=3;  MIN'SIZE(SETV)       :=3;
  3743.           MIN'SIZE(SPACEV)    :=2;  MIN'SIZE(STATUSV)    :=2;
  3744.           MIN'SIZE(TAKEV)     :=2;  MIN'SIZE(TYPEV)      :=2;
  3745.           MIN'SIZE(VERIFYV)   :=1;
  3746.  
  3747.           MIN'SIZE(DEBUGV)    :=3;  MIN'SIZE(DELAYV)     :=3;
  3748.           MIN'SIZE(HANDSHAKEV):=1;  MIN'SIZE(LINEV)      :=2;
  3749.           MIN'SIZE(LOGV)      :=2;  MIN'SIZE(SENDV'1)    :=3;
  3750.           MIN'SIZE(SPEEDV)    :=2;  MIN'SIZE(SOHV)       :=2;
  3751.           MIN'SIZE(RECEIVEV'1):=1;
  3752.  
  3753.           MIN'SIZE(AUTOV)     :=1;  MIN'SIZE(BIN128V)    :=4;
  3754.           MIN'SIZE(BINARYV)   :=4;  MIN'SIZE(BLOCKFV)    :=2;
  3755.           MIN'SIZE(DEVICEV)   :=1;  MIN'SIZE(FIXRECV)    :=2;
  3756.           MIN'SIZE(FCODEV)    :=2;  MIN'SIZE(MAXRECV)    :=4;
  3757.           MIN'SIZE(MAXEXTV)   :=4;  MIN'SIZE(PAUSEV)     :=2;
  3758.           MIN'SIZE(PROGV)     :=2;  MIN'SIZE(RECLENV)    :=1;
  3759.           MIN'SIZE(SAVESPV)   :=1;  MIN'SIZE(TEXTV)      :=2;
  3760.           MIN'SIZE(TXT80V)    :=2;  MIN'SIZE(EXPTABV)    :=1;
  3761.           MIN'SIZE(FASTV)     :=2;
  3762.  
  3763.           MIN'SIZE(NONEV)     :=1;  MIN'SIZE(OFFV)       :=2;
  3764.           MIN'SIZE(ONV)       :=2;  MIN'SIZE(XONV)       :=3;
  3765.           MIN'SIZE(XON2V)     :=4;  MIN'SIZE(YESV)       :=1;
  3766.         MY'CAPS    := 0 CAT
  3767.                       1 (LONGP'F) CAT
  3768.                       0 (WINDOWS'F) CAT
  3769.                       0 (ATTRS'F);
  3770.           move TEST'CMD:=("SETVAR NOTHING, 0", CR);
  3771.           COMMAND(TEST'CMD, ERROR, PARM);
  3772.           if = then
  3773.                DFLT'TTYPE := 10        << HPPA machines >>
  3774.           else
  3775.                DFLT'TTYPE := 13;       << Classic machines >>
  3776.  
  3777.      end
  3778.           else
  3779.      begin
  3780.           R'ERROR := true;
  3781.      end;
  3782.  
  3783.      if TAKE'VAL > 0 then
  3784.      begin
  3785.           move PBUF:="F599KM00 ", 2;
  3786.           PLEN:=TOS-@PBUF;
  3787.           ASCII(TAKE'VAL, -10, PBUF(PLEN-2));
  3788.           TAKENUM:=FOPEN(PBUF, %5, %2000);
  3789.           if TAKENUM = 0 then
  3790.           begin
  3791.                move PBUF(PLEN):="take file open error", 2;
  3792.                PLEN:=TOS-@PBUF;
  3793.                FWRITE(CONUM, PBUF'W, -PLEN, 0);
  3794.           end;
  3795.      end;
  3796.  
  3797.      LONGPACK'SIZE := MAX'LONGPACK'SIZE-10;
  3798.  
  3799.      KINIT := not R'ERROR;
  3800.  
  3801. end;
  3802. $PAGE "HELP - User Help Function"
  3803. $control segment=HELP'S
  3804. procedure HELP(ITEM, LEVEL, RCVCASE);
  3805. value           ITEM,
  3806.                 LEVEL,
  3807.                 RCVCASE;
  3808. integer         ITEM,
  3809.                 LEVEL,
  3810.                 RCVCASE;
  3811.  
  3812. option variable;
  3813. <<*WARNING* No check is made for missing params!!!!!!!!!!!!>>
  3814. begin
  3815.  
  3816.      <<----------------------------------------------------------->>
  3817.  
  3818.      M'ST " " M'EN;
  3819.      case ITEM of
  3820.      begin
  3821.  
  3822.           << COMMANDS IN GENERAL >>
  3823.           begin
  3824.  
  3825.                M'ST "Commands:" M'EN;
  3826.                M'ST " " M'EN;
  3827.                M'ST "     TAKE"      M'EN;
  3828.                M'ST "     SERVE"     M'EN;
  3829.                M'ST "     SEND"      M'EN;
  3830.                M'ST "     RECEIVE"   M'EN;
  3831.                M'ST "     SET"       M'EN;
  3832.                M'ST "     VERIFY"    M'EN;
  3833.                M'ST "     DIR"       M'EN;
  3834.                M'ST "     SPACE"     M'EN;
  3835.                M'ST "     DELETE"    M'EN;
  3836.                M'ST "     TYPE"      M'EN;
  3837.                M'ST "     EXIT"      M'EN;
  3838.           end;
  3839.  
  3840.           << TAKE >>
  3841.  
  3842.           begin
  3843.             M'ST "Syntax:  TAKE filespec" M'EN;
  3844.             M'ST " " M'EN;
  3845.             M'ST
  3846.               "The TAKE command causes subsequent commands to be"
  3847.             M'EN;
  3848.              M'ST
  3849.                "taken from the specified file until EOF is reached."
  3850.              M'EN;
  3851.              M'ST
  3852.                "If a subsequent TAKE is encountered within the original"
  3853.              M'EN;
  3854.              M'ST
  3855.                "TAKE file, the first file is closed and execution"
  3856.              M'EN;
  3857.              M'ST
  3858.                "continues with the second.  This means that if a"
  3859.               M'EN;
  3860.              M'ST
  3861.                "TAKE appears within a TAKE file, commands that follow"
  3862.              M'EN;
  3863.              M'ST
  3864.                "it (in the original TAKE file) will be ignored."
  3865.              M'EN;
  3866.           end;
  3867.  
  3868.           << SEND >>
  3869.  
  3870.           begin
  3871.              M'ST  "Syntax:  SEND filespec1 [filespec2]" M'EN;
  3872.              M'ST " " M'EN;
  3873.              M'ST
  3874.                "This command causes a file (indicated by filespec1)"
  3875.              M'EN;
  3876.              M'ST
  3877.                "to be sent from the HP to the local KERMIT.  Wildcard"
  3878.              M'EN;
  3879.              M'ST
  3880.                "characters are not permitted.  If filespec2 is speci-"
  3881.              M'EN;
  3882.              M'ST
  3883.                "fied, the file will be sent with that name."
  3884.              M'EN;
  3885.           end;
  3886.  
  3887.           << RECEIVE >>
  3888.  
  3889.           begin
  3890.              M'ST "Syntax:  RECEIVE [filespec]" M'EN;
  3891.              M'ST " " M'EN;
  3892.              M'ST
  3893.                "The RECEIVE command causes HP KERMIT to enter receive"
  3894.              M'EN;
  3895.              M'ST
  3896.                "mode and wait for the local kermit to start sending"
  3897.              M'EN;
  3898.              M'ST
  3899.                "a file.  If filespec is specified, the file will be"
  3900.              M'EN;
  3901.              M'ST
  3902.                "stored under that name."
  3903.              M'EN;
  3904.           end;
  3905.  
  3906.           << SERVE >>
  3907.  
  3908.           begin
  3909.              M'ST "Syntax:  SERVE" M'EN;
  3910.              M'ST " " M'EN;
  3911.              M'ST
  3912.              "The SERVE command causes HP 3000 KERMIT to go into"
  3913.              M'EN;
  3914.              M'ST
  3915.                "server mode.  Once in server mode, the only way back"
  3916.              M'EN;
  3917.              M'ST
  3918.                "to command mode is the Control-Y trap."
  3919.              M'EN;
  3920.              M'ST " " M'EN;
  3921.              M'ST
  3922.                "In addition to the standard KERMIT transactions for"
  3923.              M'EN;
  3924.              M'ST
  3925.                "file transfer, the following server functions are"
  3926.              M'EN;
  3927.              M'ST
  3928.                "supported:"
  3929.              M'EN;
  3930.              M'ST " " M'EN;
  3931.              M'ST
  3932.                "FUNCTION             PROBABLE SYNTAX"
  3933.              M'EN;
  3934.              M'ST
  3935.                "                     (If available on local KERMIT)"
  3936.              M'EN;
  3937.              M'ST
  3938.                "-------------------  -------------------------------"
  3939.              M'EN;
  3940.              M'ST " " M'EN;
  3941.              M'ST
  3942.                "Finish Processing    FINISH"
  3943.              M'EN;
  3944.              M'ST
  3945.                "Type a file          REMOTE TYPE filespec"
  3946.              M'EN;
  3947.              M'ST
  3948.                "Directory Listing    REMOTE DIRECTORY [filespec]"
  3949.              M'EN;
  3950.              M'ST
  3951.                "File Space Listing   REMOTE SPACE [filespec]"
  3952.              M'EN;
  3953.              M'ST
  3954.                "Delete a file        REMOTE DELETE filespec"
  3955.              M'EN;
  3956.              M'ST " " M'EN;
  3957.              M'ST
  3958.                "Wildcard file specification may be used only for the"
  3959.              M'EN;
  3960.              M'ST
  3961.                "DIRECTORY and SPACE transactions.  Wildcard specifi-"
  3962.              M'EN;
  3963.              M'ST
  3964.                "cations are in the native HP 3000 format.  To produce"
  3965.              M'EN;
  3966.              M'ST
  3967.                "a DIRECTORY listing of all files starting with FOO use:"
  3968.              M'EN;
  3969.              M'ST  " " M'EN;
  3970.              M'ST
  3971.                "             REMOTE DIRECTORY FOO@"
  3972.              M'EN;
  3973.           end;
  3974.  
  3975.           << SET >>
  3976.  
  3977.           begin
  3978.                case LEVEL-DEBUGV+1 of
  3979.                begin
  3980.  
  3981.                   << SET COMMANDS IN GNERAL >>
  3982.  
  3983.                   begin
  3984.                      M'ST "SET items:" M'EN;
  3985.                      M'ST " " M'EN;
  3986.                      M'ST "  SET DEBUG"  M'EN;
  3987.                      M'ST "  SET DELAY"  M'EN;
  3988.                      M'ST "  SET LINE"   M'EN;
  3989.                      M'ST "  SET SEND"   M'EN;
  3990.                      M'ST "  SET SPEED"  M'EN;
  3991.                      M'ST "  SET HANDSHAKE"  M'EN;
  3992.                      M'ST "  SET RECEIVE"    M'EN;
  3993.                      M'ST "  SET LOG"    M'EN;
  3994.                      M'ST "  SET SOH"    M'EN;
  3995.                      M'ST "  SET FAST"   M'EN;
  3996.                      M'ST " "        M'EN;
  3997.                      M'ST "type 'SET item ?'for explanation" M'EN;
  3998.                 end;
  3999.  
  4000.                << SET DEBUG >>
  4001.  
  4002.                begin
  4003.                     M'ST
  4004.                      "Syntax:  SET DEBUG number"
  4005.                     M'EN;
  4006.                     M'ST " " M'EN;
  4007.                     M'ST
  4008.                      "This sets the debug level to the indicated"
  4009.                     M'EN;
  4010.                     M'ST
  4011.                      "number.  Currently, only one level exists."
  4012.                     M'EN;
  4013.                     M'ST
  4014.                      "This level is enabled by setting the number to"
  4015.                     M'EN;
  4016.                     M'ST
  4017.                      "any non-negative, non-zero number.  If DEBUG is"
  4018.                     M'EN;
  4019.                     M'ST
  4020.                      "enabled, packets sent and received are written"
  4021.                     M'EN;
  4022.                     M'ST
  4023.                      "to the LOG file.  The LOG file defaults to the"
  4024.                     M'EN;
  4025.                     M'ST
  4026.                      "job/session output file.  LOG output to the "
  4027.                     M'EN;
  4028.                     M'ST
  4029.                      "job/session output file is disabled when commu-"
  4030.                     M'EN;
  4031.                     M'ST
  4032.                      "nications are taking place unless the communica-"
  4033.                     M'EN;
  4034.                     M'ST
  4035.                      "tions line has been re-designated via the SET"
  4036.                     M'EN;
  4037.                     M'ST
  4038.                      "LINE command."
  4039.                     M'EN;
  4040.                end;
  4041.  
  4042.                << SET DELAY >>
  4043.  
  4044.                begin
  4045.                     M'ST "Syntax:  SET DELAY number" M'EN;
  4046.                     M'ST " " M'EN;
  4047.                     M'ST
  4048.                      "Causes a pause for the indicated number of"
  4049.                     M'EN;
  4050.                     M'ST
  4051.                      "seconds prior to starting a SEND command.  This"
  4052.                     M'EN;
  4053.                     M'ST
  4054.                      "is to allow the user to escape back to the local"
  4055.                     M'EN;
  4056.                     M'ST
  4057.                      "KERMIT and enter a RECEIVE command."
  4058.                     M'EN;
  4059.                end;
  4060.  
  4061.                << SET LINE >>
  4062.  
  4063.                begin
  4064.                     M'ST "Syntax:  SET LINE ldev" M'EN;
  4065.                     M'ST " " M'EN;
  4066.                     M'ST
  4067.                      "This causes the indicated ldev (logical device"
  4068.                     M'EN;
  4069.                     M'ST
  4070.                      "number) to be used for communications purposes."
  4071.                     M'EN;
  4072.                end;
  4073.  
  4074.                << SET SEND >>
  4075.  
  4076.                begin
  4077.                     M'ST "                 { PAUSE  1/10 secs}" M'EN;
  4078.                     M'ST "                 {                 }" M'EN;
  4079.                     M'ST "Syntax: SET SEND {       { ON   }  }" M'EN;
  4080.                     M'ST "                 { BINARY{ OFF  }  }" M'EN;
  4081.                     M'ST "                 {       { AUTO }  }" M'EN;
  4082.                     M'ST " " M'EN;
  4083.                     M'ST
  4084.                      "This parameter is used to alter the default"
  4085.                     M'EN;
  4086.                     M'ST
  4087.                      "conditions relating to how files are sent."
  4088.                     M'EN;
  4089.                end;
  4090.  
  4091.                << SET SPEED >>
  4092.  
  4093.                begin
  4094.                     M'ST "Syntax:  SET SPEED speed" M'EN;
  4095.                     M'ST " " M'EN;
  4096.                     M'ST
  4097.                      "Sets the communications speed to the indicated"
  4098.                     M'EN;
  4099.                     M'ST
  4100.                      "number of characters per second.  Supported"
  4101.                     M'EN;
  4102.                     M'ST
  4103.                      "speeds are: 30, 60, 120, 480, 960."
  4104.                     M'EN;
  4105.                end;
  4106.  
  4107.                << SET HANDSHAKE >>
  4108.  
  4109.                begin
  4110.                     M'ST "Syntax:  SET HANDSHAKE option" M'EN;
  4111.                     M'ST " " M'EN;
  4112.                     M'ST
  4113.                      "This specifies any handshaking that is to be"
  4114.                     M'EN;
  4115.                     M'ST
  4116.                      "done on the communications line.  Options are:"
  4117.                     M'EN;
  4118.                     M'ST " " M'EN;
  4119.                     M'ST
  4120.                      "XON  Generate an XON character prior to each"
  4121.                     M'EN;
  4122.                     M'ST
  4123.                      "read.  This is the default mode and is needed"
  4124.                     M'EN;
  4125.                     M'ST
  4126.                      "in most cases since the HP will ""lose"" any"
  4127.                     M'EN;
  4128.                     M'ST
  4129.                      "characters that are transmitted when no read is"
  4130.                     M'EN;
  4131.                     M'ST
  4132.                      "active.  The local KERMIT must be capable of"
  4133.                     M'EN;
  4134.                     M'ST
  4135.                      "waiting for an XON character before issuing a"
  4136.                     M'EN;
  4137.                     M'ST
  4138.                      "a write to the communications line."
  4139.                     M'EN;
  4140.                     M'ST " " M'EN;
  4141.                     M'ST
  4142.                      "NONE  Generate no special characters prior to a"
  4143.                     M'EN;
  4144.                     M'ST
  4145.                      "read."
  4146.                     M'EN;
  4147.                     M'ST " " M'EN;
  4148.                     M'ST
  4149.                      "XON2 Same as XON except in both directions."
  4150.                     M'EN;
  4151.                     M'ST
  4152.                      "This sets the read termination character to XON"
  4153.                     M'EN;
  4154.                     M'ST
  4155.                      "in an attempt to synchronize with another KERMIT"
  4156.                     M'EN;
  4157.                     M'ST
  4158.                      "having similar limitations."
  4159.                     M'EN;
  4160.                end;
  4161.  
  4162.                << SET RECEIVE >>
  4163.  
  4164.                case RCVCASE-BINARYV+1  of
  4165.                begin
  4166.  
  4167.                     << General stuff >>
  4168.  
  4169.                     begin
  4170.                     M'ST
  4171.                      "The SET RECEIVE parameter is used to alter the"
  4172.                     M'EN;
  4173.                     M'ST
  4174.                      "default conditions regarding file reception."
  4175.                     M'EN;
  4176.                     M'ST
  4177.                      "The various options are:"
  4178.                     M'EN;
  4179.                     M'ST " " M'EN;
  4180.                     M'ST "     SET RECEIVE DEVICE" M'EN;
  4181.                     M'ST "     SET RECEIVE FCODE"  M'EN;
  4182.                     M'ST "     SET RECEIVE BINARY" M'EN;
  4183.                     M'ST "     SET RECEIVE RECLEN" M'EN;
  4184.                     M'ST "     SET RECEIVE FIXREC" M'EN;
  4185.                     M'ST "     SET RECEIVE BLOCKF" M'EN;
  4186.                     M'ST "     SET RECEIVE MAXREC" M'EN;
  4187.                     M'ST "     SET RECEIVE MAXEXT" M'EN;
  4188.                     M'ST "     SET RECEIVE SAVESP" M'EN;
  4189.                     M'ST "     SET RECEIVE PROG"   M'EN;
  4190.                     M'ST "     SET RECEIVE TEXT"   M'EN;
  4191.                     M'ST "     SET RECEIVE TXT80"  M'EN;
  4192.                     M'ST "     SET RECEIVE BIN128" M'EN;
  4193.                     M'ST "     SET RECEIVE EXPTAB" M'EN;
  4194.                     end;
  4195.  
  4196.                     << SET RECEIVE BINARY >>
  4197.  
  4198.                     begin
  4199.                     M'ST
  4200.                      "Syntax:  SET RECEIVE BINARY { ON  }"
  4201.                     M'EN;
  4202.                     M'ST
  4203.                      "                            { OFF }"
  4204.                     M'EN;
  4205.                     M'ST " " M'EN;
  4206.                     M'ST
  4207.                      "BINARY tells how to store received files on the"
  4208.                     M'EN;
  4209.                     M'ST
  4210.                      "3000."
  4211.                     M'EN;
  4212.                     M'ST "       ON  Store files as binary." M'EN;
  4213.                     M'ST "       OFF Store files as ASCII." M'EN;
  4214.                     end;
  4215.  
  4216.                     << SET RECEIVE DEVICE >>
  4217.  
  4218.                     begin
  4219.                     M'ST
  4220.                      "Syntax:  SET RECEIVE DEVICE [ dev ]"
  4221.                     M'EN;
  4222.                     M'ST " " M'EN;
  4223.                     M'ST
  4224.                      "DEVICE specifies the device class for received"
  4225.                     M'EN;
  4226.                     M'ST
  4227.                      "files.  Default is DISC.  This command can be"
  4228.                     M'EN;
  4229.                     M'ST
  4230.                      "used to send files directly to the system line"
  4231.                     M'EN;
  4232.                     M'ST "printer." M'EN;
  4233.                     M'ST " " M'EN;
  4234.                     end;
  4235.  
  4236.                     << SET RECEIVE FCODE >>
  4237.  
  4238.                     begin
  4239.                     M'ST
  4240.                      "Syntax:  SET RECEIVE FCODE n"
  4241.                     M'EN;
  4242.                     M'ST " " M'EN;
  4243.                     M'ST
  4244.                      "FCODE specifies the file code for received files."
  4245.                     M'EN;
  4246.                     end;
  4247.  
  4248.                     << SET RECEIVE RECLEN >>
  4249.  
  4250.                     begin
  4251.                     M'ST
  4252.                      "Syntax:  SET RECEIVE RECLEN [-]n"
  4253.                     M'EN;
  4254.                     M'ST " " M'EN;
  4255.                     M'ST
  4256.                      "RECLEN specifies the maximum record length (n)"
  4257.                     m'en;
  4258.                     M'ST
  4259.                      "for a received file.  As with other HP file "
  4260.                     M'EN;
  4261.                     M'ST
  4262.                      "system commands, n is assumed to be words if"
  4263.                     M'EN;
  4264.                     M'ST
  4265.                      "positive and bytes if negative"
  4266.                     M'EN;
  4267.                     end;
  4268.  
  4269.                     << SET RECEIVE BLOCKF >>
  4270.  
  4271.                     begin
  4272.                     M'ST
  4273.                      "Syntax:  SET RECEIVE BLOCKF n"
  4274.                     M'EN;
  4275.                     M'ST " " M'EN;
  4276.                     M'ST
  4277.                      "BLOCKF specifies the blocking factor for received"
  4278.                     M'EN;
  4279.                     M'ST
  4280.                      "files.  If n is 0, the file system will calculate"
  4281.                     M'EN;
  4282.                     M'ST
  4283.                      "a blocking factor automatically."
  4284.                     M'EN;
  4285.                     end;
  4286.  
  4287.                     << SET RECEIVE FIXREC >>
  4288.  
  4289.                     begin
  4290.                     M'ST
  4291.                      "Syntax:  SET RECEIVE FIXREC { ON  }"
  4292.                     M'EN;
  4293.                     M'ST
  4294.                      "                            { OFF }"
  4295.                     M'EN;
  4296.                     M'ST " " M'EN;
  4297.                     M'ST
  4298.                      "FIXREC is used to identify fixed or variable"
  4299.                     M'EN;
  4300.                     M'ST
  4301.                      "length records.  Options are:"
  4302.                     M'EN;
  4303.                     M'ST "       ON   Use fixed length records." M'EN;
  4304.                     M'ST "       OFF  Use variable length records."M'EN;
  4305.                     end;
  4306.  
  4307.                     << SET RECEIVE MAXREC >>
  4308.  
  4309.                     begin
  4310.                     M'ST
  4311.                      "Syntax:  SET RECEIVE MAXREC n"
  4312.                     M'EN;
  4313.                     M'ST " " M'EN;
  4314.                     M'ST
  4315.                      "MAXREC specifies the maximum number of records"
  4316.                     M'EN;
  4317.                     M'ST
  4318.                      "that can be stored in a received file."
  4319.                     M'EN;
  4320.                     end;
  4321.  
  4322.                     << SET RECEIVE MAXEXT >>
  4323.  
  4324.                     begin
  4325.                     M'ST
  4326.                      "Syntax:  SET RECEIVE MAXEXT n"
  4327.                     M'EN;
  4328.                     M'ST " " M'EN;
  4329.                     M'ST
  4330.                      "MAXEXT specifies the maximum number of extents"
  4331.                     M'EN;
  4332.                     M'ST
  4333.                      "for a received file.  This number (n) must be in"
  4334.                     M'EN;
  4335.                     M'ST
  4336.                      "the range 1 ... 32."
  4337.                     M'EN;
  4338.                     end;
  4339.  
  4340.                     << SET RECEIVE SAVESP >>
  4341.  
  4342.                     begin
  4343.                     M'ST
  4344.                      "Syntax:  SET RECEIVE SAVESP { ON  }"
  4345.                     M'EN;
  4346.                     M'ST
  4347.                      "                            { OFF }"
  4348.                     M'EN;
  4349.                     M'ST " " M'EN;
  4350.                     M'ST
  4351.                      "SAVESP specifies if unused file space at the end"
  4352.                     M'EN;
  4353.                     M'ST
  4354.                      "of the file is to be returned to the operating"
  4355.                     M'EN;
  4356.                     M'ST
  4357.                      "system.  Options are:"
  4358.                     M'EN;
  4359.                     M'ST "       ON   Return unused apace" M'EN;
  4360.                     M'ST "       OFF  Do not return unused apace"M'EN;
  4361.                     end;
  4362.  
  4363.                     << SET RECEIVE PROG >>
  4364.  
  4365.                     begin
  4366.                     M'ST
  4367.                      "Syntax:  SET RECEIVE PROG"
  4368.                     M'EN;
  4369.                     M'ST " " M'EN;
  4370.                     M'ST
  4371.                      "PROG will set all of the other parameters needed"
  4372.                     M'EN;
  4373.                     M'ST
  4374.                      "to receive an HP 3000 program (executable) file."
  4375.                     M'EN;
  4376.                     M'ST
  4377.                      "It is equivalent to:"
  4378.                     M'EN;
  4379.                     M'ST "   SET RECEIVE BINARY ON" M'EN;
  4380.                     M'ST "   SET RECEIVE FIXREC ON" M'EN;
  4381.                     M'ST "   SET RECEIVE FCODE 1029" M'EN;
  4382.                     M'ST "   SET RECEIVE RECLEN 128" M'EN;
  4383.                     M'ST "   SET RECEIVE BLOCKF 1" M'EN;
  4384.                     M'ST "   SET RECEIVE MAXEXT 1" M'EN;
  4385.                     end;
  4386.  
  4387.                     << SET RECEIVE BIN128 >>
  4388.  
  4389.                     begin
  4390.                     M'ST
  4391.                      "Syntax:  SET RECEIVE BIN128"
  4392.                     M'EN;
  4393.                     M'ST " " M'EN;
  4394.                     M'ST
  4395.                      "BIN128 sets up the needed parameters for recei-"
  4396.                     M'EN;
  4397.                     M'ST
  4398.                      "ving a binary file in the ""normal"" HP repre-"
  4399.                     M'EN;
  4400.                     M'ST
  4401.                      "sentation.  It is equivalent to:"
  4402.                     M'EN;
  4403.                     M'ST "   SET RECEIVE BINARY ON" M'EN;
  4404.                     M'ST "   SET RECEIVE FIXREC OFF" M'EN;
  4405.                     M'ST "   SET RECEIVE FCODE 0" M'EN;
  4406.                     M'ST "   SET RECEIVE RECLEN 128" M'EN;
  4407.                     M'ST "   SET RECEIVE BLOCKF 0" M'EN;
  4408.                     end;
  4409.  
  4410.                     << SET RECEIVE TEXT >>
  4411.  
  4412.                     begin
  4413.                     M'ST
  4414.                      "Syntax:  SET RECEIVE TEXT"
  4415.                     M'EN;
  4416.                     M'ST " " M'EN;
  4417.                     M'ST
  4418.                      "TEXT sets up the needed parameters for reciving"
  4419.                     M'EN;
  4420.                     M'ST
  4421.                      """generic"" text files.  It is equivalent to:"
  4422.                     M'EN;
  4423.                     M'ST "   SET RECEIVE BINARY OFF" M'EN;
  4424.                     M'ST "   SET RECEIVE FIXREC OFF" M'EN;
  4425.                     M'ST "   SET RECEIVE FCODE 0" M'EN;
  4426.                     M'ST "   SET RECEIVE RECLEN -254" M'EN;
  4427.                     M'ST "   SET RECEIVE BLOCKF 0" M'EN;
  4428.                     end;
  4429.  
  4430.                     << SET RECEIVE TXT80 >>
  4431.  
  4432.                     begin
  4433.                     M'ST
  4434.                      "Syntax:  SET RECEIVE TXT80"
  4435.                     M'EN;
  4436.                     M'ST " " M'EN;
  4437.                     M'ST
  4438.                      "TXT80 sets up the needed parameters for recei-"
  4439.                     M'EN;
  4440.                     M'ST
  4441.                      "ving 80 character text files in the manner that"
  4442.                     M'EN;
  4443.                     M'ST
  4444.                      "is most convenient for the typical text editor"
  4445.                     M'EN;
  4446.                     M'ST
  4447.                      "on the HP.  It is equivalent to:"
  4448.                     M'EN;
  4449.                     M'ST "   SET RECEIVE BINARY OFF" M'EN;
  4450.                     M'ST "   SET RECEIVE FIXREC ON" M'EN;
  4451.                     M'ST "   SET RECEIVE FCODE 0" M'EN;
  4452.                     M'ST "   SET RECEIVE RECLEN -80" M'EN;
  4453.                     M'ST "   SET RECEIVE BLOCKF 16" M'EN;
  4454.                     end;
  4455.  
  4456.                     << SET RECEIVE EXPTAB >>
  4457.  
  4458.                     begin
  4459.                     M'ST
  4460.                      "Syntax:  SET RECEIVE EXPTAB { ON  }"
  4461.                     M'EN;
  4462.                     M'ST
  4463.                      "                            { OFF }"
  4464.                     M'EN;
  4465.                     M'ST " " M'EN;
  4466.                     M'ST
  4467.                      "EXPTAB expands horizontal tabs found in the"
  4468.                     M'EN;
  4469.                     M'ST
  4470.                      "data.  Tab stops are assumed to be at columns"
  4471.                     M'EN;
  4472.                     M'ST
  4473.                      "1, 9, 17, 25, etc."
  4474.                     M'EN;
  4475.                     end;
  4476.  
  4477.                end;   << case SET RECEIVE >>
  4478.  
  4479.                << SET LOG >>
  4480.  
  4481.                begin
  4482.                     M'ST
  4483.                      "Syntax:  SET LOG { [ filespec ] }"
  4484.                     M'EN;
  4485.                     M'ST
  4486.                      "                 { PURGE        }"
  4487.                     M'EN;
  4488.                     M'ST " " M'EN;
  4489.                     M'ST
  4490.                      "This command sets the LOG file to the indicated"
  4491.                     M'EN;
  4492.                     M'ST
  4493.                      "filespec.  Error and DEBUG messages (if enabled)"
  4494.                     M'EN;
  4495.                     M'ST
  4496.                      "are written to the LOG file (see SET DEBUG)."
  4497.                     M'EN;
  4498.                     M'ST
  4499.                      "If filespec is not specified, the current LOG"
  4500.                     M'EN;
  4501.                     M'ST
  4502.                      "file, if open, is closed.  If PURGE is specified,"
  4503.                     M'EN;
  4504.                      M'ST
  4505.                       "the file is closed and purged."
  4506.                      M'EN;
  4507.                end;
  4508.  
  4509.                << SET SOH >>
  4510.  
  4511.                begin
  4512.                     M'ST "Syntax:  SET SOH [%]n" M'EN;
  4513.                     M'ST " " M'EN;
  4514.                     M'ST
  4515.                      "This option sets the value of the start-of-header"
  4516.                     M'EN;
  4517.                     M'ST
  4518.                      "character used to begin each packet.  If the %-"
  4519.                     M'EN;
  4520.                     M'ST
  4521.                      "sign is used, n is assumed to be octal.  Other-"
  4522.                     M'EN;
  4523.                     M'ST
  4524.                      "wise n is assumed to be decimal.  Default value"
  4525.                     M'EN;
  4526.                     M'ST
  4527.                      "for SOH is 1."
  4528.                     M'EN;
  4529.                end;
  4530.  
  4531.                << SET FAST >>
  4532.  
  4533.                begin
  4534.                     M'ST "Syntax:  SET FAST {ON }" M'EN;
  4535.                     M'ST "                  {OFF}" M'EN;
  4536.                     M'ST " " M'EN;
  4537.                     M'ST
  4538.                      "FAST ON shortens both the number of timeouts "
  4539.                     M'EN;
  4540.                     M'ST
  4541.                      "and the timeout time for receiving packets. "
  4542.                     M'EN;
  4543.                     M'ST
  4544.                      "It is intended primarily for machine-to-machine"
  4545.                     M'EN;
  4546.                     M'ST
  4547.                      "RECEIVES by this Kermit when there are also a"
  4548.                     M'EN;
  4549.                     M'ST
  4550.                      "number of files stacked up to be transmitted by"
  4551.                     M'EN;
  4552.                     M'ST
  4553.                      "this Kermit.  The timing out may be too fast for"
  4554.                     M'EN;
  4555.                     M'ST
  4556.                      "a human sitting at a PC Keyboard, and should "
  4557.                     M'EN;
  4558.                     M'ST
  4559.                      "probably not be used in that case."
  4560.                     M'EN;
  4561.                end;
  4562.  
  4563.                end;
  4564.             end;  << SET (LEVEL) case >>
  4565.  
  4566.           << EXIT >>
  4567.  
  4568.           begin
  4569.                M'ST "Syntax:  {EXIT}" M'EN;
  4570.                M'ST "         {QUIT}" M'EN;
  4571.                M'ST " " M'EN;
  4572.                M'ST
  4573.                  "This command causes the HP KERMIT process to"
  4574.                M'EN;
  4575.                M'ST
  4576.                  "terminate in an orderly manner."
  4577.                M'EN;
  4578.           end;
  4579.  
  4580.           << DIR >>
  4581.  
  4582.           begin
  4583.                M'ST "Syntax:  DIR [filespec]" M'EN;
  4584.                M'ST " " M'EN;
  4585.                M'ST
  4586.                 "This command searches the disc directory for the"
  4587.                M'EN;
  4588.                M'ST
  4589.                 "indicated filespec, if any.  Wildcard characters"
  4590.                M'EN;
  4591.                M'ST
  4592.                 "may be used."
  4593.                M'EN;
  4594.           end;
  4595.  
  4596.           << SPACE >>
  4597.  
  4598.           begin
  4599.                M'ST "Syntax:  SPACE [groupspec]" M'EN;
  4600.                M'ST " " M'EN;
  4601.                M'ST
  4602.                 "This command reports the amount of in-use and"
  4603.                M'EN;
  4604.                M'ST
  4605.                 "available disc for the user's account and group."
  4606.                M'EN;
  4607.                M'ST
  4608.                 "(Groupspec may not be valid if the logon user does"
  4609.                M'EN;
  4610.                M'ST
  4611.                 "not have account manager capability.)"
  4612.                M'EN;
  4613.           end;
  4614.  
  4615.           << DELETE >>
  4616.  
  4617.           begin
  4618.                M'ST "Syntax:  DELETE filespec" M'EN;
  4619.                M'ST " " M'EN;
  4620.                M'ST
  4621.                 "This command causes the indicated filespec to be"
  4622.                M'EN;
  4623.                M'ST
  4624.                 "removed from disc."
  4625.                M'EN;
  4626.           end;
  4627.  
  4628.           << TYPE >>
  4629.  
  4630.  
  4631.           begin
  4632.                M'ST "Syntax:  TYPE filespec" M'EN;
  4633.                M'ST " " M'EN;
  4634.                M'ST "TYPE lists a file on your terminal." M'EN;
  4635.           end;
  4636.  
  4637.           << STATUS >>
  4638.  
  4639.           begin
  4640.                M'ST "Syntax:  { STATUS }" M'EN;
  4641.                M'ST "         { VERIFY }" M'EN;
  4642.                M'ST " " M'EN;
  4643.                M'ST
  4644.                 "STATUS provides a listing of the current file and"
  4645.                M'EN;
  4646.                M'ST
  4647.                 "transmission attributes."
  4648.                M'EN;
  4649.           end;
  4650.  
  4651.      end; << ITEM case >>
  4652.      M'ST " " M'EN;
  4653.      IB(ILEN-1) := " ";  <<Hopefully wipe out question mark>>
  4654.      FWRITE(CONUM, IB'W, -ILEN, %320);
  4655. end;
  4656. $PAGE
  4657. $PAGE "CMDINT - Command Interpreter"
  4658. $control segment=CMDINT'S
  4659. integer procedure SEARCH(TARGET, LENGTH, DICT, DEFN, START);
  4660. value                            LENGTH,             START;
  4661. integer                          LENGTH,             START;
  4662. byte array               TARGET,         DICT;
  4663. byte pointer                                   DEFN;
  4664. begin
  4665.  
  4666.      integer         I;
  4667.  
  4668.      byte pointer    P;
  4669.  
  4670.      SEARCH:=I:=0;
  4671.      @P:=@DICT;
  4672.      while P( P(0)-1 ) < byte( START )
  4673.      do @P := @P + integer( P(0) );
  4674.      while P(0) <> 0 do
  4675.      begin
  4676.           I:=I+1;
  4677.           if LENGTH <= integer( P(1) ) then
  4678.                if TARGET = P(2), (LENGTH) then
  4679.                     if LENGTH >= MIN'SIZE( integer( P(P(0)-1) ) ) then
  4680.                     begin
  4681.                          SEARCH:=I;
  4682.                          @DEFN:=@P + integer( P(0) )-1;
  4683.                          return;
  4684.                     end;
  4685.           @P:=@P + integer( P(0) );
  4686.      end;
  4687. end;
  4688.  
  4689. <<---------------------------------------------------------------->>
  4690.  
  4691. procedure CMDINT(ICMD,ICLEN);
  4692. value                 ICLEN ;
  4693. integer               ICLEN ;
  4694. byte array       ICMD       ;
  4695. begin
  4696.  
  4697.      byte array          CPARM(0:79);   << Current Parameter >>
  4698.  
  4699.      byte pointer        ITEMPTR,       << Points to found item >>
  4700.                          IB'PTR;        << Moves along input line >>
  4701.  
  4702.      integer             CPLEN,         << Length of CPARM      >>
  4703.                          CPVAL,         << Numeric value found  >>
  4704.                          ITEM,          << Index of CPARM  word >>
  4705.                          IBX,           << Index to IB          >>
  4706.                          IBYTE,         << Current Character    >>
  4707.                          X;             << Temp Variable        >>
  4708.  
  4709.      double              D'X;           << Temp Double          >>
  4710.  
  4711.      logical             DONE := false, << Done Flag >>
  4712.                          XFROK;         << Xfer OK flag >>
  4713.  
  4714.      real                P'INT,         << PAUSE Interval>>
  4715.                          BRIEFLY := 1.0;<< Give COMMAND some time >>
  4716.  
  4717.      label               TAKE'EXIT,
  4718.                          SEND'EXIT,
  4719.                          RECEIVE'EXIT,
  4720.                          SERVE'EXIT,
  4721.                          SET'EXIT;
  4722.  
  4723.      <<----------------------------------------------------------->>
  4724.  
  4725.      subroutine SCANIT(START);
  4726.      value             START;
  4727.      integer           START;
  4728.      begin
  4729.           ITEM:=NULLV;  << Default return >>
  4730.           CPLEN:=0;
  4731.           scan IB'PTR while "^ ", 1; << Skip blanks  >>
  4732.           if CARRY then              << End of input >>
  4733.           begin
  4734.                del;                  << Cut back stack >>
  4735.                return;
  4736.           end;
  4737.  
  4738.           @IB'PTR:=TOS;              << Point at the non-blank >>
  4739.           if IB'PTR = ALPHA  or  IB'PTR = "@"  then
  4740.           begin
  4741.                do begin
  4742.                     move CPARM(CPLEN):=IB'PTR while ANS, 0;
  4743.                     @IB'PTR:=TOS;    << Points after moved entity >>
  4744.                     CPLEN:=TOS - @CPARM;
  4745.                     if IB'PTR = "."  or  IB'PTR = "@"
  4746.                     or IB'PTR = "/"  then
  4747.                     begin
  4748.                          CPARM(CPLEN):=IB'PTR;
  4749.                          CPLEN:=CPLEN+1;
  4750.                          @IB'PTR:=@IB'PTR+1;
  4751.                     end;
  4752.                end
  4753.                until IB'PTR = SPECIAL;
  4754.                if SEARCH(CPARM, CPLEN, RESWDS, ITEMPTR, START) > 0 then
  4755.                     ITEM:=integer(ITEMPTR);
  4756.                return;
  4757.           end;
  4758.  
  4759.           if "0" <= integer(IB'PTR) <= "9"
  4760.           or IB'PTR = "-"  or  IB'PTR = "%"  then
  4761.           begin    << It looks numeric.  Will know for sure later. >>
  4762.                if IB'PTR = "-"  or  IB'PTR = "%"  then
  4763.                begin
  4764.                     move CPARM:=IB'PTR, (1), 2;
  4765.                     @IB'PTR:=@IB'PTR+1;
  4766.                end
  4767.                     else
  4768.                     TOS:=@CPARM;
  4769.                if not ("0" <= integer(IB'PTR) <= "9") then
  4770.                begin
  4771.                     del;                   << Cut back stack >>
  4772.                     return;
  4773.                end;
  4774.                move *:=IB'PTR while N, 0;  << Move numeric >>
  4775.                @IB'PTR:=TOS;               << Points after number>>
  4776.                CPLEN:=TOS - @CPARM;
  4777.                CPVAL:=binary(CPARM, CPLEN);
  4778.                if = then  << If this is bad then move numeric is bad >>
  4779.                     ITEM:=NUMBERV;
  4780.                return;
  4781.           end;
  4782.  
  4783.           if IB'PTR = "?" then
  4784.           begin
  4785.                ITEM:=QMARKV;
  4786.                @IB'PTR:=@IB'PTR+1;
  4787.                return;
  4788.           end;
  4789.  
  4790.           << At this point the item found is not alphanumeric,    >>
  4791.           << numeric (including optional minus sign), or question >>
  4792.           << mark. Pass it back for the command processor to work >>
  4793.           << with.                                                >>
  4794.  
  4795.           TOS:=@CPARM;
  4796.           while IB'PTR <> " "  and  IB'PTR <> "^" do
  4797.           begin
  4798.                move *:=IB'PTR, (1), 2;
  4799.                CPLEN:=CPLEN+1;
  4800.                @IB'PTR:=@IB'PTR+1;
  4801.           end;
  4802.  
  4803.           del;          << Cut back stack >>
  4804.      end;
  4805.  
  4806.      <<----------------------------------------------------------->>
  4807.      subroutine READ'USER(PROMPT);
  4808.      value                PROMPT;
  4809.      logical              PROMPT;
  4810.      begin
  4811.           IBX := 0; << Index to zero >>
  4812.           if ICLEN <> 0 then
  4813.           begin
  4814.                move IB := ICMD,(ICLEN);
  4815.                ILEN := ICLEN;
  4816.                ICLEN := 0;
  4817.           end
  4818.                else
  4819.           begin << Not initial command >>
  4820.  
  4821.                if CTLY then
  4822.                begin
  4823.                     M'ST "           " M'EN;
  4824.                     M'ST "<CONTROL-Y>" M'EN;
  4825.                     M'ST "           " M'EN;
  4826.                     if TAKENUM <> 0 then
  4827.                     begin
  4828.                          FCLOSE(TAKENUM,0,0);
  4829.                          TAKENUM := 0;
  4830.                     end;
  4831.  
  4832.                     CTLY := false;
  4833.                end;
  4834.  
  4835.                if TAKENUM <> 0 then
  4836.                begin << Open TAKE file >>
  4837.                     ILEN := FREAD(TAKENUM,IB'W,-72);
  4838.                     if > then
  4839.                     begin << End of file >>
  4840.                          FCLOSE(TAKENUM,0,0);
  4841.                          TAKENUM := 0;
  4842.                     end
  4843.                          else
  4844.                     if < then
  4845.                     begin
  4846.                          M'ST "Read error on TAKE file" M'EN;
  4847.                          FCLOSE(TAKENUM,0,0);
  4848.                          TAKENUM := 0;
  4849.                     end;
  4850.                end;
  4851.  
  4852.                if TAKENUM = 0 then
  4853.                do begin
  4854.                     if PROMPT then
  4855.                     begin
  4856.                          move PBUF := "KERMIT3000>";
  4857.                          FWRITE(CONUM,PBUF'W,-11,%320);
  4858.                     end;
  4859.                     ILEN := FREAD(CINUM,IB'W,-80);
  4860.                     if <> then
  4861.                     begin
  4862.                          move IB := "EXIT";
  4863.                          ILEN := 4;
  4864.                     end;
  4865.                end
  4866.                until ILEN > 0  or  not PROMPT;
  4867.           end;
  4868.           @IB'PTR:=@IB;
  4869.           IB(ILEN):="^";  << Stopper >>
  4870.           MY'JCW'VAL := IDLING;
  4871.      end;
  4872.  
  4873.      <<----------------------------------------------------------->>
  4874.  
  4875.      while not DONE do
  4876.      begin
  4877.           READ'USER(TRUE);
  4878.           SCANIT(NULLV);
  4879.  
  4880.           if TAKEV <= ITEM <= VERIFYV
  4881.           then case ITEM-1 of
  4882.           begin
  4883.           << TAKE >>
  4884.           begin
  4885.                SCANIT(QMARKV);
  4886.                while ITEM = QMARKV do
  4887.                begin
  4888.                     HELP(TAKEV);
  4889.                     READ'USER(FALSE);
  4890.                     SCANIT(QMARKV);
  4891.                     if CTLY then
  4892.                          go to TAKE'EXIT;
  4893.                end;
  4894.                if ITEM <> NULLV then  << No reserved words allowed >>
  4895.                begin
  4896.                     M'ST "Cannot use reserved word for filespec." M'EN;
  4897.                     go to TAKE'EXIT;
  4898.                end;
  4899.                CPARM(CPLEN) := " ";
  4900.                if TAKENUM <> 0 then
  4901.                begin
  4902.                     FCLOSE(TAKENUM,0,0);
  4903.                     TAKENUM := 0;
  4904.                end;
  4905.                TAKENUM := FOPEN(CPARM,%5,%2000);
  4906.                if TAKENUM = 0 then
  4907.                begin
  4908.                     M'ST "take error" M'EN;
  4909.                end;
  4910.           TAKE'EXIT:
  4911.           end;
  4912.  
  4913.           << SEND >>
  4914.  
  4915.           begin
  4916.                SCANIT(QMARKV); << get local file name >>
  4917.                while ITEM = QMARKV do
  4918.                begin
  4919.                     HELP(SENDV);
  4920.                     READ'USER(FALSE);
  4921.                     SCANIT(QMARKV);
  4922.                     if CTLY then
  4923.                          go to SEND'EXIT;
  4924.                end;
  4925.  
  4926.                MY'JCW'VAL := SEND'NG;  << pessimism >>
  4927.  
  4928.                while CPLEN = 0
  4929.                do begin
  4930.                     move PBUF:="HP3000 file name?";
  4931.                     FWRITE(CONUM,PBUF'W,-17,%320);
  4932.                     READ'USER(FALSE);
  4933.                     SCANIT(QMARKV);
  4934.                     if CTLY then
  4935.                          go to SEND'EXIT;
  4936.                end;
  4937.                move L'FNAME := CPARM,(CPLEN);
  4938.                L'FNAME(CPLEN) := " ";
  4939.                L'FNAME'LEN := CPLEN;
  4940.  
  4941.                if not VALID'FILE(L'FNAME, L'FNAME'LEN, OUT) then
  4942.                begin
  4943.                     M'ST ("Kermit file security error - ",
  4944.                           "see your account manager") M'EN;
  4945.                     DNUM := 0;
  4946.                     go to SEND'EXIT;
  4947.                end;
  4948.                DNUM := FOPEN(L'FNAME,5,0);
  4949.                if DNUM = 0 then
  4950.                begin
  4951.                     M'ST "File open error" M'EN;
  4952.                end
  4953.                     else
  4954.                begin
  4955.                     SCANIT(QMARKV);
  4956.                     if CPLEN <> 0 then
  4957.                     begin
  4958.                          move R'FNAME := CPARM,(CPLEN);
  4959.                     end;
  4960.                     R'FNAME'LEN := CPLEN;
  4961.  
  4962.                     if not OPEN'LINE then
  4963.                     begin
  4964.                          M'ST "Line open failure" M'EN;
  4965.                     end
  4966.                          else
  4967.                     begin
  4968.                          M'ST
  4969.                           ("Escape back to your local KERMIT ",
  4970.                            "and enter the RECEIVE command")
  4971.                          M'EN;
  4972.  
  4973.                          if I'DELAY > 0 then
  4974.                          begin
  4975.                               P'INT := real(I'DELAY);
  4976.                               PAUSE(P'INT);
  4977.                          end;
  4978.  
  4979.                          if R'FNAME'LEN <> 0 then
  4980.                               XFROK := SENDSW(R'FNAME,
  4981.                                               -R'FNAME'LEN)
  4982.                          else
  4983.                               XFROK := SENDSW(L'FNAME,
  4984.                                               -L'FNAME'LEN);
  4985.  
  4986.                          STATE := SBREAK;
  4987.                          if LDEV'CI = LDEV'LINE then
  4988.                               SHUT'LINE;  << Echo on, etc. >>
  4989.  
  4990.                          if not XFROK then
  4991.                          begin
  4992.                               M'ST "SEND failure" M'EN;
  4993.                          end
  4994.                               else
  4995.                          begin
  4996.                               M'ST "SEND completed" M'EN;
  4997.                          end;
  4998.                     end;
  4999.                end;
  5000.           SEND'EXIT:
  5001.                PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  5002.  
  5003.           L'FNAME'LEN := 0;
  5004.  
  5005.           end;
  5006.  
  5007.           << RECEIVE >>
  5008.  
  5009.           begin
  5010.                SCANIT(QMARKV);
  5011.                while ITEM = QMARKV do
  5012.                begin
  5013.                     HELP(RECEIVEV);
  5014.                     READ'USER(FALSE);
  5015.                     SCANIT(QMARKV);
  5016.                     if CTLY then
  5017.                          go to RECEIVE'EXIT;
  5018.                end;
  5019.  
  5020.                MY'JCW'VAL := RECV'NG;  << pessimism >>
  5021.  
  5022.                while CPLEN = 0
  5023.                do begin
  5024.                     move PBUF:="HP3000 file name?";
  5025.                     FWRITE(CONUM,PBUF'W,-17,%320);
  5026.                     READ'USER(FALSE);
  5027.                     SCANIT(QMARKV);
  5028.                     if CTLY then
  5029.                          go to RECEIVE'EXIT;
  5030.                end;
  5031.                move L'FNAME := CPARM,(CPLEN);
  5032.                L'FNAME'LEN := CPLEN;
  5033.                if VALID'FILE(L'FNAME, L'FNAME'LEN, IN) then
  5034.                << Its ok.  No action necessary. >>
  5035.                     else
  5036.                begin
  5037.                     M'ST ("Kermit file security error - ",
  5038.                           "see your account manager") M'EN;
  5039.                     go to RECEIVE'EXIT;
  5040.                END;
  5041.  
  5042.                move PBUF:="listf ", 2;
  5043.                move *:=L'FNAME, (L'FNAME'LEN), 2;
  5044.                move *:=(";$null", %15);
  5045.                COMMAND(PBUF, ERROR, PARM);
  5046.                if > then  << OK.  Its not there already. >>
  5047.                     else
  5048.                begin
  5049.                     move PBUF:=
  5050.                      "File is already present.  OK to remove? (Y/N)", 2;
  5051.                     PLEN:=TOS-@PBUF;
  5052.                     FWRITE(CONUM, PBUF'W, -PLEN, %320);
  5053.                     READ'USER(FALSE);
  5054.                     SCANIT(ONV);
  5055.                     if ITEM=YESV then
  5056.                     begin
  5057.                          move PBUF:="purge ",2;
  5058.                          move*:=L'FNAME, (L'FNAME'LEN), 2;
  5059.                          move *:=%15;
  5060.                          COMMAND(PBUF, ERROR, PARM);
  5061.                     end
  5062.                          else
  5063.                     begin
  5064.                          M'ST "RECEIVE attempt abandoned" M'EN;
  5065.                          go to RECEIVE'EXIT;
  5066.                     end;
  5067.                end;
  5068.  
  5069.  
  5070.                if not OPEN'LINE then
  5071.                begin
  5072.                     M'ST "Line open error" M'en;
  5073.                end
  5074.                     else
  5075.                begin
  5076.                     M'ST
  5077.                      ("Escape back to your local KERMIT ",
  5078.                       "and enter the SEND command")
  5079.                     M'EN;
  5080.  
  5081.                     XFROK := RECSW(false);
  5082.  
  5083.                     if LDEV'CI = LDEV'LINE then
  5084.                          SHUT'LINE;  << Echo on, etc. >>
  5085.  
  5086.                     if not XFROK then
  5087.                     begin
  5088.                          M'ST "RECEIVE error" M'EN;
  5089.                     end
  5090.                          else
  5091.                     begin
  5092.                          M'ST "RECEIVE complete" M'EN;
  5093.                     end;
  5094.                end;
  5095.           RECEIVE'EXIT:
  5096.           PUTJCW(KERM'JCW, MY'JCW'VAL, JCW'ERR);
  5097.  
  5098.           L'FNAME'LEN := 0;
  5099.  
  5100.           end;
  5101.  
  5102.           << SERVE >>
  5103.  
  5104.           begin
  5105.                SCANIT(QMARKV);
  5106.                if ITEM = QMARKV then
  5107.                begin
  5108.                     HELP(SERVEV);
  5109.                     READ'USER(FALSE);
  5110.                     if CTLY then
  5111.                          go to SERVE'EXIT;
  5112.                end;
  5113.                if not OPEN'LINE then
  5114.                begin
  5115.                     M'ST "Line open failure" M'EN;
  5116.                end
  5117.                     else
  5118.                begin
  5119.                     M'ST
  5120.                      ("Entering SERVER mode - ",
  5121.                       "escape back to your local KERMIT")
  5122.                     M'EN;
  5123.                     SERVER;
  5124.  
  5125.                     if LDEV'CI = LDEV'LINE then SHUT'LINE;
  5126.  
  5127.                     <<DONE := not CTLY;>>
  5128.                end;
  5129.           SERVE'EXIT:
  5130.           end;
  5131.  
  5132.           << SET >>
  5133.  
  5134.           begin
  5135.                SCANIT(DEBUGV);
  5136.                if ITEM = QMARKV then
  5137.                begin
  5138.                     HELP(SETV, DEBUGV-1);
  5139.                     READ'USER(FALSE);
  5140.                     SCANIT(DEBUGV);
  5141.                     if CTLY then
  5142.                          go to SET'EXIT;
  5143.                end;
  5144.                if not (DEBUGV <= ITEM <= FASTV) then
  5145.                begin
  5146.                     M'ST "set error" M'EN
  5147.                end
  5148.                     else
  5149.                case ITEM - DEBUGV of
  5150.                begin
  5151.  
  5152.                << SET DEBUG >>
  5153.  
  5154.                begin
  5155.                     SCANIT(QMARKV);
  5156.                     while ITEM = QMARKV do
  5157.                     begin
  5158.                          HELP(SETV, DEBUGV);
  5159.                          READ'USER(FALSE);
  5160.                          SCANIT(QMARKV);
  5161.                          if CTLY then
  5162.                               go to SET'EXIT;
  5163.                     end;
  5164.                     if ITEM = NUMBERV then
  5165.                          DEBUG'MODE:=CPVAL
  5166.                          else
  5167.                     begin
  5168.                          M'ST "set debug error" M'EN;
  5169.                     end;
  5170.                end;
  5171.  
  5172.                << SET DELAY >>
  5173.  
  5174.                begin
  5175.                     SCANIT(QMARKV);
  5176.                     while ITEM = QMARKV do
  5177.                     begin
  5178.                          HELP(SETV, DELAYV);
  5179.                          READ'USER(FALSE);
  5180.                          SCANIT(QMARKV);
  5181.                          if CTLY then
  5182.                               go to SET'EXIT;
  5183.                     end;
  5184.                     if CPLEN = 0 then
  5185.                     begin
  5186.                          I'DELAY := 0;
  5187.                     end
  5188.                          else
  5189.                     begin
  5190.                          if ITEM = NUMBERV then
  5191.                               I'DELAY:=CPVAL
  5192.                               else
  5193.                          begin
  5194.                               M'ST "set delay error" M'EN;
  5195.                          end;
  5196.                     end;
  5197.                end;
  5198.  
  5199.                << SET LINE >>
  5200.  
  5201.                begin
  5202.                     SCANIT(QMARKV);
  5203.                     while ITEM = QMARKV do
  5204.                     begin
  5205.                          HELP(SETV, LINEV);
  5206.                          READ'USER(FALSE);
  5207.                          SCANIT(QMARKV);
  5208.                          if CTLY then
  5209.                               go to SET'EXIT;
  5210.                     end;
  5211.                     if CPLEN = 0 then
  5212.                     begin
  5213.                          LDEV'LINE := 0;
  5214.                          SHUT'LINE;
  5215.                     end
  5216.                          else
  5217.                     begin
  5218.                          if ITEM <> NUMBERV then
  5219.                          begin
  5220.                               M'ST "set line error" M'EN;
  5221.                          end
  5222.                               else
  5223.                          begin
  5224.                               LDEV'LINE:=CPVAL;
  5225.                               SHUT'LINE;
  5226.                          end;
  5227.                     end;
  5228.                     ASCII(LDEV'LINE,-10,KERM'JCW(7));
  5229.                end;
  5230.  
  5231.                << SET SEND >>
  5232.  
  5233.                begin
  5234.                     SCANIT(PAUSEV);
  5235.                     while ITEM = QMARKV do
  5236.                     begin
  5237.                          HELP(SETV, SENDV'1);
  5238.                          READ'USER(FALSE);
  5239.                          SCANIT(PAUSEV);
  5240.                          if CTLY then
  5241.                               go to SET'EXIT;
  5242.                     end;
  5243.                     if ITEM = PAUSEV then
  5244.                     begin
  5245.                          SCANIT(QMARKV);
  5246.                          if ITEM <> NUMBERV then
  5247.                          begin
  5248.                               M'ST "send pause error" M'EN;
  5249.                          end
  5250.                               else
  5251.                          PAUSE'CNT:=CPVAL;
  5252.                     end
  5253.  
  5254.                          else
  5255.                     if ITEM = BINARYV then
  5256.                     begin
  5257.                          SCANIT(AUTOV); << POTENTIAL TROUBLE >>
  5258.                          if (AUTOV <= ITEM <= OFFV) then
  5259.                          SND'BINARY:=ITEM-AUTOV
  5260.                               else
  5261.                          begin
  5262.                               M'ST "set send binary error" M'EN;
  5263.                          end;
  5264.                     end
  5265.                          else
  5266.                     begin
  5267.                          M'ST "set send error" M'EN;
  5268.                     end
  5269.                end;
  5270.  
  5271.                << SET SPEED >>
  5272.  
  5273.                begin
  5274.                     SCANIT(QMARKV);
  5275.                     while ITEM = QMARKV do
  5276.                     begin
  5277.                          HELP(SETV, SPEEDV);
  5278.                          READ'USER(FALSE);
  5279.                          SCANIT(QMARKV);
  5280.                          if CTLY then
  5281.                               go to SET'EXIT;
  5282.                     end;
  5283.                     X := CPVAL;
  5284.                     if (X <> 30) land (X <> 60) land (X <> 120) land
  5285.                        (X <> 240) land (X <> 480) land (X <> 960) then
  5286.                     begin
  5287.                          M'ST
  5288.  
  5289.                          "Invalid SPEED, use 30,60,120,240,480,960"
  5290.  
  5291.                          M'EN;
  5292.                     end
  5293.                          else
  5294.                     TSPEED := X;
  5295.                end;
  5296.  
  5297.                << SET HANDSHAKE >>
  5298.  
  5299.                begin
  5300.                     SCANIT(ONV);
  5301.                     while ITEM = QMARKV do
  5302.                     begin
  5303.                          HELP(SETV, HANDSHAKEV);
  5304.                          READ'USER(FALSE);
  5305.                          SCANIT(ONV);
  5306.                          if CTLY then
  5307.                               go to SET'EXIT;
  5308.                     end;
  5309.                     if (NONEV <= ITEM <= XON2V) then
  5310.                     HNDSHK:=ITEM-NONEV
  5311.                          else
  5312.                     begin
  5313.                          M'ST "set handshake error" M'EN;
  5314.                     end;
  5315.                end;
  5316.  
  5317.                << SET RECEIVE >>
  5318.  
  5319.                begin
  5320.                     SCANIT(PAUSEV);
  5321.                     while ITEM = QMARKV do
  5322.                     begin
  5323.                          HELP(SETV, RECEIVEV'1, BINARYV-1);
  5324.                          READ'USER(FALSE);
  5325.                          SCANIT(PAUSEV);
  5326.                          if CTLY then
  5327.                               go to SET'EXIT;
  5328.                     end;
  5329.                     if not (BINARYV <= ITEM <= EXPTABV)  then
  5330.                     begin
  5331.                          M'ST "set receive error" M'EN;
  5332.                     end
  5333.                          else
  5334.                     case ITEM-BINARYV of
  5335.                     begin
  5336.  
  5337.                     << SET RECEIVE BINARY >>
  5338.  
  5339.                     begin
  5340.                          SCANIT(ONV);
  5341.                          while ITEM = QMARKV do
  5342.                          begin
  5343.                               HELP(SETV, RECEIVEV'1, BINARYV);
  5344.                               READ'USER(FALSE);
  5345.                               SCANIT(ONV);
  5346.                               if CTLY then
  5347.                                    go to SET'EXIT;
  5348.                          end;
  5349.                          if ITEM = ONV  or  ITEM = OFFV then
  5350.                          RCV'BINARY:=(ITEM=ONV)
  5351.                               else
  5352.                          begin
  5353.                               M'ST "set receive binary error" M'EN;
  5354.                          end;
  5355.                     end;
  5356.  
  5357.                     << SET RECEIVE DEVICE >>
  5358.  
  5359.                     begin
  5360.                          SCANIT(QMARKV);
  5361.                          while ITEM = QMARKV do
  5362.                          begin
  5363.                               HELP(SETV, RECEIVEV'1, DEVICEV);
  5364.                               READ'USER(FALSE);
  5365.                               SCANIT(QMARKV);
  5366.                                    if CTLY then
  5367.                                         go to SET'EXIT;
  5368.                          end;
  5369.                          if CPLEN <> 0 then
  5370.                          begin
  5371.                               move RCV'DEV := CPARM,(CPLEN);
  5372.                               RCV'DEV(CPLEN) := CR;
  5373.                          end
  5374.                          else
  5375.                               move RCV'DEV := ("DISC", CR);
  5376.                     end;
  5377.  
  5378.                     << SET RECEIVE FCODE >>
  5379.  
  5380.                     begin
  5381.                          SCANIT(QMARKV);
  5382.                          while ITEM = QMARKV do
  5383.                          begin
  5384.                               HELP(SETV, RECEIVEV'1, FCODEV);
  5385.                               READ'USER(FALSE);
  5386.                               SCANIT(QMARKV);
  5387.                               if CTLY then
  5388.                                    go to SET'EXIT;
  5389.                          end;
  5390.                          if ITEM <> NUMBERV then
  5391.                          begin
  5392.                               M'ST "set receive fcode error" M'EN;
  5393.                          end
  5394.                               else
  5395.                          begin
  5396.                               RCV'FCODE := CPVAL;
  5397.                          end;
  5398.                     end;
  5399.  
  5400.                     << SET RECEIVE RECLEN >>
  5401.  
  5402.                     begin
  5403.                          SCANIT(QMARKV);
  5404.                          while ITEM = QMARKV do
  5405.                          begin
  5406.                               HELP(SETV, RECEIVEV'1, RECLENV);
  5407.                               READ'USER(FALSE);
  5408.                               SCANIT(QMARKV);
  5409.                               if CTLY then
  5410.                                    go to SET'EXIT;
  5411.                          end;
  5412.                          if ITEM <> NUMBERV then
  5413.                          begin
  5414.                               M'ST "set receive reclen error" M'EN;
  5415.                          end
  5416.                               else
  5417.                          if CPVAL <> 0 then
  5418.                          begin
  5419.                               RCV'RECLEN := CPVAL;
  5420.                          end
  5421.                               else
  5422.                          RCV'RECLEN := -254;
  5423.                     end;
  5424.  
  5425.                     << SET RECEIVE BLOCKF >>
  5426.  
  5427.                     begin
  5428.                          SCANIT(QMARKV);
  5429.                          while ITEM = QMARKV do
  5430.                          begin
  5431.                               HELP(SETV, RECEIVEV'1, BLOCKFV);
  5432.                               READ'USER(FALSE);
  5433.                               SCANIT(QMARKV);
  5434.                               if CTLY then
  5435.                                    go to SET'EXIT;
  5436.                          end;
  5437.                          if ITEM <> NUMBERV then
  5438.                          begin
  5439.                               M'ST "set receive blockf error" M'EN;
  5440.                          end
  5441.                               else
  5442.                          begin
  5443.                               RCV'BLOCKF := CPVAL;
  5444.                          end;
  5445.                     end;
  5446.  
  5447.                     << SET RECEIVE FIXREC >>
  5448.  
  5449.                     begin
  5450.                          SCANIT(ONV);
  5451.                          while ITEM = QMARKV do
  5452.                          begin
  5453.                               HELP(SETV, RECEIVEV'1, FIXRECV);
  5454.                               READ'USER(FALSE);
  5455.                               SCANIT(ONV);
  5456.                               if CTLY then
  5457.                                    go to SET'EXIT;
  5458.                          end;
  5459.                          if ITEM = ONV  or  ITEM = OFFV then
  5460.                          RCV'FIXREC:=(ITEM=ONV)
  5461.                               else
  5462.                          begin
  5463.                               M'ST "set receive fixrec error" M'EN;
  5464.                          end;
  5465.                     end;
  5466.  
  5467.                     << SET RECEIVE MAXREC >>
  5468.  
  5469.                     begin
  5470.                          SCANIT(QMARKV);
  5471.                          while ITEM = QMARKV do
  5472.                          begin
  5473.                               HELP(SETV, RECEIVEV'1, MAXRECV);
  5474.                               READ'USER(FALSE);
  5475.                               SCANIT(QMARKV);
  5476.                               if CTLY then
  5477.                                    go to SET'EXIT;
  5478.                          end;
  5479.                          D'X := DBINARY(CPARM,CPLEN);
  5480.                          if <> then
  5481.                          begin
  5482.                               M'ST "set receive maxrec error" M'EN;
  5483.                          end
  5484.                               else
  5485.                          begin
  5486.                               RCV'MAXREC := D'X;
  5487.                          end
  5488.                     end;
  5489.  
  5490.                     << SET RECEIVE MAXEXT >>
  5491.  
  5492.                     begin
  5493.                          SCANIT(QMARKV);
  5494.                          while ITEM = QMARKV do
  5495.                          begin
  5496.                               HELP(SETV, RECEIVEV'1, MAXEXTV);
  5497.                               READ'USER(FALSE);
  5498.                               SCANIT(QMARKV);
  5499.                               if CTLY then
  5500.                                    go to SET'EXIT;
  5501.                          end;
  5502.                          if ITEM <> NUMBERV then
  5503.                          begin
  5504.                               M'ST "set receive maxext error" M'EN;
  5505.                          end
  5506.                               else
  5507.                          begin
  5508.                               RCV'MAXEXT := CPVAL;
  5509.                          end
  5510.                     end;
  5511.  
  5512.                     << SET RECEIVE SAVESP >>
  5513.  
  5514.                     begin
  5515.                          SCANIT(ONV);
  5516.                          while ITEM = QMARKV do
  5517.                          begin
  5518.                               HELP(SETV, RECEIVEV'1, SAVESPV);
  5519.                               READ'USER(FALSE);
  5520.                               SCANIT(ONV);
  5521.                               if CTLY then
  5522.                                    go to SET'EXIT;
  5523.                          end;
  5524.                          if ITEM = ONV  or  ITEM = OFFV then
  5525.                          RCV'SAVESP:=(ITEM=ONV)
  5526.                               else
  5527.                          begin
  5528.                               M'ST "set receive savesp error" M'EN;
  5529.                          end;
  5530.                     end;
  5531.  
  5532.                     << SET RECEIVE PROG >>
  5533.  
  5534.                     begin
  5535.                          SCANIT(QMARKV);
  5536.                          while ITEM = QMARKV do
  5537.                          if ITEM = QMARKV then
  5538.                          begin
  5539.                               HELP(SETV, RECEIVEV'1, PROGV);
  5540.                               READ'USER(FALSE);
  5541.                               SCANIT(QMARKV);
  5542.                               if CTLY then
  5543.                                    go to SET'EXIT;
  5544.                          end;
  5545.                          RCV'BINARY := true;
  5546.                          RCV'FIXREC := true;
  5547.                          RCV'FCODE  := 1029;
  5548.                          RCV'RECLEN := 128;
  5549.                          RCV'BLOCKF := 1;
  5550.                          RCV'MAXEXT := 1;
  5551.                     end;
  5552.  
  5553.                     << SET RECEIVE BIN128 >>
  5554.  
  5555.                     begin
  5556.                          SCANIT(QMARKV);
  5557.                          while ITEM = QMARKV do
  5558.                          if ITEM = QMARKV then
  5559.                          begin
  5560.                               HELP(SETV, RECEIVEV'1, BIN128V);
  5561.                               READ'USER(FALSE);
  5562.                               SCANIT(QMARKV);
  5563.                               if CTLY then
  5564.                                    go to SET'EXIT;
  5565.                          end;
  5566.                          RCV'BINARY := true;
  5567.                          RCV'FIXREC := false;
  5568.                          RCV'FCODE  := 0;
  5569.                          RCV'RECLEN := 128;
  5570.                          RCV'BLOCKF := 0;
  5571.                     end;
  5572.  
  5573.                     << SET RECEIVE TEXT >>
  5574.  
  5575.                     begin
  5576.                          SCANIT(QMARKV);
  5577.                          while ITEM = QMARKV do
  5578.                          if ITEM = QMARKV then
  5579.                          begin
  5580.                               HELP(SETV, RECEIVEV'1, TEXTV);
  5581.                               READ'USER(FALSE);
  5582.                               SCANIT(QMARKV);
  5583.                               if CTLY then
  5584.                                    go to SET'EXIT;
  5585.                          end;
  5586.                          RCV'BINARY := false;
  5587.                          RCV'FIXREC := false;
  5588.                          RCV'FCODE  := 0;
  5589.                          RCV'RECLEN := -254;
  5590.                          RCV'BLOCKF := 0;
  5591.                     end;
  5592.  
  5593.                     << SET RECEIVE TXT80 >>
  5594.  
  5595.                     begin
  5596.                          SCANIT(QMARKV);
  5597.                          while ITEM = QMARKV do
  5598.                          begin
  5599.                               HELP(SETV, RECEIVEV'1, TXT80V);
  5600.                               READ'USER(FALSE);
  5601.                               SCANIT(QMARKV);
  5602.                               if CTLY then
  5603.                                    go to SET'EXIT;
  5604.                          end;
  5605.                          RCV'BINARY := false;
  5606.                          RCV'FIXREC := true;
  5607.                          RCV'FCODE  := 0;
  5608.                          RCV'RECLEN := -80;
  5609.                          RCV'BLOCKF := 16;
  5610.                     end;
  5611.  
  5612.                     << SET RECEIVE EXPTAB >>
  5613.  
  5614.                     begin
  5615.                          SCANIT(ONV);
  5616.                          while ITEM = QMARKV  do
  5617.                          begin
  5618.                               HELP(SETV, RECEIVEV'1, EXPTABV);
  5619.                               READ'USER(FALSE);
  5620.                               SCANIT(ONV);
  5621.                               if CTLY then
  5622.                                    go to SET'EXIT;
  5623.                          end;
  5624.                          if ITEM = ONV  or  ITEM = OFFV  then
  5625.                               EXP'TABS:=(ITEM=ONV)
  5626.                               else
  5627.                          begin
  5628.                               M'ST "set receive exptab error" M'EN;
  5629.                          end;
  5630.                     end;
  5631.  
  5632.                     end;  << SET RECEIVE cases >>
  5633.                end;
  5634.  
  5635.                << SET LOG >>
  5636.  
  5637.                begin
  5638.                     SCANIT(PAUSEV);
  5639.                     while ITEM = QMARKV do
  5640.                     begin
  5641.                          HELP(SETV, LOGV);
  5642.                          READ'USER(FALSE);
  5643.                          SCANIT(PAUSEV);
  5644.                          if CTLY then
  5645.                               go to SET'EXIT;
  5646.                     end;
  5647.                     if LOGNUM <> 0 and LOGNUM <> CONUM then
  5648.                     begin
  5649.                          if ITEM = PURGEV  then
  5650.                          begin
  5651.                               FCLOSE(LOGNUM,%4,0);
  5652.                               CPLEN := 0;
  5653.                          end
  5654.                          else
  5655.                               FCLOSE(LOGNUM,%11,0);
  5656.                          LOGNUM := 0;
  5657.                     end
  5658.                          else
  5659.                     if ITEM = PURGEV  then
  5660.                          CPLEN := 0;
  5661.  
  5662.                  << SCANIT;  Was done above >>
  5663.                     if CPLEN = 0 then
  5664.                     begin
  5665.                          << Take no action >>
  5666.                     end
  5667.                          else
  5668.                     begin
  5669.                     move LOGNAME:=CPARM, (LOGNAME'LEN:=CPLEN);
  5670.                     move PBUF:="listf ", 2;
  5671.                     move *:=LOGNAME, (LOGNAME'LEN), 2;
  5672.                     move *:=(";$null", %15);
  5673.                     COMMAND(PBUF, ERROR, PARM);
  5674.                     if ERROR=907 then  << OK.  Its not there already. >>
  5675.                          else
  5676.                     begin
  5677.                          move PBUF:=
  5678.                           ("File is already present.  ",
  5679.                            "Ok to remove? (Y/N)"), 2;
  5680.                          PLEN:=TOS-@PBUF;
  5681.                          FWRITE(CONUM, PBUF'W, -PLEN, %320);
  5682.                          READ'USER(FALSE);
  5683.                          SCANIT(ONV);
  5684.                          if ITEM=YESV then
  5685.                          begin
  5686.                               move PBUF:="purge ",2;
  5687.                               move *:=LOGNAME, (LOGNAME'LEN), 2;
  5688.                               PLEN:=TOS-@PBUF;
  5689.                               PBUF(PLEN):=%15;
  5690.                               COMMAND(PBUF, ERROR, PARM);
  5691.                          end
  5692.                               else
  5693.                          begin
  5694.                               M'ST "SET LOG attempt abandoned" M'EN;
  5695.                               go to SET'EXIT;
  5696.                          end;
  5697.                     end;
  5698.                     LOGNAME(LOGNAME'LEN):=" ";
  5699.                     LOGNUM:=FOPEN(LOGNAME,%4,%1,64,,,,2,,10016D,32);
  5700.                     if LOGNUM = 0 then
  5701.                     begin
  5702.                          M'ST "File open error" M'EN;
  5703.                     end;
  5704.                     end;
  5705.                end;
  5706.  
  5707.                     << SET SOH >>
  5708.  
  5709.                     begin
  5710.                          SCANIT(QMARKV);
  5711.                          while ITEM = QMARKV do
  5712.                          begin
  5713.                               HELP(SETV, SOHV);
  5714.                               READ'USER(FALSE);
  5715.                               SCANIT(QMARKV);
  5716.                               if CTLY then
  5717.                                    go to SET'EXIT;
  5718.                          end;
  5719.                          if ITEM = NUMBERV then
  5720.                               SOH:=byte(CPVAL)
  5721.                               else
  5722.                          begin
  5723.                               M'ST "set soh error" M'EN;
  5724.                          end;
  5725.                     end;
  5726.                     << SET FAST >>
  5727.  
  5728.                     begin
  5729.                          SCANIT(ONV);
  5730.                          while ITEM = QMARKV do
  5731.                          begin
  5732.                               HELP(SETV, FASTV);
  5733.                               READ'USER(FALSE);
  5734.                               SCANIT(ONV);
  5735.                               if CTLY then
  5736.                                    go to SET'EXIT;
  5737.                          end;
  5738.                          if ITEM = ONV  or  ITEM = OFFV then
  5739.                          IMPATIENT:=(ITEM=ONV)
  5740.                               else
  5741.                          begin
  5742.                               M'ST "set fast error" M'EN;
  5743.                          end;
  5744.                     end;
  5745.  
  5746.                end; << SET cases >>
  5747.  
  5748.           SET'EXIT:
  5749.           end;
  5750.  
  5751.           << EXIT >>
  5752.  
  5753.           begin
  5754.                SCANIT(QMARKV);
  5755.                while ITEM = QMARKV do
  5756.                begin
  5757.                     HELP(EXITV);
  5758.                     READ'USER(FALSE);
  5759.                     SCANIT(QMARKV);
  5760.                     if CTLY then
  5761.                        go to EXIT'EXIT;
  5762.                end;
  5763.                DONE := true;
  5764.           EXIT'EXIT:
  5765.           end;
  5766.  
  5767.           << DIR >>
  5768.  
  5769.           begin
  5770.                SCANIT(QMARKV);
  5771.                while ITEM = QMARKV do
  5772.                begin
  5773.                     HELP(DIRV);
  5774.                     READ'USER(FALSE);
  5775.                     SCANIT(QMARKV);
  5776.                     if CTLY then
  5777.                          go to DIR'EXIT;
  5778.                end;
  5779.                begin
  5780.                     move PBUF := "LISTF ", 2;
  5781.                     move * := CPARM, (CPLEN), 2;
  5782.                     move * := (", 2", CR);
  5783.                     COMMAND(PBUF, ERROR, PARM);
  5784.                     if ERROR > 0 then
  5785.                     begin
  5786.                          move PBUF := "CIerror ", 2;
  5787.                          PLEN := TOS-@PBUF;
  5788.                          PLEN := PLEN+ASCII(ERROR, 10, PBUF(PLEN));
  5789.                          FWRITE(CONUM, PBUF'W, -PLEN, 0);
  5790.                     end;
  5791.                end;
  5792.           DIR'EXIT:
  5793.           end;
  5794.  
  5795.           << SPACE >>
  5796.  
  5797.           begin
  5798.                SCANIT(QMARKV);
  5799.           while ITEM = QMARKV do
  5800.                begin
  5801.                     HELP(SPACEV);
  5802.                     READ'USER(FALSE);
  5803.                     SCANIT(QMARKV);
  5804.                     if CTLY then
  5805.                          go to SPACE'EXIT;
  5806.                end;
  5807.                begin
  5808.                     move PBUF := "REPORT ", 2;
  5809.                     move * := CPARM, (CPLEN), 2;
  5810.                     move * := CR;
  5811.                     COMMAND(PBUF, ERROR, PARM);
  5812.                     if ERROR > 0 then
  5813.                     begin
  5814.                          move PBUF := "CIerror ", 2;
  5815.                          PLEN := TOS-@PBUF;
  5816.                          PLEN := PLEN+ASCII(ERROR, 10, PBUF(PLEN));
  5817.                          FWRITE(CONUM, PBUF'W, -PLEN, 0);
  5818.                     end
  5819.                          else
  5820.                     begin
  5821.                          M'ST " " M'EN;  << Cosmetic output >>
  5822.                     end;
  5823.                end;
  5824.           SPACE'EXIT:
  5825.           end;
  5826.  
  5827.           << DELETE >>
  5828.  
  5829.           begin
  5830.                SCANIT(QMARKV);
  5831.                while ITEM = QMARKV do
  5832.                begin
  5833.                     HELP(DELETEV);
  5834.                     READ'USER(FALSE);
  5835.                     SCANIT(QMARKV);
  5836.                     if CTLY then
  5837.                          go to DELETE'EXIT;
  5838.                end;
  5839.                if VALID'FILE(CPARM, CPLEN, IN) then
  5840.                begin
  5841.                     move PBUF := "PURGE ", 2;
  5842.                     move * := CPARM, (CPLEN), 2;
  5843.                     move * := CR;
  5844.                     COMMAND(PBUF, ERROR, PARM);
  5845.                     if ERROR > 0 then
  5846.                     begin
  5847.                          move PBUF := "CIerror ", 2;
  5848.                          PLEN := TOS-@PBUF;
  5849.                          PLEN := PLEN+ASCII(ERROR, 10, PBUF(PLEN));
  5850.                          FWRITE(CONUM, PBUF'W, -PLEN, 0);
  5851.                     end;
  5852.                     PAUSE(BRIEFLY);  << Let COMMAND finish >>
  5853.                end
  5854.                     else
  5855.                begin
  5856.                     M'ST "Filespec missing or invalid" M'EN;
  5857.                end;
  5858.           DELETE'EXIT:
  5859.           end;
  5860.  
  5861.           << TYPE >>
  5862.  
  5863.           begin
  5864.                SCANIT(QMARKV); << get local file name >>
  5865.                while ITEM = QMARKV do
  5866.                begin
  5867.                     HELP(TYPEV);
  5868.                     READ'USER(FALSE);
  5869.                     SCANIT(QMARKV);
  5870.                     if CTLY then
  5871.                          go to SEND'EXIT;
  5872.                end;
  5873.                while CPLEN = 0
  5874.                do begin
  5875.                     move PBUF:="HP3000 file name?";
  5876.                     FWRITE(CONUM,PBUF'W,-17,%320);
  5877.                     READ'USER(FALSE);
  5878.                     SCANIT(QMARKV);
  5879.                     if CTLY then
  5880.                          go to SEND'EXIT;
  5881.                end;
  5882.                move L'FNAME := CPARM,(CPLEN);
  5883.                L'FNAME(CPLEN) := " ";
  5884.                L'FNAME'LEN := CPLEN;
  5885.  
  5886.                M'ST " " M'EN;
  5887.                if TYPESW then
  5888.                begin
  5889.                     M'ST " " M'EN;
  5890.                     M'ST "TYPE completed" M'EN;
  5891.                end
  5892.                     else
  5893.                begin
  5894.                     M'ST " " M'EN;
  5895.                     M'ST "TYPE failure" M'EN;
  5896.                end;
  5897.  
  5898.                L'FNAME'LEN := 0;
  5899.  
  5900.           end;
  5901.  
  5902.           << VERIFY >>
  5903.  
  5904.           begin
  5905.                SCANIT(QMARKV);
  5906.                while ITEM = QMARKV do
  5907.                begin
  5908.                     HELP(VERIFYV);
  5909.                     READ'USER(FALSE);
  5910.                     SCANIT(QMARKV);
  5911.                     if CTLY then
  5912.                          go to VERIFY'EXIT;
  5913.                end;
  5914.                VERIFY;
  5915.           VERIFY'EXIT:
  5916.           end;
  5917.  
  5918.           end << case >>
  5919.                else
  5920.           if ITEM = QMARKV then
  5921.                HELP(NULLV)
  5922.  
  5923.                else
  5924.           begin
  5925.                M'ST "command error" M'EN;
  5926.           end;
  5927.      end;
  5928. end;
  5929.  
  5930. <<*****************************************************************>>
  5931.  
  5932. $PAGE "Outer Block"
  5933. $control segment=KERMIT
  5934.      if (TAKE'VAL:=PARM'VAL)=0 then <<Must be in outer block to work>>
  5935.           TAKE'VAL:=GETJCW;
  5936.      if not KINIT then
  5937.      begin
  5938.           QUIT(7300+TAKE'VAL);
  5939.      end
  5940.           else
  5941.      begin
  5942.           CMDINT(INFO'STR,INFO'LEN);
  5943.           SHUT'LINE;
  5944.           if HAVE'KTEMP then KILL'KTEMP;
  5945.           if LOGNUM <> 0 then
  5946.                FCLOSE(LOGNUM, %11, 0);
  5947.      end;
  5948. END.
  5949.