home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / cmsqueens / cm2ker.pas < prev    next >
Pascal/Delphi Source File  |  2020-01-01  |  110KB  |  2,510 lines

  1. 20-May-88 14:33:11-EDT,112639;000000000001
  2. Return-Path: <@CUVMA.COLUMBIA.EDU:VIC@QUCDN.BITNET>
  3. Received: from CUVMA.COLUMBIA.EDU by CU20B.COLUMBIA.EDU with TCP; Fri 20 May 88 14:32:38-EDT
  4. Received: from CUVMA.COLUMBIA.EDU(MAILER) by CUVMA.COLUMBIA.EDU(SMTP) ; Fri, 20 May 88 14:24:17 EDT
  5. Received: from QUCDN.NETNORTH by CUVMA.COLUMBIA.EDU (Mailer X1.25) with BSMTP
  6.  id 1343; Fri, 20 May 88 14:24:06 EDT
  7. Received: by QUCDN (Mailer X1.24) id 2511; Fri, 20 May 88 14:08:09 EDT
  8. Date:    Fri, 20 May 88 14:04 EDT
  9. From:    VIC%QUCDN.BITNET@CUVMA.COLUMBIA.EDU
  10. To:      sy.fdc@cu20b.columbia.edu
  11. Subject: pascalvs kermit-cms
  12.  
  13.     Well if you are going stash away a copy of the pascalvs kermit some
  14. where, you might as well stash the latest version of it.  I have attached
  15. our latest version of kermit-cms below.       Victor Lee.
  16. ------------cut here -------------------------------------------------------
  17. PROGRAM  KERMIT ;
  18. (* ***************************************************************** *)
  19. (* KERMIT - File transfer Program.                                   *)
  20. (* Author - Victor Lee, Queen's University, Kingston, Canada         *)
  21. (*          VIC at QUCDN                                             *)
  22. (* Date   - 1983 December                                            *)
  23. (*          1984 January  - added KERMIT server code.                *)
  24. (*          1984 April    - new linemode facility for series1.       *)
  25. (*                        - fix DEL char recognition.                *)
  26. (*                        - If the 8th bit is set for a ASCII char   *)
  27. (*                          the 8th bit quote char will be store     *)
  28. (*                          in the file as 80 hex char and not an"&" *)
  29. (*                          which is the default bit8 quote char.    *)
  30. (*          1984 August   - send nak if we get a N type packet       *)
  31. (*                          instead of aborting immediately.         *)
  32. (*                                                                   *)
  33. (*          1984 September- when sending a file to the micro a 80hex *)
  34. (*                          character will be treated as an 8th bit  *)
  35. (*                          flag for the character to follow. This   *)
  36. (*                          will permit WORDSTAR file to be sent     *)
  37. (*                          back to the micro without distortion.    *)
  38. (*          1985 January  - assume all non-KERMIT commands to be     *)
  39. (*                          CMS commands.                            *)
  40. (*          1985 February - Eliminate leading blanks in commands.    *)
  41. (*          1985 February - Add an initial 'Receive Packet' to the   *)
  42. (*                          receive command just incase the other    *)
  43. (*                          Kermit can act as a SERVER.  Also        *)
  44. (*                          Kermit to be fired off with parameters   *)
  45. (*                          which is usefull if the other kermit     *)
  46. (*                          is a server kermit.                      *)
  47. (*                          Include send and receive "AS" function.  *)
  48. (*                          Implement other server functions such    *)
  49. (*                          as TYPE and ERASE.                       *)
  50. (*                          Implement break on sending files.i.e.    *)
  51. (*                          Control X,Z,C,and E.                     *)
  52. (*          1985 April 3  - Add two byte Checksum and CRC checksum.  *)
  53. (*          1985 April 15 - Add some advance server functions such   *)
  54. (*                          DIRECTORY, ERASE, and TYPE.              *)
  55. (*          1985 May 22  -  New Series/1 I/O . LINEMODE not needed   *)
  56. (*          1985 July 25 -  Fix multiple Receive file bug.           *)
  57. (*                       -  Save and Restore current term settings   *)
  58. (*                          and turn MSG back ON.                    *)
  59. (*                       -  Look at PARMS for first command          *)
  60. (*          1985 Sept 6  -  Add Rename command and fix commands      *)
  61. (*                          to accept d:fn.ft format.                *)
  62. (*          1985 Sept 27 -  Fix RECVCHAR bug caused by a garbage     *)
  63. (*                          null char .                              *)
  64. (*                        - Fix FILETOPACKET which prevents creation *)
  65. (*                          of a too large of a packet.              *)
  66. (*                        - Add ONERROR procedure.                   *)
  67. (*          1985 Nov 1    - Fix RECEIVE file with parameter bug      *)
  68. (*                          due to stricter pascal checking.         *)
  69. (*          1985 Dec 5    - Non CR EOL char bug fixed.               *)
  70. (*          1985 Dec 6    - Ignore NUL chars  in RECVCHAR.           *)
  71. (*          1986 Feb 11   - Fix repeat char bug in RECVFILE procedure*)
  72. (*          1986 April 25 - Allow setting translate via remote       *)
  73. (*                          Kermit command .                         *)
  74. (*          1986 April 30 - Add DATE and TIME setting via the        *)
  75. (*                          VARIABLE command .                       *)
  76. (*          1986 May 8    - Allow large binary files to be transfer- *)
  77. (*                          red by using RECFM = F  which will not   *)
  78. (*                          use CR LF as EOL marker.                 *)
  79. (*          1986 May 16   - Do not use CR LF to produce and EOLine   *)
  80. (*                          for all binary files (TRANSLATION OFF).  *)
  81. (*                          In order to retreive files which uses    *)
  82. (*                          EOLine for CRLF , set LRECL = OLD other- *)
  83. (*                          wise LRECL should be a numeric value.    *)
  84. (*          1986 July 2   - If no DOT separator between filename and *)
  85. (*                          filetype, look for a blank separator.    *)
  86. (*                        - Quote the REPEATCHAR if it is found in   *)
  87. (*                          the file to be sent.                     *)
  88. (*          1986 July 24  - Fix bug in REMOTECOMMAND type 'R' which  *)
  89. (*                          could get an improper filename length.   *)
  90. (*                        - Fix to throw away grabbage at the begin- *)
  91. (*                          ing of the packet  (before the SOH).     *)
  92. (*                        - Fix REPEATCHAR bug in RECVFILE.          *)
  93. (*          1987 Jan 7    - Check for seq number to prevent duplicate*)
  94. (*                          packets.                                 *)
  95. (*                                                                   *)
  96. (*          1988 March 2  - Long Packet code and minor bug fixes.    *)
  97. (*          1988 March 29 - Repeat character compression .           *)
  98. (*          1988 April 13 - Eliminate special characters from file   *)
  99. (*                          name and type,replace with $.            *)
  100. (*          1988 April 18 - Handle a Null Buffer.                    *)
  101. (*                        - Stay in server mode except for valid     *)
  102. (*                          kermit commands.                         *)
  103. (*          1988 April 20 - Fix bug is sending file after BREAK.     *)
  104. (*                                                                   *)
  105. (*                                                                   *)
  106. (*  1.   This version of kermit will handle binary files,            *)
  107. (*       i.e. it will handle 8th bit quoting.                        *)
  108. (*                                                                   *)
  109. (*  2.   By default all characters are received are converted from   *)
  110. (*       ASCII and stored as EBCDIC. Also all characters send are    *)
  111. (*       converted from EBCDIC to ASCII.  To avoid the translation  *)
  112. (*       for non-text file you must set TRANSLATION OFF.             *)
  113. (*                                                                   *)
  114. (*  3.   This version of kermit will work through the Series/1-      *)
  115. (*       Yale ASCII IUP.                                             *)
  116. (*                                                                   *)
  117. (*  4.   This version contains a slot for all the documented         *)
  118. (*       advanced server functions, however only some are implemented*)
  119. (*                                                                   *)
  120. (* ***************************************************************** *)
  121. (*  Utility Procedures                                               *)
  122. (*       SENDPACKET                                                  *)
  123. (*       RECVPACKET                                                  *)
  124. (*       RESENDIT                                                    *)
  125. (*       SENDACK                                                     *)
  126. (*       GETTOKEN                                                    *)
  127. (*                                                                   *)
  128. (*  Command Procedures                                               *)
  129. (*       SENDFILE  - Sends a file to another computer.               *)
  130. (*       RECVFILE  - Receive a file from another computer.           *)
  131. (*       SHOWIT    - Display the options and status of last tranfer. *)
  132. (*       SETIT     - Set the options.                                *)
  133. (*       HELP      - Displays the commands available.                *)
  134. (*       REMOTECOMMAND - handle commands initiated by micro.         *)
  135. (*                                                                   *)
  136. (* ***************************************************************** *)
  137. %PRINT OFF
  138. %INCLUDE CMS
  139. %PRINT ON
  140. CONST
  141.     MAXINPUT = 1920 ;  (* 80 X 24 screen *)
  142. TYPE
  143.     BYTE     = PACKED 0..255 ;
  144.     TWOBYTES = PACKED 0..65535 ;
  145.     OVERLAY = (ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE);
  146.     PACKET = RECORD CASE OVERLAY OF
  147.           ONE   :( CHARS : PACKED ARRAY [1..MAXINPUT] OF CHAR );
  148.           TWO   :( BYTES : PACKED ARRAY [1..MAXINPUT] OF BYTE );
  149.              END ;
  150.  
  151.     STATETYPE = (S,SF,SD,SZ,SB,C,A,R,RF,RD) ;
  152.  
  153.     ABORTTYPE = (NOSOH,BADSF,NOT_S,NOT_SFBZ,NOT_DZ);
  154.  
  155.     COMMANDS = ($BAD,
  156.                 $SEND,
  157.                 $RECEIVE,
  158.                 $SERVER,
  159.                 $SET ,
  160.                 $SHOW,
  161.                 $STATUS,
  162.                 $HELP,
  163.                 $QUES,
  164.                 $CMS,
  165.                 $CP,
  166.                 $QUIT,
  167.                 $EXIT );
  168.     WHATFLAGS= ($ZERO,
  169.                 $TRANSLATION,
  170.                 $EXTEND1,
  171.                 $RECFM,
  172.                 $LRECL,
  173.                 $PACKETSIZE,
  174.                 $EXTEND2,
  175.                 $EOLCHAR,
  176.                 $CNTRL_QUOTE,
  177.                 $EXTEND3,
  178.                 $BIT8_QUOTE,
  179.                 $EXTEND4,
  180.                 $REPEATCHAR,
  181.                 $EXTEND4A,
  182.                 $CHECKTYPE,
  183.                 $EXTEND5,
  184.                 $DUMMY);
  185.  
  186.  CONST
  187.     COMMTABLE = 'BAD     ' ||
  188.                 'SEND    ' ||
  189.                 'RECEIVE ' ||
  190.                 'SERVER  ' ||
  191.                 'SET     ' ||
  192.                 'SHOW    ' ||
  193.                 'STATUS  ' ||
  194.                 'HELP    ' ||
  195.                 '?       ' ||
  196.                 'CMS     ' ||
  197.                 'CP      ' ||
  198.                 'QUIT    ' ||
  199.                 'EXIT    ' ;
  200.     WHATTABLE = 'BAD     ' ||
  201.                 'TRANSLAT' ||
  202.                 'ION     ' ||
  203.                 'RECFM   ' ||
  204.                 'LRECL   ' ||
  205.                 'PACKETSI' ||
  206.                 'ZE      ' ||
  207.                 'EOLCHAR ' ||
  208.                 'CNTRL_QU' ||
  209.                 'OTE     ' ||
  210.                 'BIT8_QUO' ||
  211.                 'TE      ' ||
  212.                 'REPEATCH' ||
  213.                 'AR      ' ||
  214.                 'CHECKTYP' ||
  215.                 'E       ' ||
  216.                 'DUMMY   ' ;
  217.  
  218. (* THIS IS THE ASCII TO EBCDIC TABLE  *)
  219.     ASCIITOEBCDIC =
  220.            '010203372D2E2F1605250B0C0D0E0F'XC ||
  221.          '101112133C3D322618193F271C1D1E1F'XC ||
  222.          '405A7F7B5B6C507D4D5D5C4E6B604B61'XC ||
  223.          'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'XC ||
  224.          '7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'XC ||
  225.          'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'XC ||
  226.          '79818283848586878889919293949596'XC ||
  227.          '979899A2A3A4A5A6A7A8A9C04FD0A107'XC ;
  228. (*  THIS IS THE EBCDIC TO ASCII CONVERSION TABLE                   *)
  229. (*   CHARACTERS NOT REPRESENTABLE IN ASCII ARE REPLACED BY A NULL  *)
  230.     EBCDICTOASCII =
  231.            '0102030009007F0009000B0C0D0E0F'XC ||
  232.          '1011121300000800181900001C1D1E1F'XC ||
  233.          '00000000000A171B0000000000050607'XC ||
  234.          '0000160000000004000000001415001A'XC ||
  235.          '200000000000000000005C2E3C282B7C'XC ||
  236.          '2600000000000000000021242A293B5E'XC ||
  237.          '2D2F00000000000000007C2C255F3E3F'XC ||
  238.          '000000000000000000603A2340273D22'XC ||
  239.          '00616263646566676869007B00000000'XC ||
  240.          '006A6B6C6D6E6F707172007D00000000'XC ||
  241.          '007E737475767778797A0000005B0000'XC ||
  242.          '000000000000000000000000005D0000'XC ||
  243.          '7B414243444546474849000000000000'XC ||
  244.          '7D4A4B4C4D4E4F505152000000000000'XC ||
  245.          '5C00535455565758595A000000000000'XC ||
  246.          '303132333435363738397C0000000000'XC ;
  247.  (* The backslash character is translated by the SERIES/1 as '4A'hex *)
  248.  (* The comten however translates it as a 'E0'hex                    *)
  249.  (* Therefore we will translate both to a '5C'ASCII                  *)
  250.     SOH = '01'XC ;
  251.  
  252.  
  253.  
  254. VAR
  255.     RUNNING,GETREPLY  : BOOLEAN ;
  256.     INPUTSTRING    : STRING (MAXINPUT);    (* COMMAND STRING *)
  257.     OLDSETTINGS    : STRING (100);    (* TERMINAL SETTINGS *)
  258.     COMMAND        : ALFA ;
  259.     SETTING        : ALFA ;
  260.     REQUEST        : STRING(9) ;
  261.     CINDEX         : INTEGER;
  262.     CHECKBYTES     : INTEGER ;
  263.     I,J,K,LEN,RC,RET : INTEGER;
  264.     FULLSCREENDEVICE : BOOLEAN ;
  265.     FULLSCREENIO     : BOOLEAN ;
  266.     TRANSLATION,FB : BOOLEAN ;
  267.     FIXBLOCK       : BOOLEAN ;
  268.     LRECL          : STRING(8) ;
  269.     STATE          : STATETYPE ;
  270.     ABORT          : ABORTTYPE ;
  271.  
  272.     (* Packet variables *)                           (* format   *)
  273.     (* Receive       Send     *)                     (* SOH      *)
  274.        INCOUNT,      OUTCOUNT      : BYTE ;          (* COUNT    *)
  275.        INSEQ,        OUTSEQ        : BYTE ;          (* SEQNUM   *)
  276.        INPACKETTYPE, OUTPACKETTYPE : CHAR ;          (* TYPE     *)
  277.        LENX1,LENX2,HCHECK          : BYTE ;  (* LENX1,LENX2,HCHECK *)
  278.        REPLYMSG,     SENDMSG       : PACKET ;        (* DATA...  *)
  279.        CHECKSUM                    : INTEGER ;       (* CHECKSUM *)
  280.        CRC                         : TWOBYTES;       (* CRC-CCITT*)
  281.  
  282.        INDATACOUNT,  OUTDATACOUNT  : INTEGER ;       (* COUNT    *)
  283.     SENDBUFF,RECVBUFF : PACKET ;
  284.     MAXLENGTH,SI,RI,RECVLENGTH,FC : TWOBYTES ;
  285.     EOLINE : BOOLEAN ;
  286.  
  287.     FILETOSEND : TEXT ;
  288.  
  289. STATIC
  290.     RPACKETSIZE,SPACKETSIZE      : INTEGER ;
  291.     PSIZE,ECHAR      : BYTE  ;
  292.     CNTRL_QUOTE, BIT8_QUOTE  : CHAR ;
  293.     CHECKTYPE,REPEATCHAR     : CHAR ;
  294.     CAPAS,WINDO              : BYTE ;
  295. VALUE
  296.        RPACKETSIZE := 94  ;
  297.        SPACKETSIZE := 94  ;
  298.        PSIZE       := 94  ;     (* PACKET size 94 maximum *)
  299.        ECHAR       := 13  ;      (* End of line char - CR *)
  300.        CNTRL_QUOTE := '#' ;
  301.        BIT8_QUOTE  := '&' ;
  302.        CHECKTYPE   := '1' ;      (* 1 BYTE checksum *)
  303.        REPEATCHAR  := ' ' ;
  304.        CAPAS       := '00'X ;
  305.        WINDO       := 0 ;
  306.  
  307. LABEL  PROMPT ;
  308. PROCEDURE UPCASE (TOKEN : ALFA) ; EXTERNAL ;
  309. PROCEDURE FULLSERV(VAR FUNCTIONCODE : TWOBYTES ;
  310.                    VAR ABUFFER : PACKET ;
  311.                    VAR MAXLENGTH : TWOBYTES ;
  312.                    VAR RECVLENGTH : TWOBYTES) ; EXTERNAL ;
  313. %PAGE
  314. (* **************************************************************** *)
  315. (* *******     U T I L I T Y  -  P R O C E D U R E S       ******** *)
  316. (* **************************************************************** *)
  317.  
  318. (* ===============================================================  *)
  319. (* CRCHECK  -  This procedure generates a CRC (CCITT) .             *)
  320. (*             The generator polynomial is X^16+X^12+X^5+1          *)
  321. (*             which is 1021 hex or the reverse 8408 hex            *)
  322. (* Side Effect - The global variable CRC is updated. The CRC should *)
  323. (*               be zero at the start of each CRC calculation and   *)
  324. (*               should be called once for each byte to checked.    *)
  325. (*               no other call to this procedure is necessary.      *)
  326. (*              The CRC is done on all 8 bits in the byte.          *)
  327. (* ===============================================================  *)
  328. PROCEDURE CRCHECK(MYBYTE : BYTE);
  329. var
  330.     j,c,t     : integer;
  331.     begin
  332.     c := MYBYTE ;
  333.     for j := 0 to 7 do
  334.          begin
  335.          t := CRC && c ;
  336.          CRC := CRC >> 1;
  337.          if odd(t) then CRC := CRC && '8408'x;
  338.          c := c >> 1;
  339.          end;
  340.    end;
  341.  
  342. (* ===============================================================  *)
  343. (* INITSCREEN  - Initializes the terminal for transparent I/O.      *)
  344. (* Side Effect -                                                    *)
  345. (* ===============================================================  *)
  346. PROCEDURE INITSCREEN ;
  347.     BEGIN (* INIT SCREEN *)
  348.     FC := 0 ;  (* INIT SCREEN *)
  349.     FULLSERV(FC,SENDBUFF,SI,RI);
  350.     SI := 8 ;
  351.     SENDBUFF.CHARS := 'C3115D7F110001'XC ;
  352.     END ; (* INIT SCREEN *)
  353.  
  354.  
  355. (* ===============================================================  *)
  356. (* FINISCREEN - terminates transparent I/O to terminal.            *)
  357. (* Side Effect - The global variable SENDSTRING is sent as data.    *)
  358. (* ===============================================================  *)
  359. PROCEDURE FINISCREEN ;
  360.     BEGIN (* FINI  SCREEN *)
  361.     FC := 5 ; (* FINISCREEN *)
  362.     FULLSERV(FC,SENDBUFF,MAXLENGTH,RECVLENGTH);
  363.     END ; (* FINI  SCREEN *)
  364.  
  365. (* ===============================================================  *)
  366. (* RITESCREEN  - sends a packet to the terminal.                    *)
  367. (* Side Effect - The global variable SENDSTRING is sent as data.    *)
  368. (* ===============================================================  *)
  369. PROCEDURE RITESCREEN ;
  370.     BEGIN (* WRITE SCREEN *)
  371.     FC := 2 ; (* WRITE SCREEN *)
  372.     FULLSERV(FC,SENDBUFF,SI,RI);
  373.     IF FC <> 0 THEN BEGIN FINISCREEN ;writeln('HALT'); HALT ; END;
  374.     END ; (* WRITE SCREEN *)
  375.  
  376. (* ===============================================================  *)
  377. (* READSCREEN - get a packet from the terminal.                     *)
  378. (* Side Effect - The global variable SENDSTRING is sent as data.    *)
  379. (* ===============================================================  *)
  380. PROCEDURE READSCREEN ;
  381.     BEGIN (* READ  SCREEN *)
  382.     FC := 3 ; (* READ SCREEN *)
  383.     MAXLENGTH := MAXINPUT + 10 ;
  384.     FULLSERV(FC,RECVBUFF,MAXLENGTH,RECVLENGTH);
  385.     IF FC <> 0 THEN
  386.         BEGIN (* FAILED *)
  387.         FINISCREEN ;
  388.         writeln('readscreen halt'); halt ;
  389.         END ; (* FAILED *) ;
  390.     RI := 4 ;   (*  POINT TO BEGINING OF DATA *)
  391.     SI := 8 ;    (* RESET FOR NEXT PACKET *)
  392.     END ; (* READ  SCREEN *)
  393.  
  394. (* ===============================================================  *)
  395. (* ONERROR   -                                                      *)
  396. (* ===============================================================  *)
  397. Procedure ONERROR;
  398.     Begin (* On Error Procedure *)
  399.     IF  FULLSCREENIO THEN
  400.         BEGIN FINISCREEN; FULLSCREENIO := FALSE; END;
  401.     Writeln('  Unexpected Error ');
  402.     End ; (* On Error Procedure *)
  403. (* ===============================================================  *)
  404. (* SENDCHAR -  This procedure sends a char to the terminal.         *)
  405. (*             It does simple pascal WRITE unless it is going via   *)
  406. (*             the series/1 which is flagged by boolean             *)
  407. (*             FULLSCREENDEVICE.                                    *)
  408. (* Side Effect - The global variable SENDBUFF and SI are updated.   *)
  409. (* ===============================================================  *)
  410. PROCEDURE SENDCHAR(MYCHAR : CHAR);
  411.     BEGIN (* Send Char *)
  412.     IF MYCHAR <> CHAR(13) THEN       (* Not End of Packet *)
  413.          IF FULLSCREENDEVICE THEN
  414.               BEGIN (* Put char into buffer *)
  415.               IF ORD(MYCHAR) <> 0 THEN
  416.                   SENDBUFF.BYTES[SI]:=
  417.                         ORD(EBCDICTOASCII[ORD(MYCHAR)]) |'80'X ;
  418.               SI := SI + 1 ;
  419.               END  (* Put char into buffer *)
  420.                              ELSE WRITE(MYCHAR)
  421.                              ELSE         (* End of Packet *)
  422.          IF FULLSCREENDEVICE  THEN
  423.               BEGIN (* end of line *)
  424.               SENDBUFF.BYTES[SI] := '8D'X ;
  425.               RITESCREEN ;
  426.               END   (* end of line *)
  427.                               ELSE WRITELN('');
  428.     END ; (* Send Char *)
  429.  
  430. (* ===============================================================  *)
  431. (* RECVCHAR -  This procedure gets a char from the terminal.        *)
  432. (*             It does simple pascal READ  unless it is going via   *)
  433. (*             the series/1 which is flagged by  FULLSCREENDEVICE.  *)
  434. (* Side Effect - The global variable RECVBUFF and RI are updated.   *)
  435. (*               EOLINE is set                                      *)
  436. (* ===============================================================  *)
  437. PROCEDURE RECVCHAR(VAR MYCHAR : CHAR);
  438.     BEGIN (* Recv Char *)
  439.     If FULLSCREENDEVICE THEN
  440.          BEGIN (* Get char from buffer *)
  441.          IF RECVBUFF.BYTES[RI]=0 THEN MYCHAR:='00'XC ELSE
  442.          MYCHAR := ASCIITOEBCDIC[RECVBUFF.BYTES[RI] & '7F'X] ;
  443.          RI := RI + 1 ;
  444.          END   (* Get char from buffer *)
  445.       (*              ELSE IF MYCHAR = '0D'XC THEN READLN(MYCHAR) *)
  446.                                               ELSE READ(MYCHAR) ;
  447.     IF FULLSCREENDEVICE  THEN
  448.       IF (MYCHAR='0D'XC) OR (RI>=RECVLENGTH) THEN EOLINE := TRUE
  449.                                              ELSE EOLINE := FALSE
  450.                          ELSE EOLINE := EOLN(INPUT);
  451.     IF (MYCHAR = '00'XC) THEN
  452.       IF (RI < RECVLENGTH)  THEN RECVCHAR(MYCHAR) (* ignore nulls *)
  453.                             ELSE BEGIN
  454.                                 MYCHAR := '0D'XC ;
  455.                                 EOLINE := TRUE ;
  456.                                 END ;
  457.     END ; (* Recv Char *)
  458.  
  459. (* ===============================================================  *)
  460. (* SENDPACKET -This procedure sends the SENDMSG packet .            *)
  461. (*          1. The COUNT sent includes SEQ,PACKETTYPE,and CHECKSUM  *)
  462. (*             i.e. it is 3 larger than the DATACOUNT.              *)
  463. (*          2. The COUNT and SEQ and CHECKSUM values are offset by  *)
  464. (*             32 decimal (20hex) to make it a printable ASCII char.*)
  465. (*          3. The CHECKSUM are calculated on the ASCII value of    *)
  466. (*             the printable characters.                            *)
  467. (*          4. All character sent must be converted to EBCDIC       *)
  468. (*             which get translated back to ASCII by the hardware.  *)
  469. (*             The DATA and PACKETTYPE are stored in this program   *)
  470. (*             as EBCDIC. The other char are assumed ASCII.         *)
  471. (* Assumptions:                                                     *)
  472. (*       The following Global variables must be correctly set       *)
  473. (*       before calling this procedure .                            *)
  474. (*       1. OUTDATACOUNT - an integer-byte count of data characters.*)
  475. (*       2. OUTSEQ    - an integer-byte count of sequence number.   *)
  476. (*       3. OUTPACKETTYPE - an EBCDIC char  of type .               *)
  477. (*       4. SENDMSG   - an EBCDIC array of data to be sent.         *)
  478. (* ===============================================================  *)
  479. PROCEDURE SENDPACKET ;
  480.  VAR
  481.     I,SUM : INTEGER ;
  482.     BEGIN (* SENDPACKET procedure *)
  483.     SENDCHAR(SOH) ;                                       (* SOH   *)
  484.      SUM := 0 ;
  485.      CRC := 0 ;
  486.     CHECKBYTES := 1 ;
  487.     IF NOT((OUTPACKETTYPE = 'S') OR (INPACKETTYPE = 'S')
  488.                              OR (INPACKETTYPE = 'R')) THEN
  489.          IF CHECKTYPE = '2' THEN CHECKBYTES := 2   ELSE
  490.            IF CHECKTYPE = '3' THEN CHECKBYTES := 3 ;
  491.     IF OUTDATACOUNT > 91 THEN OUTCOUNT := 0
  492.                          ELSE OUTCOUNT := OUTDATACOUNT+2+CHECKBYTES ;
  493.     SENDCHAR(ASCIITOEBCDIC[OUTCOUNT+32]) ;                (* COUNT *)
  494.      SUM := SUM + OUTCOUNT + 32;
  495.      CRCHECK(OUTCOUNT + 32);
  496.     SENDCHAR(ASCIITOEBCDIC[OUTSEQ+32]) ;                  (* SEQ   *)
  497.      SUM := SUM + OUTSEQ + 32;
  498.      CRCHECK(OUTSEQ + 32);
  499.     SENDCHAR(OUTPACKETTYPE) ;                             (* TYPE  *)
  500.      SUM := SUM + ORD( EBCDICTOASCII[ORD(OUTPACKETTYPE)] ) ;
  501.      CRCHECK( ORD( EBCDICTOASCII[ORD(OUTPACKETTYPE)] )) ;
  502.  
  503.     IF OUTCOUNT = 0 THEN (* Long Packets format *)
  504.          BEGIN (* send LENX1 LENX2 and HCHECK *)
  505.          LENX1 := TRUNC((OUTDATACOUNT + CHECKBYTES)/95) ;
  506.          SENDCHAR(ASCIITOEBCDIC[LENX1+32]) ;              (* LENX1 *)
  507.          SUM := SUM + LENX1 + 32 ;
  508.          CRCHECK(LENX1 + 32) ;
  509.          LENX2 := (OUTDATACOUNT + CHECKBYTES) MOD 95 ;
  510.          SENDCHAR(ASCIITOEBCDIC[LENX2+32]) ;              (* LENX2 *)
  511.          SUM := SUM + LENX2 + 32 ;
  512.          CRCHECK(LENX2 + 32) ;
  513.          HCHECK := (SUM + (SUM AND 'C0'X) DIV '40'X ) AND '3F'X ;
  514.          SENDCHAR(ASCIITOEBCDIC[HCHECK+32]) ;             (* HCHECK *)
  515.          SUM := SUM + HCHECK + 32 ;
  516.          CRCHECK(HCHECK + 32) ;
  517.          END ; (* send LENX1 LENX2 and HCHECK *)
  518.  
  519.     IF OUTDATACOUNT > 0 THEN
  520.      FOR I := 1 TO OUTDATACOUNT DO
  521.        WITH SENDMSG DO
  522.          BEGIN (* Send Data *)
  523.          SENDCHAR(CHARS[I]) ;                             (* DATA   *)
  524.          IF BYTES[I] <> 0 THEN
  525.             SUM := SUM + ORD(EBCDICTOASCII[BYTES[I]]) ;
  526.          CRCHECK(ORD(EBCDICTOASCII[BYTES[I]]));
  527.          END ; (* Send Data *)
  528.  
  529.      IF CHECKBYTES = 1 THEN
  530.          BEGIN (* One char checksum *)
  531.          CHECKSUM := (SUM + (SUM AND 'C0'X) DIV '40'X ) AND '3F'X ;
  532.          SENDCHAR(ASCIITOEBCDIC[CHECKSUM+32]);      (* CHECKSUM  *)
  533.          SENDCHAR('0D'XC) ;
  534.          END   (* One  char checksum *)
  535.                                ELSE
  536.        IF CHECKBYTES = 2  THEN
  537.          BEGIN (* Two char checksum *)
  538.          CHECKSUM := (SUM DIV '40'X)  AND '3F'X ;  (* BIT 11 - 6 *)
  539.          SENDCHAR(ASCIITOEBCDIC[CHECKSUM+32]);    (* CHECKSUM1 *)
  540.          CHECKSUM := (SUM         )  AND '3F'X ;  (* BIT 0 - 5  *)
  541.          SENDCHAR(ASCIITOEBCDIC[CHECKSUM+32]);    (* CHECKSUM2 *)
  542.          SENDCHAR('0D'XC) ;
  543.          END   (* Two char checksum *)
  544.                                ELSE
  545.          BEGIN (* CRC-CCITT  3 character *)
  546.          SENDCHAR(ASCIITOEBCDIC[((CRC DIV '1000'X) AND '0F'X) +32]);
  547.          SENDCHAR(ASCIITOEBCDIC[((CRC DIV '0040'X) AND '3F'X) +32]);
  548.          SENDCHAR(ASCIITOEBCDIC[((CRC            ) AND '3F'X) +32]);
  549.          SENDCHAR('0D'XC) ;
  550.          END ; (* CRC-CCITT  3 character *)
  551.     END ; (* SENDPACKET procedure  *)
  552.  
  553. (* ===============================================================  *)
  554. (* RECVPACKET -This Function returns TRUE if it successfully        *)
  555. (*             recieved a packet and FALSE if it had an error.      *)
  556. (*  Side Effects:                                                   *)
  557. (*       The following global variables will be set.                *)
  558. (*       1. INCOUNT - an integer value of the msg char count .      *)
  559. (*       2. INSEQ - an integer value of the sequence count.         *)
  560. (*       3. TYPE  - an EBCDIC character of message type(Y,N,D,F,etc)*)
  561. (*       4. REPLYMSG - an EBCDIC array of the data sent.            *)
  562. (*                                                                  *)
  563. (*         a)  All characaters are received as EBCDIC values and    *)
  564. (*             must be converted back to ASCII before using.        *)
  565. (* ===============================================================  *)
  566. FUNCTION  RECVPACKET : BOOLEAN ;
  567.  VAR
  568.     I,SUM,RESENDS  : INTEGER ;
  569.     INCHAR        : CHAR ;
  570. LABEL FINDSOH ;
  571.  
  572.     BEGIN (* RECVPACKET procedure *)
  573.     IF FULLSCREENDEVICE THEN READSCREEN ;
  574. FINDSOH:
  575.     RECVCHAR(INCHAR) ;         (* SOH   *)
  576.     IF EOLINE THEN
  577.          BEGIN (* Null response *)
  578.          RECVPACKET := TRUE;
  579.          INPACKETTYPE:='N';
  580.          RETURN;
  581.          END;  (* Null response *)
  582.     IF INCHAR <> SOH THEN GOTO FINDSOH;              (* SOH   *)
  583.     SUM := 0 ;
  584.     CRC := 0 ;
  585.  
  586.     RECVCHAR (INCHAR) ;
  587.       INCOUNT := ORD(EBCDICTOASCII[ORD(INCHAR)]) ;     (* COUNT *)
  588.       SUM := SUM + INCOUNT ;
  589.       CRCHECK(INCOUNT) ;
  590.       INCOUNT := INCOUNT - 32 ; (* To absolute value *)
  591.  
  592.     RECVCHAR (INCHAR) ;
  593.       INSEQ := ORD(EBCDICTOASCII[ORD(INCHAR)]);      (* SEQ   *)
  594.       SUM := SUM + INSEQ ;
  595.       CRCHECK(INSEQ) ;
  596.       INSEQ := INSEQ - 32 ;
  597.  
  598.     RECVCHAR (INCHAR) ;
  599.       INPACKETTYPE := INCHAR ;                       (* TYPE  *)
  600.       SUM := SUM +ORD(EBCDICTOASCII[ORD(INCHAR)]) ;
  601.       CRCHECK(ORD(EBCDICTOASCII[ORD(INCHAR)]));
  602.  
  603.     CHECKBYTES := 1 ;
  604.     IF NOT ((INPACKETTYPE = 'S') OR (OUTPACKETTYPE = 'S') OR
  605.             (INPACKETTYPE = 'R') ) THEN
  606.          IF CHECKTYPE = '2' THEN CHECKBYTES := 2  ELSE
  607.            IF CHECKTYPE = '3' THEN CHECKBYTES := 3 ;
  608.  
  609.     IF INCOUNT = 0 THEN
  610.          BEGIN (* Long Packet Format *)
  611.          RECVCHAR (INCHAR) ;
  612.          LENX1 := ORD(EBCDICTOASCII[ORD(INCHAR)]);      (* LENX1 *)
  613.          SUM := SUM + LENX1 ;
  614.          CRCHECK(LENX1) ;
  615.          LENX1 := LENX1 - 32 ;
  616.          RECVCHAR (INCHAR) ;
  617.          LENX2 := ORD(EBCDICTOASCII[ORD(INCHAR)]);      (* LENX2 *)
  618.          SUM := SUM + LENX2 ;
  619.          CRCHECK(LENX2) ;
  620.          LENX2 := LENX2 - 32 ;
  621.          CHECKSUM := (SUM + (SUM AND 192) DIV 64 ) AND 63 ;
  622.          RECVCHAR (INCHAR) ;
  623.          HCHECK := ORD(EBCDICTOASCII[ORD(INCHAR)]);     (* HCHECK *)
  624.          IF HCHECK <> CHECKSUM + 32 THEN RECVPACKET := FALSE ;
  625.          SUM := SUM + HCHECK ;
  626.          CRCHECK(HCHECK) ;
  627.          INDATACOUNT := (95*LENX1) + LENX2 - CHECKBYTES ;
  628.          END  (* Long Packet Format *)
  629.                    ELSE
  630.          INDATACOUNT := INCOUNT - (2 + CHECKBYTES) ;
  631.     IF INDATACOUNT > 0 THEN
  632.      FOR I := 1 TO INDATACOUNT DO
  633.        WITH REPLYMSG DO
  634.          BEGIN (* Send Data *)
  635.          RECVCHAR (CHARS[I]) ;                         (* DATA   *)
  636.          SUM := (SUM AND '0FFFF'X) + ORD(EBCDICTOASCII[BYTES[I]]) ;
  637.          CRCHECK(ORD(EBCDICTOASCII[BYTES[I]]) ) ;
  638.          END ; (* Send Data *)
  639.  
  640.     RECVPACKET := TRUE  ;  (* ASSUME OK UNLESS CHECK FAILS *)
  641.     IF CHECKBYTES = 1 THEN
  642.          BEGIN (* CHECKSUM *)
  643.          CHECKSUM := (SUM + (SUM AND 192) DIV 64 ) AND 63 ;
  644.          RECVCHAR (INCHAR) ;
  645.          IF ORD(EBCDICTOASCII[ORD(INCHAR)]) <> CHECKSUM+32
  646.               THEN RECVPACKET := FALSE ;
  647.          END   (* CHECKSUM *)
  648.                                                    ELSE
  649.          IF CHECKBYTES = 2  THEN
  650.               BEGIN (* TWO BYTE CHECKSUM  *)
  651.               CHECKSUM := (SUM  DIV '40'X ) AND '3F'X ;
  652.               RECVCHAR  (INCHAR) ;
  653.               IF ORD(EBCDICTOASCII[ORD(INCHAR)]) <> CHECKSUM+32
  654.                    THEN  RECVPACKET := FALSE ;
  655.               CHECKSUM := (SUM         ) AND '3F'X ;
  656.               RECVCHAR (INCHAR) ;
  657.               IF ORD(EBCDICTOASCII[ORD(INCHAR)]) <> CHECKSUM+32
  658.                    THEN  RECVPACKET := FALSE ;
  659.               END    (* TWO BYTE CHECKSUM *)
  660.                                ELSE
  661.          BEGIN (* CRC-CCITT *)
  662.          (* First char is bits 16-12, second is bits 11-6 and   *)
  663.          (* third is bits 5-0 *)
  664.          RECVCHAR (INCHAR) ;
  665.          IF ORD(EBCDICTOASCII[ORD(INCHAR)]) <>
  666.             ((CRC DIV '1000'X) AND '0F'X) +32 THEN RECVPACKET:=FALSE;
  667.          RECVCHAR (INCHAR ) ;
  668.          IF ORD(EBCDICTOASCII[ORD(INCHAR)]) <>
  669.              ((CRC DIV '40'X) AND'3F'X)  +32 THEN RECVPACKET:=FALSE;
  670.          INCHAR := '0D'XC ;
  671.          RECVCHAR (INCHAR) ;
  672.          IF ORD(EBCDICTOASCII[ORD(INCHAR)]) <>
  673.               (CRC AND '3F'X) +32 THEN  RECVPACKET := FALSE ;
  674.          END ; (* CRC-CCITT *)
  675.     END ; (* RECVPACKET procedure  *)
  676. (* ===============================================================  *)
  677. (* RESENDIT -  This procedure RESENDS the packit if it gets a nak   *)
  678. (*             It calls itself recursively upto the number of times *)
  679. (*             specified in the intial parameter list.              *)
  680. (* Side Effects - If it fails then the STATE in the message is set *)
  681. (*                to 'A' which means ABORT .                        *)
  682. (* ===============================================================  *)
  683. PROCEDURE RESENDIT ( RETRIES : INTEGER ) ;
  684.  
  685.     BEGIN (* RESENDIT procedure *)
  686.     IF RETRIES > 0 THEN
  687.          BEGIN (* Try again *)
  688.          SENDPACKET ;
  689.          IF RECVPACKET THEN
  690.               IF INPACKETTYPE = 'Y' THEN
  691.                                     ELSE
  692.               IF INPACKETTYPE = 'N' THEN RESENDIT(RETRIES-1)
  693.                                     ELSE STATE := A
  694.                        ELSE STATE := A  ;
  695.          END   (* Try again *)
  696.                    ELSE STATE := A ;  (* Retries failed - ABORT *)
  697.     END ; (* RESENDIT procedure  *)
  698.  
  699. (* ------------------------------------------------------------ *)
  700. (*  SENDACK - Procedure   will send a ACK or NAK                *)
  701. (*            depending on the value of the Boolean parameter   *)
  702. (*            i.e. SENDACK(TRUE)  sends an ACK packet           *)
  703. (*                 SENDACK(FALSE) sends an NAK packet           *)
  704. (* ------------------------------------------------------------ *)
  705.      PROCEDURE SENDACK (B : BOOLEAN);
  706.          BEGIN (* SEND ACK or NAK *)
  707.          OUTDATACOUNT := 0 ;
  708.          OUTSEQ  := OUTSEQ + 1 ;
  709.          IF OUTSEQ >= 64 THEN OUTSEQ := 0;
  710.          IF B THEN OUTPACKETTYPE := 'Y'
  711.               ELSE OUTPACKETTYPE := 'N' ;
  712.          SENDPACKET ;
  713.          IF B THEN
  714.               ELSE OUTSEQ  := OUTSEQ - 1 ;
  715.          END ; (* SEND ACK or NAK *)
  716.  
  717. (* ===============================================================  *)
  718. (* GETTOKEN -  This procedure extracts a token from a string and    *)
  719. (*             the function returns a 8 character token value.      *)
  720. (*             the string is update with the portion that is left.  *)
  721. (* ===============================================================  *)
  722. FUNCTION GETTOKEN ( VAR INSTRING : STRING(1920)) : ALFA ;
  723.  VAR
  724.     BP,BPM : INTEGER ; (* Blank Pointer *)
  725.  
  726.     BEGIN   (* GETTOKEN *)
  727.     IF LENGTH(INSTRING) < 1 THEN GETTOKEN := '        '
  728.                             ELSE
  729.         BEGIN
  730.         BP := INDEX(INSTRING,' ');
  731.         IF BP = 0 THEN BP := LENGTH(INSTRING)+1;
  732.         BPM := MIN(BP,9);
  733.         IF BPM > LENGTH(INSTRING) THEN GETTOKEN := INSTRING
  734.                        ELSE     GETTOKEN := DELETE(INSTRING,BPM);
  735.         INSTRING := DELETE(INSTRING,1,MIN(BP,LENGTH(INSTRING)));
  736.         END;
  737.     END; (* GETTOKEN *)
  738. (* ---------------------------------------------------------------- *)
  739. (* ===============================================================  *)
  740. (* PUTINITPACKET - This procedure make the PARAMETER PACKET.        *)
  741. (* ===============================================================  *)
  742. PROCEDURE PUTINITPACKET ;
  743.      BEGIN  (*  parameters *)
  744.          OUTDATACOUNT := 9 ;
  745.          OUTSEQ   := 0 ;
  746.          WITH SENDMSG DO
  747.               BEGIN (* Setup PARM packet *)
  748.               (* The values  are tranformed by adding hex 20 to   *)
  749.               (* the true value, making the value a printable char *)
  750.               CHARS[1] := ASCIITOEBCDIC[PSIZE+32];(* Buffsize = 94  *)
  751.               CHARS[2] := ASCIITOEBCDIC['28'X] ;  (* Time out 8 sec *)
  752.               CHARS[3] := ASCIITOEBCDIC['20'X] ;  (* Num padchars=0 *)
  753.               CHARS[4] := ASCIITOEBCDIC['40'X] ;  (* Pad char=blank *)
  754.               CHARS[5] := ASCIITOEBCDIC[ECHAR+32];(* EOL char = CR  *)
  755.               CHARS[6] := CNTRL_QUOTE ;           (* Quote character *)
  756.              (* OPTIONAL PARAMETERS *)
  757.               CHARS[7] := BIT8_QUOTE ;            (* Quote character *)
  758.               CHARS[8] := CHECKTYPE  ;            (* Check type      *)
  759.               CHARS[9] := REPEATCHAR ;            (* Repeatcharacter *)
  760.               IF BIT8_QUOTE <= ' '  THEN CHARS[7] := 'Y' ;
  761.               IF CHECKTYPE  <= ' '  THEN CHARS[8] := '1' ;
  762.               IF REPEATCHAR <= ' '  THEN CHARS[9] := ' ' ;
  763.               IF  RPACKETSIZE > 94 THEN
  764.                    BEGIN (* Long Packet Size *)
  765.                    CHARS[10] := ASCIITOEBCDIC[02+32];
  766.                    CHARS[11] := ASCIITOEBCDIC[0+32];
  767.                    CHARS[12] := ASCIITOEBCDIC[TRUNC(RPACKETSIZE/95)+32];
  768.                    CHARS[13] := ASCIITOEBCDIC[(RPACKETSIZE MOD 95)+32];
  769.                    OUTDATACOUNT := 13 ;
  770.                    END ; (* Long Packet Size *)
  771.               END ; (* Setup PARAMETER packet *)
  772.      END ;  (*  parameters *)
  773. (* ------------------------------------------------------------ *)
  774.     PROCEDURE GETINITPACKET ;
  775.          BEGIN  (* Get init parameters *)
  776.          IF INDATACOUNT >= 1 THEN
  777.               PSIZE := ORD(EBCDICTOASCII[REPLYMSG.BYTES[1]])-32 ;
  778.          IF INDATACOUNT >= 5 THEN
  779.               ECHAR := ORD(EBCDICTOASCII[REPLYMSG.BYTES[5]])-32 ;
  780.          IF INDATACOUNT >= 6 THEN
  781.               CNTRL_QUOTE := REPLYMSG.CHARS[6] ;
  782.          IF INDATACOUNT >= 7 THEN
  783.               IF REPLYMSG.CHARS[7] = 'Y' THEN BIT8_QUOTE := '&'
  784.                                          ELSE
  785.               IF REPLYMSG.CHARS[7] = 'N' THEN BIT8_QUOTE := ' '
  786.                                          ELSE
  787.                      BIT8_QUOTE := REPLYMSG.CHARS[7] ;
  788.          IF INDATACOUNT >= 8 THEN
  789.             IF REPLYMSG.CHARS[8] <> CHECKTYPE  THEN
  790.               CHECKTYPE  := '1' ;    (* One char checksum DEFAULT *)
  791.          IF INDATACOUNT >= 9 THEN
  792.             IF REPLYMSG.CHARS[9] <> REPEATCHAR THEN
  793.                 REPEATCHAR := ' ' ;    (* No repeat char  *)
  794.          IF INDATACOUNT >= 10 THEN
  795.               CAPAS := ORD(EBCDICTOASCII[REPLYMSG.BYTES[10]])-32
  796.                               ELSE
  797.               CAPAS := 0 ;
  798.          IF INDATACOUNT >= 11 THEN
  799.               WINDO := ORD(EBCDICTOASCII[REPLYMSG.BYTES[11]])-32
  800.                               ELSE
  801.               WINDO := 0 ;
  802.          IF (CAPAS and '02'X) = '02'X THEN (* long blocks *)
  803.               If INDATACOUNT >= 13 THEN
  804.                  SPACKETSIZE :=                                         0)
  805.                       (ORD(EBCDICTOASCII[REPLYMSG.BYTES[12]])-32) *95 +
  806.                       (ORD(EBCDICTOASCII[REPLYMSG.BYTES[13]])-32)
  807.                                    ELSE
  808.                  SPACKETSIZE := 500
  809.                                        ELSE
  810.                  SPACKETSIZE := PSIZE ;
  811.          END ;  (* Get init parameters *)
  812. (* ------------------------------------------------------------ *)
  813. (* ===============================================================  *)
  814. (* FILETOPACKET - This procedure files in a DATA packet D or X type *)
  815. (*             with data from the file FILETOSEND.                  *)
  816. (* ===============================================================  *)
  817. PROCEDURE FILETOPACKET ;
  818.  VAR PREVCHAR,ACHAR : CHAR ;
  819.      MARKOUTCOUNT,REPCOUNT,MAXDATASIZE : INTEGER ;
  820.      REPEATING : BOOLEAN ;
  821.  LABEL TRANS,NEXT  ;
  822.     BEGIN (* FILE TO PACKET *)
  823. (*  WRITELN ('SEND DATA  ');  *)
  824.     OUTSEQ   := OUTSEQ + 1 ;
  825.     IF OUTSEQ >= 64 THEN OUTSEQ := 0 ;
  826.     OUTDATACOUNT := 0 ;
  827.     REPEATING := FALSE ;
  828.     REPCOUNT := -1 ; (* -1 to indicate start of new line or packet *)
  829.     MAXDATASIZE := MIN(1900,SPACKETSIZE) -3 -5 ;
  830.     WHILE (OUTDATACOUNT<MAXDATASIZE) AND (NOT EOF(FILETOSEND))  DO
  831.       WITH SENDMSG DO
  832.          BEGIN (* Process character *)
  833.          OUTDATACOUNT := OUTDATACOUNT + 1 ;
  834.          READ(FILETOSEND,ACHAR) ;
  835.          CHARS[OUTDATACOUNT] := ACHAR ;
  836.          IF (PREVCHAR = ACHAR) AND (REPEATCHAR>' ')
  837.                  AND (REPCOUNT>=0) AND (REPCOUNT<94)   THEN
  838.            BEGIN (* Repeated char *)
  839.            REPCOUNT := REPCOUNT + 1 ;
  840.            IF REPCOUNT > 1 THEN
  841.               BEGIN (* multiple chars *)
  842.               OUTDATACOUNT := OUTDATACOUNT - 1 ;
  843.               IF NOT EOLN(FILETOSEND) THEN GOTO NEXT ;
  844.               END ; (* multiple chars *)
  845.            END ; (* Repeated char *)
  846.          IF ((PREVCHAR<>ACHAR) OR (REPCOUNT>94) OR EOLN(FILETOSEND)
  847.               OR (REPCOUNT<0)) AND (REPEATCHAR>' ') THEN
  848.            BEGIN (* Different Char *)
  849.            IF REPCOUNT > 1 THEN
  850.               BEGIN (* add repeat count sequence *)
  851.               OUTDATACOUNT := MARKOUTCOUNT ;
  852.               CHARS[OUTDATACOUNT] := REPEATCHAR ;
  853.               BYTES[OUTDATACOUNT+1] := REPCOUNT + 1 + 32 ;
  854.               CHARS[OUTDATACOUNT+1] := ASCIITOEBCDIC[REPCOUNT+1+32] ;
  855.               CHARS[OUTDATACOUNT+2] := PREVCHAR ;
  856.               OUTDATACOUNT := OUTDATACOUNT + 2 ;
  857.               REPEATING := TRUE ;
  858.               IF PREVCHAR = ACHAR THEN REPCOUNT := 0 ;
  859.               END ; (* add repeat count sequence *)
  860.            PREVCHAR := ACHAR ;
  861.            MARKOUTCOUNT := OUTDATACOUNT ;
  862.            IF REPCOUNT <= 1 THEN REPCOUNT := 0 ;
  863.            END ; (* Different Char *)
  864.  TRANS:
  865.            IF TRANSLATION THEN
  866.               BEGIN  (*  translate char *)
  867.               IF BYTES[OUTDATACOUNT]=128 THEN (* 8bit quote next char*)
  868.                    CHARS[OUTDATACOUNT] := BIT8_QUOTE
  869.                                            ELSE
  870.               BEGIN (* double trans *)
  871.               (* The following double translation is used to   *)
  872.               (* filter out meaningless EBCDIC characters into *)
  873.               (* something more consistent. *)
  874.               IF BYTES[OUTDATACOUNT] <> 0 THEN
  875.                    CHARS[OUTDATACOUNT] :=
  876.                             EBCDICTOASCII[BYTES[OUTDATACOUNT]];
  877.               IF BYTES[OUTDATACOUNT] < 32   THEN
  878.                    BEGIN (* CONTROL QUOTING *)
  879.                    BYTES[OUTDATACOUNT+1] :=
  880.                        BYTES[OUTDATACOUNT] + 64 ;
  881.                    CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  882.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  883.                    END ; (* CONTROL QUOTING *)
  884.               IF BYTES[OUTDATACOUNT] = '7F'X THEN
  885.                    BEGIN (* DEL QUOTING *)
  886.                    CHARS[OUTDATACOUNT+1] := '3F'XC ;
  887.                    CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  888.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  889.                    END ; (* DEL QUOTING *)
  890.               IF BYTES[OUTDATACOUNT] <> 0 THEN
  891.               CHARS[OUTDATACOUNT] :=
  892.                             ASCIITOEBCDIC[BYTES[OUTDATACOUNT]] ;
  893.               IF (CHARS[OUTDATACOUNT]<> ' ') AND
  894.                 ((CHARS[OUTDATACOUNT] = CNTRL_QUOTE) OR
  895.                  (CHARS[OUTDATACOUNT] = BIT8_QUOTE) OR
  896.                  (CHARS[OUTDATACOUNT] = REPEATCHAR)) THEN
  897.                    BEGIN (* Quote the  quote *)
  898.                    CHARS[OUTDATACOUNT+1] := CHARS[OUTDATACOUNT] ;
  899.                    CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  900.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  901.                    END ; (* Quote the  quote *)
  902.               END  ; (* double trans *)
  903.               IF EOLN(FILETOSEND)  THEN
  904.                    BEGIN (* End of Line *)
  905.                    IF (ACHAR=' ') THEN (* Delete trailing blanks *)
  906.                     IF REPEATING  AND (CHARS[OUTDATACOUNT]=' ') THEN
  907.                         BEGIN (* delete repeated blanks *)
  908.                         OUTDATACOUNT := OUTDATACOUNT - 3 ;
  909.                         REPCOUNT := -1 ;
  910.                         END   (* delete repeated blanks *)
  911.                                                                   ELSE
  912.                     IF REPEATCHAR <= ' ' THEN
  913.                     WHILE (SENDMSG.CHARS[OUTDATACOUNT] = ' ')
  914.                                           AND (OUTDATACOUNT>1) DO
  915.                         OUTDATACOUNT := OUTDATACOUNT - 1 ;
  916.                    IF REPCOUNT > 1 THEN
  917.                        BEGIN (* Reset repeat count *)
  918.                        REPCOUNT := -1 ;
  919.                        OUTDATACOUNT := OUTDATACOUNT + 1 ;
  920.                        CHARS[OUTDATACOUNT] := ACHAR ;
  921.                        MARKOUTCOUNT := OUTDATACOUNT ;
  922.                        GOTO TRANS ;
  923.                        END ; (* Reset repeat count *)
  924.                    (* Add   CR and LF *)
  925.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  926.                    SENDMSG.CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  927.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  928.                    SENDMSG.CHARS[OUTDATACOUNT]:='M'; (* Carriage Ret *)
  929.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  930.                    SENDMSG.CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  931.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  932.                    SENDMSG.CHARS[OUTDATACOUNT] := 'J' ; (* Line Feed *)
  933.                    REPCOUNT := -1 ;
  934.                    READLN(FILETOSEND) ;   (* Point to next line *)
  935.                    END ; (* End of Line *)
  936.               END    (*  translate char *)
  937.                            ELSE
  938.               BEGIN (* Untranslated file *)
  939.               (* Untranslated file means the file is stored as  *)
  940.               (* 8 bit ASCII. However it must be translated into*)
  941.               (* EBCDIC so that the comten software will trans- *)
  942.               (* late it back into ASCII.                       *)
  943.               IF BYTES[OUTDATACOUNT] >= 128 THEN
  944.                  IF BIT8_QUOTE <= ' ' THEN (* No bit8 quoting *)
  945.                    (* Just drop the 8th bit  *)
  946.                    BYTES[OUTDATACOUNT]:=BYTES[OUTDATACOUNT]-128
  947.                                         ELSE
  948.                    BEGIN (* BIT8 QUOTING *)
  949.                    BYTES[OUTDATACOUNT+1]:=BYTES[OUTDATACOUNT]-128;
  950.                    CHARS[OUTDATACOUNT] := BIT8_QUOTE ;
  951.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  952.                    END ; (* BIT8 QUOTING *)
  953.               IF BYTES[OUTDATACOUNT] < 32   THEN
  954.                    BEGIN (* CONTROL QUOTING *)
  955.                    BYTES[OUTDATACOUNT+1]:=BYTES[OUTDATACOUNT]+64;
  956.                    CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  957.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  958.                    END ; (* CONTROL QUOTING *)
  959.               IF BYTES[OUTDATACOUNT] = '7F'X THEN
  960.                    BEGIN (* DEL QUOTING *)
  961.                    CHARS[OUTDATACOUNT+1] := '3F'XC ;
  962.                    CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  963.                    OUTDATACOUNT := OUTDATACOUNT + 1 ;
  964.                    END ; (* DEL QUOTING *)
  965.               IF BYTES[OUTDATACOUNT] <> 0 THEN
  966.               CHARS[OUTDATACOUNT] :=
  967.                            ASCIITOEBCDIC[BYTES[OUTDATACOUNT]] ;
  968.               IF CHARS[OUTDATACOUNT] > ' ' THEN
  969.                IF (CHARS[OUTDATACOUNT] = CNTRL_QUOTE) OR
  970.                   (CHARS[OUTDATACOUNT] = REPEATCHAR) OR
  971.                   (CHARS[OUTDATACOUNT] = BIT8_QUOTE) THEN
  972.                     BEGIN (* Quote the  quote *)
  973.                     CHARS[OUTDATACOUNT+1] := CHARS[OUTDATACOUNT] ;
  974.                     CHARS[OUTDATACOUNT] := CNTRL_QUOTE ;
  975.                     OUTDATACOUNT := OUTDATACOUNT + 1 ;
  976.                     END ; (* Quote the  quote *)
  977.               IF EOLN(FILETOSEND) THEN READLN(FILETOSEND) ;
  978.               END ; (* Untranslated file *)
  979.            IF REPCOUNT > 1 THEN
  980.               BEGIN (* Reset repeat count *)
  981.               REPCOUNT := 0 ;
  982.               OUTDATACOUNT := OUTDATACOUNT + 1 ;
  983.               CHARS[OUTDATACOUNT] := ACHAR ;
  984.               MARKOUTCOUNT := OUTDATACOUNT ;
  985.               GOTO TRANS ;
  986.               END ; (* Reset repeat count *)
  987. NEXT:
  988.          REPEATING := FALSE ;
  989.          END ; (* Process Character *)
  990.     END ; (* FILE TO PACKET *)
  991.  
  992. %PAGE
  993. (* **************************************************************** *)
  994. (* ---------------------------------------------------------------- *)
  995. (* ------     C O M M A N D  -  P R O C E D U R E S       --------- *)
  996. (* ---------------------------------------------------------------- *)
  997. (* **************************************************************** *)
  998.  
  999.  
  1000. (* **************************************************************** *)
  1001. (* SENDFILE  - This routine handles the sending of a file to      * *)
  1002. (*             the micro computer.                                * *)
  1003. (*            If the parameter string is blank it gets the file   * *)
  1004. (*            name and type from the INPUTSTRING.                 * *)
  1005. (*            If it is non blank it assumes the file name is in   * *)
  1006. (*            the parameter string, which was obtained by the     * *)
  1007. (*            remote RECEIVE fn ft command.                       * *)
  1008. (* **************************************************************** *)
  1009.  PROCEDURE SENDFILE ( FNFTFM : STRING(80));
  1010.  
  1011.  VAR
  1012.     FNAME,FTYPE,FMODE : ALFA ;
  1013.     TITLE,FILENAME : STRING(26);
  1014.     CMSCOMMAND : STRING (80);
  1015.     SENDING,EOL: BOOLEAN ;
  1016.     DIRECTORY  : PACKED ARRAY [0..255] OF STRING(20) ;
  1017.     RECFM      : PACKED ARRAY [0..255] OF CHAR ;
  1018.     BLOCKSIZE  : PACKED ARRAY [0..255] OF INTEGER ;
  1019.     RET,FILEINDEX,IX,CSI,RETRIES : INTEGER ;
  1020.     DUMMY      : CHAR ;
  1021. LABEL EXITSEND;
  1022.  
  1023.     BEGIN (* SENDFILE procedure *)
  1024. (*  WRITELN ('ready to SEND file  - Put Micro in receive mode. '); *)
  1025.     IF FULLSCREENDEVICE AND NOT FULLSCREENIO THEN  INITSCREEN ;
  1026.     IF FNFTFM = ' ' THEN
  1027.          BEGIN (* Look for file name in INPUTSTRING *)
  1028.          FNAME := GETTOKEN(INPUTSTRING);
  1029.          FTYPE := GETTOKEN(INPUTSTRING);
  1030.          FMODE := GETTOKEN(INPUTSTRING);
  1031.          TITLE := STR(FNAME) || ' ' ||STR(FTYPE) || ' ' || STR(FMODE);
  1032.          END   (* Look for file name in INPUTSTRING *)
  1033.                     ELSE
  1034.          TITLE := FNFTFM  ;
  1035.  
  1036.     CMSCOMMAND := 'LISTFILE ' || TITLE || ' (STACK FORMAT)' ;
  1037.  
  1038.     CMS( CMSCOMMAND,RET);
  1039.          (* TRY UPCASING IT *)
  1040. (*  IF RET <> 0 THEN
  1041.          BEGIN
  1042.          UPCASE(FNAME);
  1043.          UPCASE(FTYPE);
  1044.          UPCASE(FMODE);
  1045.          TITLE := STR(FNAME) || ' ' ||STR(FTYPE) || ' '
  1046.                              || STR(FMODE) ;
  1047.          CMSCOMMAND := 'LISTFILE ' || TITLE || ' (STACK FORMAT)' ;
  1048.          CMS( CMSCOMMAND,RET);     *)
  1049.          IF RET <> 0 THEN
  1050.               BEGIN (* No file *)
  1051.               IF NOT FULLSCREENIO THEN
  1052.                    WRITELN ('No file ',TITLE,' found ',RET);
  1053.                (* SEND ERROR packet *)
  1054.               OUTDATACOUNT := 15 ;
  1055.               OUTSEQ   := 0 ;
  1056.               SENDMSG.CHARS := 'No file found. ' ;
  1057.               OUTPACKETTYPE := 'E';
  1058.               SENDPACKET ;
  1059.               GOTO EXITSEND ;
  1060.               END ; (* No file *)
  1061.     (*   END ;    TRY UPCASING IT *)
  1062.     CMS('SENTRIES',RET);
  1063.     FILEINDEX := RET ;
  1064.  (* WRITELN('FILE INDEX IS ',FILEINDEX); *)
  1065.     FOR IX := 1 TO FILEINDEX DO
  1066.          READLN (DIRECTORY[IX]:21,RECFM[IX],BLOCKSIZE[IX]);
  1067.     IX := 1 ;
  1068.     STATE := S ;
  1069.     GETREPLY := FALSE ;
  1070.     SENDING := TRUE ;
  1071.     WHILE SENDING DO
  1072.        BEGIN (* Send files *)
  1073.        IF GETREPLY THEN
  1074.          BEGIN  (* Look at Packet Received *)
  1075.          IF RECVPACKET THEN
  1076.               IF INPACKETTYPE = 'Y' THEN
  1077.                                     ELSE
  1078.               IF INPACKETTYPE = 'N' THEN RESENDIT(10)
  1079.                                     ELSE
  1080.               IF INPACKETTYPE = 'R' THEN STATE := S
  1081.                                     ELSE STATE := A
  1082.                        ELSE  RESENDIT(10) ;
  1083.          IF (INPACKETTYPE = 'Y') AND (INDATACOUNT > 0) THEN
  1084.               IF REPLYMSG.CHARS[1] = 'X' THEN STATE := SZ
  1085.                                          ELSE
  1086.               IF REPLYMSG.CHARS[1] = 'Z' THEN
  1087.                    BEGIN   IX := FILEINDEX ;  STATE := SZ ; END ;
  1088.          END ; (* Look at Packet Received *)
  1089.          GETREPLY := TRUE ;
  1090.             CASE STATE OF
  1091.     S :  BEGIN (* Send INIT packit *)
  1092.          OUTPACKETTYPE := 'S' ;
  1093.          PUTINITPACKET ;
  1094.          IF FNFTFM = ' ' THEN
  1095.              CMS('CP SLEEP 10 SEC',RET);
  1096.          SENDPACKET ;
  1097.          STATE := SF ;
  1098.          END ; (* Send INIT packit *)
  1099.  
  1100.     SF:  BEGIN (* Send file header *)
  1101.          IF INDATACOUNT > 1 THEN  GETINITPACKET ;
  1102.  
  1103.     (*   WRITELN ('file ',DIRECTORY[IX],' ',RECFM[IX],BLOCKSIZE[IX]); *)
  1104.          OUTSEQ := OUTSEQ + 1 ;
  1105.          IF OUTSEQ >= 64 THEN OUTSEQ := 0 ;
  1106.          OUTPACKETTYPE := 'F' ;
  1107.          FIXBLOCK := RECFM[IX] = 'F' ;
  1108.          FILENAME  := TRIM(SUBSTR(DIRECTORY[IX],1,8)) || '.' ||
  1109.                        TRIM(SUBSTR(DIRECTORY[IX],10,8)) ;
  1110.          SENDMSG.CHARS := FILENAME  ;
  1111.          OUTDATACOUNT := LENGTH(FILENAME);
  1112.          SENDPACKET ;
  1113.          IF BLOCKSIZE[IX] > 32756 THEN
  1114.               BEGIN (* Blocksize too large *)
  1115.          (*   WRITELN('BLOCKSIZE of',BLOCKSIZE[IX],' is too large.');*)
  1116.               STATE := SZ ;
  1117.               END   (* Blocksize too large *)
  1118.                                  ELSE
  1119.               BEGIN (* Open file *)
  1120.               CMSCOMMAND:='FILEDEF FILETOSEND DISK ' ||
  1121.                              STR(DIRECTORY[IX]);
  1122.               CMS(CMSCOMMAND,RET);
  1123.               RESET(FILETOSEND);
  1124.               STATE := SD ;
  1125.               END ; (* Open file *)
  1126.          END ; (* Send file header *)
  1127.  
  1128.     SD:  BEGIN (* Send data *)
  1129.          OUTPACKETTYPE := 'D' ;
  1130.          FILETOPACKET ;
  1131.          SENDPACKET ;
  1132.          IF EOF(FILETOSEND) THEN STATE := SZ ;
  1133.          END ; (* Send data *)
  1134.  
  1135.     SZ:  BEGIN (* End of File *)
  1136.      (*  WRITELN ('end of file');  *)
  1137.          OUTDATACOUNT :=  0 ;
  1138.          OUTSEQ   := OUTSEQ + 1 ;
  1139.          IF OUTSEQ >= 64 THEN OUTSEQ := 0; ;
  1140.          OUTPACKETTYPE := 'Z' ;
  1141.          SENDPACKET ;
  1142.          IX := IX + 1 ;
  1143.          IF IX <= FILEINDEX THEN STATE := SF
  1144.                             ELSE STATE := SB ;
  1145.          END ; (* End of File *)
  1146.  
  1147.     SB:  BEGIN (* Last file sent *)
  1148.   (*     WRITELN ('SENT last file completed');  *)
  1149.          OUTDATACOUNT := 0 ;
  1150.          OUTSEQ   := OUTSEQ + 1 ;
  1151.          IF OUTSEQ >= 64 THEN OUTSEQ := 0 ;
  1152.          OUTPACKETTYPE := 'B' ;
  1153.          SENDPACKET ;
  1154.          STATE := C ;
  1155.          END ; (* Last file sent *)
  1156.  
  1157.      C:  BEGIN (* Completed Sending *)
  1158.     (*   WRITELN ('SENDing of files completed'); *)
  1159.          SENDING := FALSE ;
  1160.          END ; (* Completed Sending *)
  1161.  
  1162.      A:  BEGIN (* Abort Sending *)
  1163.      (*  WRITELN ('SENDing files ABORTED'); *)
  1164.          ABORT := BADSF ;
  1165.          SENDING := FALSE ;
  1166.                (* SEND ERROR packet *)
  1167.               OUTDATACOUNT := 15 ;
  1168.               OUTSEQ   := 0 ;
  1169.               SENDMSG.CHARS := 'Send file abort' ;
  1170.               OUTPACKETTYPE := 'E';
  1171.               SENDPACKET ;
  1172.  
  1173.          END ; (* Abort Sending *)
  1174.               END ; (* CASE of STATE *)
  1175.        END ; (* Send files *)
  1176.  
  1177. EXITSEND:
  1178.     IF FULLSCREENDEVICE THEN
  1179.          IF NOT FULLSCREENIO THEN FINISCREEN
  1180.                              ELSE (* SEND A PROMPT *)
  1181.                     BEGIN
  1182.                     SI := 8  ;
  1183.                     SENDBUFF.CHARS := 'C3115D7F110001BE'XC ;
  1184.                     RITESCREEN ; (* SEND SERVER PROMPT *)
  1185.                     SI := 8 ;     (* Reset data pointer *)
  1186.                     END ;
  1187.     END ; (* SENDFILE procedure *)
  1188.  
  1189. %PAGE
  1190. (* **************************************************************** *)
  1191. (* RECVFILE  - This routine handles the Receiving of a file from    *)
  1192. (*             the micro computer.                                  *)
  1193. (*                                                                  *)
  1194. (* Note : whenever a CR,LF pair is received it assumes it is the    *)
  1195. (*        an EOLN indicator and are not stored in the file.         *)
  1196. (*        However if we get two CR,LF in a row we can not write     *)
  1197. (*        an empty record so we must store the next CR,LF in the    *)
  1198. (*        next record .                                             *)
  1199. (* **************************************************************** *)
  1200.  PROCEDURE RECVFILE ;
  1201. VAR
  1202.     BIT8  :  BYTE ;
  1203.     LASTSEQNUM : INTEGER ;
  1204.     RECEIVING : BOOLEAN ;
  1205.     FNAME,FTYPE,FMODE  : ALFA ;
  1206.     FILENAME,FILETYPE  : STRING (16) ;
  1207.     FILEWANTED :  STRING(80);
  1208.     TEMPSTR : STRING (94);
  1209.     RET,RETRIES,COLON,DOT,IX,CNT,J : INTEGER ;
  1210.     CRFLAG,CRLFFLAG : BOOLEAN ;
  1211.     TITLE,OPEN_OPTIONS : STRING (80);
  1212.     FILEINCOMING : TEXT ;
  1213.  
  1214.  
  1215.     (* ------------------------------------------------------------ *)
  1216.     (*  SENDNAK - Procedure of RECVFILE, will check the number of   *)
  1217.     (*            RETRIES , if it is greater than 0 it will send a  *)
  1218.     (*            call SENDACK(FALSE) which send a NAK packet and   *)
  1219.     (*            decrements the RETRIES by 1.                      *)
  1220.     (*  Side Effect - RETRIES is decremented by 1.                  *)
  1221.     (*                STATE is set to A if no more retries.         *)
  1222.     (* ------------------------------------------------------------ *)
  1223.      PROCEDURE SENDNAK ;
  1224.          BEGIN (* SEND  NAK *)
  1225.          IF RETRIES > 0 THEN
  1226.               BEGIN  (* Ask for a retransmission *)
  1227.               SENDACK(FALSE);
  1228.               RETRIES := RETRIES - 1 ;
  1229.               END    (* Ask for a retransmission *)
  1230.                         ELSE
  1231.               STATE := A ;
  1232.          END ; (* SEND ACK or NAK *)
  1233.  
  1234.  
  1235.  
  1236.     BEGIN (* ------- RECVFILE procedure ------- *)
  1237. (*  WRITELN (' RECEIVE mode - Issue a SEND command from micro. '); *)
  1238.     IF FULLSCREENDEVICE AND NOT FULLSCREENIO THEN INITSCREEN ;
  1239.     IF LENGTH(INPUTSTRING) > 0 THEN
  1240.          BEGIN (* GET name of file *)
  1241.          IX := INDEX(INPUTSTRING,' ');
  1242.          IF IX  = 0 THEN  BEGIN (* One parm only *)
  1243.                           IX := LENGTH(INPUTSTRING) ;
  1244.                           FILEWANTED := INPUTSTRING ;
  1245.                           END   (* One parm only *)
  1246.                     ELSE
  1247.               FILEWANTED := DELETE(INPUTSTRING,IX+1);
  1248.          INPUTSTRING := LTRIM(DELETE(INPUTSTRING,1,IX));
  1249.          END ;  (* GET name of file *)
  1250.     FNAME := GETTOKEN(INPUTSTRING);
  1251.     UPCASE(FNAME);
  1252.     IF FNAME = 'AS     ' THEN
  1253.        FNAME := GETTOKEN(INPUTSTRING);
  1254.     FTYPE := GETTOKEN(INPUTSTRING);
  1255.     FMODE := GETTOKEN(INPUTSTRING);
  1256.     IF FNAME = ''   THEN FNAME := '=' ;
  1257.     IF FTYPE = ''   THEN FTYPE := '=' ;
  1258.     IF FMODE = ''   THEN FMODE := '=' ;
  1259.     IF (LENGTH(FILEWANTED) > 1) AND
  1260.        ((FILEWANTED<>'AS') OR (FILEWANTED<>'as')) THEN
  1261.          BEGIN (* Send R packet requesting the file *)
  1262.          OUTSEQ := 0 ;
  1263.          OUTPACKETTYPE := 'R' ;
  1264.          SENDMSG.CHARS := FILEWANTED ;
  1265.          OUTDATACOUNT := LENGTH(FILEWANTED) ;
  1266.          SENDPACKET ;
  1267.          END   (* Send R packet requesting the file *)
  1268.                                                   ELSE
  1269.          SENDACK(FALSE) ;  (* may not need it but won't hurt *)
  1270.  
  1271.     STATE := R ;
  1272.     RECEIVING := TRUE ;
  1273.     RETRIES := 10 ;       (* Up to 10 retries allowed. *)
  1274.  
  1275.     WHILE RECEIVING DO  CASE STATE OF
  1276.  
  1277.     (* R ------ Initial receive State ------- *)
  1278.     (* Valid received msg type  : S           *)
  1279.     R : BEGIN (* Initial Receive State  *)
  1280.         IF (NOT RECVPACKET) OR (INPACKETTYPE='N') THEN  SENDNAK
  1281.                                                   ELSE
  1282.         (* Get a packet *)
  1283.         IF INPACKETTYPE = 'S' THEN
  1284.          BEGIN (* Got INIT packit *)
  1285.          GETINITPACKET ;
  1286.          OUTPACKETTYPE := 'Y' ;
  1287.          PUTINITPACKET ;
  1288.          SENDPACKET ;
  1289.          STATE := RF ;
  1290.          END   (* Got  INIT  packet *)
  1291.                               ELSE
  1292.          BEGIN (* Not init packet *)
  1293.          STATE := A ;   (* ABORT if not INIT packet *)
  1294.          ABORT := NOT_S ;
  1295.          END ; (* Not init packet *)
  1296.         END ; (* Initial Receive State  *)
  1297.  
  1298.  
  1299.     (* RF ----- Receive Filename State ------- *)
  1300.     (* Valid received msg type  : S,Z,F,B     *)
  1301.     RF: IF (NOT RECVPACKET) OR (INPACKETTYPE='N') THEN  SENDNAK
  1302.                                                   ELSE
  1303.         (* Get a packet *)
  1304.         IF INPACKETTYPE = 'S' THEN STATE:=R       ELSE
  1305.         IF INPACKETTYPE = 'Z' THEN SENDACK(TRUE)  ELSE
  1306.         IF INPACKETTYPE = 'B' THEN STATE:=C       ELSE
  1307.         IF INPACKETTYPE = 'F' THEN
  1308.               BEGIN (* Got file header *)
  1309.               TEMPSTR :=  SUBSTR(STR(REPLYMSG.CHARS),1,INDATACOUNT) ;
  1310.               COLON := INDEX(TEMPSTR,':');
  1311.               IF COLON > 0 THEN
  1312.                    TEMPSTR := SUBSTR(TEMPSTR,COLON+1,
  1313.                                   LENGTH(TEMPSTR)-COLON);
  1314.               DOT := INDEX(TEMPSTR,'.');
  1315.               IF DOT = 0 THEN DOT := INDEX(TEMPSTR,' ');
  1316.               FOR J:=1 TO LENGTH(TEMPSTR) DO
  1317.                   IF ORD(TEMPSTR[J]) < 128 THEN TEMPSTR[J] := '$' ;
  1318.               FILENAME:=SUBSTR(TEMPSTR,1,DOT-1) ;
  1319.               FILETYPE:=SUBSTR(TEMPSTR,DOT+1,LENGTH(TEMPSTR)-DOT);
  1320.               IF FNAME <> '=' THEN FILENAME := STR(FNAME) ;
  1321.               IF FTYPE <> '=' THEN FILETYPE := STR(FTYPE) ;
  1322.               IF FMODE =  '=' THEN FMODE := 'A' ;
  1323.               TITLE := TRIM(FILENAME)  || '.' || TRIM(FILETYPE) ||
  1324.                                     '.' || STR(FMODE) ;
  1325.               IF FB THEN
  1326.                  OPEN_OPTIONS:='NAME=' || TITLE || ',RECFM=F'||
  1327.                                ',LRECL=' || LRECL
  1328.                     ELSE
  1329.                  OPEN_OPTIONS:='NAME=' || TITLE || ',LRECL=32756';
  1330.               REWRITE(FILEINCOMING,OPEN_OPTIONS);
  1331.               CRFLAG := FALSE ;
  1332.               CRLFFLAG := FALSE ;
  1333.               STATE := RD ;
  1334.               SENDACK(TRUE);
  1335.               END   (* Got file header *)
  1336.                              ELSE
  1337.          BEGIN (* Not S,F,B,Z packet *)
  1338.          STATE := A ;   (* ABORT if not a S,F,B,Z type packet *)
  1339.          ABORT := NOT_SFBZ ;
  1340.          END ; (* Not S,F,B,Z packet *)
  1341.  
  1342.  
  1343.     (* RD ----- Receive Data State ------- *)
  1344.     (* Valid received msg type  : D,Z      *)
  1345.     RD: IF (NOT RECVPACKET) OR (INPACKETTYPE='N') THEN SENDNAK
  1346.                                                   ELSE
  1347.         IF LASTSEQNUM = INSEQ THEN
  1348.             BEGIN (* repeated packet *)
  1349.             OUTSEQ := OUTSEQ - 1 ;
  1350.             SENDACK(TRUE)
  1351.             END   (* repeated packet *)
  1352.                               ELSE
  1353.         (* Got a good packet *)
  1354.         IF INPACKETTYPE = 'D' THEN
  1355.               BEGIN (* Receive data *)
  1356.               LASTSEQNUM := INSEQ ;
  1357.         (*    WRITELN ('RECEIVE data ');  *)
  1358.               I := 1 ;
  1359.               WHILE I <= INDATACOUNT DO
  1360.                 WITH REPLYMSG DO
  1361.                   IF TRANSLATION THEN
  1362.                    BEGIN (* SCAN EBCDIC data record *)
  1363.                    IF (CHARS[I]=REPEATCHAR) AND (REPEATCHAR<>' ') THEN
  1364.                         BEGIN (* Get number of repeated chars *)
  1365.                         I := I + 1 ;
  1366.                         CNT := ORD(EBCDICTOASCII[BYTES[I]])- 32 ;
  1367.                         I:= I + 1 ;
  1368.                         END   (* Get number of repeated chars *)
  1369.                                             ELSE CNT := 1 ;
  1370.                    IF CHARS[I] = BIT8_QUOTE THEN
  1371.                         BEGIN (* BIT8 character *)
  1372.                         CHARS[I] := '80'XC  ;
  1373.                         IF CRFLAG THEN  (* previous char was a CR *)
  1374.                              WRITE(FILEINCOMING,'0D'XC,CHARS[I])
  1375.                                   ELSE
  1376.                              WRITE  (FILEINCOMING,CHARS[I]);
  1377.                         I := I + 1 ;
  1378.                         CRFLAG := FALSE ;
  1379.                         END ; (* BIT8 character *)
  1380.                    IF CHARS[I] = CNTRL_QUOTE THEN
  1381.                         BEGIN (* CONTROL character *)
  1382.                         I := I+1 ;
  1383.                         IF (CHARS[I] <> ' ') AND
  1384.                           ((CHARS[I] = CNTRL_QUOTE) OR
  1385.                            (CHARS[I] = BIT8_QUOTE) OR
  1386.                            (CHARS[I] = REPEATCHAR)) THEN
  1387.                                                 ELSE
  1388.                           BEGIN (* control char *)
  1389.                           CHARS[I] := EBCDICTOASCII[BYTES[I]]  ;
  1390.                           IF CHARS[I] = '3F'XC THEN (* Make it a del *)
  1391.                              BYTES[I] := '7F'X
  1392.                                           ELSE
  1393.                           IF BYTES[I] >= 64 THEN (* Make it a control *)
  1394.                              BYTES[I] := BYTES[I] - 64 ;
  1395.                           IF BYTES[I] <> 0 THEN
  1396.                              CHARS[I] := ASCIITOEBCDIC[BYTES[I]]  ;
  1397.                           END ; (* control char *)
  1398.                         END ; (* CONTROL character *)
  1399.                    IF CRFLAG THEN BEGIN  (* previous char was a CR *)
  1400.                                   CRFLAG := FALSE ;
  1401.                                   IF CHARS[I] = '25'XC THEN  (*LF*)
  1402.                                    WRITELN(FILEINCOMING)
  1403.                                                        ELSE
  1404.                                    WRITE(FILEINCOMING,'0D'XC,CHARS[I])
  1405.                                   END   (* previous char was a CR *)
  1406.                              ELSE
  1407.                    IF  CHARS[I] = '0D'XC  THEN
  1408.                         BEGIN (* CR *)
  1409.                         CRFLAG := TRUE ;
  1410.                         IF CNT > 1 THEN FOR J := 2 TO CNT DO
  1411.                              WRITE  (FILEINCOMING,CHARS[I]);
  1412.                         END   (* CR *)
  1413.                                           ELSE
  1414.                         BEGIN  (* not a CR *)
  1415.                         CRFLAG := FALSE ;
  1416.                         FOR J := 1 TO CNT DO
  1417.                              WRITE  (FILEINCOMING,CHARS[I]);
  1418.                         END ;  (* not a CR *)
  1419.                    I := I + 1 ;
  1420.                    END   (* SCAN EBCDIC data record *)
  1421.                                  ELSE
  1422.  
  1423.                    BEGIN (* Revert back to ASCII data record *)
  1424.                    IF (CHARS[I]=REPEATCHAR) AND (REPEATCHAR<>' ') THEN
  1425.                         BEGIN (* Get number of repeated chars *)
  1426.                         I := I + 1 ;
  1427.                         CNT := ORD(EBCDICTOASCII[BYTES[I]]) - 32 ;
  1428.                         I:= I + 1 ;
  1429.                         END   (* Get number of repeated chars *)
  1430.                                             ELSE CNT := 1 ;
  1431.                    IF (CHARS[I]=BIT8_QUOTE) AND (BIT8_QUOTE<>' ') THEN
  1432.                         BEGIN (* 8TH BIT QUOTING  *)
  1433.                         I := I+1 ;
  1434.                         BIT8 := 128 ;
  1435.                         END   (* 8TH BIT QUOTING  *)
  1436.                                             ELSE
  1437.                         BIT8 := 0 ;
  1438.                    IF CHARS[I] = CNTRL_QUOTE THEN
  1439.                         BEGIN (* CONTROL character *)
  1440.                         I := I+1 ;
  1441.                         IF (CHARS[I] <> ' ') AND
  1442.                           ((CHARS[I] = CNTRL_QUOTE) OR
  1443.                            (CHARS[I] = BIT8_QUOTE) OR
  1444.                            (CHARS[I] = REPEATCHAR)) THEN
  1445.                              CHARS[I] := EBCDICTOASCII[BYTES[I]]
  1446.                                                     ELSE
  1447.                           BEGIN (* control char *)
  1448.                           CHARS[I] := EBCDICTOASCII[BYTES[I]]  ;
  1449.                           IF CHARS[I] = '3F'XC THEN  (* Make it a del *)
  1450.                               BYTES[I] := '7F'X
  1451.                                                ELSE
  1452.                           IF BYTES[I] >= 64 THEN (* Make it a control *)
  1453.                               BYTES[I] := BYTES[I] - 64 ;
  1454.                           END ; (* control char *)
  1455.                         END   (* CONTROL character *)
  1456.                                              ELSE
  1457.                         CHARS[I] := EBCDICTOASCII[BYTES[I]]  ;
  1458.                    BYTES[I] := BYTES[I] + BIT8 ;
  1459.                    FOR J := 1 TO CNT DO
  1460.                         WRITE  (FILEINCOMING,CHARS[I]);
  1461.                    (* no special check for CR an LF *)
  1462.                    I := I + 1 ;
  1463.                    END ; (* Revert back to ASCII data record *)
  1464.               OUTSEQ := INSEQ - 1 ;
  1465.               SENDACK(TRUE);
  1466.               END   (* Receive data *)
  1467.                               ELSE
  1468.          IF INPACKETTYPE = 'F' THEN
  1469.               BEGIN (* repeat *)
  1470.               OUTSEQ := OUTSEQ - 1 ;
  1471.               SENDACK(TRUE) ;
  1472.               END   (* repeat *)
  1473.                               ELSE
  1474.          IF INPACKETTYPE = 'Z' THEN
  1475.               BEGIN (* End of Incoming File *)
  1476.               CLOSE(FILEINCOMING);
  1477.               STATE := RF ;
  1478.               SENDACK(TRUE);
  1479.               END   (* End of Incoming File *)
  1480.                               ELSE
  1481.          BEGIN (* Not D,Z packet *)
  1482.          STATE := A;   (* ABORT - Type not  D,Z, *)
  1483.          ABORT := NOT_DZ ;
  1484.          END ; (* Not D,Z packet *)
  1485.  
  1486.  
  1487.     (* C ----- COMPLETED  State ------- *)
  1488.      C:  BEGIN (* COMPLETED Receiving *)
  1489.          SENDACK(TRUE);
  1490.     (*   WRITELN ('RECEIVEing files completed.'); *)
  1491.          RECEIVING := FALSE ;
  1492.          END ; (* COMPLETED Receiving *)
  1493.  
  1494.     (* A ----- A B O R T  State ------- *)
  1495.      A:  BEGIN (* Abort Sending *)
  1496.     (*   WRITELN ('RECEIVEing files ABORTED');    *)
  1497.          RECEIVING := FALSE ;
  1498.                (* SEND ERROR packet *)
  1499.               OUTDATACOUNT := 15 ;
  1500.               OUTSEQ   := 0 ;
  1501.               SENDMSG.CHARS := 'Send file abort' ;
  1502.               OUTPACKETTYPE := 'E';
  1503.               SENDPACKET ;
  1504.          END ; (* Abort Sending *)
  1505.  
  1506.          END ; (* CASE of STATE *)
  1507.     IF FULLSCREENDEVICE THEN
  1508.          IF NOT FULLSCREENIO THEN BEGIN READSCREEN; FINISCREEN; END ;
  1509.     END ; (* ------- RECVFILE procedure -------*)
  1510.  
  1511. %PAGE
  1512. (* **************************************************************** *)
  1513. (* SHOWIT -    This routine handles the SHOW COMMAND.             * *)
  1514. (*                                                                * *)
  1515. (* **************************************************************** *)
  1516.  PROCEDURE SHOWIT ;
  1517.     BEGIN (* SHOWIT procedure *)
  1518.     IF FULLSCREENDEVICE THEN CMS('CLRSCRN ',RC );
  1519.     WRITELN (' ------- Current Status -----------');
  1520.     WRITELN(' ');
  1521.     IF TRANSLATION THEN WRITELN (' TRANSLATION is ON  - ASCII/EBCDIC')
  1522.                    ELSE WRITELN (' TRANSLATION is OFF' );
  1523.     IF FB THEN  WRITELN (' RECFM_INPUT is F    LRECL is ',LRECL)
  1524.           ELSE  WRITELN (' RECFM_INPUT is V ');
  1525.     WRITELN('                ');
  1526.     WRITELN(' PACKET SIZE is ',RPACKETSIZE:4, ' (RECEIVE PACKET SIZE)');
  1527.     WRITELN(' EOL CHAR    is ',ECHAR:2,' decimal(ascii)');
  1528.     WRITELN(' CNTRL_QUOTE is ',CNTRL_QUOTE);
  1529.     WRITELN(' BIT8_QUOTE  is ',BIT8_QUOTE);
  1530.     WRITELN(' CHECKTYPE   is ',CHECKTYPE);
  1531.     WRITELN(' REPEATCHAR  is ',REPEATCHAR);
  1532.     WRITELN(' ');
  1533.     WRITELN(' SEND PACKET SIZE is ',SPACKETSIZE:4,
  1534.             ' to accommodate the other KERMIT.');
  1535.     WRITELN(' ');
  1536.     IF STATE = C THEN
  1537.          WRITELN('Last File transferred completed OK. ');
  1538.     IF STATE = A THEN
  1539.          BEGIN (* ABORTED file transfer *)
  1540.          WRITE  ('Last File transfer Aborted while ');
  1541.          CASE ABORT OF
  1542.              BADSF: WRITELN('attempting to send file to micro.');
  1543.              NOT_S: WRITELN('waiting for Init Packet.');
  1544.           NOT_SFBZ: WRITELN('waiting for File header packet.');
  1545.             NOT_DZ: WRITELN('waiting for a DATA  packet.');
  1546.             OTHERWISE WRITELN (' being completely confused ');
  1547.             END ; (* CASE ABORT *)
  1548.          WRITELN(' ');
  1549.          END ; (* ABORTED file transfer *)
  1550.  
  1551.     END ; (* SHOWIT procedure *)
  1552.  
  1553.  
  1554.  
  1555. %PAGE
  1556. (* **************************************************************** *)
  1557. (* SETIT  -    This routine handles the SET  COMMAND.             * *)
  1558. (*                                                                * *)
  1559. (* **************************************************************** *)
  1560.  PROCEDURE SETIT ;
  1561.     BEGIN (* SETIT  procedure *)
  1562.     IF FULLSCREENDEVICE THEN CMS('CLRSCRN ',RC );
  1563.  (* WRITELN (' -------SET ROUTINE ------- ');     *)
  1564.          COMMAND := GETTOKEN (INPUTSTRING);
  1565.          UPCASE(COMMAND);
  1566.          REQUEST := ' ' || TRIM(STR(COMMAND));
  1567.          CINDEX := INDEX(WHATTABLE,REQUEST) DIV 8 ;
  1568.  
  1569.          CASE WHATFLAGS(CINDEX) OF
  1570.           (*  BEGIN    Set WHAT command *)
  1571.     $TRANSLATION :
  1572.               BEGIN  (* TRANSLATION FLAG *)
  1573.               SETTING := GETTOKEN (INPUTSTRING);
  1574.               UPCASE(SETTING) ;
  1575.               TRANSLATION :=  NOT(SETTING = 'OFF     ') ;
  1576.               IF TRANSLATION THEN WRITELN ('TRANSLATION is ON ')
  1577.                              ELSE WRITELN ('TRANSLATION is OFF');
  1578.               END ;  (* TRANSLATION FLAG *)
  1579.     $RECFM :
  1580.               BEGIN  (* RECFM  *)
  1581.               SETTING := GETTOKEN (INPUTSTRING);
  1582.               UPCASE(SETTING) ;
  1583.               IF SETTING = 'F       ' THEN FB := TRUE
  1584.                                       ELSE FB := FALSE;
  1585.               IF FB THEN WRITELN (' INPUT RECFM is F  LRECL is ',LRECL)
  1586.                     ELSE WRITELN (' INPUT RECFM is V ');
  1587.               END ;  (* RECFM *)
  1588.     $LRECL:
  1589.               BEGIN  (* LOGICAL RECORD LENGTH  *)
  1590.               LRECL := STR(GETTOKEN (INPUTSTRING));
  1591.               END ;  (* LOGICAL RECORD LENGTH  *)
  1592.     $PACKETSIZE:
  1593.               BEGIN (* SET PACKET SIZE *)
  1594.               READSTR(INPUTSTRING,RPACKETSIZE);
  1595.               IF RPACKETSIZE > (MAXINPUT-5) THEN
  1596.                   BEGIN
  1597.                   RPACKETSIZE := MAXINPUT-5 ;
  1598.                   WRITELN ('Number too large.  Will use ',RPACKETSIZE);
  1599.                   END ;
  1600.               IF RPACKETSIZE < 26 THEN
  1601.                   BEGIN
  1602.                   WRITELN (' ERROR- Number too small. Will use 94.');
  1603.                   RPACKETSIZE := 94 ;
  1604.                   END ;
  1605.               WRITELN(' PACKET SIZE is ',RPACKETSIZE:4);
  1606.               END ; (* SET PACKET SIZE *)
  1607.    $EOLCHAR :
  1608.               BEGIN (* SET end of line char *)
  1609.               READSTR(INPUTSTRING,ECHAR);
  1610.               WRITELN(' EOLCHAR     is ',ECHAR,' decimal(ascii)');
  1611.               END ; (* SET end of line char *)
  1612.    $CNTRL_QUOTE:
  1613.               BEGIN (* SET control quote *)
  1614.               READSTR(INPUTSTRING,CNTRL_QUOTE);
  1615.               WRITELN(' CNTRL QUOTE is ',CNTRL_QUOTE);
  1616.               END ; (* SET control quote *)
  1617.    $BIT8_QUOTE:
  1618.               BEGIN (* SET bit 8 quote *)
  1619.               READSTR(INPUTSTRING,BIT8_QUOTE);
  1620.               WRITELN(' BIT8_QUOTE  is ',BIT8_QUOTE);
  1621.               END ; (* SET bit 8 quote *)
  1622.    $REPEATCHAR:
  1623.               BEGIN (* SET repeat char *)
  1624.               READSTR(INPUTSTRING,REPEATCHAR);
  1625.               WRITELN(' REPEATCHAR  is ',REPEATCHAR);
  1626.               END ; (* SET repeat char *)
  1627.    $CHECKTYPE :
  1628.               BEGIN (* SET CHECK TYPE  *)
  1629.               READSTR(INPUTSTRING,CHECKTYPE);
  1630.               WRITELN(' CHECKTYPE   is ',CHECKTYPE );
  1631.               END ; (* SET CHECK TYPE  *)
  1632.     $DUMMY:
  1633.              WRITELN (' NOT YET implemented ');
  1634.  
  1635.     OTHERWISE BEGIN (*  Invalid SET  OPTION  *)
  1636.               IF FULLSCREENDEVICE THEN CMS('CLRSCRN ',RC );
  1637.               WRITELN (' SET ',REQUEST,' - invalid option specified.');
  1638.               WRITELN (' Valid   OPTIONS are :   ');
  1639.               WRITELN (' ----------------------- ');
  1640.               WRITELN (' TRANSLATION ON/OFF - for ascii-ebcdic ');
  1641.               WRITELN (' RECFM        V/F   - Variable or Fixed');
  1642.               WRITELN (' LRECL        nnn   - Record length(decimal)');
  1643.               WRITELN (' EOLCHAR      nn    - Endline char(decimal)');
  1644.               WRITELN (' PACKETSIZE   nn    - Packet size (decimal)');
  1645.               WRITELN (' CNTRL_QUOTE  c     - Quote character ');
  1646.               WRITELN (' BIT8_QUOTE   c     - Bit8 quote character');
  1647.               END ; (*  Invalid SET  OPTION  *)
  1648.  
  1649.               END ; (* Execute the Command *)
  1650.     END ; (* SETIT  procedure *)
  1651.  
  1652. %PAGE
  1653. (* **************************************************************** *)
  1654. (* HELP   -    This routine handles the HELP   COMMAND.           * *)
  1655. (*                                                                * *)
  1656. (* **************************************************************** *)
  1657.  PROCEDURE HELP ;
  1658.     BEGIN (* HELP procedure *)
  1659.     IF FULLSCREENDEVICE THEN CMS('CLRSCRN ',RC );
  1660.     WRITELN (' The following are the valid KERMIT-CMS commands : ');
  1661.     WRITELN ('-------------------------------------------------- ');
  1662.     WRITELN (' SEND    fn ft fm              ');
  1663.     WRITELN ('                   - send  a   file, IBM to micro ');
  1664.     WRITELN (' RECEIVE fm:fn.ft  AS  fn ft fm       ');
  1665.     WRITELN ('                   - receive a file, micro to IBM');
  1666.     WRITELN (' SERVER            - go into server mode   ');
  1667.     WRITELN (' ');
  1668.     WRITELN (' SET option value  - set OPTION to VALUE ');
  1669.     WRITELN (' STATUS            - displays current options settings');
  1670.     WRITELN ('    ');
  1671.     WRITELN (' CMS  command      - issues a CMS command.');
  1672.     WRITELN (' CP   command      - issues a CP  command.');
  1673.     WRITELN ('    ');
  1674.     WRITELN (' HELP              - displays this information ');
  1675.     WRITELN (' EXIT              - exit KERMIT , terminate program.');
  1676.     WRITELN (' ');
  1677.     END ; (* HELP procedure *)
  1678.  
  1679. %PAGE
  1680. (* **************************************************************** *)
  1681. (* REMOTECOMMAND -This routine handle the  COMMANDS from a remote * *)
  1682. (*                kermit.                                         * *)
  1683. (* **************************************************************** *)
  1684.  PROCEDURE REMOTECOMMAND ;
  1685.  CONST
  1686.     SUBCOMMANDTABLE  = 'ICLFDUETRKSPWMHQJV' ;
  1687.  TYPE
  1688.     SUBCOMMANDTYPE = (ZERO,I,C,L,F,D,U,E,T,R,K,S,P,W,M,H,Q,J,V);
  1689.  VAR
  1690.     COMMANDTYPE,SUBCOMMAND,DUMMY : CHAR ;
  1691.     DOT,COLON : INTEGER ;
  1692.     RET,FILEINDEX,IX,LEN1  :  INTEGER ;
  1693.     FN,FT,FM  : STRING(16) ;
  1694.     CMSFNAME : STRING(80);
  1695.     VARCOMM : STRING(80);
  1696.     VARNAME : STRING(80);
  1697.     VARVALUE: STRING(80);
  1698.     CMSCOMMAND : STRING(80) ;
  1699.     DATE,TIME : ALFA ;
  1700.     DIRECTORY : PACKED ARRAY[0..255] OF STRING(80);
  1701. LABEL CHECKCOMMAND ;
  1702. (* ----------------------------------------------------------------- *)
  1703. PROCEDURE SENDBPACKET;
  1704.     BEGIN  (* send break packet to terminate transmission *)
  1705.      OUTDATACOUNT := 0 ;
  1706.      OUTSEQ   := OUTSEQ + 1 ;
  1707.      IF OUTSEQ >= 64 THEN OUTSEQ := 0 ;
  1708.      OUTPACKETTYPE := 'B' ;
  1709.      SENDPACKET ;
  1710.     END;   (* send break packet to terminate transmission *)
  1711. (* ----------------------------------------------------------------- *)
  1712. PROCEDURE SENDZPACKET;
  1713.      BEGIN (* End of File *)
  1714.      OUTDATACOUNT :=  0 ;
  1715.      OUTSEQ   := OUTSEQ + 1 ;
  1716.      IF OUTSEQ >= 64 THEN OUTSEQ := 0; ;
  1717.      OUTPACKETTYPE := 'Z' ;
  1718.      SENDPACKET ;
  1719.      END ; (* End of File *)
  1720. (* ----------------------------------------------------------------- *)
  1721.  PROCEDURE REMSETIT ;
  1722.  VAR TEMPSTR : STRING(256) ;
  1723.     BEGIN (* REMSETIT  procedure *)
  1724.          COMMAND := GETTOKEN (INPUTSTRING);
  1725.          UPCASE(COMMAND);
  1726.          REQUEST := ' ' || TRIM(STR(COMMAND));
  1727.          CINDEX := INDEX(WHATTABLE,REQUEST) DIV 8 ;
  1728.  
  1729.          CASE WHATFLAGS(CINDEX) OF
  1730.           (*  BEGIN    Set WHAT command *)
  1731.     $TRANSLATION :
  1732.               BEGIN  (* TRANSLATION FLAG *)
  1733.               SETTING := GETTOKEN (INPUTSTRING);
  1734.               UPCASE(SETTING) ;
  1735.               TRANSLATION :=  NOT(SETTING = 'OFF') ;
  1736.               IF TRANSLATION THEN
  1737.                    SENDMSG.CHARS := 'Translation is ON        '
  1738.                              ELSE
  1739.                    SENDMSG.CHARS := 'Translation is OFF       ';
  1740.               END ;  (* TRANSLATION FLAG *)
  1741.     $RECFM :
  1742.               BEGIN  (* RECFM  *)
  1743.               SETTING := GETTOKEN (INPUTSTRING);
  1744.               UPCASE(SETTING) ;
  1745.               IF SETTING[1] ='F'  THEN FB := TRUE
  1746.                                   ELSE FB := FALSE;
  1747.               IF FB THEN SENDMSG.CHARS := 'INPUT RECFM is F         '    '
  1748.                     ELSE SENDMSG.CHARS := 'INPUT RECFM is V         ';
  1749.               END ;  (* RECFM *)
  1750.     $LRECL:
  1751.               BEGIN  (* LOGICAL RECORD LENGTH  *)
  1752.               LRECL := STR(GETTOKEN (INPUTSTRING));
  1753.               SENDMSG.CHARS := 'INPUT LRECL is ' || LRECL ;              '
  1754.               END ;  (* LOGICAL RECORD LENGTH  *)
  1755.     $PACKETSIZE:
  1756.               BEGIN (* SET PACKET SIZE *)
  1757.               READSTR(INPUTSTRING,RPACKETSIZE);
  1758.               IF RPACKETSIZE > (MAXINPUT-5) THEN
  1759.                   BEGIN
  1760.                   RPACKETSIZE := MAXINPUT-5 ;
  1761.                   WRITESTR(TEMPSTR,RPACKETSIZE:-10);
  1762.                   SENDMSG.CHARS:='Number too large. Use  '|| TEMPSTR ;
  1763.                   END ;
  1764.               IF RPACKETSIZE < 26 THEN
  1765.                   BEGIN
  1766.                   SENDMSG.CHARS :=' Number too small. Will use 94.';
  1767.                   RPACKETSIZE := 94 ;
  1768.                   END ;
  1769.               WRITESTR(TEMPSTR,RPACKETSIZE:-10);
  1770.               SENDMSG.CHARS:=' PACKET SIZE is '|| TEMPSTR ;
  1771.               END ; (* SET PACKET SIZE *)
  1772.    $REPEATCHAR:
  1773.               BEGIN (* SET repeat char *)
  1774.               READSTR(INPUTSTRING,REPEATCHAR);
  1775.               SENDMSG.CHARS:=' REPEATCHAR  is '|| STR(REPEATCHAR) ;
  1776.               END ; (* SET repeat char *)
  1777.  
  1778.      OTHERWISE
  1779.              SENDMSG.CHARS := 'Unavailable SET specs.   ';
  1780.              END ; (*case*)
  1781.  
  1782.     OUTDATACOUNT := 25 ;
  1783.     OUTSEQ := 0 ;
  1784.     OUTPACKETTYPE := 'Y' ;
  1785.     SENDPACKET ;
  1786.     END ; (* REMSETIT  procedure *)
  1787.  
  1788. (* ---------------------------------------------------------------- *)
  1789. (* REMSHOWIT - This routine handles the REMOTE SHOW COMMAND.        *)
  1790.  PROCEDURE REMSHOWIT ;
  1791.     BEGIN (* REMSHOWIT procedure *)
  1792.     OUTDATACOUNT := 35 ;
  1793.     OUTSEQ := 0 ;
  1794.     OUTPACKETTYPE := 'X' ;
  1795.     IF TRANSLATION THEN
  1796.         SENDMSG.CHARS := 'TRANSLATION is ON - EBCDIC / ASCII '
  1797.                    ELSE
  1798.         SENDMSG.CHARS := 'TRANSLATION is OFF                 ';
  1799.     SENDPACKET ;
  1800.     IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  1801.                                          ELSE RESENDIT(10);
  1802.     OUTPACKETTYPE := 'D' ;
  1803.     OUTSEQ := OUTSEQ + 1 ;
  1804.     IF FB THEN
  1805.         SENDMSG.CHARS := 'INPUT RECFM is F.  LRECL = ' || LRECL
  1806.                    ELSE
  1807.         SENDMSG.CHARS := 'INPUT RECFM is V                    ';
  1808.     SENDPACKET ;
  1809.     IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  1810.                                          ELSE RESENDIT(10);
  1811.     OUTSEQ := OUTSEQ + 1 ;
  1812.     OUTDATACOUNT := 4 ;
  1813.     OUTPACKETTYPE := 'D' ;
  1814.     SENDMSG.CHARS := '#M#J';
  1815.     SENDPACKET ;
  1816.     IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  1817.                                          ELSE RESENDIT(10);
  1818.     SENDZPACKET ;
  1819.     IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  1820.                                          ELSE RESENDIT(10);
  1821.     SENDBPACKET ;
  1822.     END ; (* REMSHOWIT procedure *)
  1823.  
  1824. (* ----------------------------------------------------------------- *)
  1825. FUNCTION  CMSFILENAME (TEMPNAME : STRING(80) ): STRING(80) ;
  1826.      (* Converts name into a CMS name *)
  1827.      BEGIN (* CMS FILE NAME *)
  1828.      TEMPNAME := COMPRESS(TEMPNAME);
  1829.      COLON := INDEX(TEMPNAME,':');
  1830.      IF COLON > 0 THEN
  1831.      TEMPNAME:=SUBSTR(TEMPNAME,COLON+1,LENGTH(TEMPNAME)-COLON)
  1832.                           || ' ' || SUBSTR(TEMPNAME,1,COLON-1) ;
  1833.      DOT := INDEX(TEMPNAME,'.');
  1834.      IF DOT > 0 THEN TEMPNAME[DOT] := ' ' ;
  1835.      CMSFILENAME :=  TEMPNAME  ;
  1836.      END ; (* CMS FILE NAME *)
  1837. (* ----------------------------------------------------------------- *)
  1838.     BEGIN (* REMOTECOMMAND procedure *)
  1839. (*  WRITELN (' GOT a REMOTE COMMAND. ');  *)
  1840.     INDATACOUNT := ORD(EBCDICTOASCII[Ord(INPUTSTRING[2])])-32-3;
  1841.     COMMANDTYPE := INPUTSTRING[4];
  1842. CHECKCOMMAND :
  1843.     IF COMMANDTYPE = 'S' THEN                   (* SEND *)
  1844.          BEGIN (* SEND command *)
  1845.          INPUTSTRING := '    ' ;
  1846.    (*    SENDACK(TRUE); *)
  1847.          RECVFILE ;
  1848.          END   (* SEND command *)
  1849.                           ELSE
  1850.     IF COMMANDTYPE = 'R' THEN                   (* RECEIVE *)
  1851.          BEGIN (* RECEIVE command *)
  1852.          INPUTSTRING := SUBSTR(INPUTSTRING,5,INDATACOUNT);
  1853.          COLON := INDEX(INPUTSTRING,':');
  1854.          IF COLON > 1 THEN
  1855.               BEGIN (* Extract FM *)
  1856.               FM := SUBSTR(INPUTSTRING,1,COLON-1) ;
  1857.               INPUTSTRING := SUBSTR(INPUTSTRING,COLON+1,
  1858.                                      LENGTH(INPUTSTRING)-COLON);
  1859.               END   (* Extract FM *)
  1860.                      ELSE
  1861.               FM := ' ' ;
  1862.          DOT := INDEX(INPUTSTRING,'.');
  1863.          IF DOT > 1 THEN
  1864.               BEGIN  (* file name  and type *)
  1865.               FN := SUBSTR(INPUTSTRING,1,DOT-1) ;
  1866.               FT := SUBSTR(INPUTSTRING,DOT+1,LENGTH(INPUTSTRING)-DOT);
  1867.               END    (* file name and type *)
  1868.                     ELSE
  1869.               BEGIN (* no file type *)
  1870.               FN := INPUTSTRING;
  1871.               FT := ' ' ;
  1872.               END ; (*no file type *)
  1873.          SENDFILE( FN || ' ' || FT || ' ' || FM );
  1874.          END   (* RECEIVE command *)
  1875.                           ELSE
  1876.     IF COMMANDTYPE = 'C' THEN                   (* HOST COMMAND *)
  1877.          BEGIN (* HOST command *)
  1878.          INPUTSTRING := SUBSTR(INPUTSTRING,6,INDATACOUNT-1);
  1879.          CMS(INPUTSTRING,RC);
  1880.               OUTDATACOUNT := 25 ;
  1881.               OUTSEQ := 0 ;
  1882.               OUTPACKETTYPE := 'Y' ;
  1883.               SENDMSG.CHARS := 'Host Command submitted   ';
  1884.               SENDPACKET ;
  1885.          END   (* HOST command *)
  1886.                           ELSE
  1887.     IF COMMANDTYPE = 'K' THEN                   (* KERMIT COMMAND *)
  1888.          BEGIN (* KERMIT command *)
  1889.          INPUTSTRING := SUBSTR(INPUTSTRING,6,INDATACOUNT-1);
  1890.          INPUTSTRING := LTRIM(COMPRESS(INPUTSTRING));
  1891.          COMMAND := GETTOKEN (INPUTSTRING);
  1892.          UPCASE(COMMAND);
  1893.          IF COMMAND = 'SET' THEN REMSETIT
  1894.                             ELSE
  1895.          IF COMMAND = 'SHOW' THEN REMSHOWIT
  1896.                             ELSE
  1897.               BEGIN (* not set command *)
  1898.               OUTDATACOUNT := 25 ;
  1899.               OUTSEQ := 0 ;
  1900.               OUTPACKETTYPE := 'Y' ;
  1901.               SENDMSG.CHARS := STR(COMMAND) || ' not allowed  . ';
  1902.               SENDPACKET ;
  1903.               END ; (* not set command *)
  1904.          END   (* KERMIT command *)
  1905.                           ELSE
  1906.     IF COMMANDTYPE = 'I' THEN                   (* INITIALIZE   *)
  1907.          BEGIN (* INITIALIZE command *)
  1908.          INDATACOUNT := ORD(EBCDICTOASCII[Ord(INPUTSTRING[2])])-32-3;
  1909.     (*   Writeln('Remote I Packet ');  *)
  1910.          (* Get init parameters *)
  1911.          IF INDATACOUNT>= 1 THEN
  1912.               PSIZE := ORD(EBCDICTOASCII[Ord(INPUTSTRING[4+1])])-32 ;
  1913.          IF INDATACOUNT>= 5 THEN
  1914.               ECHAR := ORD(EBCDICTOASCII[Ord(INPUTSTRING[4+5])])-32 ;
  1915.          IF INDATACOUNT>= 6 THEN
  1916.               CNTRL_QUOTE := INPUTSTRING[4+6] ;
  1917.          IF  INDATACOUNT>= 7 THEN
  1918.               BIT8_QUOTE := INPUTSTRING[4+7]
  1919.                           ELSE
  1920.               BIT8_QUOTE := '00'XC ;    (* No 8th bit quoting *)
  1921.          IF INDATACOUNT>= 8 THEN
  1922.               CHECKTYPE  := INPUTSTRING[4+8]
  1923.                            ELSE
  1924.               CHECKTYPE  := '00'XC ;    (* One char checksum DEFAULT *)
  1925.          IF INDATACOUNT>= 9 THEN
  1926.               REPEATCHAR := INPUTSTRING[4+9]
  1927.                           ELSE
  1928.               REPEATCHAR := '00'XC ;    (* No repeat char  *)
  1929.          OUTPACKETTYPE := 'Y';
  1930.          PUTINITPACKET ;
  1931.          SENDPACKET ;
  1932.          IF RECVPACKET THEN
  1933.             BEGIN
  1934.             COMMANDTYPE := INPACKETTYPE ;
  1935.             INPUTSTRING := 'XXX'||  STR(INPACKETTYPE)
  1936.                   || SUBSTR(STR(REPLYMSG.CHARS),1,INDATACOUNT);
  1937.             GOTO CHECKCOMMAND ;
  1938.             END ;
  1939.          END   (* INITIALIZE command  *)
  1940.                           ELSE
  1941.     IF COMMANDTYPE = 'G' THEN                   (* GENERAL *)
  1942.          BEGIN (* General command *)
  1943.          SUBCOMMAND := INPUTSTRING[5];
  1944. (*       Writeln('Subcommand ',SUBCOMMAND);    *)
  1945.          CASE SUBCOMMANDTYPE(INDEX(SUBCOMMANDTABLE,STR(SUBCOMMAND))) OF
  1946.  
  1947.          I:   BEGIN (* LOGIN  command *)        (* LOGIN  *)
  1948.               OUTDATACOUNT := 19 ;
  1949.               OUTSEQ := 0 ;
  1950.               OUTPACKETTYPE := 'X' ;
  1951.               SENDMSG.CHARS := 'Login to KERMIT-CMS';
  1952.               SENDPACKET ;
  1953.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  1954.                                                    ELSE RESENDIT(10);
  1955.               SENDBPACKET ;
  1956.               END;  (* LOGIN  command *)
  1957.  
  1958.          C:   BEGIN (* CHANGE command *)        (* CHANGE *)
  1959.               OUTDATACOUNT := 35 ;
  1960.               OUTSEQ := 0 ;
  1961.               OUTPACKETTYPE := 'X' ;
  1962.               SENDMSG.CHARS := 'Change directory - Not Implemented ';
  1963.               SENDPACKET ;
  1964.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  1965.                                                    ELSE RESENDIT(10);
  1966.               SENDBPACKET ;
  1967.               END;  (* CHANGE command *)
  1968.  
  1969.          L:   BEGIN (* LOGOUT command *)        (* LOGOUT *)
  1970.               RUNNING := FALSE ;
  1971.               SENDACK(TRUE);
  1972.               CMS('CP LOG ',RC);
  1973.               END;  (* LOGOUT command *)
  1974.  
  1975.          F:   BEGIN (* FINISH command *)         (* FINISH *)
  1976.               RUNNING := FALSE ;
  1977.               SENDACK(TRUE);
  1978.               END;  (* FINISH command *)
  1979.  
  1980.          D:   BEGIN (* DIRECTORY command *)      (* DIRECTORY *)
  1981.               IF LENGTH(INPUTSTRING)>7 THEN
  1982.                    CMSFNAME:=SUBSTR(INPUTSTRING,7,
  1983.                        ORD(EBCDICTOASCII[ORD(INPUTSTRING[6])])-32)
  1984.                                        ELSE
  1985.                    CMSFNAME := '*' ;
  1986.               CMSCOMMAND := 'LISTFILE '|| CMSFILENAME(CMSFNAME)
  1987.                             || ' (STACK LABEL )' ;
  1988.               CMS(CMSCOMMAND,RET);
  1989.               IF RET <> 0 THEN
  1990.                    BEGIN (* No file *)
  1991.                    OUTDATACOUNT := 15 ;
  1992.                    OUTSEQ   := 0 ;
  1993.                    SENDMSG.CHARS := 'No file found. ' ;
  1994.                    OUTPACKETTYPE := 'E';
  1995.                    SENDPACKET ;
  1996.               (*   IF RECVPACKET AND
  1997.                         (INPACKETTYPE='Y') THEN
  1998.                                            ELSE RESENDIT(10); *)
  1999.                    END   (* No file *)
  2000.                           ELSE
  2001.                    BEGIN (* GOT directory *)
  2002.                    CMS('SENTRIES',RET);
  2003.                    FILEINDEX := RET ;
  2004.                    FOR IX := 1 TO FILEINDEX DO
  2005.                         READLN (DIRECTORY[IX]:80);
  2006.                    OUTSEQ  := 0 ;                 (* SEND X HEADER *)
  2007.                    SENDMSG.CHARS := CMSFNAME ;
  2008.                    OUTDATACOUNT := LENGTH(CMSFNAME);
  2009.                    OUTPACKETTYPE := 'X' ;
  2010.                    SENDPACKET ;
  2011.                    IF RECVPACKET AND
  2012.                         (INPACKETTYPE='Y') THEN
  2013.                                            ELSE RESENDIT(10);
  2014.                    STATE := SF ;
  2015.                    FOR IX := 1 TO FILEINDEX DO
  2016.                      IF STATE <> A THEN
  2017.                         BEGIN (* SEND DIRECTORY *)
  2018.                         CMSFNAME := DIRECTORY[IX] ;
  2019.                         SENDMSG.CHARS := CMSFNAME ;
  2020.                         OUTDATACOUNT := LENGTH(CMSFNAME);
  2021.                         OUTPACKETTYPE := 'D' ;
  2022.                         OUTSEQ := OUTSEQ + 1 ;
  2023.                         IF OUTSEQ >= 64 THEN OUTSEQ := 0; ;
  2024.                         SENDPACKET ;
  2025.                         IF RECVPACKET THEN
  2026.                              IF INPACKETTYPE = 'Y' THEN
  2027.                                                    ELSE RESENDIT(10)
  2028.                                       ELSE RESENDIT(10);
  2029.                         END ; (* SEND DIRECTORY *)
  2030.                    SENDZPACKET ;     (* EOF PACKET *)
  2031.                    IF RECVPACKET AND
  2032.                         (INPACKETTYPE='Y') THEN
  2033.                                            ELSE RESENDIT(10);
  2034.                    SENDBPACKET ;
  2035.                    END ; (* GOT directory *)
  2036.               END;  (* DIRECTORY command *)
  2037.  
  2038.          U:   BEGIN (* disk Usage command *)      (* Disk Usage *)
  2039.               OUTDATACOUNT := 30 ;
  2040.               OUTSEQ := 0 ;
  2041.               OUTPACKETTYPE := 'Y' ;
  2042.               SENDMSG.CHARS := 'Disk usage - Not Implemented   ';
  2043.               SENDPACKET ;
  2044.     (*        IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2045.                                                    ELSE RESENDIT(10);
  2046.               SENDBPACKET ;   *)
  2047.               END;  (* Disk Usage command *)
  2048.  
  2049.          E:   BEGIN (* Erase File command *)      (* Erase File *)
  2050.               IF LENGTH(INPUTSTRING)>7 THEN
  2051.                    CMSFNAME:=SUBSTR(INPUTSTRING,7,
  2052.                        ORD(EBCDICTOASCII[ORD(INPUTSTRING[6])])-32)
  2053.                                        ELSE
  2054.                    CMSFNAME := '*' ;
  2055.               CMSCOMMAND := 'ERASE ' || CMSFILENAME (CMSFNAME);
  2056.               CMS(CMSCOMMAND,RET) ;
  2057.  
  2058.               OUTDATACOUNT := LENGTH(CMSFNAME) + 15 ;
  2059.               OUTSEQ := 0 ;
  2060.               OUTPACKETTYPE := 'Y' ;
  2061.               IF RET = 0 THEN
  2062.                    SENDMSG.CHARS := 'file erased    ' || CMSFNAME
  2063.                          ELSE
  2064.                    SENDMSG.CHARS := 'not erased -   ' || CMSFNAME ;
  2065.               SENDPACKET ;
  2066.     (*        IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2067.                                                    ELSE RESENDIT(10);
  2068.               SENDBPACKET ;       *)
  2069.               END;  (* Erase File command *)
  2070.  
  2071.          T:   BEGIN (* TYPE  File command *)      (* TYPE  File *)
  2072.               IF LENGTH(INPUTSTRING)>7 THEN
  2073.                    CMSFNAME:=SUBSTR(INPUTSTRING,7,
  2074.                        ORD(EBCDICTOASCII[ORD(INPUTSTRING[6])])-32)
  2075.                                        ELSE
  2076.                    CMSFNAME := '*' ;
  2077.               CMSFNAME := CMSFILENAME(CMSFNAME);
  2078.               DOT := INDEX(CMSFNAME,' ');
  2079.               IF DOT = 0 THEN CMSFNAME := CMSFNAME || ' *' ;
  2080.               CMSCOMMAND := 'STATE ' || CMSFNAME  ;
  2081.               CMS(CMSCOMMAND,RET);
  2082.               IF RET <> 0 THEN
  2083.                    BEGIN (* No file *)
  2084.                    OUTDATACOUNT := 15 ;
  2085.                    OUTSEQ   := 0 ;
  2086.                    SENDMSG.CHARS := 'No file found. ' ;
  2087.                    OUTPACKETTYPE := 'E';
  2088.                    SENDPACKET ;
  2089.                    END   (* No file *)
  2090.                            ELSE
  2091.               BEGIN (* GOT  FILE *)
  2092.               DOT := INDEX(CMSFNAME,' ');
  2093.               IF DOT <> 0 THEN CMSFNAME[DOT] := '.' ;
  2094.               DOT := INDEX(CMSFNAME,' ');
  2095.               IF DOT <> 0 THEN CMSFNAME[DOT] := '.' ;
  2096.               RESET(FILETOSEND,'NAME='||CMSFNAME);
  2097.               OUTSEQ := 0 ;
  2098.               OUTPACKETTYPE := 'X' ;
  2099.               SENDMSG.CHARS := CMSFNAME ;
  2100.               OUTDATACOUNT := LENGTH(CMSFNAME);
  2101.               SENDPACKET;
  2102.        (*     SENDACK(TRUE);   *)
  2103.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2104.                                                    ELSE RESENDIT(10);
  2105.               STATE := SF ;
  2106.               WHILE NOT ( EOF(FILETOSEND) OR (STATE=A) ) DO
  2107.                    BEGIN (* SEND FILE *)
  2108.                    OUTPACKETTYPE := 'D' ;
  2109.                    FILETOPACKET ;
  2110.                    SENDPACKET ;
  2111.  
  2112.                    IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2113.                                                    ELSE RESENDIT(10);
  2114.                    IF EOLN(FILETOSEND) THEN
  2115.                               READ(FILETOSEND,DUMMY);  (* RESET *)
  2116.                    END ; (* SEND FILE *)
  2117.               SENDZPACKET ;     (* EOF PACKET *)
  2118.               IF RECVPACKET AND
  2119.                    (INPACKETTYPE='Y') THEN
  2120.                                       ELSE RESENDIT(10);
  2121.               SENDBPACKET ;
  2122.               END ; (* GOT  FILE *)
  2123.               END;  (* TYPE  File command *)
  2124.  
  2125.          R:   BEGIN (* Rename file   *)           (* RENAME *)
  2126.               OUTDATACOUNT := 30 ;
  2127.               IF LENGTH(INPUTSTRING)>7 THEN
  2128.                    BEGIN (* GOT PARM *)
  2129.                    LEN1 := ORD(EBCDICTOASCII[ORD(INPUTSTRING[6])])-32;
  2130.                    CMSFNAME:=SUBSTR(INPUTSTRING,7,LEN1);
  2131.                    END
  2132.                                        ELSE
  2133.                    CMSFNAME := '*' ;
  2134.               CMSFNAME := CMSFILENAME (CMSFNAME);
  2135.               DOT := INDEX(CMSFNAME,' ');
  2136.               IF DOT > 0 THEN
  2137.                    BEGIN  (* Check for FM *)
  2138.                    DOT := INDEX(SUBSTR(CMSFNAME,DOT+1),' ' ) ;
  2139.                    IF DOT = 0 THEN CMSFNAME := CMSFNAME || ' A' ;
  2140.                    END  (* Check for FM *)
  2141.                          ELSE  CMSFNAME := CMSFNAME || '*' ;
  2142.               CMSCOMMAND := 'RENAME ' || CMSFNAME ;
  2143.               IF LENGTH(INPUTSTRING)> (7+ LEN1) THEN
  2144.                    CMSFNAME:=SUBSTR(INPUTSTRING,8+LEN1,
  2145.                       ORD(EBCDICTOASCII[ORD(INPUTSTRING[7+LEN1])])-32)
  2146.                                        ELSE
  2147.                    CMSFNAME := '*' ;
  2148.               CMSFNAME := CMSFILENAME (CMSFNAME);
  2149.               DOT := INDEX(CMSFNAME,' ');
  2150.               IF DOT > 0 THEN
  2151.                    BEGIN  (* Check for FM *)
  2152.                    DOT := INDEX(SUBSTR(CMSFNAME,DOT+1),' ' ) ;
  2153.                    IF DOT = 0 THEN CMSFNAME := CMSFNAME || ' =' ;
  2154.                    END   (* Check for FM *)
  2155.                          ELSE  CMSFNAME := CMSFNAME || '*' ;
  2156.               IF INDEX(CMSFNAME,'*') > 0 THEN
  2157.                    BEGIN (* Invalid file *)
  2158.                    OUTDATACOUNT := 25 ;
  2159.                    OUTSEQ   := 0 ;
  2160.                    SENDMSG.CHARS := 'Invalid File Specfication ' ;
  2161.                    OUTPACKETTYPE := 'E';
  2162.                    SENDPACKET ;
  2163.                    END   (* Invalid File *)
  2164.                                          ELSE
  2165.               BEGIN (* RENAME IT *)
  2166.               CMSCOMMAND := CMSCOMMAND ||' '|| CMSFNAME ;
  2167.               CMS(CMSCOMMAND,RET) ;
  2168.  
  2169.               OUTDATACOUNT := LENGTH(CMSFNAME) + 16 ;
  2170.               OUTSEQ := 0 ;
  2171.               OUTPACKETTYPE := 'Y' ;
  2172.               IF RET = 0 THEN
  2173.                    SENDMSG.CHARS := 'File renamed - ' || CMSFNAME
  2174.                          ELSE
  2175.                    SENDMSG.CHARS := 'Not renamed to ' || CMSFNAME ;
  2176.               SENDPACKET ;
  2177.               END ; (* RENAME IT *)
  2178.               END;  (* Rename file  *)
  2179.  
  2180.          K:   BEGIN (* Copy   file   *)           (* COPY   *)
  2181.               OUTDATACOUNT := 30 ;
  2182.               OUTSEQ := 0 ;
  2183.               OUTPACKETTYPE := 'Y' ;
  2184.               SENDMSG.CHARS := 'Copy file - Not Implemented    ';
  2185.               SENDPACKET ;
  2186.               END;  (* Copy   file  *)
  2187.  
  2188.          S:   BEGIN (* Submit  command *)         (* SUBMIT  *)
  2189.               OUTDATACOUNT := 30 ;
  2190.               OUTSEQ := 0 ;
  2191.               OUTPACKETTYPE := 'X' ;
  2192.               SENDMSG.CHARS := 'SUMIT COMMAND NOT IMPLEMENTED ';
  2193.               SENDPACKET ;
  2194.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2195.                                                    ELSE RESENDIT(10);
  2196.               SENDBPACKET ;
  2197.               END;  (* Submit  command *)
  2198.  
  2199.          P:   BEGIN (* Program  command *)         (* PROGRAM *)
  2200.               OUTDATACOUNT := 30 ;
  2201.               OUTSEQ := 0 ;
  2202.               OUTPACKETTYPE := 'X' ;
  2203.               SENDMSG.CHARS := 'PROGRAM    - Not Implemented   ';
  2204.               SENDPACKET ;
  2205.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2206.                                                    ELSE RESENDIT(10);
  2207.               SENDBPACKET ;
  2208.               END;  (* PROGRAM command *)
  2209.  
  2210.          W:   BEGIN (* WHO   command *)           (* WHO  *)
  2211.               OUTDATACOUNT := 30 ;
  2212.               OUTSEQ := 0 ;
  2213.               OUTPACKETTYPE := 'X' ;
  2214.               SENDMSG.CHARS := 'WHO - Not Implemented        ';
  2215.               SENDPACKET ;
  2216.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2217.                                                    ELSE RESENDIT(10);
  2218.               SENDBPACKET ;
  2219.               END;  (* WHO  command *)
  2220.  
  2221.          M:   BEGIN (* MESSAGE  command *)        (* MESSAGE *)
  2222.               OUTDATACOUNT := 30 ;
  2223.               OUTSEQ := 0 ;
  2224.               OUTPACKETTYPE := 'X' ;
  2225.               SENDMSG.CHARS := 'MESSAGE  - not implemented    ';
  2226.               SENDPACKET ;
  2227.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2228.                                                    ELSE RESENDIT(10);
  2229.               SENDBPACKET ;
  2230.               END;  (* MESSAGE  command *)
  2231.  
  2232.          H:   BEGIN (* HELP  command *)           (* HELP *)
  2233.               OUTDATACOUNT := 15 ;
  2234.               OUTSEQ := 0 ;
  2235.               OUTPACKETTYPE := 'X' ;
  2236.               SENDMSG.CHARS := 'See KERMIT DOC ';
  2237.               SENDPACKET ;
  2238.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2239.                                                    ELSE RESENDIT(10);
  2240.               SENDBPACKET ;
  2241.               END;  (* HELP  command *)
  2242.  
  2243.          Q:   BEGIN (* QUERY status command *)     (* QUERY *)
  2244.               OUTDATACOUNT := 15 ;
  2245.               OUTSEQ := 0 ;
  2246.               OUTPACKETTYPE := 'X' ;
  2247.               SENDMSG.CHARS := 'Your ok        ';
  2248.               SENDPACKET ;
  2249.               IF RECVPACKET AND (INPACKETTYPE='Y') THEN
  2250.                                                    ELSE RESENDIT(10);
  2251.               SENDBPACKET ;
  2252.               END;  (* QUERY Status command *)
  2253.  
  2254.          J:   BEGIN (* Journal       *)           (* JOURNAL *)
  2255.               OUTDATACOUNT := 15 ;
  2256.               OUTSEQ := 0 ;
  2257.               OUTPACKETTYPE := 'Y' ;
  2258.               SENDMSG.CHARS := 'No Journal    ';
  2259.               SENDPACKET ;
  2260.               END;  (* Journal      *)
  2261.  
  2262.          V:   BEGIN (* Variable      *)           (* VARIABLE *)
  2263.               INPUTSTRING:=SUBSTR(INPUTSTRING,6,INDATACOUNT-1);
  2264.               LEN1 := ORD(EBCDICTOASCII[ORD(INPUTSTRING[1])])-32;
  2265.               IF LENGTH(INPUTSTRING)>2 THEN
  2266.                    BEGIN (* VAR COMMAND *)
  2267.                    VARCOMM:=SUBSTR(INPUTSTRING,2,LEN1);
  2268.                    INPUTSTRING := SUBSTR(INPUTSTRING,LEN1+2,
  2269.                                       LENGTH(INPUTSTRING)-(LEN1+1));
  2270.                    END  (* VAR COMMAND *)
  2271.                                         ELSE
  2272.                    VARCOMM:='X' ;
  2273.               VARCOMM[1] := CHR(ORD(VARCOMM[1]) | '40'X) ;
  2274.               IF LENGTH(INPUTSTRING)>2 THEN
  2275.                    BEGIN (* Got a variable name *)
  2276.                    LEN1 := ORD(EBCDICTOASCII[ORD(INPUTSTRING[1])])-32;
  2277.                    VARNAME:=SUBSTR(INPUTSTRING,2,LEN1);
  2278.                    INPUTSTRING := SUBSTR(INPUTSTRING,LEN1+2,
  2279.                                    LENGTH(INPUTSTRING)-(LEN1+1));
  2280.                    FOR IX:=1 TO LEN1 DO     (* Upcase it *)
  2281.                      VARNAME[IX] := CHR(ORD(VARNAME[IX]) | '40'X) ;
  2282.                    END   (* Got a variable name *)
  2283.                                        ELSE
  2284.                    VARNAME:=' ';
  2285.               IF LENGTH(INPUTSTRING)>2 THEN
  2286.                    BEGIN (* Got a variable value *)
  2287.                    LEN1 := ORD(EBCDICTOASCII[ORD(INPUTSTRING[1])])-32;
  2288.                    VARVALUE :=SUBSTR(INPUTSTRING,2,LEN1);
  2289.                    END   (* Got a variable value *)
  2290.                                        ELSE
  2291.                    VARVALUE :=' ' ;
  2292.               IF (VARCOMM[1] = 'S') OR (VARCOMM[1] = 'Q') THEN
  2293.                    IF VARNAME = 'DATE' THEN
  2294.                         BEGIN (* Set Date *)
  2295.                         DATETIME(DATE,TIME);
  2296.                         SENDMSG.CHARS := 'DATE ' || STR(DATE) || '   ';
  2297.                         END   (* Set Date *)
  2298.                                        ELSE
  2299.                    IF VARNAME = 'TIME' THEN
  2300.                         BEGIN (* Set Time *)
  2301.                         DATETIME(DATE,TIME);
  2302.                         SENDMSG.CHARS := 'TIME ' || STR(TIME) || '   ';
  2303.                         END   (* Set Time *)
  2304.                                        ELSE
  2305.               SENDMSG.CHARS := 'Variable not implemented  '
  2306.  
  2307.                                                 ELSE
  2308.               SENDMSG.CHARS := 'Not SET or QUERY variable.';
  2309.               OUTDATACOUNT := 25 ;
  2310.               OUTSEQ := 0 ;
  2311.               OUTPACKETTYPE := 'Y' ;
  2312.               SENDPACKET ;
  2313.               END;  (* Variable     *)
  2314.  
  2315.          OTHERWISE
  2316.               BEGIN (* ERROR  command *)
  2317.               OUTDATACOUNT := 15 ;
  2318.               OUTSEQ := 0 ;
  2319.               OUTPACKETTYPE := 'E' ;
  2320.               SENDMSG.CHARS := 'Unknown Command';
  2321.               SENDPACKET ;
  2322.               END ; (* ERROR  command *)
  2323.  
  2324.          END ; (* CASE OF SUBCOMMAND *)
  2325.  
  2326.          END   (* General command *)
  2327.                           ELSE
  2328.          BEGIN (* ERROR  command *)
  2329.          OUTDATACOUNT := 15 ;
  2330.          OUTSEQ := 0 ;
  2331.          OUTPACKETTYPE := 'E' ;
  2332.          SENDMSG.CHARS := 'Unknown Command';
  2333.          SENDPACKET ;
  2334.          END ; (* ERROR  command *)
  2335.     END ; (* REMOTECOMMAND procedure *)
  2336.  
  2337.  
  2338.  
  2339. %PAGE
  2340. (* **************************************************************** *)
  2341. (* *******         OUTTER BLOCK OF KERMIT                   ******* *)
  2342. (* **************************************************************** *)
  2343.  
  2344.     BEGIN
  2345.     TERMOUT(OUTPUT,'NOCC,RECFM=V');
  2346.     TERMIN (INPUT);
  2347.  
  2348.     CMS('Q TERM (STACK)  ',RC );   (* GET CURRENT TERMINAL SETTINGS *)
  2349.     READLN(OLDSETTINGS) ;   (* line 1 *)
  2350.     OLDSETTINGS := DELETE(OLDSETTINGS,INDEX(OLDSETTINGS,','),1);
  2351.     OLDSETTINGS := DELETE(OLDSETTINGS,INDEX(OLDSETTINGS,','),1);
  2352.     OLDSETTINGS := DELETE(OLDSETTINGS,INDEX(OLDSETTINGS,','),1);
  2353.     OLDSETTINGS := DELETE(OLDSETTINGS,INDEX(OLDSETTINGS,','),1);
  2354.     READLN(INPUTSTRING) ;    (* line 2 *)
  2355.     OLDSETTINGS := OLDSETTINGS || ' ' ||SUBSTR(INPUTSTRING,1,12);
  2356.     READLN(INPUTSTRING) ;    (* line 3 *)
  2357.  
  2358.     CMS('DEVTYPE (STK)  ',RC );
  2359.     READLN(INPUTSTRING) ;
  2360.     FULLSCREENDEVICE := INDEX(INPUTSTRING,'GRAPHICS') = 1 ;
  2361.                                   (* true if via series/1 *)
  2362.     IF FULLSCREENDEVICE THEN CMS('CP TERM CHARDEL OFF',RC)
  2363.                       ELSE CMS('CP TERM CHARDEL ' || '16'XC,RC) ;
  2364.     CMS('CP TERM LINEND OFF LINEDEL OFF  ESCAPE OFF ',RC );
  2365.     CMS('CP TERM LINESIZE 132  ',RC);
  2366.     CMS('CP SET MSG OFF   ',RC);
  2367.  
  2368.    (* set intial default values *)
  2369.     TRANSLATION := TRUE ;
  2370.     LRECL := '80' ;
  2371.     FULLSCREENIO := FALSE ;
  2372.     WRITELN(' Begin KERMIT Program ');
  2373.  
  2374.     INPUTSTRING := PARMS ;
  2375.     RUNNING := TRUE ;
  2376.     WHILE RUNNING DO
  2377.          BEGIN (* Command Loop *)
  2378. PROMPT:
  2379.          IF FULLSCREENIO THEN
  2380.               BEGIN (* FULL SCREEN IO *)
  2381.               READSCREEN ;
  2382.               FOR RI := 4 TO RECVLENGTH DO
  2383.                 IF RECVBUFF.BYTES[RI] <> '00'X THEN
  2384.                    RECVBUFF.CHARS[RI] :=
  2385.                     ASCIITOEBCDIC[RECVBUFF.BYTES[RI] & '7F'X] ;
  2386.  
  2387.               INPUTSTRING:=SUBSTR(STR(RECVBUFF.CHARS),4,RECVLENGTH-4);
  2388.               END  (* FULL  SCREEN IO *)
  2389.                          ELSE
  2390.               BEGIN  (* NORMAL IO *)
  2391.               WRITELN ('KERMIT-CMS>') ;
  2392.               IF (BIT8_QUOTE = ' ') AND (NOT TRANSLATION) THEN
  2393.                  BEGIN (* Warning *)
  2394.                  WRITELN('**** WARNING - TRANSLATION is turned off,');
  2395.                  WRITELN ('other kermit can not handle the 8th bit.');
  2396.                  END ; (* Warning *)
  2397.               IF CNTRL_QUOTE = '#' THEN  (* default value ok *)
  2398.                                    ELSE
  2399.                   BEGIN (* Warning *)
  2400.                   WRITELN ('*** WARNING - Non standard CNTRL_QUOTE is ',
  2401.                                  CNTRL_QUOTE);
  2402.                   WRITELN (' Standard CNTRL_QUOTE is # ');
  2403.                   END ; (* Warning *)
  2404.               IF LENGTH(INPUTSTRING) < 1 THEN  READLN (INPUTSTRING);
  2405.               END ;  (* NORMAL IO *)
  2406.  
  2407.          INPUTSTRING := LTRIM(INPUTSTRING);
  2408.          IF INPUTSTRING = ' '  THEN
  2409.             BEGIN
  2410.              IF FULLSCREENIO THEN
  2411.                     BEGIN
  2412.                     SI := 8  ;
  2413.                     SENDBUFF.CHARS :=   (* SERVER MODE> *)
  2414.                      'C3115D7F110001BE'XC ;
  2415.                     RITESCREEN ; (* SEND SERVER PROMPT *)
  2416.                     SI := 8 ;     (* Reset data pointer *)
  2417.                     END ;
  2418.              GOTO PROMPT;
  2419.              END ;
  2420.          J :=  INDEX(INPUTSTRING,SOH) ;
  2421.          IF J>0 THEN
  2422.               BEGIN (* REMOTE COMMAND *)
  2423.               IF J>1 THEN INPUTSTRING := DELETE(INPUTSTRING,1,J-1);
  2424.               IF FULLSCREENDEVICE AND NOT FULLSCREENIO THEN
  2425.                     BEGIN (* INIT SCREEN IO *)
  2426.                     FULLSCREENIO := TRUE ;
  2427.                     INITSCREEN ;
  2428.                     SI := 19 ;
  2429.                     SENDBUFF.CHARS :=   (* SERVER MODE> *)
  2430.                      'C3115D7F110001534552564552204D4F4445BE'XC ;
  2431.                     RITESCREEN ; (* SEND SERVER PROMPT *)
  2432.                     SI := 8 ;     (* Reset data pointer *)
  2433.                     SENDACK(FALSE);
  2434.                     GOTO PROMPT ;
  2435.                     END ; (* INIT SCREEN IO *)
  2436.               REMOTECOMMAND ;
  2437.               END   (* REMOTE COMMAND *)
  2438.                                               ELSE
  2439.               BEGIN (* Local Command *)
  2440.               INPUTSTRING := LTRIM(COMPRESS(INPUTSTRING));
  2441.               COMMAND := GETTOKEN (INPUTSTRING);
  2442.               UPCASE(COMMAND);
  2443.               REQUEST := ' ' || TRIM(STR(COMMAND));
  2444.               CINDEX := INDEX(COMMTABLE,REQUEST) DIV 8 ;
  2445.               IF CINDEX = 0 THEN
  2446.                     BEGIN
  2447.                     SI := 8  ;
  2448.                     SENDBUFF.CHARS :=   (* SERVER MODE> *)
  2449.                      'C3115D7F110001BE'XC ;
  2450.                     RITESCREEN ; (* SEND SERVER PROMPT *)
  2451.                     SI := 8 ;     (* Reset data pointer *)
  2452.                     GOTO PROMPT;
  2453.                     END ;
  2454.               IF  FULLSCREENIO THEN
  2455.                    BEGIN FINISCREEN; FULLSCREENIO := FALSE; END;
  2456.               CASE COMMANDS(CINDEX) OF
  2457.               (*  BEGIN    Execute the Command *)
  2458.     $BAD  :   BEGIN (* bad  command *)
  2459.               WRITELN(COMMAND,' is an bad command. ');
  2460.               END ; (* bad  command *)
  2461.     $SEND :   SENDFILE (' ') ;
  2462.     $RECEIVE: RECVFILE ;
  2463.     $SERVER : IF FULLSCREENDEVICE THEN
  2464.                 IF NOT FULLSCREENIO THEN
  2465.                     BEGIN (* INIT SCREEN IO *)
  2466.                     FULLSCREENIO := TRUE ;
  2467.                     INITSCREEN ;
  2468.                     SI := 20 ;
  2469.                     SENDBUFF.CHARS :=   (* SERVER MODE> *)
  2470.                      'C3115D7F110001534552564552204D4F4445BE84'XC ;
  2471.                     RITESCREEN ; (* SEND SERVER PROMPT *)
  2472.                     SI := 8 ;     (* Reset data pointer *)
  2473.                     END   (* INIT SCREEN IO *)
  2474.                                    ELSE
  2475.                                   ELSE
  2476.                     WRITELN(' SERVER MODE ','37'XC);
  2477.  
  2478.     $SET  :   SETIT    ;
  2479.     $SHOW :   SHOWIT ;
  2480.     $STATUS:  SHOWIT ;
  2481.     $HELP :   HELP ;
  2482.     $QUES :   HELP ;
  2483.     $CMS  :   CMS(INPUTSTRING,RC);
  2484.     $CP   :   CMS('CP ' || INPUTSTRING,RC);
  2485.     $QUIT,
  2486.     $EXIT :   RUNNING := FALSE ;
  2487.     OTHERWISE  IF FULLSCREENIO THEN
  2488.                     BEGIN
  2489.                     SI := 8  ;
  2490.                     SENDBUFF.CHARS :=   (* SERVER MODE> *)
  2491.                      'C3115D7F110001BE'XC ;
  2492.                     RITESCREEN ; (* SEND SERVER PROMPT *)
  2493.                     SI := 8 ;     (* Reset data pointer *)
  2494.                     GOTO PROMPT;
  2495.                     END
  2496.                                 ELSE
  2497.                     WRITELN(COMMAND,' is an INVALID command') ;
  2498.               END ; (* Execute the Command *)
  2499.          END ; (* Local Command *)
  2500.         INPUTSTRING := '';
  2501.         END ; (* Command Loop *)
  2502.  
  2503.     IF  FULLSCREENIO THEN
  2504.         BEGIN READSCREEN ; FINISCREEN; FULLSCREENIO := FALSE; END;
  2505.     CMS('CP TERM ' || OLDSETTINGS,RC);
  2506.     CMS('CP SET MSG ON  ',RC);
  2507.     WRITELN('Terminal settings restored and MSG is ON ');
  2508.     WRITELN(' End of KERMIT  ');
  2509.     END.
  2510.