.TITLE OSIT$CMD_SOURCE Read a command and execute it remotely
.IDENT /X-2/
;
;****************************************************************************
;* *
;* COPYRIGHT (c) 1987, 1988, 1991 BY *
;* DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS. *
;* ALL RIGHTS RESERVED. *
;* *
;* THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED *
;* ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE *
;* INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER *
;* COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY *
;* OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY *
;* TRANSFERRED. *
;* *
;* THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE *
;* AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT *
;* CORPORATION. *
;* *
;* DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS *
;* SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. *
;* *
;* *
;****************************************************************************
;
;++
; FACILITY: VOTS example program to communicates with another example
; program called OSIT$CMD_EXECUTOR.
;
; FUNCTIONAL DESCRIPTION:
;
; Demonstrate task-to-task communication in MACRO. Read a command on the
; local system and send the command to the remote task, OSIT$CMD_EXECUTOR.EXE,
; which executes the command and sends the output back to this task.
;
; ENVIRONMENT: user mode
;
; AUTHOR: S.T. CREATION-DATE: December 8, 1987
;
; MODIFIED BY:
;
; X-2 PEY0000 Paul Yager 12-Apr-1994
; Initial port to Alpha, correct OSIT$CMD_EXECUTOR NCL example.
;
; REQUIRED FILES:
;
; osit$cmd_source.mar Gets a command from the user
; osit$cmd_executor.com Runs osit$cmd_executor.exe
; It also contains hints about using DEBUG.
; osit$cmd_executor.mar Receives the command and executes it.
; It runs on the target node (also called the
; executor node.)
; osit$cmd_source.cld Defines the command to run osit$cmd_source
;
; HOW TO ASSEMBLE AND LINK
;
; macro/list=osit$cmd_source/object=osit$cmd_source -
; sys$library:osit+
osit$cmd_source
;
; For '' substitute the directory to which you have copied
; the files
;
; link osit$cmd_source
;
; IMPORTANT INFORMATION:
;
; In order for osit$cmd_executor to run, you must create an APPLICATION
; named OSIT$CMD_EXECUTOR on the TARGET node.
;
; Example NCL commands to do this are:
;
; SET NCL DEFAULT ENTITY NODE 0 OSI TRANSPORT APPLICATION OSIT$CMD_EXECUTOR
; CREATE
; SET FILE NAME USER$DISK:[SOMEONE]OSIT$CMD_EXECUTOR.COM
; SET CALLED TSEL {%X4F53495424434D445F4558454355544F52}
; SET USER NAME "SOMEONE"
;
;
; HOW TO RUN OSIT$CMD_SOURCE:
;
; $set command osit$cmd_source ! assumes the files are in sys$login
;
; $execute_on
;
; where is the VOTS Address of the target node.
;
; Example:
;
; $execute_on x25_pss%234934567765
;
; OSIT$CMD_SOURCE, waiting for OSIT$CMD_EXECUTOR to accept the connection
;
; Enter a command (or CTRL/Z to exit): SHOW TIME
; 22-DEC-1987 16:27:09
; Enter a command (or CTRL/Z to exit): ! CTRL/Z exit
; $
;--
.SUBTITLE DECLARATIONS
;+
; Include system macros for definition
;-
$DSCDEF ; Descriptor definitions
$IODEF ; I/O function codes
$RMSDEF ; RMS status values
$SSDEF ; System status values
;+
; Include VOTS macros
;-
$osit$constants
$osit$itemdef
;+
; MACROS:
;-
;
; Macro to push the arguments in reverse order and call
; the library routine cli$get_value
;
.MACRO CLI_GET_VALUE QUALIFIER_DSC QUALVAL_DSC
PUSHAW QUALVAL_DSC + DSC$W_LENGTH
PUSHAQ QUALVAL_DSC
PUSHAQ QUALIFIER_DSC
CALLS #3,G^CLI$GET_VALUE
.ENDM CLI_GET_VALUE
;
; Macro to push the arguments in reverse order and call
; the library routine lib$get_input
;
.MACRO LIB_GET_INPUT CMD_DSC PROMPT_DSC CMD_LEN
PUSHAW CMD_LEN
PUSHAQ PROMPT_DSC
PUSHAQ CMD_DSC
CALLS #3,G^LIB$GET_INPUT
.ENDM LIB_GET_INPUT
;+
; Local symbols:
;-
HDR_SIZE = 4 ; Application header size
HDR_W_STATUS = 0 ; Application status field
IOSB_W_LENGTH = 2 ; Offset to length in IOSB
MAX_ADDR = 80 ; Limit VOTS address length
MAX_CMD = 256 ; Limit command length
MAX_CMDHDR = MAX_CMD + HDR_SIZE ; Command length plus appl. header
MAX_LIST = 120 ; Limit Item List length
MAX_RSP = 256 ; Limit data length
MAX_RSPHDR = MAX_RSP + HDR_SIZE ; Response length plus appl. header
;+
; Declare external routines
;-
.EXTRN -
CLI$GET_VALUE,- ; Get the value of a qualifier
LIB$GET_INPUT,- ; Get input from SYS$INPUT
LIB$PUT_OUTPUT,- ; Write output to SYS$OUTPUT
LIB$STOP ; Report errors
.SBTTL RO_DATA - Read Only DATA
.PSECT RO_DATA RD,NOWRT,NOEXE
;
; Descriptors
;
ADDRQUAL_DSC: .ASCID /ADDRESS/ ; Label of address parameter (.cld)
OSITDEV_DSC: .ASCID /OSIT$DEVICE/
PRGNAME_DSC: .ASCID /OSIT$CMD_SOURCE waiting for OSIT$CMD_EXECUTOR to accept the connection/
PROMPT_DSC: .ASCID ?Enter a command (or CTRL/Z to exit): ?
TOOSHORT_DSC: .ASCID /OSIT$CMD_EXECUTOR sent a message which was too short./
TSAP_DSC: .ASCID /OSIT$CMD_EXECUTOR/
.SBTTL RW_DATA - Read Write DATA
.PSECT RW_DATA RD,WRT,NOEXE
;
; Buffer and descriptor for the command which is entered
;
CMDHDR: .BLKB HDR_SIZE ; Reserved for the application header
CMD: .BLKB MAX_CMD ; Start of command entered
CMDHDR_DSC: .WORD MAX_CMDHDR ; Used to send the command (length)
.BYTE DSC$K_DTYPE_T ; Text
.BYTE DSC$K_CLASS_S ; String
.ADDRESS CMDHDR ; Pointer
CMD_DSC: .WORD MAX_CMD ; Used to read the command from sys$input
.BYTE DSC$K_DTYPE_T ; Text
.BYTE DSC$K_CLASS_S ; String
.ADDRESS CMD ; Pointer
CMD_LEN: .BLKL 1 ; Length of the command entered
;
; Buffer and descriptor for the input item list used to
; establish the connection.
;
IN_ITEM: .BLKB MAX_LIST ; Input item list
IN_ITEM_DSC: .WORD MAX_LIST ; Length
.BYTE DSC$K_DTYPE_T ; Text
.BYTE DSC$K_CLASS_S ; String
.ADDRESS IN_ITEM ; Pointer
;
; I/O Status block used in QIO calls
;
IOSB: .BLKQ ; I/O status block
;
; Message vector used to report errors returned from the
; command executor node.
;
MSGVEC: ; Message vector
.WORD 1 ; Count of vector items
.WORD 15 ; All options on (FAC, SEV, IDT, TXT)
MSGVEC_CODE: .BLKL 1 ; Message code
;
; Buffer and descriptors used to read the command output from
; the executor node by doing QIOs to the transport connection channel.
;
RSPHDR: .BLKB HDR_SIZE ; Reserved for the application header
RSP: .BLKB MAX_RSP ; Start of a command output line
RSP_DSC: .WORD MAX_RSP ; Used to write the line to sys$output
.BYTE DSC$K_DTYPE_T ; Text
.BYTE DSC$K_CLASS_S ; String, pointer
.ADDRESS RSP ; Pointer
;
; VMS channel number for the transport connection to the executor node.
;
TC_CHAN: .BLKW 1 ; Connection channel
;
; Buffer and descriptor for the VOTS address of the executor node.
;
VOTS_ADDR: .BLKB MAX_ADDR ;
VOTS_ADDR_DSC: .WORD MAX_ADDR ; Used by cli$get_value
.BYTE DSC$K_DTYPE_T ; Text
.BYTE DSC$K_CLASS_S ; String
.ADDRESS VOTS_ADDR ; Pointer
.SBTTL CODE - Start of program
.PSECT CODE RD,NOWRT,EXE
.ENTRY CMD_SOURCE,0
;
; Preset the application Header status to success
;
MOVW #SS$_NORMAL,CMDHDR + HDR_W_STATUS
;
; Tell the user the program name and let the user know what is
; happening.
;
PUSHAQ PRGNAME_DSC ; Dsc of output string
CALLS #1,G^LIB$PUT_OUTPUT ; Identify the program to the user
;
; Get the VOTS address of the executor node. It is a parameter.
;
CLI_GET_VALUE -
ADDRQUAL_DSC VOTS_ADDR_DSC
BLBS R0,10$ ; On failure, goto r0_error
JMP R0_ERROR
;
; VOTS_ADDR_DSC now contains the address of the target node, that is, the
; node which will execute the commands.
; Assign a channel to OSIT$DEVICE and request a connection to the target node.
; Use the item list interface.
;
10$: $ASSIGN_S - ; Assign a channel to osit$device
CHAN = TC_CHAN,-
DEVNAM = OSITDEV_DSC ;
BLBS R0,20$ ; On failure, goto r0_error
JMP R0_ERROR
20$: MOVAQ IN_ITEM_DSC,R6
; R6 points to the item list descriptor
CLRW DSC$W_LENGTH(R6) ; Zero the item size
MOVL DSC$A_POINTER(R6),R3 ; R3 points to the item list
MOVAL VOTS_ADDR_DSC,R7 ; R4 points to the VOTS address dsc
MOVL #OSIT$K_ITEM_ADDRESS,R8
MOVZWL DSC$W_LENGTH(R7),-
R2 ; R2 is the item size
ADDL2 #OSIT$K_ITEM_HEADER_SIZE,R2
ADDW R2,- ; Update the item list length
DSC$W_LENGTH(R6)
MOVW R2,(R3)+ ; Fill in the item length
MOVW R8,(R3)+ ; Fill in the item code
MOVC3 - ; Copy the item, update R3
DSC$W_LENGTH(R7), -
@DSC$A_POINTER(R7), -
(R3)
MOVAL TSAP_DSC,R7
MOVL #OSIT$K_ITEM_CALLED_TSAP,R8
MOVZWL DSC$W_LENGTH(R7),-
R2 ; R2 is the item size
ADDL2 #OSIT$K_ITEM_HEADER_SIZE,R2
ADDW R2,- ; Update the item list length
DSC$W_LENGTH(R6)
MOVW R2,(R3)+ ; Fill in the item length
MOVW R8,(R3)+ ; Fill in the item code
MOVC3 - ; Copy the item, update R3
DSC$W_LENGTH(R7), -
@DSC$A_POINTER(R7), -
(R3)
$QIOW_S - ; Request a connection to the target
CHAN = TC_CHAN,- ; node and wait for the connection
FUNC = #IO$_ACCESS,- ; to be set up.
IOSB = IOSB,- ;
P1 = IN_ITEM_DSC ;
BLBS R0,30$
JMP R0_ERROR
30$: MOVZWL IOSB,R0 ; Get the status of the connect request
BLBS R0,READ_CMD ; On failure, goto iosb_error or ro_error
JMP IOSB_ERROR
;
; The connection to the target task has been established.
; Read a user command and send it to the target node to be
; executed. The target node will send back the output from
; the command and it will be displayed. The process is then repeated
; until the user exits or an error is detected.
READ_CMD:
MOVW #MAX_CMD,-
CMD_DSC + DSC$W_LENGTH ; Set maximum size for command
LIB_GET_INPUT -
CMD_DSC PROMPT_DSC CMD_LEN
BLBS R0,10$ ; if success, continue at 10$
CMPL #RMS$_EOF,R0 ; Does the user want to exit?
BEQL 5$ ; Yes, exit with success
JMP R0_ERROR ; No, there is an error, goto r0_error
5$: MOVL #SS$_NORMAL,R0 ;
BRW LEAVE ; The user wants to exit, goto leave
10$: MOVZWL CMD_LEN,R4 ; R4 is the command length
BEQL READ_CMD ; Zero length command, try again.
;
; The command is in CMD_DSC. Add the protocol
; information needed by the application protocol and send the
; command to the target node.
; The application protocol information is in a fixed size
; header which contains a status field.
;
ADDL2 #HDR_SIZE,R4 ; R4 is the command+protocol length
$QIOW_S - ; Send the command to the target
CHAN = TC_CHAN,- ; node.
FUNC = #IO$_WRITEVBLK,- ;
IOSB = IOSB,- ; p1 is the buffer address
P1 = CMDHDR,- ; p2 is the buffer length
P2 = R4
BLBS R0,20$
JMP R0_ERROR
20$: MOVZWL IOSB,R0
BLBS R0,READ_RSP
JMP IOSB_ERROR
;
; The command has been sent.
; Read the responses to the command until the status field
; comes back with ss$_endoffile in it.
;
READ_RSP:
$QIOW_S - ; Read a line of the response
CHAN = TC_CHAN,- ;
FUNC = #IO$_READVBLK,- ;
IOSB = IOSB,- ;
P1 = RSPHDR,- ; p1 is the buffer address
P2 = #MAX_RSPHDR ; p2 is the maximum size
BLBS R0,10$
JMP R0_ERROR
10$: MOVZWL IOSB,R0
BLBS R0,15$
JMP IOSB_ERROR
;
; If this is the end of the responses, loop back and read another
; command. If the target node returned an error, report it and
; then loop back for another command.
;
15$: MOVZWL IOSB + IOSB_W_LENGTH,- ; R4 is the length of the line+header
R4
CMPW R4,#HDR_SIZE ; Make sure there is a header
BGEQU 16$
JMP APPL_ERROR ; If not, goto appl_error
16$: MOVZWL RSPHDR + HDR_W_STATUS,- ; R0 is the status of the response
R0
CMPW R0,#SS$_ENDOFFILE ; Is this the end of the responses?
BEQL 40$ ; If Yes, read another command.
BLBC R0,20$ ; The command failed, report the error
SUBL2 #HDR_SIZE,R4 ; R4 is the length of the line
;
; Display the response line.
;
MOVAQ RSP_DSC,R3
MOVW R4,DSC$W_LENGTH(R3) ; Set the line length
PUSHL R3 ; arg 1, buffer descriptor
CALLS #1,G^LIB$PUT_OUTPUT ; Display the line
BRW READ_RSP ; Read another response line
;
; The target node indicated a failure. Report it.
;
20$: MOVL R0,MSGVEC_CODE ; Put the code in msgvec.
$PUTMSG_S - ; Display the error message.
MSGVEC = MSGVEC ;
BRW READ_CMD ; Continue
40$: BRW READ_CMD ; Loop back to read another command
;
; Write a null command so that the executor can exit cleanly
; Wait for the executor to disconnect the link
;
LEAVE:
$QIOW_S - ; Write a null command
CHAN = TC_CHAN,- ;
FUNC = #IO$_WRITEVBLK,- ;
IOSB = IOSB,- ;
P1 = CMDHDR,- ; p1 is the buffer address
P2 = #HDR_SIZE ; p2 is the buffer length
BLBS R0,10$
JMP R0_ERROR
10$: MOVZWL IOSB,R0 ; Check IOSB
BLBS R0,15$ ; On failure, goto iosb_error
JMP R0_ERROR
15$: $QIOW_S - ; Read a line, expect it to fail
CHAN = TC_CHAN,- ; because the executor will disconnect.
FUNC = #IO$_READVBLK,- ;
IOSB = IOSB,- ;
P1 = RSPHDR,- ; p1 is the buffer address
P2 = #MAX_RSPHDR ; p2 is the maximum size
MOVL #SS$_NORMAL,R0 ; Exit with success
20$: RET
;
; Report an R0 error
;
R0_ERROR:
PUSHL R0 ; Argument for lib$stop
CALLS #1,G^LIB$STOP ; Exit and report the error
;
; Report an I/O status block error
;
IOSB_ERROR:
PUSHL IOSB+4 ; report iost2
PUSHL #0 ; Arg 2 is 0 (FAO count)
PUSHL R0 ; Arg 1 is r0
CALLS #3,G^LIB$STOP ; Exit and report the error
;
; Report an error in the application
;
APPL_ERROR:
PUSHAQ TOOSHORT_DSC ;
CALLS #1,G^LIB$PUT_OUTPUT ; Display the error message
$EXIT_S ; Exit
RET
.END CMD_SOURCE