.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