home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / b / vmstrm.bli < prev    next >
Text File  |  2020-01-01  |  98KB  |  3,794 lines

  1. MODULE KERTRM (IDENT = '3.3.120',
  2.     ADDRESSING_MODE(EXTERNAL = GENERAL, NONEXTERNAL = GENERAL)
  3.     ) =
  4. BEGIN
  5. !<BLF/WIDTH:100>
  6.  
  7. !++
  8. ! FACILITY:
  9. !
  10. !    KERMIT-32 terminal processing.
  11. !
  12. ! ABSTRACT:
  13. !
  14. !    This module will do all of the terminal processing for KERMIT-32.
  15. !    It contains the output routines for the terminal to send and
  16. !    receive messages as well as the routines to output text for debugging.
  17. !
  18. ! ENVIRONMENT:
  19. !
  20. !    VAX/VMS user mode.
  21. !
  22. ! AUTHOR: Robert C. McQueen, CREATION DATE: 25-March-1983
  23. !--
  24.  
  25. %SBTTL 'Table of Contents'
  26. !
  27. ! TABLE OF CONTENTS:
  28. !
  29. %SBTTL 'Revision History'
  30.  
  31. !++
  32. !
  33. ! Start of version 1.    25-March-1983
  34. !
  35. ! 1.0.000    By: Robert C. McQueen        On: 25-March-1983
  36. !        Create this module.
  37. !
  38. ! 1.1.001    By: W. Hom            On: 6-July-83
  39. !        Implement CONNECT command.
  40. !
  41. ! 1.1.002    By: Nick Bush            On: 7-July-83
  42. !        Fix RECEIVE QIO to time out correctly.
  43. !
  44. ! 1.2.003    By: Robert C. McQueen        On: 16-Aug-83
  45. !        Get the status correctly for the SS$_TIMEOUT checks.
  46. !
  47. ! 1.2.004    By: Robert C. McQueen        On: 9-Sept-1983
  48. !        Flag if we just opened the terminal, so that we can
  49. !        clear the input that is coming into the terminal.  This
  50. !        will clear up some of the junk that we get on start up.
  51. !
  52. ! 2.0.005    Release VAX/VMS Kermit-32 version 2.0
  53. !
  54. ! 2.0.006    By: Nick Bush            On: 10-Nov-1983
  55. !        Fix local echo and IBM mode.
  56. !
  57. ! 2.0.013    By: Nick Bush            On: 11-Nov-1983
  58. !        Make it possible to redirect debugging output to DBG$OUTPUT.
  59. !
  60. ! 2.0.015    By: Nick Bush            On: 17-Nov-1983
  61. !        Always purge typeahead when posting the receive QIO.
  62. !        Also eat any received data just before sending a packet.
  63. !
  64. ! 2.0.020    By: Nick Bush            On: 9-Dec-1983
  65. !        Only abort (when remote) if we seen two control-Y's in
  66. !        succession.  This way a single glitch does not kill us.
  67. !
  68. ! 2.0.021    By: Nick Bush            On: 12-Dec-1983
  69. !        Add status type-out character (^A), debug toggle
  70. !        character (^D), and force timeout character (^M)
  71. !        to those accepted during a transfer when we are remote.
  72. !
  73. ! 2.0.023    By: Nick Bush            On: 16-Dec-1983
  74. !        Add a default terminal name for the communications line.
  75. !        If KER$COMM is defined, that will be the default.
  76. !
  77. ! 2.0.027    By: Nick Bush            On: 20-Jan-1983
  78. !        Fix reset of parity to use the correct field in the
  79. !        IO status block from the IO$_SENSEMODE.  It was using
  80. !        the LF fill count instead.
  81. !
  82. ! 2.0.031    By: Nick Bush            On: 4-Feb-1983
  83. !        Change connect code to improve response (hopefully
  84. !        without worsening throughput or runtime requirements).
  85. !        When either terminal is idle we will be waiting for
  86. !        a single character with a larger buffered read queued
  87. !        up immediately after it.
  88. !
  89. ! 2.0.033    By: Nick Bush            On: 6-March-1984
  90. !        Change command input and terminal processing so that
  91. !        we will always have SYS$OUTPUT and SYS$COMMAND open
  92. !        when they are terminals, and will also always have
  93. !        the transfer terminal line open.  This makes it
  94. !        unnecessary for the user to allocate a dialup line
  95. !        in order to go between CONNECT and a transfer command,
  96. !        and keep anyone else from grabbing the line between
  97. !        commands.
  98. !        Also add the command parsing for the rest of the LOCAL/REMOTE
  99. !        commands.  This makes use of the fact that we have
  100. !        SYS$COMMAND open to allow us to read passwords without echo.
  101. !        Commands which should only be done when Kermit is local
  102. !        (GET, BYE, etc.) will now give an error if the transfer
  103. !        line is the same as the controlling terminal.
  104. !        SEND will now check for the files existance before calling
  105. !        KERMSG to send it.
  106. !
  107. ! 2.0.034    By: Nick Bush                On: 7-March-1984
  108. !        Default the parity type to be that of the default transfer
  109. !        line.  This should make things simpler for systems which use
  110. !        parity by default.
  111. !
  112. ! 2.0.035    By: Nick Bush                On: 8-March-1984
  113. !        Add LOG SESSION command to set a log file for CONNECT.
  114. !        While we are doing so, clean up the command parsing a little
  115. !        so that we don't have as many COPY_xxx routines.
  116. !
  117. ! 2.0.036    By: Robert C. McQueen            On: 20-March-1984
  118. !        Fix call to LOG_OPEN to make the debug log file work.
  119. !        Module: KERTRM
  120. !
  121. ! 2.0.037    By: Robert C. McQueen            On: 20-March-1984
  122. !        Fix call to LOG_OPEN for debug log file.
  123. !        Module: KERTRM.
  124. !
  125. ! 2.0.042    By: Nick Bush                On: 26-March-1984
  126. !        Fix connect processing to make it easy to type messages
  127. !        on the user's terminal while connected.  Use this
  128. !        to type messages when log file stopped and started.
  129. !        Include the node name in the messages to keep
  130. !        users who are running through multiple Kermit's from
  131. !        getting confused.
  132. !
  133. ! 2.0.043    By: Nick Bush                On: 28-March-1984
  134. !        Fix SET PARITY ODD to work.  Somehow, the table entry
  135. !        had PR_NONE instead of PR_ODD.  Also add status type
  136. !        out and help message to connect command.
  137. !
  138. ! 3.0.045    Start of version 3.
  139. !
  140. ! 3.0.046    By: Nick Bush                On: 29-March-1984
  141. !        Fix debugging log file to correctly set/clear file open
  142. !        flag.  Also make log files default to .LOG.
  143. !
  144. ! 3.1.054    By: Nick Bush                On: 13-July-1984
  145. !        Change TERM_OPEN to take an argument which determines
  146. !        whether it should post any QIO's.  This makes it unnecessary
  147. !        for TERM_CONNECT to cancel the QIO's, and avoids problems
  148. !        with DECnet remote terminals.
  149. !
  150. ! 3.1.060    By: Nick Bush                On: 16-March-1985
  151. !        Increase size of terminal name buffers to account for large
  152. !        unit numbers (most likely seen with VTA's).
  153. !
  154. ! 3.1.061    By: Nick Bush                On: 16-March-1985
  155. !        Only attempt to set parity back when closing terminal.
  156. !
  157. ! 3.1.065    By: Nick Bush                On: 10-April-1985
  158. !        Split IBM handshaking from parity and local echo.  Allow
  159. !        link time setting of IBM_MODE defaults by defining symbols:
  160. !
  161. !        IBM_MODE_CHARACTER = character value of handshake character
  162. !        IBM_MODE_ECHO = 1 for local echo, 2 for no local echo
  163. !        IBM_MODE_PARITY = (0 = none), (1 = mark), (2 = even),
  164. !            (3 = odd), (4 = space).
  165. !
  166. !        If not specified, Kermit will continue to use DC1, local echo
  167. !        and odd parity for IBM_MODE.
  168. !
  169. !
  170. ! Start of version 3.2 on 8-May-1985
  171. !
  172. ! 3.2.073    By: Robert McQueen            On: 11-March-1985
  173. !        Fix a problem restoring the terminal characteristics under
  174. !        VMS 4.x
  175. !
  176. ! 3.2.100    By: Gregory P. Welsh            On: 1-June-1986
  177. !        Added code for Transmit function (COMND_TRANSMIT).
  178. !
  179. ! Start of version 3.3
  180. !
  181. ! 3.3.101    By: Robert McQueen            On: 2-July-1986
  182. !        Change $TRNLOG system service to be LIB$SYS_TRNLOG and
  183. !        handle the errors better.  (LIB$ shouldn't change even if the
  184. !        system service does).
  185. !
  186. ! 3.3.102    By: Robert McQueen            On: 5-July-1986
  187. !        Add changes/fixes suggested by Art Guion and David Deley.
  188. !        - Turn off FALLBACK terminal characteristics for eightbit
  189. !          operations.
  190. !        - Decrease IBM timeouts when waiting for a handshake.
  191. !
  192. ! 3.3.105    By: Robert McQueen            On: 8-July-1986
  193. !        Attempt to fix the truncation errors that we now get from
  194. !        LINK with BLISS-32 v4.2.  Also do code clean up in VMSTRM and
  195. !        VMSFIL.
  196. !
  197. ! 3.3.115    JHW004        Jonathan H. Welch,    9-May-1988 14:35
  198. !        Added the ability to send a break character to
  199. !        the outgoing terminal session using the sequence
  200. !        esc-chr B.  The break will be sent after the next 
  201. !        character arrives.  This is because there must be
  202. !        no outstanding I/O on a channel in order to modify
  203. !        terminal characteristics (necessary to send a break).
  204. !
  205. ! 3.3.116    JHW008        Jonathan H. Welch,    12-Apr-1990 12:20
  206. !        Added and modified routines in to notify the user if
  207. !        SS$_HANGUP occurs on the outgoing terminal line.
  208. !
  209. ! 3.3.117    JHW012        Jonathan H. Welch,     18-May-1990 7:56
  210. !        Modified asn_wth_mbx to obtain the master PID in the
  211. !        process tree before asking for JPI$_TERMINAL.  $GETJPI
  212. !        was returning a null string for this item when called
  213. !        from a subprocess resulting in a "No default terminal 
  214. !        line for transfers" message.
  215. !
  216. ! 3.3.118    JHW013        Jonathan H. Welch,    18-May-1990 13:00
  217. !        Extended the buffer size for terminal names from 20 
  218. !        characters to 255 to make sure any terminal name can
  219. !        be accomodated.
  220. !
  221. ! 3.3.119    JHW014        Jonathan H. Welch,    5-Jun-1990 12:38
  222. !        Modified asn_wth_mbx to add a ':' to the end of the
  223. !               terminal name is one is not returned by VMS.
  224. !               This will keep LIB$GETDVI from failing with an
  225. !               "invalid device name" which results in the kermit
  226. !               error "no default terminal line for transfers."
  227. !
  228. ! 3.3.120    JHW016        Jonathan H. Welch,    17-Oct-1990 9:42
  229. !        Modified asn_wth_mbx to work properly in non-interactive mode.
  230. !--
  231.  
  232. %SBTTL 'Library files'
  233. !
  234. ! INCLUDE FILES:
  235. !
  236. !
  237. ! System definitions
  238. !
  239.  
  240. LIBRARY 'SYS$LIBRARY:STARLET';
  241.  
  242. !
  243. ! KERMIT common definitions
  244. !
  245.  
  246. REQUIRE 'KERCOM';
  247.  
  248. REQUIRE 'KERERR';
  249.  
  250. %SBTTL 'Structure definitions -- $GETDVI arguments'
  251. !
  252. ! $GETDVI interface fields and structure definition
  253. !
  254.  
  255. LITERAL
  256.     ITEM_SIZE = 3;            ! Length of a DVI item list entry
  257.  
  258. !
  259. ! Fields for accessing the items in a DVI item list
  260. !
  261.  
  262. FIELD
  263.     ITEM_FIELDS =
  264.     SET
  265.     ITEM_BFR_LENGTH = [0, 0, 16, 0],
  266.     ITEM_ITEM_CODE = [0, 16, 16, 0],
  267.     ITEM_BFR_ADDRESS = [1, 0, 32, 0],
  268.     ITEM_RTN_LENGTH = [2, 0, 32, 0]
  269.     TES;
  270.  
  271. !
  272. ! Structure definition for item list
  273.  
  274. STRUCTURE
  275.     ITEM_LIST [I, O, P, S, E; N] =
  276.     [(N + 1)*ITEM_SIZE*4]
  277.     (ITEM_LIST + ((I*ITEM_SIZE) + O)*4)<P, S, E>;
  278.  
  279. %SBTTL 'Structures definitions -- Terminal characteristics'
  280. !
  281. ! Terminal characteristics words
  282. !
  283.  
  284. LITERAL
  285.     TC$_CHAR_LENGTH = 12;
  286.  
  287. !
  288. ! Fields for accessing the items in a characteristic block
  289. !
  290.  
  291. FIELD
  292.     TC$_FIELDS =
  293.     SET
  294.     TC$_CLASS = [0, 0, 8, 0],
  295.     TC$_TYPE = [0, 8, 8, 0],
  296.     TC$_BFR_SIZE = [0, 16, 16, 0],
  297.     TC$_PAGE_LEN = [1, 24, 8, 0],
  298.     TC$_CHAR = [1, 0, 24, 0],
  299.     TC$_CHAR_2 = [2, 0, 32, 0]
  300.     TES;
  301.  
  302. !
  303. ! Structure definition for item list
  304. !
  305.  
  306. STRUCTURE
  307.     TC$_CHAR_STR [O, P, S, E; N] =
  308.     [TC$_CHAR_LENGTH]
  309.     (TC$_CHAR_STR + O*4)<P, S, E>;
  310.  
  311. %SBTTL 'Literals'
  312. !
  313. ! Literal definitions
  314. !
  315.  
  316. LITERAL
  317.     MAX_NODE_NAME = 255,            ! Size of a node name
  318.     TERM_NAME_SIZE = 255,            ! Size of a terminal name - be generous
  319.     RECV_BUFF_SIZE = MAX_MSG + 20,        ! Size of receive buffer
  320.     GET_DEV_EFN = 7,                ! For GET_DEV_CHAR
  321.     CONS_O_EFN = 6,                ! Event flag for console output
  322.     CONS_EFN = 5,                ! Event flag for console input
  323.     TERM_O_EFN = 4,                ! Event flag for terminal output
  324.     TIME_EFN = 3,                ! Event flag number for receive timer
  325.     TERM_EFN = 2;                ! Event flag number to use for Terminal input
  326.  
  327. %SBTTL 'Storage'
  328. !
  329. ! OWN STORAGE:
  330. !
  331. !
  332. ! Communications routines storage
  333. !
  334.  
  335. OWN
  336.     FORCE_ABORT,                ! Force abort next receive
  337.     FORCE_TIMEOUT,                ! Force time out on next receive
  338.     TERM_FIRST_TIME,                ! First time QIO to read done
  339.     TERM_CHAN,                    ! Channel the terminal is opened on
  340.     mbx_chan : INITIAL(0),            ! Mailbox channel associated with TERM_CHAN device.
  341.     new_mbx_chan : INITIAL(0),            ! Mailbox channel associated with new (temporary) TERM_CHAN device.
  342.     CONS_CHAN,                    ! Channel the console terminal is opened on
  343.     SYS_OUTPUT_CHAN,                ! Channel to SYS$OUTPUT (if it is a terminal)
  344.     SYS_OUTPUT_OPEN,                ! SYS$OUTPUT open
  345.     SYS_OUTPUT_NAME : VECTOR [TERM_NAME_SIZE, BYTE],    ! Text of physical name for SYS$OUTPUT
  346.     SYS_OUTPUT_DESC : BLOCK [8, BYTE],        ! Descriptor for physical name
  347.     SYS_COMMAND_CHAN,                ! Channel to SYS$COMMAND if a terminal
  348.     SYS_COMMAND_OPEN,                ! SYS$COMMAND open
  349.     SYS_COMMAND_NAME : VECTOR [TERM_NAME_SIZE, BYTE],    ! Text of physical name for SYS$COMMAND
  350.     SYS_COMMAND_DESC : BLOCK [8, BYTE],        ! Descriptor for physical name
  351.     TERM_NAME : VECTOR [TERM_NAME_SIZE, BYTE],    ! Text of current transfer terminal name
  352.     JOB_TERM_NAME : VECTOR [TERM_NAME_SIZE, BYTE],    ! Text of jobs controlling terminal name
  353.     TERM_OPEN_FLAG,                ! The transfer terminal is open
  354.     SESSION_FAB : $FAB_DECL,            ! FAB for session logging
  355.     SESSION_RAB : $RAB_DECL,            ! RAB for session logging
  356.     SESSION_NAME : VECTOR [MAX_FILE_NAME, BYTE],    ! Actual name of session log file
  357.     SESSION_OPEN,                ! Session log file open
  358.     SESSION_LOGGING,                ! Session logging enabled
  359.     DEBUG_FAB : $FAB_DECL,            ! FAB for debugging
  360.     DEBUG_RAB : $RAB_DECL,            ! RAB for debugging
  361.     DEBUG_NAME : VECTOR [MAX_FILE_NAME, BYTE],    ! Name of debugging log file
  362.     DEBUG_REDIRECTED,                ! Debugging output redirected
  363.     NODE_NAME : VECTOR [MAX_NODE_NAME, BYTE],    ! Node name text
  364.     IO_STATUS : VECTOR [4, WORD],        ! IOSB for receive QIO
  365.     RECV_BUFFER : VECTOR [CH$ALLOCATION (RECV_BUFF_SIZE, CHR_SIZE)],    ! Input buffer
  366.     OLD_PARITY : BLOCK [8, BYTE],        ! Old IOSB information
  367.     OLD_TERM_CHAR : TC$_CHAR_STR FIELD (TC$_FIELDS),    ! Old terminal chars
  368.     NEW_TERM_CHAR : TC$_CHAR_STR FIELD (TC$_FIELDS);    ! New terminal chars
  369.  
  370. GLOBAL
  371.     NODE_DESC : BLOCK [8, BYTE] PRESET            ! Descriptor for node name
  372.         ([DSC$B_CLASS ] = DSC$K_CLASS_S,        ! String class
  373.          [DSC$B_DTYPE ] = DSC$K_DTYPE_T,        ! Text descriptor
  374.          [DSC$W_LENGTH ] = MAX_NODE_NAME,        ! Maximum length
  375.          [DSC$A_POINTER ] = NODE_NAME),        ! Address of the item
  376.     DEBUG_DESC : BLOCK [8, BYTE] PRESET            ! Debugging log file
  377.          ([DSC$B_CLASS ] = DSC$K_CLASS_S,        !  descriptor
  378.           [DSC$B_DTYPE ] = DSC$K_DTYPE_T,        ! Standard string descriptor
  379.           [DSC$W_LENGTH ] = 0,            !  initialially zero length
  380.           [DSC$A_POINTER ] = DEBUG_NAME),        !  pointing to DEBUG_NAME
  381.     SESSION_DESC : BLOCK [8, BYTE],        ! Descriptor for session log file name
  382.     TERM_DESC : BLOCK [8, BYTE],        ! Descriptor for current transfer terminal
  383.     JOB_TERM_DESC : BLOCK [8, BYTE],        ! Descriptor for controlling terminal (if any)
  384.     TRANS_DELAY,                                ! The transmit delay      
  385.     TRANS_ECHO_FLAG,                            ! The transmit echo flag  
  386.     TERM_FLAG,                    ! Terminal setup for transfer
  387.     Send_Break_TTY_Flag;            ! Flag to indicate if a break should be sent.
  388.  
  389. %SBTTL 'External routines'
  390. !
  391. ! EXTERNAL REFERENCES:
  392. !
  393. !
  394. ! System library routines
  395. !
  396.  
  397. EXTERNAL ROUTINE
  398.     LIB$ASN_WTH_MBX : ADDRESSING_MODE (GENERAL),
  399.     LIB$GETJPI : ADDRESSING_MODE (GENERAL),
  400.     LIB$GETDVI : ADDRESSING_MODE (GENERAL),
  401.     LIB$PUT_SCREEN : ADDRESSING_MODE (GENERAL),
  402.     LIB$PUT_OUTPUT : ADDRESSING_MODE (GENERAL),
  403.     LIB$EMUL : ADDRESSING_MODE (GENERAL),
  404.     LIB$ADDX : ADDRESSING_MODE (GENERAL),
  405.     LIB$SIGNAL : ADDRESSING_MODE (GENERAL),
  406.     LIB$WAIT : ADDRESSING_MODE (GENERAL);
  407.  
  408. !
  409. ! Forward routines:
  410. !
  411.  
  412. FORWARD ROUTINE
  413.     TERM_DUMP : NOVALUE,            ! Routine to type on terminal
  414.     GET_DEV_CHAR,                ! Get device characteristics
  415.     Term_Hangup : NOVALUE,
  416.     Mbx_Ast_Rtn : NOVALUE,
  417.     asn_wth_mbx,
  418.     Send_Break_TTY,
  419.     DO_RECEIVE_QIO,
  420.     DO_CONS_QIO;
  421.  
  422. %SBTTL 'External storage'
  423.  
  424. !++
  425. ! The following is the various external storage locations that are
  426. ! referenced from this module.
  427. !--
  428.  
  429. !
  430. ! KERMSG storage
  431. !
  432.  
  433. EXTERNAL
  434.     PARITY_TYPE,                ! Type of parity being used
  435.     ECHO_FLAG,                    ! Local echo
  436.     IBM_CHAR,                    ! IBM mode turn-around character
  437.     RCV_EOL,                    ! Receive EOL character
  438.     SEND_TIMEOUT,                ! Receive time out counter
  439.     CONNECT_FLAG;                ! Flag if communications line is TT:
  440.  
  441. !
  442. ! KERMIT storage
  443. !
  444.  
  445. EXTERNAL
  446.     ESCAPE_CHR;                    ! Escape char. for CONNECT.
  447.  
  448. %SBTTL 'Terminal routines -- TERM_INIT - Initialize this module'
  449.  
  450. GLOBAL ROUTINE TERM_INIT : NOVALUE =
  451.  
  452. !++
  453. ! FUNCTIONAL DESCRIPTION:
  454. !
  455. !    This routine will initialize the terminal processing module.  It will
  456. !    initialize the various data locations in this module.
  457. !
  458. ! CALLING SEQUENCE:
  459. !
  460. !    TERM_INIT();
  461. !
  462. ! INPUT PARAMETERS:
  463. !
  464. !    None.
  465. !
  466. ! IMPLICIT INPUTS:
  467. !
  468. !    None.
  469. !
  470. ! OUTPUT PARAMETERS:
  471. !
  472. !    None.
  473. !
  474. ! IMPLICIT OUTPUTS:
  475. !
  476. !    None.
  477. !
  478. ! COMPLETION CODES:
  479. !
  480. !    None.
  481. !
  482. ! SIDE EFFECTS:
  483. !
  484. !    None.
  485. !
  486. !--
  487.  
  488.     BEGIN
  489.  
  490.     LOCAL
  491.     COUNTER,                ! Counter for logical name translation
  492.     STATUS,                    ! System call status
  493.     DEV_TYPE,                ! Device type result
  494.     RSL_LENGTH : VOLATILE,            ! Resulting length of translation
  495.     RSL_NAME : BLOCK [TERM_NAME_SIZE, BYTE], ! Translated name
  496.     RSL_DESC : BLOCK [8, BYTE],        ! Descriptor for translated name
  497.  
  498.     NODE_ITEM_LIST : FIELD(ITEM_FIELDS) ITEM_LIST [2] PRESET ! Node name
  499.           ([0, ITEM_BFR_LENGTH ] = MAX_NODE_NAME,        ! Translation
  500.            [0, ITEM_ITEM_CODE ] = LNM$_STRING,        ! Item list
  501.            [0, ITEM_BFR_ADDRESS ] = NODE_NAME,        ! to xlate
  502.            [0, ITEM_RTN_LENGTH ] = NODE_DESC[DSC$W_LENGTH]), ! SYS$NODE
  503.  
  504.     ITMLST : ITEM_LIST [1] FIELD (ITEM_FIELDS) PRESET
  505.            ([0, ITEM_ITEM_CODE ] = JPI$_TERMINAL,        ! Get terminal name
  506.         [0, ITEM_BFR_LENGTH ] = TERM_NAME_SIZE - 1, ! Max name size
  507.         [0, ITEM_BFR_ADDRESS ] = JOB_TERM_NAME + 1, ! Place to store it
  508.         [0, ITEM_RTN_LENGTH ] = RSL_LENGTH);        ! Resulting length
  509.  
  510. !
  511. ! Initialize session log file descriptor
  512. !
  513.     SESSION_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  514.     SESSION_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  515.     SESSION_DESC [DSC$W_LENGTH] = 0;
  516.     SESSION_DESC [DSC$A_POINTER] = SESSION_NAME;
  517. !
  518. ! Get system node name (if any)
  519. !
  520.     NODE_DESC [DSC$W_LENGTH] = MAX_NODE_NAME;
  521.     STATUS = $TRNLNM(ATTR = %REF(LNM$M_CASE_BLIND), 
  522.     TABNAM = %ASCID 'LNM$SYSTEM', LOGNAM = %ASCID 'SYS$NODE',
  523.     ITMLST = NODE_ITEM_LIST);
  524.  
  525.     COUNTER = 64;                ! Max number of translations
  526.  
  527.     WHILE .STATUS                ! Translation fails
  528.     AND .COUNTER GTR 0            ! or we do too many translations
  529.     DO
  530.     BEGIN
  531.     STATUS = $TRNLNM(ATTR = %REF(LNM$M_CASE_BLIND), 
  532.         TABNAM = %ASCID 'LNM$SYSTEM', LOGNAM = NODE_DESC, 
  533.         ITMLST = NODE_ITEM_LIST);
  534.     COUNTER = .COUNTER - 1;
  535.     END;
  536. !
  537. ! If call failed, we don't really know the node name
  538. !
  539.     IF (NOT .STATUS) OR (NODE_NAME[0] EQL 0)
  540.     THEN
  541.     NODE_DESC[DSC$W_LENGTH] = 0;
  542. !
  543. ! Get controlling terminal
  544. !
  545.     JOB_TERM_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  546.     JOB_TERM_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  547.     JOB_TERM_DESC [DSC$W_LENGTH] = TERM_NAME_SIZE;
  548.     JOB_TERM_DESC [DSC$A_POINTER] = JOB_TERM_NAME;
  549.     JOB_TERM_NAME [0] = %C'_';
  550.  
  551.     STATUS = $GETJPIW (ITMLST = ITMLST);
  552.     JOB_TERM_DESC [DSC$W_LENGTH] = .RSL_LENGTH + 1;
  553.  
  554.     IF NOT .STATUS OR .RSL_LENGTH EQL 0 THEN JOB_TERM_DESC [DSC$W_LENGTH] = 0;
  555.  
  556. !
  557. ! Open the output device and command device (if they are terminals)
  558. !
  559.     SYS_OUTPUT_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  560.     SYS_OUTPUT_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  561.     SYS_OUTPUT_DESC [DSC$W_LENGTH] = TERM_NAME_SIZE;
  562.     SYS_OUTPUT_DESC [DSC$A_POINTER] = SYS_OUTPUT_NAME;
  563.     STATUS = GET_DEV_CHAR (%ASCID'SYS$OUTPUT', SYS_OUTPUT_DESC, DEV_TYPE);
  564.  
  565.     IF .STATUS AND .DEV_TYPE EQL DC$_TERM
  566.     THEN
  567.     BEGIN
  568.     STATUS = $ASSIGN (CHAN = SYS_OUTPUT_CHAN, DEVNAM = SYS_OUTPUT_DESC);
  569.  
  570.     IF .STATUS THEN SYS_OUTPUT_OPEN = TRUE;
  571.  
  572.     END;
  573.  
  574.     SYS_COMMAND_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  575.     SYS_COMMAND_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  576.     SYS_COMMAND_DESC [DSC$W_LENGTH] = TERM_NAME_SIZE;
  577.     SYS_COMMAND_DESC [DSC$A_POINTER] = SYS_COMMAND_NAME;
  578.     STATUS = GET_DEV_CHAR (%ASCID'SYS$COMMAND', SYS_COMMAND_DESC, DEV_TYPE);
  579.  
  580.     IF .STATUS AND .DEV_TYPE EQL DC$_TERM
  581.     THEN
  582.     BEGIN
  583.     STATUS = $ASSIGN (CHAN = SYS_COMMAND_CHAN, DEVNAM = SYS_COMMAND_DESC);
  584.  
  585.     IF .STATUS THEN SYS_COMMAND_OPEN = TRUE;
  586.  
  587.     END;
  588. !
  589. ! Set up the terminal name descriptor
  590. !
  591.     TERM_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  592.     TERM_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  593.     TERM_DESC [DSC$A_POINTER] = TERM_NAME;
  594.     TERM_DESC [DSC$W_LENGTH] = TERM_NAME_SIZE;
  595. !
  596. ! If KER$COMM is a terminal, then use it as the default.
  597. !
  598.     STATUS = GET_DEV_CHAR (%ASCID'KER$COMM', TERM_DESC, DEV_TYPE);
  599.  
  600.     IF NOT .STATUS OR .DEV_TYPE NEQ DC$_TERM
  601.     THEN
  602.     BEGIN
  603. !
  604. ! If KER$COMM is not a terminal (or is not anything), try SYS$INPUT.
  605. !
  606.     TERM_DESC [DSC$W_LENGTH] = TERM_NAME_SIZE;
  607.     STATUS = GET_DEV_CHAR (%ASCID'SYS$INPUT', TERM_DESC, DEV_TYPE);
  608.  
  609.     IF NOT .STATUS OR .DEV_TYPE NEQ DC$_TERM
  610.     THEN
  611.         BEGIN
  612. !
  613. ! If SYS$INPUT is not a terminal, check out SYS$OUTPUT.  We will already have
  614. ! it open if it is a terminal.
  615. !
  616.  
  617.         IF .SYS_OUTPUT_OPEN
  618.         THEN
  619.         BEGIN
  620.         CH$COPY (.SYS_OUTPUT_DESC [DSC$W_LENGTH],
  621.             CH$PTR (.SYS_OUTPUT_DESC [DSC$A_POINTER]), CHR_NUL, TERM_NAME_SIZE,
  622.             CH$PTR (TERM_NAME));
  623.         TERM_DESC [DSC$W_LENGTH] = .SYS_OUTPUT_DESC [DSC$W_LENGTH];
  624.         END
  625.         ELSE
  626.         BEGIN
  627. !
  628. ! SYS$OUTPUT is not a terminal.  Next we try SYS$COMMAND.  It should already
  629. ! be open if it is a valid terminal.
  630. !
  631.  
  632.         IF .SYS_COMMAND_OPEN
  633.         THEN
  634.             BEGIN
  635.             CH$COPY (.SYS_COMMAND_DESC [DSC$W_LENGTH],
  636.             CH$PTR (.SYS_COMMAND_DESC [DSC$A_POINTER]), CHR_NUL, TERM_NAME_SIZE,
  637.             CH$PTR (TERM_NAME));
  638.             TERM_DESC [DSC$W_LENGTH] = .SYS_OUTPUT_DESC [DSC$W_LENGTH];
  639.             END
  640.         ELSE
  641.             BEGIN
  642. !
  643. ! Here we start to get desparate.  Nothing we have tried so far was a terminal.
  644. ! Try the terminal which is controlling the job which owns this process.
  645. !
  646.             TERM_DESC [DSC$W_LENGTH] = .JOB_TERM_DESC [DSC$W_LENGTH];
  647.             CH$COPY (.JOB_TERM_DESC [DSC$W_LENGTH],
  648.             CH$PTR (.JOB_TERM_DESC [DSC$A_POINTER]), CHR_NUL, TERM_NAME_SIZE,
  649.             CH$PTR (TERM_NAME));
  650.             END;
  651.  
  652.         END;
  653.  
  654.         END;
  655.  
  656.     END;
  657.  
  658. !
  659. ! At this point TERM_DESC should be set up with something resembling
  660. ! the phyiscal name of a terminal (unless this is a detached process).
  661. ! We can now assign a channel to the terminal and tell the user what the
  662. ! default device is.
  663. !
  664.     CH$WCHAR (CHR_NUL, CH$PTR (TERM_NAME, .TERM_DESC [DSC$W_LENGTH]));
  665.     status = asn_wth_mbx(term_desc, %REF(100), %REF(100), term_chan, mbx_chan);
  666.     TERM_DUMP (UPLIT BYTE(CHR_CRT, CHR_LFD), 2);
  667.  
  668.     IF .STATUS
  669.     THEN
  670.     BEGIN
  671.  
  672.     BIND
  673.         DEFTRM_TEXT = %ASCID'Default terminal for transfers is: ';
  674.  
  675.     MAP
  676.         DEFTRM_TEXT : BLOCK [8, BYTE];
  677.  
  678.     TERM_OPEN_FLAG = TRUE;
  679.     TERM_DUMP (.DEFTRM_TEXT [DSC$A_POINTER], .DEFTRM_TEXT [DSC$W_LENGTH]);
  680.     TERM_DUMP (TERM_NAME, .TERM_DESC [DSC$W_LENGTH]);
  681.         IF .mbx_chan NEQ 0 THEN Term_Hangup();
  682.     END
  683.     ELSE
  684.     BEGIN
  685.  
  686.     BIND
  687.         NODEFTRM_TEXT = %ASCID'No default terminal line for transfers';
  688.  
  689.     MAP
  690.         NODEFTRM_TEXT : BLOCK [8, BYTE];
  691.  
  692.     TERM_OPEN_FLAG = FALSE;
  693.     TERM_DESC [DSC$W_LENGTH] = 0;
  694.     TERM_DUMP (.NODEFTRM_TEXT [DSC$A_POINTER], .NODEFTRM_TEXT [DSC$W_LENGTH])
  695.     END;
  696.  
  697.     TERM_DUMP (UPLIT BYTE(CHR_CRT, CHR_LFD), 2);
  698. !
  699. ! Initialize the flags
  700. !
  701.     TERM_FLAG = FALSE;
  702.     TRANS_DELAY = '0';   ! init transmit delay to .0 seconds
  703. !
  704. ! If we really did get the terminal open, then determine what type of
  705. ! parity it uses, and default to using that parity.
  706. !
  707.  
  708.     IF .TERM_OPEN_FLAG
  709.     THEN
  710.     BEGIN
  711.     STATUS = $QIOW (CHAN = .TERM_CHAN, FUNC = IO$_SENSEMODE, P1 = OLD_TERM_CHAR,
  712.         P2 = TC$_CHAR_LENGTH, IOSB = OLD_PARITY);
  713.  
  714.     IF .STATUS
  715.     THEN
  716.  
  717.         IF (.OLD_PARITY [6, 0, 8, 0] AND TT$M_PARITY) NEQ 0
  718.         THEN
  719.  
  720.         IF (.OLD_PARITY [6, 0, 8, 0] AND TT$M_ODD) NEQ 0
  721.         THEN
  722.             PARITY_TYPE = PR_ODD
  723.         ELSE
  724.             PARITY_TYPE = PR_EVEN
  725.  
  726.         ELSE
  727.         PARITY_TYPE = PR_NONE;
  728.  
  729.     END;
  730.  
  731.     END;                    ! End of TERM_INIT
  732.  
  733.  
  734. %SBTTL 'ASN_WTH_MBX - Assign channel to device and mailbox.'
  735.  
  736. global ROUTINE ASN_WTH_MBX(p_device_name, p_message_size, p_buffer_quota, 
  737.                            p_device_channel, p_mailbox_channel) =
  738.  
  739. !++
  740. ! FUNCTIONAL DESCRIPTION:
  741. !
  742. ! This routine will assign a channel to TERM_DESC and if TERM_DESC is not
  743. ! the users' terminal create and assign a mailbox to receive messages
  744. ! about the outgoing session's state (in particular we're watching for
  745. ! SS$_HANGUP).
  746. !
  747. ! CALLING SEQUENCE:
  748. !
  749. !    STATUS = ASN_WTH_MBX();
  750. !
  751. ! INPUT PARAMETERS:
  752. !
  753. !    None.
  754. !
  755. ! IMPLICIT INPUTS:
  756. !
  757. !    TERM_DESC
  758. !
  759. ! OUPTUT PARAMETERS:
  760. !
  761. !    None.
  762. !
  763. ! IMPLICIT OUTPUTS:
  764. !
  765. !    TERM_CHAN, MBX_CHAN
  766. !
  767. ! COMPLETION CODES:
  768. !
  769. !    Status of LIB$GETJPI, $ASN_WTH_MBX, and/or $ASSIGN
  770. !
  771. ! SIDE EFFECTS:
  772. !
  773. !    A channel is assigned to TERM_CHAN and conditionally a mailbox
  774. !       is created and a channel assigned to it.
  775. !
  776.  
  777.  
  778. BEGIN
  779.  
  780.     BIND
  781.         buffer_quota = .p_buffer_quota,
  782.         device_channel = .p_device_channel,
  783.         device_name = .p_device_name,
  784.         message_size = .p_message_size,
  785.         mailbox_channel = .p_mailbox_channel;
  786.  
  787.     LOCAL
  788.         master_pid,
  789.         mode,
  790.         sts,
  791.         terminal_name : BLOCK [term_name_size, BYTE],
  792.         terminal_desc : BLOCK [8, BYTE] PRESET
  793.                                       ([DSC$B_CLASS] = DSC$K_CLASS_S,
  794.                                        [DSC$B_DTYPE] = DSC$K_DTYPE_T,
  795.                                        [DSC$W_LENGTH] = term_name_size,
  796.                                        [DSC$A_POINTER] = terminal_name),
  797.         temp_name : BLOCK [term_name_size, BYTE],
  798.         temp_desc : BLOCK [8, BYTE] PRESET
  799.                                   ([DSC$B_CLASS] = DSC$K_CLASS_S,
  800.                                    [DSC$B_DTYPE] = DSC$K_DTYPE_T,
  801.                                    [DSC$W_LENGTH] = term_name_size,
  802.                                    [DSC$A_POINTER] = temp_name);
  803.     MAP
  804.         device_name : BLOCK [term_name_size, BYTE];
  805.  
  806.     sts = LIB$GETJPI(%REF(JPI$_MODE),0,0,mode);
  807.     if .mode NEQ JPI$K_INTERACTIVE
  808.     THEN
  809.         $ASSIGN(CHAN = device_channel, DEVNAM = device_name)
  810.     ELSE
  811.         BEGIN
  812.  
  813.         sts = LIB$GETJPI(%REF(JPI$_MASTER_PID),0,0,master_pid,0,0);
  814.         IF NOT .sts THEN RETURN .sts;
  815.  
  816.         sts = LIB$GETJPI(%REF(JPI$_TERMINAL),
  817.                          master_pid,
  818.                          0,
  819.                          0,
  820.                          temp_desc,
  821.                          temp_desc);
  822.         IF NOT .sts THEN RETURN .sts;
  823.         IF .(.temp_desc[dsc$a_pointer] - 1 +
  824.              .temp_desc[dsc$w_length])<0,8> NEQ %C ':'
  825.         THEN
  826.             BEGIN
  827.             (.temp_desc[dsc$a_pointer] + .temp_desc[dsc$w_length])<0,8> = %C ':';
  828.             temp_desc[dsc$w_length] = .temp_desc[dsc$w_length] + 1;
  829.             END;
  830.  
  831.         sts = LIB$GETDVI(%REF(DVI$_DEVNAM),
  832.                          0,
  833.                          temp_desc,
  834.                          0,
  835.                          terminal_desc,
  836.                          terminal_desc);
  837.         IF NOT .sts THEN RETURN .sts;
  838.  
  839.         IF CH$EQL(.terminal_desc[DSC$W_LENGTH], .terminal_desc[DSC$A_POINTER],
  840.                   .device_name[DSC$W_LENGTH], .device_name[DSC$A_POINTER],
  841.                   %C' ')
  842.         THEN
  843.             BEGIN
  844.             IF .mailbox_channel NEQ 0 THEN $DASSGN(CHAN = .mailbox_channel);
  845.             mailbox_channel = 0;
  846.             $ASSIGN(CHAN = device_channel, DEVNAM = device_name)
  847.             END
  848.         ELSE
  849.             LIB$ASN_WTH_MBX(device_name, message_size, buffer_quota, 
  850.                             device_channel, mailbox_channel)
  851.         END
  852. END;
  853.  
  854. %SBTTL 'SET_TRANS_TERM - Set new transfer terminal line'
  855.  
  856. GLOBAL ROUTINE SET_TRANS_TERM (NEW_NAME) =
  857.  
  858. !++
  859. ! FUNCTIONAL DESCRIPTION:
  860. !
  861. ! This routine will validate the terminal name that a user wishes to set
  862. ! as the transfer line.  If the name is valid, it will store the physical
  863. ! name in TERM_DESC, and open the new terminal line.
  864. !
  865. ! CALLING SEQUENCE:
  866. !
  867. !    STATUS = SET_TRANS_TERM (NEW_NAME);
  868. !
  869. ! INPUT PARAMETERS:
  870. !
  871. !    NEW_NAME - Descriptor for new terminal name.
  872. !
  873. ! IMPLICIT INPUTS:
  874. !
  875. !    TERM_OPEN_FLAG, TERM_CHAN
  876. !
  877. ! OUPTUT PARAMETERS:
  878. !
  879. !    None.
  880. !
  881. ! IMPLICIT OUTPUTS:
  882. !
  883. !    None.
  884. !
  885. ! COMPLETION CODES:
  886. !
  887. !    True/false status value - error code
  888. !
  889. ! SIDE EFFECTS:
  890. !
  891. !    None.
  892. !
  893. !--
  894.  
  895.     BEGIN
  896.  
  897.     MAP
  898.     NEW_NAME : REF BLOCK [8, BYTE];        ! Descriptor for new name
  899.  
  900.     LOCAL
  901.     NEW_CHAN,                ! Temp for channel to new terminal
  902.     RSL_DESC : BLOCK [8, BYTE],        ! Descriptor for physical name
  903.     RSL_NAME : VECTOR [TERM_NAME_SIZE, BYTE],    ! String of resulting name
  904.     DEV_TYPE,                ! Device type
  905.     STATUS;                    ! Random status values
  906.  
  907. !
  908. ! Set up descriptor
  909. !
  910.     RSL_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  911.     RSL_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  912.     RSL_DESC [DSC$W_LENGTH] = TERM_NAME_SIZE;    ! Maximum length
  913.     RSL_DESC [DSC$A_POINTER] = RSL_NAME;    ! Where to store name
  914.     STATUS = GET_DEV_CHAR (.NEW_NAME, RSL_DESC, DEV_TYPE);
  915.  
  916.     IF NOT .STATUS THEN RETURN .STATUS;
  917.  
  918.     IF .DEV_TYPE NEQ DC$_TERM THEN RETURN KER_LINTERM;
  919.  
  920. !
  921. ! The device is a terminal, now make sure we can get it.
  922. !
  923. ! If we are CONNECTing to the same device and this device is a LAT
  924. ! device then we must deassign our channel to it (in order for things
  925. ! to reset properly).  There is a chance the reassignment will fail.
  926. ! If this happens then we are in a bad state - no valid output device.
  927. !
  928. ! Otherwise keep a channel to either the old or new device at all times.
  929.     IF CH$EQL(.rsl_desc[DSC$W_LENGTH], .rsl_desc[DSC$A_POINTER],
  930.               .term_desc[DSC$W_LENGTH], .term_desc[DSC$A_POINTER],
  931.               %C' ') AND
  932.        CH$EQL(4, .rsl_desc[DSC$A_POINTER], 4, UPLIT('_LTA'))
  933. !       (..rsl_desc[DSC$A_POINTER] EQL '_LTA')
  934.     THEN
  935.         BEGIN
  936.         IF .mbx_chan NEQ 0
  937.         THEN
  938.             BEGIN
  939.             $DASSGN (CHAN = .mbx_chan);
  940.             mbx_chan = 0;
  941.             END;
  942.         $DASSGN (CHAN = .TERM_CHAN);
  943.         status = asn_wth_mbx(rsl_desc, %REF(100), %REF(100),
  944.                              new_chan, new_mbx_chan);
  945.         IF NOT .STATUS THEN RETURN .STATUS;
  946.         END
  947.     ELSE
  948.         BEGIN
  949.         status = asn_wth_mbx(rsl_desc, %REF(100), %REF(100),
  950.                              new_chan, new_mbx_chan);
  951.         IF NOT .STATUS THEN RETURN .STATUS;
  952. !
  953. ! We have the new terminal.  Deassign the old one and copy the new data
  954. !
  955.         $DASSGN (CHAN = .TERM_CHAN);
  956.         IF .mbx_chan NEQ 0
  957.         THEN
  958.             BEGIN
  959.             $DASSGN (CHAN = .mbx_chan);
  960.             mbx_chan = 0;
  961.             END;
  962.         CH$COPY (.RSL_DESC [DSC$W_LENGTH], CH$PTR (RSL_NAME), CHR_NUL,
  963.                  TERM_NAME_SIZE, CH$PTR (TERM_NAME));
  964.         TERM_DESC [DSC$W_LENGTH] = .RSL_DESC [DSC$W_LENGTH];
  965.         END;
  966.  
  967.     TERM_CHAN = .NEW_CHAN;
  968.     IF .new_mbx_chan NEQ 0 THEN mbx_chan = .new_mbx_chan;
  969.     IF .mbx_chan NEQ 0 THEN Term_Hangup();
  970.  
  971.  
  972.     RETURN KER_NORMAL;
  973.     END;                    ! End of SET_TRANS_TERM
  974.  
  975. %SBTTL 'TERM_DUMP - This routine will dump text on the terminal'
  976.  
  977. GLOBAL ROUTINE TERM_DUMP (BUFFER_ADDRESS, BUFFER_COUNT) : NOVALUE =
  978.  
  979. !++
  980. ! FUNCTIONAL DESCRIPTION:
  981. !
  982. !    This routine will dump the text specified on the user's terminal.
  983. !    It will then return to the caller.
  984. !
  985. ! CALLING SEQUENCE:
  986. !
  987. !    TERM_DUMP( TEXT-BUFFER-ADDRESS, COUNT)
  988. !
  989. ! INPUT PARAMETERS:
  990. !
  991. !    TEXT-BUFFER-ADDRESS - Address of the buffer containing the characters.
  992. !
  993. !    COUNT - Count of the characters in the buffer.
  994. !
  995. ! IMPLICIT INPUTS:
  996. !
  997. !    None.
  998. !
  999. ! OUPTUT PARAMETERS:
  1000. !
  1001. !    None.
  1002. !
  1003. ! IMPLICIT OUTPUTS:
  1004. !
  1005. !    None.
  1006. !
  1007. ! COMPLETION CODES:
  1008. !
  1009. !    None.
  1010. !
  1011. ! SIDE EFFECTS:
  1012. !
  1013. !    None.
  1014. !
  1015. !--
  1016.  
  1017.     BEGIN
  1018.  
  1019.     LOCAL
  1020.     TEXT_DESC : BLOCK [8, BYTE];
  1021.  
  1022.     IF NOT .CONNECT_FLAG
  1023.     THEN
  1024.     BEGIN
  1025.  
  1026.     IF .SYS_OUTPUT_OPEN
  1027.     THEN
  1028.         $QIOW (CHAN = .SYS_OUTPUT_CHAN, EFN = CONS_O_EFN,
  1029.         FUNC = IO$_WRITEVBLK, P1 = .BUFFER_ADDRESS, P2 = .BUFFER_COUNT, P4 = 0)
  1030.     ELSE
  1031.         BEGIN
  1032.         TEXT_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  1033.         TEXT_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  1034.         TEXT_DESC [DSC$W_LENGTH] = .BUFFER_COUNT;
  1035.         TEXT_DESC [DSC$A_POINTER] = .BUFFER_ADDRESS;
  1036.         LIB$PUT_OUTPUT (TEXT_DESC);
  1037.         END;
  1038.  
  1039.     END;
  1040.  
  1041.     END;                    ! End of TERM_DUMP
  1042.  
  1043. %SBTTL 'DBG_DUMP - This routine will dump text on the terminal'
  1044.  
  1045. GLOBAL ROUTINE DBG_DUMP (BUFFER_ADDRESS, BUFFER_COUNT) : NOVALUE =
  1046.  
  1047. !++
  1048. ! FUNCTIONAL DESCRIPTION:
  1049. !
  1050. !    This routine will dump the text specified on the user's terminal.
  1051. !    It will then return to the caller.
  1052. !
  1053. ! CALLING SEQUENCE:
  1054. !
  1055. !    DBG_DUMP( TEXT-BUFFER-ADDRESS, COUNT)
  1056. !
  1057. ! INPUT PARAMETERS:
  1058. !
  1059. !    TEXT-BUFFER-ADDRESS - Address of the buffer containing the characters.
  1060. !
  1061. !    COUNT - Count of the characters in the buffer.
  1062. !
  1063. ! IMPLICIT INPUTS:
  1064. !
  1065. !    None.
  1066. !
  1067. ! OUPTUT PARAMETERS:
  1068. !
  1069. !    None.
  1070. !
  1071. ! IMPLICIT OUTPUTS:
  1072. !
  1073. !    None.
  1074. !
  1075. ! COMPLETION CODES:
  1076. !
  1077. !    None.
  1078. !
  1079. ! SIDE EFFECTS:
  1080. !
  1081. !    None.
  1082. !
  1083. !--
  1084.  
  1085.     BEGIN
  1086.  
  1087.     LOCAL
  1088.     STATUS,                    ! Status from $PUT
  1089.     TEXT_DESC : BLOCK [8, BYTE];
  1090.  
  1091.     IF NOT .CONNECT_FLAG AND NOT .DEBUG_REDIRECTED    ! Check where debugging should go
  1092.     THEN
  1093.     BEGIN
  1094.  
  1095.     IF .SYS_OUTPUT_OPEN
  1096.     THEN
  1097.         $QIOW (CHAN = .SYS_OUTPUT_CHAN, EFN = CONS_O_EFN,
  1098.         FUNC = IO$_WRITEVBLK OR IO$M_NOFORMAT, P1 = .BUFFER_ADDRESS, P2 = .BUFFER_COUNT)
  1099.     ELSE
  1100.         BEGIN
  1101.         TEXT_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  1102.         TEXT_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  1103.         TEXT_DESC [DSC$W_LENGTH] = .BUFFER_COUNT;
  1104.         TEXT_DESC [DSC$A_POINTER] = .BUFFER_ADDRESS;
  1105.         LIB$PUT_OUTPUT (TEXT_DESC);
  1106.         END;
  1107.  
  1108.     END
  1109.     ELSE
  1110.  
  1111.     IF .DEBUG_REDIRECTED
  1112.     THEN
  1113.         BEGIN
  1114.  
  1115.         EXTERNAL ROUTINE
  1116.         LOG_CHAR,            ! Routine to write a character to log file
  1117.         LOG_CLOSE;            ! Routine to close log file
  1118.  
  1119.         LOCAL
  1120.         POINTER;
  1121.  
  1122.         POINTER = CH$PTR (.BUFFER_ADDRESS);
  1123.  
  1124.         DECR I FROM .BUFFER_COUNT TO 1 DO
  1125.  
  1126.         IF NOT LOG_CHAR (CH$RCHAR_A (POINTER), DEBUG_RAB)
  1127.         THEN
  1128.             BEGIN
  1129.             LOG_CLOSE (DEBUG_FAB, DEBUG_RAB);
  1130.             DEBUG_REDIRECTED = FALSE;
  1131.             END;
  1132.  
  1133.         END;
  1134.  
  1135.     END;                    ! End of DBG_DUMP
  1136.  
  1137. %SBTTL 'GET_COMMAND - Get a command line'
  1138.  
  1139. GLOBAL ROUTINE GET_COMMAND (CMD_DESC, PROMPT_DESC, CMD_LENGTH, ECHO_FLAG) =
  1140.  
  1141. !++
  1142. ! FUNCTIONAL DESCRIPTION:
  1143. !
  1144. !    This routine will get a command line from SYS$COMMAND:.  If
  1145. ! SYS$COMMAND is a terminal, it will do input using a QIO, which will
  1146. ! allow input without echo if desired.  If SYS$COMMAND is not a terminal,
  1147. ! it will use LIB$GET_COMMAND.
  1148. !
  1149. ! CALLING SEQUENCE:
  1150. !
  1151. !    STATUS = GET_COMMAND (CMD_DESC, PROMPT_DESC, CMD_LENGTH, ECHO_FLAG);
  1152. !
  1153. ! INPUT PARAMETERS:
  1154. !
  1155. !    CMD_DESC - String descriptor for command being input
  1156. !    PROMPT_DESC - String descriptor for prompt
  1157. !    ECHO_FLAG - True if input should be echoed, false if not
  1158. !
  1159. ! IMPLICIT INPUTS:
  1160. !
  1161. !    SYS_COMMAND_OPEN - Flag whether SYS$COMMAND is open
  1162. !    SYS_COMMAND_CHAN - Channel SYS$COMMAND is open on, if open
  1163. !
  1164. ! OUPTUT PARAMETERS:
  1165. !
  1166. !    CMD_LENGTH - Actual length of command input
  1167. !
  1168. ! IMPLICIT OUTPUTS:
  1169. !
  1170. !    None.
  1171. !
  1172. ! COMPLETION CODES:
  1173. !
  1174. !    Returns status value, true unless error has occured.
  1175. !
  1176. ! SIDE EFFECTS:
  1177. !
  1178. !    None.
  1179. !
  1180. !--
  1181.  
  1182.     BEGIN
  1183.  
  1184.     MAP
  1185.     CMD_DESC : REF BLOCK [8, BYTE],        ! Where to put input
  1186.     PROMPT_DESC : REF BLOCK [8, BYTE];    ! Prompt string
  1187.  
  1188.     EXTERNAL ROUTINE
  1189.     TT_CRLF : NOVALUE, ! Type a CRLF
  1190.     STR$UPCASE : ADDRESSING_MODE (GENERAL),    ! Upcase a string
  1191.     LIB$GET_COMMAND : ADDRESSING_MODE (GENERAL);    ! Get string from SYS$COMMAND
  1192.  
  1193.     LOCAL
  1194.     QIO_FUNC,                ! Function for QIO
  1195.     IOSB : VECTOR [4, WORD],        ! IOSB for QIO
  1196.     STATUS;                    ! Random status values
  1197.  
  1198.     IF .SYS_COMMAND_OPEN
  1199.     THEN
  1200.     BEGIN
  1201.     QIO_FUNC = IO$_READPROMPT;        ! Assume just read with prompt
  1202.  
  1203.     IF NOT .ECHO_FLAG THEN QIO_FUNC = IO$_READPROMPT OR IO$M_NOECHO;    ! Don't echo input
  1204.  
  1205.     STATUS = $QIOW (CHAN = .SYS_COMMAND_CHAN, FUNC = .QIO_FUNC, IOSB = IOSB,
  1206.         P1 = .CMD_DESC [DSC$A_POINTER], P2 = .CMD_DESC [DSC$W_LENGTH],
  1207.         P5 = .PROMPT_DESC [DSC$A_POINTER], P6 = .PROMPT_DESC [DSC$W_LENGTH]);
  1208.  
  1209.     IF NOT .STATUS THEN RETURN .STATUS;
  1210.  
  1211. !
  1212. ! If we didn't echo, then dump a CRLF so we look nice
  1213. !
  1214.  
  1215.     IF NOT .ECHO_FLAG THEN TT_CRLF ();
  1216.  
  1217.     IF .IOSB [0]
  1218.     THEN
  1219.         BEGIN
  1220.         .CMD_LENGTH = .IOSB [1];        ! Get actual length input
  1221.  
  1222.         IF .IOSB [3] EQL 1 AND .IOSB [2] EQL CHR_CTL_Z THEN RETURN RMS$_EOF;
  1223.  
  1224.         END;
  1225.  
  1226. !
  1227. ! Upcase the resulting string
  1228. !
  1229.     STATUS = STR$UPCASE (.CMD_DESC, .CMD_DESC);
  1230.  
  1231.     IF NOT .STATUS THEN RETURN .STATUS;
  1232.  
  1233.     RETURN .IOSB [0];            ! Return resulting status
  1234.     END;
  1235.  
  1236. !
  1237. ! Here if SYS$COMMAND is not open.  Get the command via LIB$GET_COMMAND.
  1238. !
  1239.     RETURN LIB$GET_COMMAND (.CMD_DESC, .PROMPT_DESC, .CMD_LENGTH);
  1240.     END;                    ! End of GET_COMMAND
  1241.  
  1242. %SBTTL 'Communcations line -- TERM_OPEN'
  1243.  
  1244. GLOBAL ROUTINE TERM_OPEN (POST_QIOS) =
  1245.  
  1246. !++
  1247. ! FUNCTIONAL DESCRIPTION:
  1248. !
  1249. !    This routine will assign a channel that is used in the CONNECT
  1250. !    processing and to send/receive a file from.
  1251. !
  1252. ! CALLING SEQUENCE:
  1253. !
  1254. !    TERM_OPEN(POST_QIOS);
  1255. !
  1256. ! INPUT PARAMETERS:
  1257. !
  1258. !    POST_QIOS - True if initial read QIO's should be posted.
  1259. !
  1260. ! IMPLICIT INPUTS:
  1261. !
  1262. !    TERM_DESC - Descriptor of a vector of ASCII characters that represent
  1263. !    the name of the terminal to use.
  1264. !
  1265. !    TERM_CHAN - Channel open to terminal if TERM_OPEN_FLAG is true.
  1266. !
  1267. ! OUTPUT PARAMETERS:
  1268. !
  1269. !    None.
  1270. !
  1271. ! IMPLICIT OUTPUTS:
  1272. !
  1273. !    TERM_CHAN - Channel number of the terminal line we are using.
  1274. !
  1275. ! COMPLETION CODES:
  1276. !
  1277. !    SS$_NORMAL or error condition.
  1278. !
  1279. ! SIDE EFFECTS:
  1280. !
  1281. !    None.
  1282. !
  1283. !--
  1284.  
  1285.     BEGIN
  1286.  
  1287.     EXTERNAL ROUTINE
  1288.     LOG_FAOL,                ! Write FAOL style text
  1289.     LOG_OPEN;                ! Open a log file
  1290.  
  1291.     EXTERNAL
  1292.     TRANSACTION_OPEN,
  1293.     TRANSACTION_DESC : BLOCK [8, BYTE],
  1294.     TRANSACTION_FAB : $FAB_DECL,
  1295.     TRANSACTION_RAB : $RAB_DECL;
  1296.  
  1297.     LOCAL
  1298.     STATUS;
  1299.  
  1300. !
  1301. ! If the terminal is not open, we must open it first.
  1302. !
  1303.  
  1304.     IF NOT .TERM_OPEN_FLAG
  1305.     THEN
  1306.  
  1307.     IF .TERM_DESC [DSC$W_LENGTH] GTR 0
  1308.     THEN
  1309.         BEGIN
  1310.         STATUS = SET_TRANS_TERM (TERM_DESC);
  1311.  
  1312.         IF NOT .STATUS THEN RETURN .STATUS;
  1313.  
  1314.         END
  1315.     ELSE
  1316.         RETURN KER_LINTERM;
  1317.  
  1318. !
  1319. ! Set up connect flag properly
  1320. !
  1321.  
  1322.     IF CH$NEQ (.SYS_OUTPUT_DESC [DSC$W_LENGTH], CH$PTR (.SYS_OUTPUT_DESC [DSC$A_POINTER]),
  1323.         .TERM_DESC [DSC$W_LENGTH], CH$PTR (TERM_NAME), CHR_NUL) OR NOT .SYS_OUTPUT_OPEN
  1324.     THEN
  1325.     CONNECT_FLAG = FALSE
  1326.     ELSE
  1327.     CONNECT_FLAG = TRUE;
  1328.  
  1329. !
  1330. ! If we aren't connected, remember the channel to use for the console I/O
  1331. !
  1332.  
  1333.     IF NOT .CONNECT_FLAG AND .SYS_OUTPUT_OPEN THEN CONS_CHAN = .SYS_OUTPUT_CHAN;
  1334.  
  1335. !
  1336. ! Get current settings for transfer terminal
  1337. !
  1338.     STATUS = $QIOW (CHAN = .TERM_CHAN, FUNC = IO$_SENSEMODE, P1 = OLD_TERM_CHAR,
  1339.     P2 = TC$_CHAR_LENGTH, IOSB = OLD_PARITY);
  1340.  
  1341.     IF NOT .STATUS
  1342.     THEN
  1343.     BEGIN
  1344.     LIB$SIGNAL (.STATUS);
  1345.     RETURN .STATUS;
  1346.     END;
  1347.  
  1348.     NEW_TERM_CHAR [TC$_BFR_SIZE] = .OLD_TERM_CHAR [TC$_BFR_SIZE];
  1349.     NEW_TERM_CHAR [TC$_TYPE] = .OLD_TERM_CHAR [TC$_TYPE];
  1350.     NEW_TERM_CHAR [TC$_CLASS] = .OLD_TERM_CHAR [TC$_CLASS];
  1351.     NEW_TERM_CHAR [TC$_PAGE_LEN] = .OLD_TERM_CHAR [TC$_PAGE_LEN];
  1352.     NEW_TERM_CHAR [TC$_CHAR] = (.OLD_TERM_CHAR [TC$_CHAR] OR TT$M_NOBRDCST) AND NOT (TT$M_CRFILL OR
  1353.     TT$M_LFFILL OR TT$M_WRAP OR TT$M_NOTYPEAHD);
  1354. ! We do not want to use eightbit if using parity
  1355.  
  1356.     IF .PARITY_TYPE EQL PR_NONE
  1357.     THEN
  1358.     NEW_TERM_CHAR [TC$_CHAR] = .NEW_TERM_CHAR [TC$_CHAR] OR TT$M_EIGHTBIT
  1359.     ELSE
  1360.     NEW_TERM_CHAR [TC$_CHAR] = .NEW_TERM_CHAR [TC$_CHAR] AND NOT TT$M_EIGHTBIT;
  1361.  
  1362.     NEW_TERM_CHAR [TC$_CHAR_2] = TT2$M_XON OR TT2$M_PASTHRU OR
  1363.     (.OLD_TERM_CHAR [TC$_CHAR_2] AND NOT TT2$M_FALLBACK);
  1364.  
  1365.     STATUS = $QIOW (CHAN = .TERM_CHAN, FUNC = IO$_SETMODE, P1 = NEW_TERM_CHAR,
  1366.     P2 = TC$_CHAR_LENGTH, P5 = TT$M_ALTRPAR);
  1367.  
  1368.     IF NOT .STATUS
  1369.     THEN
  1370.     BEGIN
  1371.     LIB$SIGNAL (.STATUS);
  1372.     RETURN .STATUS;
  1373.     END;
  1374.  
  1375.     TERM_FLAG = TRUE;                ! Terminal now open
  1376.     TERM_FIRST_TIME = TRUE;            ! Flag first time QIO should clear input
  1377.     FORCE_TIMEOUT = FALSE;            ! Don't timeout for no reason
  1378.     FORCE_ABORT = FALSE;            ! Don't abort yet
  1379. !
  1380. ! Now post the initial receive QIO
  1381. !
  1382.  
  1383.     IF .POST_QIOS                ! Need the QIO's?
  1384.     THEN
  1385.     BEGIN
  1386.     STATUS = DO_RECEIVE_QIO ();
  1387.  
  1388.     IF NOT .STATUS
  1389.     THEN
  1390.         BEGIN
  1391.         LIB$SIGNAL (.STATUS);
  1392.         RETURN KER_RECERR;
  1393.         END;
  1394.  
  1395. !
  1396. ! Also post the QIO for the console
  1397. !
  1398.  
  1399.     IF NOT .CONNECT_FLAG AND .SYS_OUTPUT_OPEN
  1400.     THEN
  1401.         BEGIN
  1402.         STATUS = DO_CONS_QIO ();
  1403.  
  1404.         IF NOT .STATUS
  1405.         THEN
  1406.         BEGIN
  1407.         LIB$SIGNAL (.STATUS);
  1408.         $CANCEL (CHAN = .TERM_CHAN);
  1409.         $DASSGN (CHAN = .TERM_CHAN);
  1410.         RETURN KER_RECERR;
  1411.         END;
  1412.  
  1413.         END;
  1414.  
  1415.     END;
  1416.  
  1417. !
  1418. ! Open any debugging log file
  1419. !
  1420.  
  1421.     IF .DEBUG_DESC [DSC$W_LENGTH] GTR 0
  1422.     THEN
  1423.  
  1424.     IF LOG_OPEN (DEBUG_DESC, DEBUG_FAB, DEBUG_RAB)
  1425.     THEN
  1426.         DEBUG_REDIRECTED = TRUE
  1427.     ELSE
  1428.         DEBUG_REDIRECTED = FALSE
  1429.  
  1430.     ELSE
  1431.     DEBUG_REDIRECTED = FALSE;
  1432.  
  1433.     IF .TRANSACTION_DESC [DSC$W_LENGTH] GTR 0
  1434.     THEN
  1435.  
  1436.     IF LOG_OPEN (TRANSACTION_DESC, TRANSACTION_FAB, TRANSACTION_RAB)
  1437.     THEN
  1438.         BEGIN
  1439.         TRANSACTION_OPEN = TRUE;
  1440.         LOG_FAOL (%ASCID'!-!-!11%D!/!-!%T!_Starting transaction log in file !AS!/',
  1441.         UPLIT (0, TRANSACTION_DESC), TRANSACTION_RAB);
  1442.         END
  1443.     ELSE
  1444.         TRANSACTION_OPEN = FALSE
  1445.  
  1446.     ELSE
  1447.     TRANSACTION_OPEN = FALSE;
  1448.  
  1449.     RETURN KER_NORMAL;
  1450.     END;                    ! End of TERM_OPEN
  1451.  
  1452. %SBTTL 'Communications line -- TERM_CLOSE'
  1453.  
  1454. GLOBAL ROUTINE TERM_CLOSE =
  1455.  
  1456. !++
  1457. ! FUNCTIONAL DESCRIPTION:
  1458. !
  1459. !    This routine will deassign the channel that was assigned by
  1460. !    TERM_OPEN.
  1461. !
  1462. ! CALLING SEQUENCE:
  1463. !
  1464. !    TERM_CLOSE();
  1465. !
  1466. ! INPUT PARAMETERS:
  1467. !
  1468. !    None.
  1469. !
  1470. ! IMPLICIT INPUTS:
  1471. !
  1472. !    TERM_CHAN - Channel number to deassign.
  1473. !
  1474. ! OUTPUT PARAMETERS:
  1475. !
  1476. !    None.
  1477. !
  1478. ! IMPLICIT OUTPUTS:
  1479. !
  1480. !    None.
  1481. !
  1482. ! COMPLETION CODES:
  1483. !
  1484. !    SS$_NORMAL or error condition.
  1485. !
  1486. ! SIDE EFFECTS:
  1487. !
  1488. !    None.
  1489. !
  1490. !--
  1491.  
  1492.     BEGIN
  1493.  
  1494.     EXTERNAL ROUTINE
  1495.     LOG_FAOL,                ! Routine to dump FAOL string
  1496.     LOG_CLOSE;                ! Routine to close log file
  1497.  
  1498.     EXTERNAL
  1499.     TRANSACTION_OPEN,
  1500.     TRANSACTION_DESC : BLOCK [8, BYTE],
  1501.     TRANSACTION_FAB,
  1502.     TRANSACTION_RAB;
  1503.  
  1504.     LOCAL
  1505.     PAR,                    ! Parity being set
  1506.     STATUS;                    ! Status returned by system service
  1507.  
  1508.     STATUS = $CANCEL (CHAN = .TERM_CHAN);    ! Kill pending QIO
  1509.  
  1510.     IF .SYS_OUTPUT_OPEN THEN $CANCEL (CHAN = .CONS_CHAN);
  1511.  
  1512.     CONNECT_FLAG = FALSE;
  1513.     PAR = (.OLD_PARITY [6, 0, 8, 0] AND (TT$M_ODD OR TT$M_PARITY)) OR TT$M_ALTRPAR;
  1514.                         ! Only set parity
  1515.     STATUS = $QIOW (CHAN = .TERM_CHAN, FUNC = IO$_SETMODE, P1 = OLD_TERM_CHAR,
  1516.     P2 = TC$_CHAR_LENGTH, P4 = .OLD_PARITY [4, 0, 16, 0], P5 = .PAR);
  1517.  
  1518.     IF NOT .STATUS
  1519.     THEN
  1520.     BEGIN
  1521.     LIB$SIGNAL (.STATUS);
  1522.     RETURN .STATUS;
  1523.     END;
  1524.  
  1525. !
  1526. ! Flag terminal parameters are reset
  1527. !
  1528.     TERM_FLAG = FALSE;
  1529. !
  1530. ! Close the debugging log file
  1531. !
  1532.  
  1533.     IF .DEBUG_REDIRECTED
  1534.     THEN
  1535.     BEGIN
  1536.     LOG_CLOSE (DEBUG_FAB, DEBUG_RAB);
  1537.     DEBUG_REDIRECTED = FALSE;
  1538.     END;
  1539.  
  1540. !
  1541. ! Close the transaction log
  1542. !
  1543.  
  1544.     IF .TRANSACTION_OPEN
  1545.     THEN
  1546.     BEGIN
  1547.     LOG_FAOL (%ASCID'!-!-!11%D!/!-!%T!_Closing transaction log file !AS!/',
  1548.         UPLIT (0, TRANSACTION_DESC), TRANSACTION_RAB);
  1549.     LOG_CLOSE (TRANSACTION_FAB, TRANSACTION_RAB);
  1550.     TRANSACTION_OPEN = FALSE;
  1551.     END;
  1552.  
  1553. !
  1554. ! If all worked, say so
  1555. !
  1556.     RETURN KER_NORMAL
  1557.     END;                    ! End of TERM_CLOSE
  1558.  
  1559. %SBTTL 'Communications line -- SEND'
  1560.  
  1561. GLOBAL ROUTINE SEND (ADDRESS, LENGTH) =
  1562.  
  1563. !++
  1564. ! FUNCTIONAL DESCRIPTION:
  1565. !
  1566. !    This routine will send a stream of 8-bit bytes over the terminal
  1567. !    line to the remote KERMIT.  This routine is called from KERMSG.
  1568. !
  1569. ! CALLING SEQUENCE:
  1570. !
  1571. !    SEND(Address-of-msg, Length-of-msg);
  1572. !
  1573. ! INPUT PARAMETERS:
  1574. !
  1575. !    None.
  1576. !
  1577. ! IMPLICIT INPUTS:
  1578. !
  1579. !    TERM_CHAN - Channel number to deassign.
  1580. !
  1581. ! OUTPUT PARAMETERS:
  1582. !
  1583. !    None.
  1584. !
  1585. ! IMPLICIT OUTPUTS:
  1586. !
  1587. !    None.
  1588. !
  1589. ! COMPLETION CODES:
  1590. !
  1591. !    SS$_NORMAL or error condition.
  1592. !
  1593. ! SIDE EFFECTS:
  1594. !
  1595. !    None.
  1596. !
  1597. !--
  1598.  
  1599.     BEGIN
  1600.  
  1601.     LOCAL
  1602.     CUR_EFN,                ! Current EFN settings
  1603.     STATUS;                    ! Status returned by $QIOW
  1604.  
  1605. !
  1606. ! If we already got a complete buffer of input we should ignore it.
  1607. ! This is because we are probably retransmitting something and the
  1608. ! incoming data is the response to the previous copy of this message.
  1609. ! If we don't ignore it, we could get into a situation where every message
  1610. ! gets transmitted twice.
  1611. !
  1612.     STATUS = $READEF (EFN = TERM_EFN, STATE = CUR_EFN);
  1613.  
  1614.     IF (.CUR_EFN AND 1^TERM_EFN) EQL 1 THEN DO_RECEIVE_QIO ();
  1615.  
  1616.     STATUS = $QIOW (CHAN = .TERM_CHAN, EFN = TERM_O_EFN, FUNC = IO$_WRITEVBLK + IO$M_NOFORMAT,
  1617.     P1 = .ADDRESS, P2 = .LENGTH);
  1618.  
  1619.     IF .STATUS EQL SS$_NORMAL
  1620.     THEN
  1621.     RETURN KER_NORMAL
  1622.     ELSE
  1623.     BEGIN
  1624.     LIB$SIGNAL (.STATUS);
  1625.     RETURN .STATUS;
  1626.     END;
  1627.  
  1628.     END;                    ! End of SEND
  1629.  
  1630. %SBTTL 'Communications line -- RECEIVE'
  1631.  
  1632. GLOBAL ROUTINE RECEIVE (ADDRESS, LENGTH) =
  1633.  
  1634. !++
  1635. ! FUNCTIONAL DESCRIPTION:
  1636. !
  1637. !    This routine will receive a stream of 8-bit bytes over the terminal
  1638. !    line to the remote KERMIT.  This routine is called from KERMSG.
  1639. !    The text that is stored will always contain the control-A as the
  1640. !    first character.
  1641. !
  1642. ! CALLING SEQUENCE:
  1643. !
  1644. !    RECEIVE(Address-of-msg);
  1645. !
  1646. ! INPUT PARAMETERS:
  1647. !
  1648. !    None.
  1649. !
  1650. ! IMPLICIT INPUTS:
  1651. !
  1652. !    TERM_CHAN - Channel number to deassign.
  1653. !
  1654. ! OUTPUT PARAMETERS:
  1655. !
  1656. !    None.
  1657. !
  1658. ! IMPLICIT OUTPUTS:
  1659. !
  1660. !    None.
  1661. !
  1662. ! COMPLETION CODES:
  1663. !
  1664. !    SS$_NORMAL or error condition.
  1665. !
  1666. ! SIDE EFFECTS:
  1667. !
  1668. !    None.
  1669. !
  1670. !--
  1671.  
  1672.     BEGIN
  1673.  
  1674.     EXTERNAL
  1675.     RCV_SOH;                ! Character to use for start of packet
  1676.  
  1677.     LOCAL
  1678.     QWORD_TIMEOUT : VECTOR [2, LONG],    ! Quad word TIMEOUT value
  1679.     TIMER_VALUE : VECTOR [2, LONG],        ! Quad word TIME value
  1680.     OLD_POINTER,                ! Pointer into the message
  1681.     NEW_POINTER,                ! Other pointer for finding SOH
  1682.     CUR_LENGTH,                ! Running length while finding SOH
  1683.     CUR_EFN,                ! Current EFN value
  1684.     STATUS;                    ! Status returned by $QIO
  1685.  
  1686.     OWN
  1687.     INT_CHR_SEEN;                ! Interrupt character seen last
  1688.  
  1689. !
  1690. ! Flag we haven't seen a ^Y yet.  We must get two control-Y's in fairly
  1691. ! quick succession (no timeouts in between) in order to give up.
  1692. !
  1693.     INT_CHR_SEEN = FALSE;
  1694. !
  1695. ! Set up the timer if we have a time out parameter
  1696. !
  1697.  
  1698.     IF NOT .FORCE_TIMEOUT THEN STATUS = $CLREF (EFN = TIME_EFN);
  1699.  
  1700.     IF .SEND_TIMEOUT GTR 0
  1701.     THEN
  1702.     BEGIN
  1703.     STATUS = $CANTIM (REQIDT = TIME_EFN);
  1704.     STATUS = $GETTIM (TIMADR = TIMER_VALUE);
  1705.     STATUS = LIB$EMUL (SEND_TIMEOUT, UPLIT (10000000), UPLIT (0), QWORD_TIMEOUT);
  1706.     STATUS = LIB$ADDX (TIMER_VALUE, QWORD_TIMEOUT, QWORD_TIMEOUT);
  1707.     STATUS = $SETIMR (DAYTIM = QWORD_TIMEOUT, EFN = TIME_EFN, REQIDT = TIME_EFN);
  1708.     END;
  1709.  
  1710. !
  1711. ! Loop until we get something that is acceptable
  1712. !
  1713.  
  1714.     WHILE TRUE DO
  1715.     BEGIN
  1716. !
  1717. ! Wait for something to happen.  Either the terminal EFN will come up
  1718. ! indicating we have some data, or the timer EFN will indicate that
  1719. ! the time has run out.
  1720. !
  1721.     STATUS = $WFLOR (EFN = TERM_EFN, MASK = (1^TERM_EFN OR 1^TIME_EFN));
  1722.     STATUS = $READEF (EFN = TERM_EFN, STATE = CUR_EFN);
  1723.     FORCE_TIMEOUT = FALSE;            ! Timeout had it chance to happen
  1724. !
  1725. ! If the terminal EFN is not set, the time must have expired.  Therefore,
  1726. ! we have timed out, and need to return that fact.
  1727. !
  1728.  
  1729.     IF (.CUR_EFN AND 1^TERM_EFN) EQL 0 THEN RETURN KER_TIMEOUT;
  1730.  
  1731. !
  1732. ! If we have a request to abort, start it up the chain.
  1733. !
  1734.  
  1735.     IF .FORCE_ABORT
  1736.     THEN
  1737.         BEGIN
  1738.         STATUS = $CANTIM (REQIDT = TIME_EFN);
  1739.         RETURN KER_ABORTED;
  1740.         END;
  1741.  
  1742. !
  1743. ! Check if the QIO completed successfully.  If not, we will return
  1744. ! an error.
  1745. !
  1746.  
  1747.     IF NOT .IO_STATUS [0]
  1748.     THEN
  1749.         BEGIN
  1750.         LIB$SIGNAL (.IO_STATUS [0]);
  1751.         RETURN KER_RECERR;
  1752.         END;
  1753.  
  1754. !
  1755. ! First check for a control-Y as the terminator.  If it was, then
  1756. ! just abort now, since the user probably typed it.
  1757. !
  1758.  
  1759.     IF .CONNECT_FLAG
  1760.     THEN
  1761.  
  1762.         IF (.IO_STATUS [2] EQL CHR_CTL_Y) AND (.RCV_EOL NEQ CHR_CTL_Y)
  1763.         THEN
  1764.         BEGIN
  1765.  
  1766.         IF .INT_CHR_SEEN AND .IO_STATUS [1] EQL 0
  1767.         THEN
  1768.             BEGIN
  1769.             STATUS = $CANTIM (REQIDT = TIME_EFN);
  1770.             RETURN KER_ABORTED
  1771.             END
  1772.         ELSE
  1773.             BEGIN
  1774.             INT_CHR_SEEN = TRUE;
  1775.             IO_STATUS [1] = 0;        ! Force no input seen
  1776.             END
  1777.  
  1778.         END
  1779.         ELSE
  1780.         INT_CHR_SEEN = FALSE;        ! Last character not ^Y
  1781.  
  1782. !
  1783. ! Now find the final start of header character in the buffer.  We
  1784. ! will only return the text from that point on.  If there is no SOH,
  1785. ! then just get another buffer.  It was probably noise on the line.
  1786. !
  1787.     OLD_POINTER = CH$PTR (RECV_BUFFER, 0, CHR_SIZE);
  1788.     CUR_LENGTH = .IO_STATUS [1];        ! Length without terminating character
  1789.     NEW_POINTER = CH$FIND_CH (.CUR_LENGTH, .OLD_POINTER, .RCV_SOH);
  1790. !
  1791. ! If we found a start of header character, then we probably have something
  1792. ! to return.  However, first we must find the last start of header, in case
  1793. ! something is garbled.
  1794. !
  1795.  
  1796.     IF NOT CH$FAIL (.NEW_POINTER)
  1797.     THEN
  1798.         BEGIN
  1799. !
  1800. ! Search until we can't find any more start of headers, or until we run
  1801. ! out of string to search (last character before EOL is an SOH).
  1802. !
  1803.  
  1804.         WHILE (.CUR_LENGTH GTR 0) AND ( NOT CH$FAIL (.NEW_POINTER)) DO
  1805.         BEGIN
  1806.         CUR_LENGTH = .CUR_LENGTH - CH$DIFF (.NEW_POINTER, .OLD_POINTER);
  1807.                     ! Adjust the length for the characters we are skipping
  1808.         OLD_POINTER = .NEW_POINTER;    ! Remember where we start
  1809.         NEW_POINTER = CH$FIND_CH (.CUR_LENGTH - 1, CH$PLUS (.OLD_POINTER, 1), .RCV_SOH);
  1810.         ! Find the next SOH (if any)
  1811.         END;
  1812.  
  1813. !
  1814. ! If we have something left of the buffer, move from the SOH until the end
  1815. ! into the callers buffer.
  1816. !
  1817.  
  1818.         IF (.CUR_LENGTH GTR 0)
  1819.         THEN
  1820.         BEGIN
  1821.         .LENGTH = .CUR_LENGTH + 1;
  1822.  
  1823.         IF .PARITY_TYPE EQL PR_NONE    ! Have eight-bit?
  1824.         THEN
  1825.             CH$MOVE (.CUR_LENGTH + 1, .OLD_POINTER, CH$PTR (.ADDRESS, 0, CHR_SIZE))
  1826.         ELSE
  1827.             BEGIN
  1828.             NEW_POINTER = CH$PTR (.ADDRESS, 0, CHR_SIZE);
  1829.  
  1830.             DECR CUR_LENGTH FROM .CUR_LENGTH TO 0 DO
  1831.             CH$WCHAR_A ((CH$RCHAR_A (OLD_POINTER) AND %O'177'), NEW_POINTER);
  1832.  
  1833.             END;
  1834.  
  1835.         EXITLOOP
  1836.         END
  1837.  
  1838.         END;                ! End of IF NOT CH$FAIL(.POINTER)
  1839.  
  1840. !
  1841. ! If we have gotten here, we have input a buffer without a valid message.
  1842. ! Make sure we post the QIO again
  1843. !
  1844.     STATUS = DO_RECEIVE_QIO ();
  1845.  
  1846.     IF NOT .STATUS
  1847.     THEN
  1848.         BEGIN
  1849.         LIB$SIGNAL (.STATUS);
  1850.         RETURN KER_RECERR
  1851.         END;
  1852.  
  1853.     END;                    ! End of WHILE TRUE DO
  1854.  
  1855. !
  1856. ! If we have gotten here, we have a valid message to return.
  1857. ! Post the QIO so the buffer is available for the next message.
  1858. !
  1859.     STATUS = DO_RECEIVE_QIO ();
  1860.  
  1861.     IF NOT .STATUS
  1862.     THEN
  1863.     BEGIN
  1864.     LIB$SIGNAL (.STATUS);
  1865.     RETURN KER_RECERR
  1866.     END;
  1867.  
  1868.     RETURN KER_NORMAL;                ! Return happy
  1869.     END;                    ! End of RECEIVE
  1870.  
  1871. %SBTTL 'Communications line -- IBM_WAIT'
  1872.  
  1873. GLOBAL ROUTINE IBM_WAIT =
  1874.  
  1875. !++
  1876. ! FUNCTIONAL DESCRIPTION:
  1877. !
  1878. !    This routine will wait until the IBM turnaround character
  1879. !    is seen on the communications line, or until the timeout
  1880. !    parameter is exceeded.
  1881. !
  1882. ! CALLING SEQUENCE:
  1883. !
  1884. !    STATUS = IBM_WAIT ();
  1885. !
  1886. ! INPUT PARAMETERS:
  1887. !
  1888. !    None.
  1889. !
  1890. ! IMPLICIT INPUTS:
  1891. !
  1892. !    TERM_CHAN - Channel number for terminal
  1893. !
  1894. ! OUTPUT PARAMETERS:
  1895. !
  1896. !    Status value is returned as routine value.
  1897. !
  1898. ! IMPLICIT OUTPUTS:
  1899. !
  1900. !    None.
  1901. !
  1902. ! COMPLETION CODES:
  1903. !
  1904. !    SS$_NORMAL or error condition.
  1905. !
  1906. ! SIDE EFFECTS:
  1907. !
  1908. !    None.
  1909. !
  1910. !--
  1911.  
  1912.     BEGIN
  1913.  
  1914.     LOCAL
  1915.     QWORD_TIMEOUT : VECTOR [2, LONG],    ! Quad word TIMEOUT value
  1916.     TIMER_VALUE : VECTOR [2, LONG],        ! Quad word TIME value
  1917.     CUR_EFN,                ! Current EFN value
  1918.     STATUS;                    ! Status returned by $QIO
  1919.  
  1920. !
  1921. ! Set up the timer if we have a time out parameter
  1922. !
  1923.     STATUS = $CLREF (EFN = TIME_EFN);
  1924.  
  1925.     IF .SEND_TIMEOUT GTR 0
  1926.     THEN
  1927.     BEGIN
  1928.     STATUS = $CANTIM (REQIDT = TIME_EFN);
  1929.     STATUS = $GETTIM (TIMADR = TIMER_VALUE);
  1930.     STATUS = LIB$EMUL (SEND_TIMEOUT, UPLIT (1000000), UPLIT (0), QWORD_TIMEOUT);
  1931.     STATUS = LIB$ADDX (TIMER_VALUE, QWORD_TIMEOUT, QWORD_TIMEOUT);
  1932.     STATUS = $SETIMR (DAYTIM = QWORD_TIMEOUT, EFN = TIME_EFN, REQIDT = TIME_EFN);
  1933.     END;
  1934.  
  1935. !
  1936. ! Loop until we get something that is acceptable
  1937. !
  1938.  
  1939.     WHILE TRUE DO
  1940.     BEGIN
  1941. !
  1942. ! Wait for something to happen.  Either the terminal EFN will come up
  1943. ! indicating we have some data, or the timer EFN will indicate that
  1944. ! the time has run out.
  1945. !
  1946.     STATUS = $WFLOR (EFN = TERM_EFN, MASK = (1^TERM_EFN OR 1^TIME_EFN));
  1947.     STATUS = $READEF (EFN = TERM_EFN, STATE = CUR_EFN);
  1948. !
  1949. ! If the terminal EFN is not set, the time must have expired.  Therefore,
  1950. ! pretend we got the character.
  1951. !
  1952.  
  1953.     IF (.CUR_EFN AND 1^TERM_EFN) EQL 0 THEN RETURN KER_NORMAL;
  1954.  
  1955. !
  1956. ! Check if the QIO completed successfully.  If not, we will return
  1957. ! an error.
  1958. !
  1959.  
  1960.     IF NOT .IO_STATUS [0]
  1961.     THEN
  1962.         BEGIN
  1963.         LIB$SIGNAL (.IO_STATUS [0]);
  1964.         RETURN KER_RECERR;
  1965.         END;
  1966.  
  1967. !
  1968. ! First check for a control-Y as the terminator.  If it was, then
  1969. ! just abort now, since the user probably typed it.
  1970. !
  1971.  
  1972.     IF .CONNECT_FLAG
  1973.     THEN
  1974.  
  1975.         IF (.IO_STATUS [2] EQL CHR_CTL_Y) AND (.RCV_EOL NEQ CHR_CTL_Y)
  1976.         THEN
  1977.         BEGIN
  1978.         STATUS = $CANTIM (REQIDT = TIME_EFN);
  1979.         RETURN KER_ABORTED
  1980.         END;
  1981.  
  1982. ! Check if terminator was the turnaround character
  1983.  
  1984.     IF (.IO_STATUS [2] EQL .IBM_CHAR) THEN EXITLOOP;
  1985.  
  1986. !
  1987. ! Make sure we post the QIO again
  1988. !
  1989.     STATUS = DO_RECEIVE_QIO ();
  1990.  
  1991.     IF NOT .STATUS
  1992.     THEN
  1993.         BEGIN
  1994.         LIB$SIGNAL (.STATUS);
  1995.         RETURN KER_RECERR
  1996.         END;
  1997.  
  1998.     END;                    ! End of WHILE TRUE DO
  1999.  
  2000. !
  2001. ! If we have gotten here, we have a valid message to return.
  2002. ! Post the QIO so the buffer is available for the next message.
  2003. !
  2004.     STATUS = DO_RECEIVE_QIO ();
  2005.  
  2006.     IF NOT .STATUS
  2007.     THEN
  2008.     BEGIN
  2009.     LIB$SIGNAL (.STATUS);
  2010.     RETURN KER_RECERR
  2011.     END;
  2012.  
  2013.     RETURN KER_NORMAL;                ! Return happy
  2014.     END;                    ! End of RECEIVE
  2015.  
  2016. %SBTTL 'GET_DEV_CHAR - Determine device characteristics'
  2017.     ROUTINE GET_DEV_CHAR (LOG_NAME_DESC, PHYS_NAME_DESC, DEV_CLASS) =
  2018.  
  2019. !++
  2020. ! FUNCTIONAL DESCRIPTION:
  2021. !
  2022. ! This routine will get the device characteristics from VMS.  It returns
  2023. ! both the physical name of the device and the device class.
  2024. !
  2025. ! CALLING SEQUENCE:
  2026. !
  2027. !    STATUS = GET_DEV_CHAR (LOG_NAME_DESC, PHYS_NAME_DESC, DEV_CLASS);
  2028. !
  2029. ! INPUT PARAMETERS:
  2030. !
  2031. !    LOG_NAME_DESC - Descriptor for logical device for which the device
  2032. !            class is desired.
  2033. !
  2034. ! IMPLICIT INPUTS:
  2035. !
  2036. !    None.
  2037. !
  2038. ! OUPTUT PARAMETERS:
  2039. !
  2040. !    PHYS_NAME_DESC - Descriptor for physical device name
  2041. !    DEV_CLASS - Device class for device
  2042. !
  2043. ! IMPLICIT OUTPUTS:
  2044. !
  2045. !    None.
  2046. !
  2047. ! COMPLETION CODES/RETURN VALUE:
  2048. !
  2049. !    Status value returned from $GETDVI if it fails,
  2050. !        KER_NORMAL otherwise.
  2051. !
  2052. ! SIDE EFFECTS:
  2053. !
  2054. !    None.
  2055. !
  2056. !--
  2057.  
  2058.     BEGIN
  2059.  
  2060.     MAP
  2061.     PHYS_NAME_DESC : REF BLOCK [8, BYTE];    ! Physical name descriptor
  2062.  
  2063.     LOCAL
  2064.     ITMLST : ITEM_LIST [2] FIELD (ITEM_FIELDS),
  2065.     PHYS_NAME_LENGTH : VOLATILE,
  2066.     STATUS;
  2067.  
  2068. !
  2069. ! Set up item list for device class
  2070. !
  2071.     ITMLST [0, ITEM_ITEM_CODE] = DVI$_DEVCLASS;
  2072.     ITMLST [0, ITEM_BFR_LENGTH] = 4;        ! 4 byte result
  2073.     ITMLST [0, ITEM_BFR_ADDRESS] = .DEV_CLASS;    ! Where to return result
  2074.     ITMLST [0, ITEM_RTN_LENGTH] = 0;        ! We know how long it is
  2075. !
  2076. ! Item list entry for device name
  2077. !
  2078.     ITMLST [1, ITEM_ITEM_CODE] = DVI$_DEVNAM;    ! Want the name of the device
  2079.     ITMLST [1, ITEM_BFR_LENGTH] = .PHYS_NAME_DESC [DSC$W_LENGTH];    ! Max length to return
  2080.     ITMLST [1, ITEM_BFR_ADDRESS] = .PHYS_NAME_DESC [DSC$A_POINTER];    ! Where to return name
  2081.     ITMLST [1, ITEM_RTN_LENGTH] = PHYS_NAME_LENGTH;    ! Where to return length
  2082. !
  2083. ! End the list of items
  2084. !
  2085.     ITMLST [2, ITEM_ITEM_CODE] = 0;
  2086.     ITMLST [2, ITEM_BFR_LENGTH] = 0;
  2087. !
  2088. ! Request the information
  2089. !
  2090.     STATUS = $GETDVIW (EFN = GET_DEV_EFN, DEVNAM = .LOG_NAME_DESC, ITMLST = ITMLST);
  2091.  
  2092.     IF NOT .STATUS THEN RETURN .STATUS;
  2093. !
  2094. ! Assign the length and return happy
  2095. !
  2096.     PHYS_NAME_DESC [DSC$W_LENGTH] = .PHYS_NAME_LENGTH;
  2097.     RETURN KER_NORMAL;
  2098.     END;                    ! End of GET_DEV_CHAR
  2099. %SBTTL 'Term_Hangup'
  2100. global ROUTINE Term_Hangup : NOVALUE =
  2101.  
  2102. !++
  2103. ! FUNCTIONAL DESCRIPTION:
  2104. !
  2105. ! This routine puts a read-attention AST on the mailbox associated with
  2106. ! TERM_DESC - the port being used for external communications.  The
  2107. ! mailbox will receive 3 types of messages: Unsolicited data, Terminal
  2108. ! hangup, and Broadcast messages.  Only Terminal hangup messages are of
  2109. ! interest here.
  2110. !
  2111. !
  2112. ! CALLING SEQUENCE:
  2113. !
  2114. !    TERM_HANGUP();
  2115. !
  2116. ! INPUT PARAMETERS:
  2117. !
  2118. !    None.
  2119. !
  2120. ! IMPLICIT INPUTS:
  2121. !
  2122. !    MBX_CHAN - The channel to the mailbox associated with TERM_DESC.
  2123. !
  2124. ! OUPTUT PARAMETERS:
  2125. !
  2126. !    None.
  2127. !
  2128. ! IMPLICIT OUTPUTS:
  2129. !
  2130. !    None.
  2131. !
  2132. ! COMPLETION CODES:
  2133. !
  2134. !    Return status from $QIOW
  2135. !
  2136. ! SIDE EFFECTS:
  2137. !
  2138. !    A write-attention AST is queued to the mailbox.  The ast routine
  2139. !    MBX_AST_RTN will be called if a message is written to the mailbox.
  2140. !
  2141. !--
  2142.  
  2143.     BEGIN
  2144.  
  2145.     LOCAL
  2146.         Function,
  2147.         Iosb : VECTOR [4, WORD],    ! I/O status block.
  2148.     Sts;
  2149.  
  2150.     Function = IO$_SETMODE + IO$M_WRTATTN;
  2151.     Sts = $QIOW(CHAN = .Mbx_Chan,
  2152.                 FUNC = .Function,
  2153.                 IOSB = Iosb,
  2154.                 P1 = Mbx_Ast_Rtn);
  2155.  
  2156.     IF .sts THEN sts = .Iosb[0];
  2157.     IF NOT .sts THEN LIB$SIGNAL(.Sts);
  2158.  
  2159.     END;
  2160. %SBTTL 'Mbx_Ast_Rtn'
  2161. ROUTINE Mbx_Ast_Rtn : NOVALUE =
  2162.  
  2163. !++
  2164. ! FUNCTIONAL DESCRIPTION:
  2165. !
  2166. !    This routine is called at AST level whenever a mailbox message
  2167. !    arrives in the mailbox associated with TERM_DESC.  If the message
  2168. !    is a hangup notification the user will be 1) notified his outgoing
  2169. !    connection is no longer present (technically there is no longer
  2170. !    a channel to the device represented in TERM_DESC) and 2) 
  2171. !
  2172. ! CALLING SEQUENCE:
  2173. !
  2174. !    MBX_AST_RTN();
  2175. !
  2176. ! INPUT PARAMETERS:
  2177. !
  2178. !       None.
  2179. !
  2180. ! IMPLICIT INPUTS:
  2181. !
  2182. !    TERM_DESC
  2183. !    MBX_CHAN - The channel to the mailbox associated with TERM_DESC.
  2184. !
  2185. ! OUTPUT PARAMETERS:
  2186. !
  2187. !    None.
  2188. !
  2189. ! IMPLICIT OUTPUTS:
  2190. !
  2191. !    MBX_CHAN
  2192. !
  2193. ! COMPLETION CODES:
  2194. !
  2195. !    SS$_NORMAL or error condition.
  2196. !
  2197. ! SIDE EFFECTS:
  2198. !
  2199. !    A message may be output to the user if his outgoing session is
  2200. !    no longer valid.
  2201. !
  2202. !--
  2203.  
  2204.     BEGIN
  2205.  
  2206.     LOCAL
  2207.         Function,
  2208.         Iosb : VECTOR [4, WORD],
  2209.         Mbx_Msg : VECTOR [124, BYTE],
  2210.         Sts;
  2211.  
  2212.  
  2213.     Function = IO$_READVBLK;
  2214.  
  2215.     Sts = $QIOW(CHAN = .Mbx_Chan,
  2216.                 FUNC = .Function,
  2217.                 IOSB = Iosb,
  2218.                 P1 = Mbx_Msg,
  2219.                 P2 = 100);
  2220.  
  2221.     IF .Sts THEN Sts = .Iosb[0];
  2222.     IF NOT .sts THEN LIB$SIGNAL(.Sts);
  2223.  
  2224.     IF .Mbx_Msg<0,16> EQL MSG$_TRMHANGUP
  2225.     THEN
  2226.         BEGIN
  2227. !        asn_wth_mbx(term_desc, %REF(100), %REF(100), term_chan, mbx_chan);
  2228.         $DASSGN(CHAN = .mbx_chan);
  2229.         mbx_chan = 0;
  2230.         LIB$SIGNAL(SS$_HANGUP)
  2231.         END
  2232.     ELSE
  2233.         Term_Hangup();
  2234.  
  2235.     END;
  2236.  
  2237. %SBTTL 'Send_Break_TTY'
  2238. GLOBAL ROUTINE Send_Break_TTY =
  2239.  
  2240. !++
  2241. ! FUNCTIONAL DESCRIPTION:
  2242. !
  2243. ! This routine sends a break to the user's current terminal line.
  2244. !
  2245. !
  2246. ! CALLING SEQUENCE:
  2247. !
  2248. !    STATUS = Send_Break_TTY ();
  2249. !
  2250. ! INPUT PARAMETERS:
  2251. !
  2252. !    None.
  2253. !
  2254. ! IMPLICIT INPUTS:
  2255. !
  2256. !    Term_Desc - The current outgoing terminal line.
  2257. !
  2258. ! OUPTUT PARAMETERS:
  2259. !
  2260. !    None.
  2261. !
  2262. ! IMPLICIT OUTPUTS:
  2263. !
  2264. !    None.
  2265. !
  2266. ! COMPLETION CODES:
  2267. !
  2268. !    Return status from $QIOW
  2269. !
  2270. ! SIDE EFFECTS:
  2271. !
  2272. !    A break is sent to the user's outgoing terminal line.
  2273. !
  2274. !--
  2275.  
  2276.     BEGIN
  2277.  
  2278.     LOCAL
  2279.         Char : VECTOR [2],        ! Terminal characteristics.
  2280.         Iosb : VECTOR [4, WORD],    ! I/O status block.
  2281.         Parity_Flags,
  2282.         Sts;
  2283.  
  2284.     Sts = $QIOW(CHAN = .Term_Chan,
  2285.                 FUNC = IO$_SENSEMODE,
  2286.                 IOSB = Iosb,
  2287.                 P1 = Char);
  2288.     IF .Sts THEN Sts = .Iosb [0];
  2289.     IF NOT .Sts THEN RETURN .Sts;
  2290.  
  2291.     Parity_Flags<4,16> = .Iosb [3];
  2292.  
  2293.     Sts = $QIOW(CHAN = .Term_Chan,
  2294.                 FUNC = IO$_SETMODE,
  2295.                 IOSB = Iosb,
  2296.                 P1 = Char,
  2297.                 P5 = (.Parity_Flags OR TT$M_BREAK));
  2298.     IF .Sts THEN Sts = .Iosb [0];
  2299.     IF NOT .Sts THEN RETURN .Sts;
  2300.  
  2301.     LIB$WAIT(%REF(%E'0.25'));
  2302.  
  2303.     Sts = $QIOW(CHAN = .Term_Chan,
  2304.                 FUNC = IO$_SETMODE,
  2305.                 IOSB = Iosb,
  2306.                 P1 = Char,
  2307.                 P5 = .Parity_Flags);
  2308.     IF (.Sts) THEN Sts = .Iosb [0];
  2309.  
  2310.     Send_Break_TTY_Flag = 0;
  2311.  
  2312.     RETURN .Sts;
  2313.     END;
  2314. %SBTTL 'DO_RECEIVE_QIO'
  2315. ROUTINE DO_RECEIVE_QIO =
  2316.  
  2317. !++
  2318. ! FUNCTIONAL DESCRIPTION:
  2319. !
  2320. ! This routine is called to perform a QIO input from the terminal.  This
  2321. ! ensures that there is usually a receive buffer pending.
  2322. !
  2323. ! CALLING SEQUENCE:
  2324. !
  2325. !    STATUS = DO_RECEIVE_QIO ();
  2326. !
  2327. ! INPUT PARAMETERS:
  2328. !
  2329. !    None.
  2330. !
  2331. ! IMPLICIT INPUTS:
  2332. !
  2333. !    RCV_EOL - Receive end-of-line character
  2334. !
  2335. ! OUPTUT PARAMETERS:
  2336. !
  2337. !    None.
  2338. !
  2339. ! IMPLICIT OUTPUTS:
  2340. !
  2341. !    IO_STATUS - IOSB for the QIO
  2342. !    RCV_BUFFER - Data input from terminal
  2343. !
  2344. ! COMPLETION CODES:
  2345. !
  2346. !    None.
  2347. !
  2348. ! SIDE EFFECTS:
  2349. !
  2350. !    TERM_EFN is set when I/O completes
  2351. !
  2352. !--
  2353.  
  2354.     BEGIN
  2355.  
  2356.     LOCAL
  2357.     QIO_FUNC,
  2358.     TERMINATOR : VECTOR [2, LONG],
  2359.     STATUS;                    ! For status of QIO call
  2360.  
  2361. !
  2362. ! Initialize the terminating characters for the QIO.  Only terminate
  2363. ! on the end-of-line character and a control-Y
  2364. !
  2365.     TERMINATOR [0] = 0;
  2366.     TERMINATOR [1] = 1^.RCV_EOL OR 1^CHR_CTL_Y;
  2367.  
  2368.     IF .IBM_CHAR GEQ 0 THEN TERMINATOR [1] = .TERMINATOR [1] OR 1^.IBM_CHAR;
  2369.  
  2370.                         ! Need IBM turnaround?
  2371. !
  2372. ! Initialize the QIO function
  2373. ! Always purge typeahead
  2374. !
  2375.     QIO_FUNC = IO$_TTYREADALL OR IO$M_NOECHO OR IO$M_PURGE;
  2376.     RETURN $QIO (CHAN = .TERM_CHAN, EFN = TERM_EFN, FUNC = .QIO_FUNC, IOSB = IO_STATUS,
  2377.         P1 = RECV_BUFFER, P2 = RECV_BUFF_SIZE, P4 = TERMINATOR);
  2378.     END;                    ! End of DO_RECEIVE_QIO
  2379. %SBTTL 'DO_CONS_QIO'
  2380. ROUTINE DO_CONS_QIO =
  2381.  
  2382. !++
  2383. ! FUNCTIONAL DESCRIPTION:
  2384. !
  2385. ! This routine is called to perform a QIO input from the terminal.  This
  2386. ! ensures that there is usually a receive buffer pending.
  2387. !
  2388. ! CALLING SEQUENCE:
  2389. !
  2390. !    STATUS = DO_CONS_QIO ();
  2391. !
  2392. ! INPUT PARAMETERS:
  2393. !
  2394. !    None.
  2395. !
  2396. ! IMPLICIT INPUTS:
  2397. !
  2398. !    RCV_EOL - Receive end-of-line character
  2399. !
  2400. ! OUPTUT PARAMETERS:
  2401. !
  2402. !    None.
  2403. !
  2404. ! IMPLICIT OUTPUTS:
  2405. !
  2406. !    IO_STATUS - IOSB for the QIO
  2407. !    RCV_BUFFER - Data input from terminal
  2408. !
  2409. ! COMPLETION CODES:
  2410. !
  2411. !    None.
  2412. !
  2413. ! SIDE EFFECTS:
  2414. !
  2415. !    TERM_EFN is set when I/O completes
  2416. !
  2417. !--
  2418.  
  2419.     BEGIN
  2420.  
  2421.     EXTERNAL
  2422.     ABT_CUR_FILE,
  2423.     ABT_ALL_FILE,
  2424.     DEBUG_FLAG,
  2425.     TYP_STS_FLAG;
  2426.  
  2427.     LOCAL
  2428.     I,                    ! Random index variable
  2429.     TERMINATOR : VECTOR [2, LONG],        ! Pointer at terminator mask
  2430.     TERM_MASK : VECTOR [8, LONG],        ! Terminator mask
  2431.     STATUS;                    ! For status of QIO call
  2432.  
  2433.     LITERAL
  2434.     CONS_BUFF_SIZE = 1;
  2435.  
  2436.     OWN
  2437.     CONS_STATUS : VECTOR [4, WORD],
  2438.     CONS_BUFFER : VECTOR [CONS_BUFF_SIZE, BYTE];
  2439.  
  2440. !
  2441. ! AST routine for console
  2442. !
  2443.     ROUTINE CONS_AST (DUMMY) =
  2444.     BEGIN
  2445.  
  2446.     IF .CONS_STATUS [0]
  2447.     THEN
  2448.  
  2449.         SELECT .CONS_STATUS [2] OF
  2450.         SET
  2451.  
  2452.         [CHR_CTL_Z] :
  2453.             ABT_ALL_FILE = TRUE;
  2454.  
  2455.         [CHR_CTL_X] :
  2456.             ABT_CUR_FILE = TRUE;
  2457.  
  2458.         [CHR_CTL_Y] :
  2459.             RETURN SS$_NORMAL;
  2460.  
  2461.         [CHR_CTL_C] :
  2462.             BEGIN
  2463.             FORCE_TIMEOUT = TRUE;
  2464.             FORCE_ABORT = TRUE;
  2465.             END;
  2466.  
  2467.         [CHR_CTL_D] :
  2468.             DEBUG_FLAG = NOT .DEBUG_FLAG;
  2469.  
  2470.         [CHR_CTL_A] :
  2471.             TYP_STS_FLAG = TRUE;
  2472.  
  2473.         [CHR_CTL_M] :
  2474.             FORCE_TIMEOUT = TRUE;
  2475.  
  2476.         [CHR_CTL_Z, CHR_CTL_X, CHR_CTL_A, CHR_CTL_M, CHR_CTL_C] :
  2477. ! Make sure what we did gets noticed, even if we are currently waiting
  2478. ! forever for input.
  2479.  
  2480.             IF .FORCE_TIMEOUT OR .SEND_TIMEOUT EQL 0 THEN $SETEF (EFN = TIME_EFN);
  2481.  
  2482.         TES;
  2483.  
  2484.     IF .CONS_STATUS [0] NEQ SS$_CANCEL AND .CONS_STATUS [0] NEQ SS$_ABORT
  2485.     THEN
  2486.         RETURN DO_CONS_QIO ()
  2487.     ELSE
  2488.         RETURN SS$_NORMAL;
  2489.  
  2490.     END;
  2491. !
  2492. ! Start of main portion of DO_CONS_QIO
  2493. !
  2494.     TERMINATOR [0] = 32;            ! Length of terminator mask in bytes
  2495.     TERMINATOR [1] = TERM_MASK;            ! Address of mask
  2496.  
  2497.     INCR I FROM 0 TO 7 DO
  2498.     TERM_MASK [.I] = -1;            ! All characters are terminators
  2499.  
  2500.     RETURN $QIO (CHAN = .CONS_CHAN, EFN = CONS_EFN, FUNC = IO$_TTYREADALL OR IO$M_NOECHO,
  2501.         IOSB = CONS_STATUS, ASTADR = CONS_AST, P1 = CONS_BUFFER, P2 = CONS_BUFF_SIZE,
  2502.         P4 = TERMINATOR);
  2503.     END;                    ! End of DO_CONS_QIO
  2504. %SBTTL 'TERM_CONNECT'
  2505.  
  2506. GLOBAL ROUTINE TERM_CONNECT =
  2507.  
  2508. !++
  2509. ! FUNCTIONAL DESCRIPTION:
  2510. !
  2511. !    This routine TERM_CONNECT will enable two terminal-like devices,
  2512. !    MY_TERM and  TERM_NAME, to communicate with each other.  Anything
  2513. !    that the user types on his terminal, MYTERM, will be sent to the
  2514. !    other  device,  TERM_NAME,  over the terminal line  TERM_CHAN.
  2515. !    Anything that TERM_NAME cares to output will be sent to MYTERM.
  2516. !    The main routine TERM_CONNECT performs the initialization.  It
  2517. !    opens the input and output files and connects streams.
  2518. !
  2519. ! CALLING SEQUENCE:
  2520. !
  2521. !    TERM_CONNECT();
  2522. !
  2523. ! INPUT PARAMETERS:
  2524. !
  2525. !    None.
  2526. !
  2527. ! IMPLICIT INPUTS:
  2528. !
  2529. !    TERM_DESC - Descriptor of a vector of ASCII characters that represent
  2530. !    the name of the terminal to use.
  2531. !
  2532. ! OUTPUT PARAMETERS:
  2533. !
  2534. !    None.
  2535. !
  2536. ! IMPLICIT OUTPUTS:
  2537. !
  2538. !    TERM_CHAN - Channel number used by the terminal line to TERM_DESC.
  2539. !
  2540. ! COMPLETION CODES:
  2541. !
  2542. !    SS$_NORMAL or error condition.
  2543. !
  2544. ! SIDE EFFECTS:
  2545. !
  2546. !    None.
  2547. !
  2548. !--
  2549.  
  2550.     BEGIN
  2551.  
  2552.     EXTERNAL ROUTINE
  2553.     LOG_OPEN,                ! Open log file
  2554.     LOG_CLOSE;                ! Close log file
  2555.  
  2556.     LITERAL
  2557.     OUT_BUFLEN = 80,            ! Max # of char. in output buffer
  2558.     INP_BUFSIZ = 80,            ! Max # of char. in input buffer
  2559.     NUM_OUT_BUF = 2,            ! # of output buffers per device
  2560.     NUM_IN_BUF = 2,                ! # of input buffers per device
  2561.     MYT = 0,                ! Device MY_TERM
  2562.     TRM = 1,                ! Device TERM_NAME
  2563.     OFFSET = 1,                ! IOSB : offset to terminator
  2564.     EOFSIZ = 3,                ! IOSB : terminator size
  2565.     T_EFN_DISP = NUM_OUT_BUF,
  2566.     XITEFN = 2*NUM_OUT_BUF + 1,        ! Exit event flag number
  2567.     EFN_MASK = (1^XITEFN - 1) AND ( NOT 1);    ! Mask of flags set by CONNECT
  2568.  
  2569.     STRUCTURE
  2570.     IOSB_VECTOR [D, BUFNUM, INFO; NUMBUF] =
  2571.         [NUMBUF*16]
  2572.         (IOSB_VECTOR + (D*NUMBUF + BUFNUM)*8 + 2*INFO)<0, 16, 0>,
  2573.     BUFFER_VECTOR [D, BUFNUM; NUMBUF, BUFSIZ] =
  2574.         [NUMBUF*BUFSIZ*2 + NUMBUF]
  2575.         (BUFFER_VECTOR + (D*NUMBUF + BUFNUM)*BUFSIZ + D);
  2576.  
  2577.     OWN
  2578.     BTIMUP : VECTOR [4, WORD],        ! Time limit in binary format
  2579.     CHANNEL : VECTOR [2, LONG],        ! Contains channel #s
  2580.     CHR_COUNT : VECTOR [2, WORD] INITIAL (0),    ! # of char. in out buffer
  2581.     ESC_FLG : INITIAL (FALSE),        ! Was last char. the ESCAPE_CHR
  2582.     IN_IOSB : IOSB_VECTOR [NUM_IN_BUF],    ! IOSB status block
  2583.     INP_BUF : BUFFER_VECTOR [NUM_IN_BUF, INP_BUFSIZ],    ! Input buffers
  2584.     MSG : VECTOR [80, BYTE],        ! Combined escape message
  2585.     MSG_DES : BLOCK [8, BYTE],        ! Descriptor for message
  2586.     OUT_BUF : BUFFER_VECTOR [NUM_OUT_BUF, OUT_BUFLEN],    ! Output buffers
  2587.     OUT_BUFNUM : VECTOR [2, BYTE],        ! Present output buffer
  2588.     OUT_EFN : VECTOR [2, BYTE],        ! Present event flag #
  2589.     OUT_PTR : VECTOR [2, LONG],        ! CS-pointer for output buffer
  2590.     MYT_QIO_FUNC,                ! Function for QIO input for my terminal
  2591.     ESC_CHR_LEN,                ! Length of escape character message
  2592.     ESC_CHR_MSG : VECTOR [30, BYTE],    ! Escape character message
  2593.     STATE;                    ! Used by $READEF to store state of EFs
  2594.  
  2595.     BIND
  2596.     CON_MSG_1 = %ASCID'Connecting to ',
  2597.     CON_MSG_2 = %ASCID'.  Type ',
  2598.     CON_MSG_3 = %ASCID'C to return to VAX/VMS Kermit-32]',
  2599.     CON_MSG_4 = %ASCID'Returning to VAX/VMS Kermit-32]';
  2600.  
  2601.     MAP
  2602.     CON_MSG_1 : BLOCK [8, BYTE],
  2603.     CON_MSG_2 : BLOCK [8, BYTE],
  2604.     CON_MSG_3 : BLOCK [8, BYTE],
  2605.     CON_MSG_4 : BLOCK [8, BYTE];
  2606.  
  2607.     BIND
  2608.     ATIMUP = %ASCID'0 00:00:00.050',    ! Time to wait for more output
  2609.     MYT_CHAN = CHANNEL [1],
  2610.     MY_TERM = %ASCID'SYS$INPUT:';
  2611.  
  2612.     LABEL
  2613.     CONN_STREAMS;
  2614.  
  2615.     LOCAL
  2616.     CON_MSG : VECTOR [80, BYTE],
  2617.     CON_MSG_DESC : BLOCK [8, BYTE],
  2618.     STATUS;
  2619.  
  2620. %SBTTL 'TERM_CONNECT -- TYPE_OUT_BUF'
  2621.     ROUTINE TYPE_OUT_BUF (DEV) =
  2622.  
  2623. !++
  2624. !    This routine send the contents of the output buffer to the other
  2625. !    device.   It also resets the  OUT_PTR  and the CHR_COUNT  and it
  2626. !    increments  OUT_EFN  and  OUT_BUFNUM.
  2627. !--
  2628.  
  2629.     BEGIN
  2630.  
  2631.     LOCAL
  2632.         STATUS;
  2633.  
  2634. !                Check to make sure exit flag not set before $QIO
  2635.  
  2636.     IF (STATUS = $READEF (EFN = XITEFN, STATE = STATE)) NEQ SS$_WASCLR
  2637.     THEN
  2638.         BEGIN
  2639.         $SETEF (EFN = .OUT_EFN [.DEV]);
  2640.         RETURN .STATUS;
  2641.         END;
  2642.  
  2643.     $WAITFR (EFN = .OUT_EFN [.DEV]);
  2644.     $CLREF (EFN = .OUT_EFN [.DEV]);
  2645.  
  2646.     IF $READEF (EFN = XITEFN, STATE = STATE) EQL SS$_WASCLR
  2647.     THEN
  2648.         STATUS = $QIO (CHAN = .CHANNEL [.DEV], EFN = .OUT_EFN [.DEV],
  2649.         FUNC = IO$_WRITEVBLK OR IO$M_NOFORMAT, P1 = OUT_BUF [.DEV, .OUT_BUFNUM [.DEV]],
  2650.         P2 = .CHR_COUNT [.DEV])
  2651.     ELSE
  2652.         BEGIN
  2653.         $SETEF (EFN = .OUT_EFN [.DEV]);
  2654.         RETURN .STATUS;
  2655.         END;
  2656.  
  2657.     CHR_COUNT [.DEV] = 0;
  2658.     OUT_EFN [.DEV] = .OUT_EFN [.DEV] + 1;
  2659.  
  2660.     IF (OUT_BUFNUM [.DEV] = .OUT_BUFNUM [.DEV] + 1) GEQ NUM_OUT_BUF
  2661.     THEN
  2662.         BEGIN
  2663.         OUT_BUFNUM [.DEV] = 0;
  2664.         OUT_EFN [.DEV] = .DEV*T_EFN_DISP + 1;
  2665.         END;
  2666.  
  2667.     OUT_PTR [.DEV] = CH$PTR (OUT_BUF [.DEV, .OUT_BUFNUM [.DEV]]);
  2668.  
  2669.     IF NOT .STATUS
  2670.     THEN
  2671.         BEGIN
  2672.         LIB$SIGNAL (.STATUS);
  2673.         $SETEF (EFN = XITEFN);
  2674.         END;
  2675.  
  2676.     RETURN .STATUS;
  2677.     END;
  2678. %SBTTL 'TERM_CONNECT -- TIME_UP'
  2679.     ROUTINE TIME_UP (OUTEFN) : NOVALUE =
  2680.  
  2681. !++
  2682. !    AST routine called 0.1 second after first character is input.  It calls
  2683. !    TYPE_OUT_BUF to transmit output buffer.
  2684. !--
  2685.  
  2686.     BEGIN
  2687.  
  2688.     LOCAL
  2689.         DEV;
  2690.  
  2691.     IF (.OUTEFN - T_EFN_DISP) LEQ 0
  2692.     THEN
  2693.         DEV = 0                ! Device was MY_TERM
  2694.     ELSE
  2695.         DEV = 1;                ! Device was TERM_NAME
  2696.  
  2697.     TYPE_OUT_BUF (.DEV);
  2698.     END;                    ! End of TIME_UP
  2699. %SBTTL 'TERM_CONNECT -- STORE_INPUT'
  2700.     ROUTINE STORE_INPUT (DEV, INP_POINTER, NUM_CHR_IN) : NOVALUE =
  2701.  
  2702. !++
  2703. !    This routine stores the input buffer in the output buffer and keeps
  2704. !    track of the number of characters in the output buffer.  It also
  2705. !    calls TYPE_OUT_BUF when the output buffer is full and it sets up
  2706. !    the timer routine TIME_UP.
  2707. !--
  2708.  
  2709.     BEGIN
  2710.  
  2711.     EXTERNAL ROUTINE
  2712.         LOG_CHAR,                ! Routine to log characters
  2713.         GEN_PARITY;                ! Routine to generate parity
  2714.  
  2715.     LOCAL
  2716.         STATUS;
  2717.   
  2718.     IF (STATUS = $READEF (EFN = XITEFN, STATE = STATE)) NEQ SS$_WASCLR THEN RETURN;
  2719.  
  2720.     IF .NUM_CHR_IN EQL 0 THEN RETURN .STATUS;
  2721.  
  2722.     IF .NUM_CHR_IN + .CHR_COUNT [.DEV] GTR OUT_BUFLEN
  2723.     THEN
  2724.         BEGIN
  2725. !
  2726. ! If we don't have enough room in the buffer for all of the characters, call
  2727. ! ourself to dump what will fit, then proceed with what remains.
  2728. !
  2729.  
  2730.         LOCAL
  2731.         SAVED_CHR_CNT;            ! Saved character count
  2732.  
  2733.         SAVED_CHR_CNT = OUT_BUFLEN - .CHR_COUNT [.DEV];
  2734.         NUM_CHR_IN = .NUM_CHR_IN - .SAVED_CHR_CNT;
  2735.         STORE_INPUT (.DEV, .INP_POINTER, .SAVED_CHR_CNT);
  2736.         INP_POINTER = CH$PLUS (.INP_POINTER, .SAVED_CHR_CNT);
  2737.         END;
  2738.  
  2739.     IF .CHR_COUNT [.DEV] EQL 0
  2740.     THEN
  2741.         BEGIN
  2742.         STATUS = $SETIMR (DAYTIM = BTIMUP, ASTADR = TIME_UP, REQIDT = .OUT_EFN [.DEV]);
  2743.  
  2744.         IF NOT .STATUS
  2745.         THEN
  2746.         BEGIN
  2747.         LIB$SIGNAL (.STATUS);
  2748.         $SETEF (EFN = XITEFN);
  2749.         RETURN .STATUS;
  2750.         END;
  2751.  
  2752.         END;
  2753.  
  2754. ! We must generate parity for the communications terminal
  2755.  
  2756.     IF .DEV EQL 0
  2757.     THEN
  2758.         BEGIN
  2759.  
  2760.         LOCAL
  2761.         POINTER;
  2762.  
  2763.         POINTER = .INP_POINTER;
  2764.  
  2765.         DECR I FROM .NUM_CHR_IN TO 1 DO
  2766.         CH$WCHAR_A (GEN_PARITY (CH$RCHAR_A (POINTER)), OUT_PTR [.DEV]);
  2767.  
  2768.         END
  2769.     ELSE
  2770.         OUT_PTR [.DEV] = CH$MOVE (.NUM_CHR_IN, .INP_POINTER, .OUT_PTR [.DEV]);
  2771.  
  2772. !
  2773. ! If we want logging, do it now
  2774. !
  2775.  
  2776.     IF (.DEV EQL 1 OR .ECHO_FLAG) AND .SESSION_OPEN AND .SESSION_LOGGING
  2777.     THEN
  2778.         BEGIN
  2779.  
  2780.         LOCAL
  2781.         STATUS,
  2782.         POINTER;
  2783.  
  2784.         POINTER = .INP_POINTER;
  2785.  
  2786.         DECR I FROM .NUM_CHR_IN TO 1 DO
  2787.  
  2788.         IF NOT LOG_CHAR (CH$RCHAR_A (POINTER), SESSION_RAB)
  2789.         THEN
  2790.             BEGIN
  2791.             SESSION_LOGGING = FALSE;
  2792.             EXITLOOP;
  2793.             END;
  2794.  
  2795.         END;
  2796.  
  2797.     IF (CHR_COUNT [.DEV] = .CHR_COUNT [.DEV] + .NUM_CHR_IN) GEQ OUT_BUFLEN - INP_BUFSIZ
  2798.     THEN
  2799.         BEGIN
  2800.         $CANTIM (REQIDT = .OUT_EFN [.DEV]);
  2801.         TYPE_OUT_BUF (.DEV);
  2802.         END;
  2803.  
  2804.     RETURN .STATUS;
  2805.     END;                    ! End of STORE_INPUT
  2806. %SBTTL 'TERM_CONNECT -- MYTINP'
  2807.     ROUTINE MYTINP (INP_BUFNUM) =
  2808.  
  2809. !++
  2810. !    This AST routine gets characters from the channel MYT_CHAN and outputs
  2811. !    them on the channel TERM_CHAN.  It also checks to see  if  the  exit
  2812. !    characters have been typed.  If they have been typed, MYTINP sets the
  2813. !    event flag XITEFN.  INP_BUFNUM contains the # of the input buffer.
  2814. !--
  2815.  
  2816.     BEGIN
  2817.  
  2818.     OWN
  2819.         STATUS,
  2820.         NUM_CHR_IN;
  2821.  
  2822. %SBTTL 'TERM_CONNECT -- MYTINP -- CHK_FOR_EXIT'
  2823.     ROUTINE CHK_FOR_EXIT (INP_BUFNUM) =
  2824.  
  2825. !++
  2826. !    This routine checks to see if the exit characters have been typed.  It
  2827. !    returns TRUE if found and FALSE if not.  If only 1 ESCAPE_CHR found
  2828. !    then ESC_FLG is set to TRUE.
  2829. !--
  2830.  
  2831.         BEGIN
  2832.         ROUTINE TYPE_MSG (MSG_DESC, OPEN_FLAG, CLOSE_FLAG, CRLF_FLAG) : NOVALUE =
  2833.         BEGIN
  2834.  
  2835.         MAP
  2836.             MSG_DESC : REF BLOCK [8, BYTE];
  2837.  
  2838.         IF .OPEN_FLAG
  2839.         THEN
  2840.             BEGIN
  2841.             STORE_INPUT (TRM, CH$PTR (UPLIT BYTE(%C'[')), 1);
  2842.  
  2843.             IF .NODE_DESC [DSC$W_LENGTH] GTR 0
  2844.             THEN
  2845.             STORE_INPUT (TRM,
  2846.                 CH$PTR (.NODE_DESC [DSC$A_POINTER]), .NODE_DESC [DSC$W_LENGTH]);
  2847.  
  2848.             END;
  2849.  
  2850.         STORE_INPUT (TRM, CH$PTR (.MSG_DESC [DSC$A_POINTER]), .MSG_DESC [DSC$W_LENGTH]);
  2851.  
  2852.         IF .CLOSE_FLAG THEN STORE_INPUT (TRM, CH$PTR (UPLIT BYTE(%C']')), 1);
  2853.  
  2854.         IF .CRLF_FLAG THEN STORE_INPUT (TRM, CH$PTR (UPLIT BYTE(CHR_CRT, CHR_LFD)), 2);
  2855.  
  2856.         END;
  2857.  
  2858.         LOCAL
  2859.         EAT_CHR,            ! Number of input characters to eat
  2860.         ESC_PTR,
  2861.         INDEX : INITIAL (0),        ! Displacement of ESC from beginning of buffer
  2862.         PTR0;                ! Points to beginning of input buffer
  2863.  
  2864.         PTR0 = CH$PTR (INP_BUF [MYT, .INP_BUFNUM]);
  2865.  
  2866.         IF .ESC_FLG EQL TRUE        ! ESCAPE_CHR was previously typed.
  2867.         THEN
  2868.         BEGIN
  2869.         INDEX = 0;
  2870.         ESC_PTR = .PTR0;
  2871.         ESC_FLG = FALSE;
  2872.         END
  2873.         ELSE
  2874.  
  2875.         IF (ESC_PTR = CH$FIND_CH (.NUM_CHR_IN, .PTR0, .ESCAPE_CHR)) EQL 0
  2876.         THEN
  2877.             RETURN FALSE
  2878.         ELSE
  2879.             BEGIN
  2880.             INDEX = CH$DIFF (.PTR0, .ESC_PTR);
  2881.  
  2882.             IF .INDEX NEQ (NUM_CHR_IN = .NUM_CHR_IN - 1)
  2883.             THEN
  2884.             BEGIN
  2885.             CH$COPY (.NUM_CHR_IN - .INDEX, CH$PLUS (.ESC_PTR, 1), 0,
  2886.                 .NUM_CHR_IN - .INDEX, .ESC_PTR);
  2887.             END
  2888.             ELSE             ! ESCAPE_CHR was last character.
  2889.             BEGIN
  2890.             ESC_FLG = TRUE;
  2891.             RETURN FALSE;
  2892.             END;
  2893.  
  2894.             END;
  2895.  
  2896.         EAT_CHR = 0;            ! No characters to eat
  2897.  
  2898.         SELECTONE CH$RCHAR (.ESC_PTR) OF
  2899.         SET
  2900.  
  2901.         ['?'] :
  2902.             BEGIN
  2903.             TYPE_MSG (%ASCID'Escape commands are:', TRUE, FALSE, TRUE);
  2904.                     Type_Msg (%ASCID'    B - Sends a break', FALSE, FALSE, TRUE);
  2905.             TYPE_MSG (%ASCID'    C - Return to VAX/VMS Kermit-32', FALSE, FALSE, TRUE);
  2906.             TYPE_MSG (%ASCID'    Q - Suspend logging to session log file (if any)', FALSE,
  2907.             FALSE, TRUE);
  2908.             TYPE_MSG (%ASCID'    R - Resume logging to session log file (if any)', FALSE,
  2909.             FALSE, TRUE);
  2910.             TYPE_MSG (%ASCID'    S - Show status', FALSE, FALSE, TRUE);
  2911.             TYPE_MSG (%ASCID'    0 - Send a null', FALSE, FALSE, TRUE);
  2912.             TYPE_MSG (%ASCID'    ? - Type this text', FALSE, FALSE, TRUE);
  2913.             TYPE_MSG (%ASCID'    ', FALSE, FALSE, FALSE);
  2914.             STORE_INPUT (TRM, ESC_CHR_MSG, .ESC_CHR_LEN);
  2915.             TYPE_MSG (%ASCID' - Send escape character', FALSE, TRUE, TRUE);
  2916.             EAT_CHR = 1;
  2917.             END;
  2918.  
  2919.         ['B', 'b'] :
  2920.                     BEGIN
  2921.                     Send_Break_TTY_Flag = 1;
  2922.             EAT_CHR = 1;
  2923.                     END;
  2924.  
  2925.         ['C', 'c'] :
  2926.             BEGIN
  2927.             NUM_CHR_IN = .INDEX;
  2928.             RETURN TRUE;
  2929.             END;
  2930.  
  2931.         ['Q', 'q'] :
  2932.             BEGIN
  2933.  
  2934.             BIND
  2935.             NO_LOG_TEXT = %ASCID'logging already disabled',
  2936.             STOP_LOG_TEXT = %ASCID'logging disabled';
  2937.  
  2938.             IF .SESSION_LOGGING
  2939.             THEN
  2940.             TYPE_MSG (STOP_LOG_TEXT, TRUE, TRUE, TRUE)
  2941.             ELSE
  2942.             TYPE_MSG (NO_LOG_TEXT, TRUE, TRUE, TRUE);
  2943.  
  2944.             SESSION_LOGGING = FALSE;
  2945.             EAT_CHR = 1;
  2946.             END;
  2947.  
  2948.         ['R', 'r'] :
  2949.             BEGIN            ! Resume logging
  2950.  
  2951.             BIND
  2952.             NO_LOG_TEXT = %ASCID'no log file to enable',
  2953.             START_LOG_TEXT = %ASCID'logging enabled';
  2954.  
  2955.             SESSION_LOGGING = .SESSION_OPEN;
  2956.  
  2957.             IF .SESSION_LOGGING
  2958.             THEN
  2959.             TYPE_MSG (START_LOG_TEXT, TRUE, TRUE, TRUE)
  2960.             ELSE
  2961.             TYPE_MSG (NO_LOG_TEXT, TRUE, TRUE, TRUE);
  2962.  
  2963.             EAT_CHR = 1;
  2964.             END;
  2965.  
  2966.         ['S', 's'] :
  2967.             BEGIN
  2968.             TYPE_MSG (%ASCID'Connected to ', TRUE, FALSE, FALSE);
  2969.             TYPE_MSG (TERM_DESC, FALSE, FALSE, TRUE);
  2970.             TYPE_MSG (%ASCID'    Escape character: "', FALSE, FALSE, FALSE);
  2971.             STORE_INPUT (TRM, ESC_CHR_MSG, .ESC_CHR_LEN);
  2972.             TYPE_MSG (%ASCID'"', FALSE, FALSE, TRUE);
  2973.             TYPE_MSG (%ASCID'    Local echo: ', FALSE, FALSE, FALSE);
  2974.  
  2975.             IF .ECHO_FLAG
  2976.             THEN
  2977.             TYPE_MSG (%ASCID'On', FALSE, FALSE, TRUE)
  2978.             ELSE
  2979.             TYPE_MSG (%ASCID'Off', FALSE, FALSE, TRUE);
  2980.  
  2981.             TYPE_MSG (%ASCID'    Parity: ', FALSE, FALSE, FALSE);
  2982.  
  2983.             CASE .PARITY_TYPE FROM PR_MIN TO PR_MAX OF
  2984.             SET
  2985.  
  2986.             [PR_NONE] :
  2987.                 TYPE_MSG (%ASCID'None', FALSE, FALSE, TRUE);
  2988.  
  2989.             [PR_ODD] :
  2990.                 TYPE_MSG (%ASCID'Odd', FALSE, FALSE, TRUE);
  2991.  
  2992.             [PR_EVEN] :
  2993.                 TYPE_MSG (%ASCID'Even', FALSE, FALSE, TRUE);
  2994.  
  2995.             [PR_MARK] :
  2996.                 TYPE_MSG (%ASCID'Mark', FALSE, FALSE, TRUE);
  2997.  
  2998.             [PR_SPACE] :
  2999.                 TYPE_MSG (%ASCID'Space', FALSE, FALSE, TRUE);
  3000.             TES;
  3001.  
  3002.             TYPE_MSG (%ASCID'    Logging: ', FALSE, FALSE, FALSE);
  3003.  
  3004.             IF .SESSION_OPEN GTR 0
  3005.             THEN
  3006.             BEGIN
  3007.             TYPE_MSG (SESSION_DESC, FALSE, FALSE, FALSE);
  3008.  
  3009.             IF .SESSION_LOGGING
  3010.             THEN
  3011.                 TYPE_MSG (%ASCID' Enabled', FALSE, TRUE, TRUE)
  3012.             ELSE
  3013.                 TYPE_MSG (%ASCID' Disabled', FALSE, TRUE, TRUE);
  3014.  
  3015.             END
  3016.             ELSE
  3017.             TYPE_MSG (%ASCID' None specifed', FALSE, TRUE, TRUE);
  3018.  
  3019.             EAT_CHR = 1;        ! Eat the "S"
  3020.             END;
  3021.  
  3022.         [.ESCAPE_CHR] :
  3023.             CH$WCHAR (.ESCAPE_CHR, .ESC_PTR);    ! Write the escape character
  3024.  
  3025.         ['0'] :
  3026.             CH$WCHAR (CHR_NUL, .ESC_PTR);    ! Write a null
  3027.  
  3028.         [OTHERWISE] :
  3029.             BEGIN            ! Send a bell char. to MY_TERM
  3030.             STORE_INPUT (TRM, CH$PTR (UPLIT BYTE(CHR_BEL)), 1);
  3031.             EAT_CHR = 1;        ! Eat the character
  3032.             END;
  3033.         TES;
  3034.  
  3035.         IF .EAT_CHR GTR 0
  3036.         THEN
  3037.  
  3038.         IF (NUM_CHR_IN = .NUM_CHR_IN - .EAT_CHR) NEQ .INDEX
  3039.         THEN
  3040.             CH$COPY (.NUM_CHR_IN - .INDEX, CH$PLUS (.ESC_PTR, .EAT_CHR), CHR_NUL,
  3041.             .NUM_CHR_IN - .INDEX, .ESC_PTR);
  3042.  
  3043.         RETURN FALSE;
  3044.         END;                ! End of CHK_FOR_EXIT
  3045. %SBTTL 'TERM_CONNECT -- MYTINP'
  3046. ! Main portion of MYTINP
  3047.  
  3048.     IF (STATUS = $READEF (EFN = XITEFN, STATE = STATE)) NEQ SS$_WASCLR THEN RETURN .STATUS;
  3049.  
  3050.     NUM_CHR_IN = .IN_IOSB [MYT, .INP_BUFNUM, OFFSET] + .IN_IOSB [MYT, .INP_BUFNUM, EOFSIZ];
  3051.  
  3052.     IF .NUM_CHR_IN NEQ 0
  3053.     THEN
  3054.  
  3055.         IF CHK_FOR_EXIT (.INP_BUFNUM)
  3056.         THEN
  3057.         BEGIN
  3058.         $CANTIM ();
  3059.         $SETEF (EFN = XITEFN);        ! Exit characters typed.  Set flag.
  3060.         RETURN 1;
  3061.         END
  3062.         ELSE
  3063.         STORE_INPUT (MYT, CH$PTR (INP_BUF [MYT, .INP_BUFNUM]), .NUM_CHR_IN);
  3064.  
  3065.                         ! Store char.
  3066.  
  3067.     IF (STATUS = $READEF (EFN = XITEFN, STATE = STATE)) EQL SS$_WASCLR
  3068.     THEN
  3069. ! If we got some characters, then queue up the next read for lots of
  3070. ! characters with a 0 timeout (get what we can).  Otherwise queue up
  3071. ! a read for one character waiting forever.
  3072.  
  3073.         IF .NUM_CHR_IN GTR 0 OR .INP_BUFNUM NEQ 0
  3074.         THEN
  3075. ! Queue up a read for the console terminal
  3076.         STATUS = $QIO (CHAN = .MYT_CHAN, FUNC = .MYT_QIO_FUNC OR IO$M_TIMED,
  3077.             ASTADR = MYTINP, P1 = INP_BUF [MYT, .INP_BUFNUM], P2 = INP_BUFSIZ, P3 = 0,
  3078.             ASTPRM = .INP_BUFNUM, IOSB = IN_IOSB [MYT, .INP_BUFNUM, 0])
  3079.         ELSE
  3080.         STATUS = $QIO (CHAN = .MYT_CHAN, FUNC = .MYT_QIO_FUNC, ASTADR = MYTINP,
  3081.             P1 = INP_BUF [MYT, .INP_BUFNUM], P2 = 1, ASTPRM = .INP_BUFNUM,
  3082.             IOSB = IN_IOSB [MYT, .INP_BUFNUM, 0]);
  3083.  
  3084.     IF NOT .STATUS
  3085.     THEN
  3086.         BEGIN
  3087.         LIB$SIGNAL (.STATUS);
  3088.         $SETEF (EFN = XITEFN);
  3089.         END;
  3090.  
  3091.     RETURN .STATUS;
  3092.     END;                    ! End of MYTINP
  3093. %SBTTL 'TERM_CONNECT -- TRMINP'
  3094.     ROUTINE TRMINP (INP_BUFNUM) =
  3095.  
  3096. !++
  3097. !    This AST routine receives characters from the channel TERM_CHAN and
  3098. !    outputs the characters to the channel MYT_CHAN.  INP_BUFNUM contains
  3099. !    the number of the input buffer.
  3100. !--
  3101.  
  3102.     BEGIN
  3103.  
  3104.     LOCAL
  3105.         NUM_CHR_IN,
  3106.         STATUS;
  3107.  
  3108.     IF (STATUS = $READEF (EFN = XITEFN, STATE = STATE)) NEQ SS$_WASCLR THEN RETURN .STATUS;
  3109.  
  3110.     NUM_CHR_IN = .IN_IOSB [TRM, .INP_BUFNUM, OFFSET] + .IN_IOSB [TRM, .INP_BUFNUM, EOFSIZ];
  3111.  
  3112.     IF .NUM_CHR_IN NEQ 0
  3113.     THEN
  3114.         STORE_INPUT (TRM, CH$PTR (INP_BUF [TRM, .INP_BUFNUM]),
  3115.         .NUM_CHR_IN);
  3116.  
  3117.     IF (STATUS = $READEF (EFN = XITEFN, STATE = STATE)) EQL SS$_WASCLR
  3118.     THEN
  3119.             BEGIN
  3120.  
  3121. ! Now that there are no pending I/Os we can call the routine to send
  3122. ! a break signal to the outgoing terminal line if necessary.
  3123. ! Pending I/Os would block the QIO SETMODE instruction from taking
  3124. ! place, effectively hanging kermit until the current I/O read
  3125. ! completes (if ever).
  3126.  
  3127.             IF .Send_Break_TTY_Flag EQL 1
  3128.             THEN Send_Break_TTY ();
  3129.  
  3130. !
  3131. ! If we actually got something input, then queue up a read with a 0
  3132. ! timeout for the whole buffer.  Otherwise, queue up a single character
  3133. ! read, if this is the first buffer.
  3134. !
  3135.  
  3136.         IF .NUM_CHR_IN GTR 0 OR .INP_BUFNUM NEQ 0
  3137.         THEN
  3138.         STATUS = $QIO (CHAN = .TERM_CHAN,
  3139.             FUNC = IO$_TTYREADALL OR IO$M_NOECHO OR IO$M_TIMED, ASTADR = TRMINP,
  3140.             P1 = INP_BUF [TRM, .INP_BUFNUM], P2 = INP_BUFSIZ, P3 = 0,
  3141.             IOSB = IN_IOSB [TRM,
  3142.             .INP_BUFNUM, 0], ASTPRM = .INP_BUFNUM)
  3143.         ELSE
  3144.         STATUS = $QIO (CHAN = .TERM_CHAN, FUNC = IO$_TTYREADALL OR IO$M_NOECHO,
  3145.             ASTADR = TRMINP, P1 = INP_BUF [TRM, .INP_BUFNUM], P2 = 1,
  3146.             IOSB = IN_IOSB [TRM,
  3147.             .INP_BUFNUM, 0], ASTPRM = .INP_BUFNUM);
  3148.  
  3149.             END;
  3150.  
  3151.     IF NOT .STATUS
  3152.     THEN
  3153.         BEGIN
  3154.         LIB$SIGNAL (.STATUS);
  3155.         $SETEF (EFN = XITEFN);
  3156.         END;
  3157.  
  3158.     RETURN .STATUS;
  3159.     END;                    ! End of TRMINP
  3160. %SBTTL 'TERM_CONNECT -- ESC_MSG'
  3161.     ROUTINE ESC_MSG (ESC_TEXT) =
  3162.     BEGIN
  3163.  
  3164.     MAP
  3165.         ESC_TEXT : REF VECTOR [, BYTE];
  3166.  
  3167.     SELECTONE .ESCAPE_CHR OF
  3168.         SET
  3169.  
  3170.         [CHR_NUL, 0] :
  3171.         BEGIN
  3172.  
  3173.         BIND
  3174.             NUL_TXT = %ASCID'^@ or control-space on VT-100';
  3175.  
  3176.         MAP
  3177.             NUL_TXT : BLOCK [8, BYTE];
  3178.  
  3179.         CH$MOVE (.NUL_TXT [DSC$W_LENGTH], CH$PTR (.NUL_TXT [DSC$A_POINTER]),
  3180.             CH$PTR (.ESC_TEXT));
  3181.         RETURN .NUL_TXT [DSC$W_LENGTH];
  3182.         END;
  3183.  
  3184.         [CHR_RS, %O'36'] :
  3185.         BEGIN
  3186.  
  3187.         BIND
  3188.             RS_TXT = %ASCID'^^ or ^~ on VT-100';
  3189.  
  3190.         MAP
  3191.             RS_TXT : BLOCK [8, BYTE];
  3192.  
  3193.         CH$MOVE (.RS_TXT [DSC$W_LENGTH], CH$PTR (.RS_TXT [DSC$A_POINTER]),
  3194.             CH$PTR (.ESC_TEXT));
  3195.         RETURN .RS_TXT [DSC$W_LENGTH];
  3196.         END;
  3197.  
  3198.         [CHR_US, %O'37'] :
  3199.         BEGIN
  3200.  
  3201.         BIND
  3202.             US_TXT = %ASCID'^_ or ^? on VT-100';
  3203.  
  3204.         MAP
  3205.             US_TXT : BLOCK [8, BYTE];
  3206.  
  3207.         CH$MOVE (.US_TXT [DSC$W_LENGTH], CH$PTR (.US_TXT [DSC$A_POINTER]),
  3208.             CH$PTR (.ESC_TEXT));
  3209.         RETURN .US_TXT [DSC$W_LENGTH];
  3210.         END;
  3211.  
  3212.         [1 TO %O'37'] :
  3213.         BEGIN
  3214.         ESC_TEXT [0] = %C'^';
  3215.         ESC_TEXT [1] = .ESCAPE_CHR + %O'100';
  3216.         RETURN 2;
  3217.         END;
  3218.  
  3219.         [CHR_DEL, %O'177'] :
  3220.         BEGIN
  3221.         ESC_TEXT = 'DEL';
  3222.         RETURN 3;
  3223.         END;
  3224.         TES;
  3225.  
  3226.     RETURN 0;                ! No escape character?
  3227.     END;                    ! End of ESC_MSG
  3228. %SBTTL 'TERM_CONNECT -- COMND_TRANSMIT'
  3229.  
  3230. GLOBAL ROUTINE COMND_TRANSMIT : NOVALUE =       ! and below
  3231.  
  3232. !++
  3233. ! FUNCTIONAL DESCRIPTION:
  3234. !
  3235. !   This routine transmits a file (or files) to the remote side one character
  3236. !   at a time.  It can display the numbers of the lines as they are transfered,
  3237. !   or echo back to the controling terminal from the remote so that progress of
  3238. !   the transmit can be monitored.  It can also delay between 0 and .9 secs
  3239. !   after each carriage return for machines that cannot keep up with the
  3240. !   transfer.  The file is transmitted blindly (except line feeds are removed)
  3241. !   with no error correction or packets.  This is useful for sending files to
  3242. !   systems where KERMIT is unavailable.
  3243. !
  3244. ! CALLING SEQUENCE:
  3245. !
  3246. !   COMND_TRANSMIT ();
  3247. !
  3248. ! IMPLICIT INPUTS:
  3249. !
  3250. !   TRANS_DELAY - time (0.0 - 0.9 seconds) to delay after carriage return is transmitted.
  3251. !   TRANS_ECHO_FLAG - flags whether data from remote side is echoed to the console terminal (ON);
  3252. !                     or line numbers are printed during transmit.
  3253. !
  3254. ! IMPLICIT OUTPUTS:
  3255. !
  3256. !   None
  3257. !
  3258. ! COMPLETION_CODES:
  3259. !
  3260. !   Standard status values.
  3261. !
  3262. ! SIDE EFFECTS:
  3263. !
  3264. !   Line feed characters are not transmitted.
  3265. !--
  3266.  
  3267.     BEGIN
  3268.  
  3269.     EXTERNAL
  3270.     FILE_SIZE,
  3271.     FILE_NAME : VECTOR [CH$ALLOCATION (MAX_FILE_NAME)],
  3272.     TY_FIL;
  3273.  
  3274.     EXTERNAL ROUTINE
  3275.     FILE_OPEN;
  3276.  
  3277.     LOCAL
  3278.     STATUS,                                             ! KERMIT status values
  3279.     TRANSMIT_DELAY : VECTOR [CH$ALLOCATION(8)],    ! String for transmit delay
  3280.     TR_DESC :     BLOCK [8,BYTE];              ! Descriptor for transmit delay
  3281.  
  3282.     OWN
  3283.     SAVE_FILE_NAME : VECTOR [CH$ALLOCATION (MAX_FILE_NAME)],       ! File name
  3284.     SAVE_FILE_SIZE,                                                ! File size
  3285.     SAVE_TY_FIL,                                          ! File type out flag
  3286.     DELAY : VECTOR [2,LONG,SIGNED];  ! Time after transmitting carriage return
  3287.  
  3288.     BIND
  3289.     D_TIME = PLIT('0 ::00.');    ! First part of delta time used to find delay
  3290.  
  3291. %SBTTL 'TERM_CONNECT -- TRANSMIT_FILE'
  3292.  
  3293.     ROUTINE TRANSMIT_FILE =       ! and below
  3294.  
  3295.     !++
  3296.     ! FUNCTIONAL DESCRIPTION:
  3297.     !
  3298.     ! This routine transmits the current file (that has already been opened) and
  3299.     ! then opens the next file (if there is one).
  3300.     !
  3301.     !--
  3302.         BEGIN        ! TRANSMIT_FILE
  3303.  
  3304.         EXTERNAL
  3305.           ABT_ALL_FILE,
  3306.           ABT_CUR_FILE,
  3307.           SMG$_PASALREXI,                          ! Pasteboard exits for device msg
  3308.           FLAG_FILE_OPEN;
  3309.  
  3310.         EXTERNAL ROUTINE
  3311.           NEXT_FILE,
  3312.           FILE_OPEN,
  3313.           FILE_CLOSE,
  3314.           TT_TEXT,
  3315.           TT_CRLF : NOVALUE,
  3316.           SY_DISMISS : NOVALUE,
  3317.           SMG$CREATE_PASTEBOARD : ADDRESSING_MODE (GENERAL),
  3318.           SMG$DELETE_PASTEBOARD : ADDRESSING_MODE (GENERAL);
  3319.  
  3320.         LOCAL
  3321.           STATUS,                                             ! KERMIT status values
  3322.           ISTAT,                                                ! qiow status values
  3323.           PASTE_STAT,                                            ! SMG status values
  3324.           NEW_ID : VECTOR [1, LONG, UNSIGNED];             ! Dummy new pasteboard id
  3325.  
  3326.         OWN   
  3327.           LINE_NUM;                                            ! Line number counter
  3328.  
  3329. %SBTTL 'TERM_CONNECT -- TRANSMIT_CHARACTERS'
  3330.  
  3331.           ROUTINE TRANSMIT_CHARACTERS : NOVALUE =       ! and below
  3332.  
  3333.       !++
  3334.       ! FUNCTIONAL DESCRIPTION:
  3335.       !
  3336.           ! This routine is a loop that transmits all of the characters in a file,
  3337.           ! one character per pass.
  3338.           !
  3339.           !--
  3340.           BEGIN        ! TRANSMIT_CHARACTERS
  3341.   
  3342.           LITERAL
  3343.             WAIT_EFN = 22,
  3344.             CHARACTER_LEN = 1;
  3345.  
  3346.           EXTERNAL ROUTINE
  3347.             GET_FILE,
  3348.             TT_NUMBER,
  3349.             TT_OUTPUT : NOVALUE;
  3350.  
  3351.           LOCAL
  3352.             STATUS,                                             ! KERMIT status values
  3353.             TSTAT,                                               ! timer status values
  3354.             ISTAT,                                                ! qiow status values
  3355.             CHARACTER,                             ! Character from get-a-char routine
  3356.             TERM_IOSB : VECTOR [4, WORD, UNSIGNED];    ! IO status block for term chan
  3357. !
  3358. ! Begin TRANSMIT_CHARACTERS:
  3359. !
  3360.           DO
  3361.  
  3362.             BEGIN        ! Transmit a character
  3363. ! Get next character
  3364.             STATUS = GET_FILE (CHARACTER);                  
  3365.  
  3366.             IF .STATUS AND NOT .STATUS EQL KER_EOF AND NOT .CHARACTER EQL CHR_LFD         ! Did we get one?
  3367.             THEN
  3368.  
  3369.               BEGIN        ! Have a character
  3370. ! Write character out transfer terminal:
  3371.                 ISTAT = $QIOW (CHAN = .TERM_CHAN, EFN = TERM_O_EFN,
  3372.                   FUNC = IO$_WRITEVBLK + IO$M_NOFORMAT,
  3373.                   IOSB = TERM_IOSB,
  3374.                   P1 = CHARACTER, P2 = CHARACTER_LEN);
  3375.                 IF NOT .ISTAT THEN LIB$SIGNAL (.ISTAT);
  3376.                 IF NOT .TERM_IOSB THEN LIB$SIGNAL (.TERM_IOSB);
  3377.                 IF .CHARACTER EQL CHR_CRT 
  3378.                 THEN
  3379.                   BEGIN        ! Just transmitted a carriage return
  3380.  
  3381.                     IF NOT .DELAY EQL 0
  3382.                     THEN 
  3383. ! Delay desired time:
  3384.                       BEGIN
  3385.                         TSTAT = $SETIMR (EFN = WAIT_EFN, DAYTIM = DELAY);
  3386.                         IF NOT .STATUS THEN LIB$SIGNAL (.TSTAT);
  3387.                         TSTAT = $WAITFR (EFN = WAIT_EFN);
  3388.                         IF NOT .STATUS THEN LIB$SIGNAL (.TSTAT);
  3389.                       END;
  3390.  
  3391.                     IF NOT .TRANS_ECHO_FLAG
  3392.                     THEN
  3393. ! Purge term_chan typeahead buffer to get rid of the echoed data and type packet number to console:
  3394.                       BEGIN
  3395.                         TSTAT = $QIOW (CHAN = .TERM_CHAN, FUNC = IO$_READVBLK OR IO$M_PURGE,
  3396.                           P1 = INP_BUF [TRM, 0], P2 = 0, IOSB = IN_IOSB [TRM, 0, 0]);
  3397.                         IF NOT .TSTAT THEN LIB$SIGNAL (.TSTAT);
  3398.                         TT_NUMBER (.LINE_NUM);
  3399.                         TT_TEXT (UPLIT (%ASCIZ' '));
  3400.                         TT_OUTPUT ();
  3401.                         LINE_NUM = .LINE_NUM + 1;
  3402.                       END;
  3403.  
  3404.                   END;        ! Just transmitted a cariage return
  3405.  
  3406.               END;        ! Have a character
  3407.  
  3408.             END            ! Transmit a character
  3409.               UNTIL NOT .STATUS OR .STATUS EQL KER_EOF OR NOT .ISTAT OR NOT .TERM_IOSB
  3410.                     OR .FORCE_ABORT OR .ABT_CUR_FILE OR .ABT_ALL_FILE;
  3411.  
  3412.       END;        ! End TRANSMIT_CHARACTERS 
  3413. !
  3414. ! Begin TRANSMIT_FILE: 
  3415. !
  3416.         FLAG_FILE_OPEN = TRUE;
  3417.         TT_TEXT (UPLIT (%ASCIZ'    File: '));
  3418.         TT_TEXT (FILE_NAME);                                ! Type out file name
  3419.         TT_CRLF ();
  3420.         FILE_SIZE = .SAVE_FILE_SIZE;                  ! Reset the file name size
  3421.         INCR I FROM 0 TO .FILE_SIZE - 1 DO
  3422.             FILE_NAME [.I] = .SAVE_FILE_NAME [.I];
  3423.         TY_FIL = .SAVE_TY_FIL;                             ! Reset type out flag
  3424.         LINE_NUM = 1;                           ! Initialize line number counter
  3425.  
  3426.         IF (STATUS = TERM_OPEN (TRUE))                       ! Open the terminal
  3427.         THEN
  3428.  
  3429.           BEGIN        ! Term open
  3430. ! Cancel qio's to term_chan to start from scratch:
  3431.           STATUS = $CANCEL (CHAN = .TERM_CHAN);
  3432.           IF NOT .STATUS THEN LIB$SIGNAL (.STATUS);
  3433.  
  3434. ! Test to see if we are supposed to echo from the term_chan to the cons_chan:
  3435.           IF .TRANS_ECHO_FLAG
  3436.           THEN
  3437.  
  3438.             BEGIN    ! Echo data
  3439. ! Clear screen (by creating a default pasteboard using SMG utility):
  3440.               SY_DISMISS (3);             ! Wait a bit so user can see file name
  3441.               PASTE_STAT = SMG$CREATE_PASTEBOARD (NEW_ID);
  3442.               IF NOT .PASTE_STAT THEN LIB$SIGNAL (.PASTE_STAT);
  3443.  
  3444. ! Prepare event flags
  3445.               $CLREF (EFN = XITEFN);
  3446.               INCR FLAG FROM 1 TO XITEFN - 1 DO
  3447.                 $SETEF (EFN = .FLAG);
  3448.               $SETAST (ENBFLG = 0);               ! Disable AST until after all QIOs
  3449.  
  3450. ! Set up read qio's to echo characters to controling terminal
  3451.               ISTAT = $QIO (CHAN = .TERM_CHAN, FUNC = IO$_TTYREADALL OR IO$M_NOECHO,
  3452.                 ASTADR = TRMINP, P1 = INP_BUF [TRM, 0], P2 = INP_BUFSIZ, P3 = 0,
  3453.                 IOSB = IN_IOSB [TRM, 0, 0], ASTPRM = 0);
  3454.               IF NOT .ISTAT THEN LIB$SIGNAL (.ISTAT);
  3455.               INCR INP_BUFNUM FROM 1 TO NUM_IN_BUF - 1 DO
  3456.                 BEGIN
  3457.                   ISTAT = $QIO (CHAN = .TERM_CHAN, FUNC = IO$_TTYREADALL OR
  3458.                     IO$M_NOECHO OR IO$M_TIMED, ASTADR=TRMINP,
  3459.                     P1=INP_BUF[TRM,.INP_BUFNUM], P2=INP_BUFSIZ, P3=0,
  3460.                     IOSB = IN_IOSB [TRM, .INP_BUFNUM, 0], ASTPRM = .INP_BUFNUM);
  3461.                   IF NOT .ISTAT THEN LIB$SIGNAL (.ISTAT);
  3462.                 END;
  3463.               $SETAST (ENBFLG = 1);                                     ! Enable AST
  3464.             END      ! End echo data  
  3465.  
  3466.           ELSE         ! No echo; output line number title to console:
  3467.  
  3468.               TT_TEXT (UPLIT (%ASCIZ'    Transmitting line number... '));
  3469.  
  3470. ! Start a loop that handles one character per pass:
  3471.           TRANSMIT_CHARACTERS ();
  3472.  
  3473. ! Finished transmitting file - close it:
  3474.           FILE_CLOSE ();
  3475.           ABT_CUR_FILE = FALSE;
  3476.           IF .TRANS_ECHO_FLAG THEN SY_DISMISS (1);      ! Wait a bit so user can see the end of the file
  3477.  
  3478. ! Cancel read qio's:
  3479.           $SETAST (ENBFLG = 0);                                  ! Disable AST's
  3480.           STATUS = $CANCEL (CHAN = .TERM_CHAN);
  3481.           IF NOT .STATUS THEN LIB$SIGNAL (.STATUS);
  3482.           STATUS = $CANCEL (CHAN = .CONS_CHAN);
  3483.           IF NOT .STATUS THEN LIB$SIGNAL (.STATUS);
  3484.  
  3485. ! Clear screen again if we did it before - ie delete pasteboard if we created one:
  3486.           IF .TRANS_ECHO_FLAG AND NOT .PASTE_STAT EQL SMG$_PASALREXI 
  3487.           THEN
  3488.             BEGIN
  3489.             PASTE_STAT = SMG$DELETE_PASTEBOARD (NEW_ID);
  3490.             IF NOT .PASTE_STAT THEN LIB$SIGNAL (.PASTE_STAT);
  3491.             END
  3492.           ELSE
  3493.             BEGIN
  3494.             TT_CRLF ();
  3495.             TT_CRLF ();
  3496.             END;
  3497.  
  3498. ! Post normal qio's that were canceled:
  3499.           STATUS = DO_CONS_QIO();
  3500.           IF NOT .STATUS
  3501.           THEN
  3502.             BEGIN
  3503.             LIB$SIGNAL (.STATUS);
  3504.             RETURN KER_RECERR
  3505.             END;
  3506.  
  3507.           STATUS = DO_RECEIVE_QIO();
  3508.           IF NOT .STATUS
  3509.           THEN
  3510.             BEGIN
  3511.             LIB$SIGNAL (.STATUS);
  3512.             RETURN KER_RECERR
  3513.             END;
  3514.  
  3515. ! Close the console terminal to clean up:
  3516.           STATUS = TERM_CLOSE ();
  3517.           IF NOT .STATUS THEN LIB$SIGNAL (.STATUS);
  3518.           $SETAST (ENBFLG = 1);                                   ! Enable AST's
  3519.           END;        ! Term open
  3520.  
  3521. ! Determine if there is another file to send.
  3522.         SAVE_TY_FIL = .TY_FIL;                        ! Save current type out flag
  3523.         TY_FIL = FALSE;                            ! Supress the type out of names
  3524.         IF NOT .ABT_ALL_FILE AND NOT .FORCE_ABORT THEN STATUS=NEXT_FILE () ELSE STATUS=KER_NOMORFILES;
  3525.         TY_FIL = .SAVE_TY_FIL;                           ! Reset the type out flag
  3526.         ABT_ALL_FILE = FALSE;
  3527.         FORCE_ABORT = FALSE;
  3528.         FORCE_TIMEOUT = FALSE;
  3529.     RETURN .STATUS;
  3530.  
  3531.         END;          ! End TRANSMIT_FILE
  3532.  
  3533. !
  3534. ! Begin COMND_TRANSMIT:
  3535. !
  3536. ! Initialize variables
  3537.     CHR_COUNT [0] = 0;
  3538.     CHR_COUNT [1] = 0;
  3539.     OUT_BUFNUM [0] = 0;
  3540.     OUT_BUFNUM [1] = 0;
  3541.     OUT_EFN [0] = 1;
  3542.     OUT_EFN [1] = T_EFN_DISP + 1;
  3543.     OUT_PTR [0] = CH$PTR (OUT_BUF [0, .OUT_BUFNUM [0]]);
  3544.     OUT_PTR [1] = CH$PTR (OUT_BUF [1, .OUT_BUFNUM [1]]);
  3545.  
  3546. ! Assign channels to devices TERM_NAME and MY_TERM.
  3547.     STATUS = TERM_OPEN (FALSE);            ! Open terminal, no QIO's
  3548.  
  3549.     IF .CONNECT_FLAG                ! Check if TERM_NAME is TT:
  3550.     THEN
  3551.     BEGIN
  3552.     TERM_CLOSE ();
  3553.     LIB$SIGNAL (KER_CON_SAME);
  3554.     RETURN KER_CON_SAME;
  3555.     END;
  3556.  
  3557.     IF NOT .STATUS
  3558.     THEN
  3559.     BEGIN
  3560.     LIB$SIGNAL (.STATUS);
  3561.     RETURN .STATUS;
  3562.     END;
  3563.  
  3564.     IF NOT .SYS_OUTPUT_OPEN            ! Make sure we have terminals
  3565.     THEN
  3566.     BEGIN
  3567.     TERM_CLOSE ();
  3568.     LIB$SIGNAL (KER_LINTERM);        ! Must both be terminals
  3569.     RETURN KER_LINTERM;            ! So give up if not
  3570.     END;
  3571.  
  3572.     CHANNEL [0] = .TERM_CHAN;
  3573.     CHANNEL [1] = .CONS_CHAN;
  3574.  
  3575.     IF NOT .STATUS
  3576.     THEN
  3577.     BEGIN
  3578.     TERM_CLOSE ();
  3579.     LIB$SIGNAL (.STATUS);
  3580.     RETURN .STATUS;
  3581.     END;
  3582.  
  3583. ! Have two terminals - Set up delay:
  3584.     CH$COPY (7,CH$PTR(D_TIME),  1,CH$PTR(TRANS_DELAY), %C ' ', 8,CH$PTR(TRANSMIT_DELAY));
  3585.     TR_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  3586.     TR_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  3587.     TR_DESC [DSC$W_LENGTH] = 8;
  3588.     TR_DESC [DSC$A_POINTER] = TRANSMIT_DELAY;
  3589.     STATUS = $BINTIM (TIMBUF=TR_DESC, TIMADR=DELAY);  ! Calculate delta time
  3590.     IF NOT .STATUS THEN LIB$SIGNAL (.STATUS);
  3591.  
  3592. ! Get the first file and try to open it:
  3593.     SAVE_TY_FIL = .TY_FIL;                          ! Save current type out flag
  3594.     TY_FIL = FALSE;                              ! Supress the type out of names
  3595.     SAVE_FILE_SIZE = .FILE_SIZE;                       ! Save the file name size
  3596.     INCR I FROM 0 TO .FILE_SIZE - 1 DO
  3597.         SAVE_FILE_NAME [.I] = .FILE_NAME [.I];
  3598.  
  3599. ! If we can open the file, then transmit it:
  3600.     IF FILE_OPEN (FNC_READ)
  3601.     THEN        ! Loop to handle one file at a time:
  3602.       DO
  3603.         STATUS = TRANSMIT_FILE ()
  3604.       UNTIL ( NOT .STATUS) OR (.STATUS EQL KER_NOMORFILES)
  3605.     ELSE
  3606.         TY_FIL = .SAVE_TY_FIL;                             ! Reset type out flag
  3607.  
  3608.   END;                  ! End COMND_TRANSMIT routine
  3609. %SBTTL 'TERM_CONNECT -- INITIALIZATION'
  3610. ! Initialize variables
  3611.     CHR_COUNT [0] = 0;
  3612.     CHR_COUNT [1] = 0;
  3613.     ESC_FLG = FALSE;
  3614.     OUT_BUFNUM [0] = 0;
  3615.     OUT_BUFNUM [1] = 0;
  3616.     OUT_EFN [0] = 1;
  3617.     OUT_EFN [1] = T_EFN_DISP + 1;
  3618.     OUT_PTR [0] = CH$PTR (OUT_BUF [0, .OUT_BUFNUM [0]]);
  3619.     OUT_PTR [1] = CH$PTR (OUT_BUF [1, .OUT_BUFNUM [1]]);
  3620.     $BINTIM (TIMBUF = ATIMUP, TIMADR = BTIMUP);
  3621. !
  3622. ! Initialize Connect message
  3623. !
  3624.     ESC_CHR_LEN = ESC_MSG (ESC_CHR_MSG);
  3625.     CON_MSG_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  3626.     CON_MSG_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  3627.     CON_MSG_DESC [DSC$A_POINTER] = CON_MSG;
  3628.     CON_MSG_DESC [DSC$W_LENGTH] = 1 + .NODE_DESC [DSC$W_LENGTH] + .CON_MSG_1 [DSC$W_LENGTH] +
  3629.     .TERM_DESC [DSC$W_LENGTH] + .CON_MSG_2 [DSC$W_LENGTH] + .ESC_CHR_LEN + .CON_MSG_3 [DSC$W_LENGTH]
  3630.     ;
  3631.     CH$COPY (1, CH$PTR (UPLIT BYTE(%C'[')), .NODE_DESC [DSC$W_LENGTH],
  3632.     CH$PTR (.NODE_DESC [DSC$A_POINTER]), .CON_MSG_1 [DSC$W_LENGTH],
  3633.     CH$PTR (.CON_MSG_1 [DSC$A_POINTER]), .TERM_DESC [DSC$W_LENGTH],
  3634.     CH$PTR (.TERM_DESC [DSC$A_POINTER]), .CON_MSG_2 [DSC$W_LENGTH],
  3635.     CH$PTR (.CON_MSG_2 [DSC$A_POINTER]), .ESC_CHR_LEN, CH$PTR (ESC_CHR_MSG),
  3636.     .CON_MSG_3 [DSC$W_LENGTH], CH$PTR (.CON_MSG_3 [DSC$A_POINTER]), CHR_NUL,
  3637.     .CON_MSG_DESC [DSC$W_LENGTH], CH$PTR (CON_MSG));
  3638. !
  3639. ! Assign channels to devices TERM_NAME and MY_TERM.
  3640. !
  3641.     STATUS = TERM_OPEN (FALSE);            ![054] Open terminal, no QIO's
  3642.  
  3643.     IF .CONNECT_FLAG                ! Check if TERM_NAME is TT:
  3644.     THEN
  3645.     BEGIN
  3646.     TERM_CLOSE ();
  3647.     LIB$SIGNAL (KER_CON_SAME);
  3648.     RETURN KER_CON_SAME;
  3649.     END;
  3650.  
  3651.     IF NOT .STATUS
  3652.     THEN
  3653.     BEGIN
  3654.     LIB$SIGNAL (.STATUS);
  3655.     RETURN .STATUS;
  3656.     END;
  3657.  
  3658.     IF NOT .SYS_OUTPUT_OPEN            ![013] Make sure we have terminals
  3659.     THEN
  3660.     BEGIN
  3661.     TERM_CLOSE ();
  3662.     LIB$SIGNAL (KER_LINTERM);        ![013] Must both be terminals
  3663.     RETURN KER_LINTERM;            ![013] So give up if not
  3664.     END;
  3665.  
  3666. ![054]    STATUS = $CANCEL (CHAN = .TERM_CHAN);    ! Kill all pending QIOs for terminal
  3667.     CHANNEL [0] = .TERM_CHAN;
  3668.     CHANNEL [1] = .CONS_CHAN;
  3669. ![054]    STATUS = $CANCEL (CHAN = .CONS_CHAN);    ! Kill pending QIOs for console as well
  3670. !    STATUS = $ASSIGN (DEVNAM = MY_TERM, CHAN = MYT_CHAN);
  3671.  
  3672.     IF NOT .STATUS
  3673.     THEN
  3674.     BEGIN
  3675.     TERM_CLOSE ();
  3676.     LIB$SIGNAL (.STATUS);
  3677.     RETURN .STATUS;
  3678.     END;
  3679.  
  3680. !
  3681. ! Open any session logging file
  3682. !
  3683.     SESSION_OPEN = FALSE;            ! Assume not logging
  3684.     SESSION_LOGGING = FALSE;            !  .  .  .
  3685.  
  3686.     IF .SESSION_DESC [DSC$W_LENGTH] GTR 0
  3687.     THEN
  3688.     BEGIN
  3689.     STATUS = LOG_OPEN (SESSION_DESC, SESSION_FAB, SESSION_RAB);
  3690.  
  3691.     IF .STATUS
  3692.     THEN
  3693.         BEGIN
  3694.         SESSION_OPEN = TRUE;
  3695.         SESSION_LOGGING = TRUE;
  3696.         END;
  3697.  
  3698.     END;
  3699.  
  3700. ! Prepare event flags
  3701.     $CLREF (EFN = XITEFN);
  3702.  
  3703.     INCR FLAG FROM 1 TO XITEFN - 1 DO
  3704.     $SETEF (EFN = .FLAG);
  3705.  
  3706. !
  3707. ! Set up proper function for reading from console terminal.  This is done
  3708. ! so that the NOECHO flag only gets used if LOCAL_ECHO is OFF.
  3709. !
  3710.     MYT_QIO_FUNC = IO$_TTYREADALL;
  3711.  
  3712.     IF NOT .ECHO_FLAG THEN MYT_QIO_FUNC = IO$M_NOECHO OR IO$_TTYREADALL;
  3713.  
  3714. ! Connect streams
  3715. CONN_STREAMS :
  3716.     BEGIN
  3717. !                     Send connect message
  3718.     LIB$PUT_OUTPUT (%ASCID'');
  3719.     LIB$PUT_OUTPUT (CON_MSG_DESC);
  3720.     LIB$PUT_OUTPUT (%ASCID'');
  3721.     $SETAST (ENBFLG = 0);            ! Disable AST until after all QIOs
  3722. !
  3723. ! The first input for each terminal will be for one character.
  3724. ! This read will wait forever for a character.  The subsequent
  3725. ! reads will have a timeout of 0 (immediate return).  This
  3726. ! gets us good response without using large amounts of run time.
  3727. !
  3728.     STATUS = $QIO (CHAN = .MYT_CHAN, FUNC = .MYT_QIO_FUNC, ASTADR = MYTINP, P1 = INP_BUF [MYT, 0],
  3729.     P2 = 1, IOSB = IN_IOSB [MYT, 0, 0], ASTPRM = 0);
  3730.  
  3731.     IF NOT .STATUS THEN LEAVE CONN_STREAMS;
  3732.  
  3733.     STATUS = $QIO (CHAN = .TERM_CHAN, FUNC = IO$_TTYREADALL OR IO$M_NOECHO, ASTADR = TRMINP,
  3734.     P1 = INP_BUF [TRM, 0], P2 = INP_BUFSIZ, P3 = 0, IOSB = IN_IOSB [TRM, 0, 0], ASTPRM = 0);
  3735.  
  3736.     IF NOT .STATUS THEN LEAVE CONN_STREAMS;
  3737.  
  3738.     INCR INP_BUFNUM FROM 1 TO NUM_IN_BUF - 1 DO
  3739.     BEGIN
  3740. ! Queue up an input for console terminal
  3741.     STATUS = $QIO (CHAN = .MYT_CHAN, FUNC = .MYT_QIO_FUNC OR IO$M_TIMED, ASTADR = MYTINP,
  3742.         P1 = INP_BUF [MYT, .INP_BUFNUM], P2 = INP_BUFSIZ, P3 = 0,
  3743.         IOSB = IN_IOSB [MYT,
  3744.         .INP_BUFNUM, 0], ASTPRM = .INP_BUFNUM);
  3745.  
  3746.     IF NOT .STATUS THEN LEAVE CONN_STREAMS;
  3747.  
  3748.     STATUS = $QIO (CHAN = .TERM_CHAN, FUNC = IO$_TTYREADALL OR IO$M_NOECHO OR IO$M_TIMED,
  3749.         ASTADR = TRMINP, P1 = INP_BUF [TRM, .INP_BUFNUM], P2 = INP_BUFSIZ, P3 = 0,
  3750.         IOSB = IN_IOSB [TRM, .INP_BUFNUM, 0], ASTPRM = .INP_BUFNUM);
  3751.  
  3752.     IF NOT .STATUS THEN LEAVE CONN_STREAMS;
  3753.  
  3754.     END;
  3755.  
  3756.     $SETAST (ENBFLG = 1);            ! Enable AST
  3757.     $WAITFR (EFN = XITEFN);            ! Wait for exit flag
  3758.     $WFLAND (EFN = 0, MASK = EFN_MASK);        ! Go when outputs completed
  3759.     CON_MSG_DESC [DSC$W_LENGTH] = 1 + .NODE_DESC [DSC$W_LENGTH] + .CON_MSG_4 [DSC$W_LENGTH];
  3760.     CH$COPY (1, CH$PTR (UPLIT BYTE(%C'[')), .NODE_DESC [DSC$W_LENGTH],
  3761.     CH$PTR (.NODE_DESC [DSC$A_POINTER]), .CON_MSG_4 [DSC$W_LENGTH],
  3762.     CH$PTR (.CON_MSG_4 [DSC$A_POINTER]), CHR_NUL, .CON_MSG_DESC [DSC$W_LENGTH],
  3763.     CH$PTR (.CON_MSG_DESC [DSC$A_POINTER]));
  3764.     LIB$PUT_OUTPUT (CON_MSG_DESC);
  3765.     LIB$PUT_OUTPUT (%ASCID'');
  3766.     END;
  3767. !
  3768. ! Program end -- Close both channels and return with STATUS
  3769. !
  3770.     $CANTIM ();
  3771. !
  3772. ! Close any log file
  3773. !
  3774.  
  3775.     IF .SESSION_OPEN THEN LOG_CLOSE (SESSION_FAB, SESSION_RAB);
  3776.  
  3777.     SESSION_OPEN = FALSE;
  3778. !
  3779. ! Call TERM_CLOSE to clean up
  3780. !
  3781.     STATUS = TERM_CLOSE ();
  3782.  
  3783.     IF NOT .STATUS THEN LIB$SIGNAL (.STATUS);
  3784.  
  3785.     $SETAST (ENBFLG = 1);
  3786.     RETURN .STATUS;
  3787.     END;                    ! End of TERM_CONNECT
  3788.  
  3789. %SBTTL 'End of KERTRM'
  3790. END                        ! End of module
  3791.  
  3792. ELUDOM
  3793.