HP OpenVMS Systemsask the wizard |
The Question is: How do I create a run/execute que that will do a passthru function for printing. I.E. I want to print from an application that only supports printing to a que, but I am dialed in with a VT terminal with a printer port via a modem connection. The Answer is : The OpenVMS Wizard is aware of freeware/shareware OpenVMS print symbionts available that can route printer output to a VT terminal with an attached printer. Effectively, this print symbiont allocates a connection to the target terminal device (typically using SHARE privilege), sends the terminal escape sequence to route output to the attached printer, sends the contents of the file to the terminal and thus through to the printer, then switches the output back to the terminal via an escape sequence. No, the OpenVMS Wizard does not have any immediate suggestions nor sources for this print symbiont. The attached symbiont was acquired from a posting on CompuServe many years ago, author unknown -- two versions are posted, the original OpenVMS VAX and an OpenVMS Alpha port. (If you are or know of the author of this, please contact the OpenVMS Wizard.) To build this symbiont, please follow the instructions in the OpenVMS manual set for the creation of customization of print symbionts, and the steps to configure the symbiont. -------------------------------------------------------------------------------- .TITLE SLAVE_SMB - An symbiont for terminal slave printers ;+ ; This printer symbiont routes print jobs back to the user's terminal ; for printing on the terminal connected slave printer (if there is one ; and if the user is still logged on). This enables slave printing to ; be seamlessly integrated into the VMS system as a queue. If it is ; likely that more than one user will want to use this facility, then ; several such queues should be set up, all fed from the same generic ; queue. The symbiont is multithreaded, supporting up to 16 streams. ; Note, however, that there is a complication in the case of clusters. ; The generic and multiple execution queues should (in the homogeneous ; case) be duplicated on each node with cluster unique names. The slave ; queue complex should therefore be referenced through a cluster common ; logical pointing to a node's specific slave generic queue. ;- ;+ ; Modification history ; 24-JAN-1990 : Created. ; 08-FEB-1990 : Single threaded version to named device. ; 09-FEB-1990 : Single threaded version to device named in /PARAMETER. ; 10-FEB-1990 : Legal device checking & terminal state control added. ; 18-FEB-1990 : Modified to delay (in EXEC mode) between keyboard lock ; and terminal -> transparent print mode. ; Note _strange_ system bug fix. ; 02-JUN-1990 : LIB$WAIT replaced by $SETIMR & $WAITFR_S to avoid kludge. ; 21-NOV-1990 : Set term to VT200-8bit and reset to VT100 mode, to allow ; for printing of graphics character set. ;- .LIBRARY 'SYS$LIBRARY:LIB' ;+ ; System definitions ;- $PSMDEF ; PSM definitions $SMBDEF ; SMB definitions $DSCDEF ; DSC definitions $OPCDEF ; OPC definitions $PRVDEF ; PRV definitions $DVIDEF ; GETDVI item codes $IODEF ; I/O function codes $SSDEF ; Status codes $DCDEF ; Device class symbols ;+ ; Define argument offsets for user supplied services called by symbiont ;- CONTEXT = 04 ; Symbiont context WORK_AREA = 08 ; User context FUNC = 12 ; Function code FUNC_DESC = 16 ; Function dependent descriptor FUNC_ARG = 20 ; Function dependent argument ;+ ; D_DESC - Macro to create dynamic descriptors ;- .MACRO D_DESC .WORD 0 ; DSC$W_LENGTH = 0 .BYTE DSC$K_DTYPE_T ; DSC$B_DTYPE = STRING .BYTE DSC$K_CLASS_D ; DSC$B_CLASS = DYNAMIC .LONG 0 ; DSC$A_POINTER = 0 .ENDM ;+ ; STR_DESC - Macro to create string descriptors ;- .MACRO STR_DESC TEXT,?STR .WORD %LENGTH(TEXT) .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_D .LONG STR STR: .ASCII /TEXT/ .ENDM ;+ ; Symbiont data ;- TT_CHAN: .BLKW 1 ; Channel to user's TT TT_NAME: D_DESC ; TT name from PARAMETER_1 TT_TYPE: .BLKL 1 ; Device class from LIB$GETDVI NL_NAME: .ASCID /NL:/ ; Null device for junking IO_STATUS: .BLKQ 1 ; I/O status block ;+ ; Symbiont buffer pointers ;- B_ADDR: .LONG 0 B_SIZE: .LONG 0 ;+ ; Create form feed string descriptor ;- FF = 12 FORM_FEED: .WORD 1 .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_D .LONG FF_ADDR FF_ADDR: .ASCII <FF> ;+ ; Terminal control sequences ;- ESC = 27 LOCK_1: .BYTE ESC .ASCII /[2h/ ; lock keyboard LOCK_1_LEN = < . - LOCK_1 > LOCK_0: .BYTE ESC .ASCII /[2l/ ; unlock keyboard LOCK_0_LEN = < . - LOCK_0 > XPRINT_1: .BYTE ESC .ASCII /[5i/ ; transparent print on XPRINT_1_LEN = < . - XPRINT_1 > XPRINT_0: .BYTE ESC .ASCII /[4i/ ; transparent print off XPRINT_0_LEN = < . - XPRINT_0 > VT200_8BIT: .BYTE ESC .ASCII /[62;2"p/ ; VT200 8-bit Terminal mode on .BYTE ESC .ASCII / G/ ; 8-bit Trasmission mode on VT200 VT200_8BIT_LEN = < . - VT200_8BIT > VT100: .BYTE ESC .ASCII /[61"p/ ; VT100 Terminal mode on VT100_LEN = < . - VT100 > ;+ ; OPR_DESC - Macro to create operator message descriptors ;- .MACRO OPR_DESC TEXT,?OPR .WORD %LENGTH(TEXT)+8 .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_D .LONG OPR OPR: .BYTE OPC$_RQ_RQST .BYTE OPC$M_NM_CENTRL .WORD 0 .LONG 0 .ASCII /TEXT/ .ENDM ;+ ; Create operator messages ;- BAD_TT: OPR_DESC <Slave Symbiont - Invalid TERM device> ;+ ; Process name descriptor ;- PROC_NAME: .ASCID /Slave Symbiont/ ;+ ; Own storage for values passed by reference ;- CODE: .LONG 0 ; Service or item code STREAMS: .LONG 1 ; Number of simultaneous streams BUFSIZ: .LONG 512 ; Output buffer size ;+ ; Own storage for symbiont status ;- COUNT: .LONG 0 ; # calls to COMPLETE ;+ ; Privilege mask - NETMBX + BYPASS + LOG_IO + PHY_IO + CMEXEC ;- PRVMSK: .LONG PRV$M_NETMBX ! - PRV$M_BYPASS ! - PRV$M_LOG_IO ! - PRV$M_PHY_IO ! - PRV$M_CMEXEC .LONG 0 ;+ ; Main routine - Invoked at image startup ;- .ENTRY SLAVE_SMB,^M<> ; Save nothing ;+ ; Supply private output routine - PSM$K_OUTPUT ;- MOVZBL #PSM$K_OUTPUT,CODE ; Set the service code PUSHAL OUTPUT ; Address of modified routine PUSHAL CODE ; Address of service code CALLS #2,G^PSM$REPLACE ; Replace the routine BLBC R0,10$ ; Exit if any errors ;+ ; Supply private input routine - PSM$K_JOB_COMPLETION ;- MOVZBL #PSM$K_JOB_COMPLETION,CODE ; Set the service code PUSHAL COMPLETE ; Address of modified routine PUSHAL CODE ; Address of service code CALLS #2,G^PSM$REPLACE ; Replace the routine BLBC R0,10$ ; Exit if any errors ;+ ; Set privileges required for symbiont operation ;- $SETPRV_S - ENBFLG = #1, - PRVADR = PRVMSK BLBC R0,10$ ;+ ; Set process name ;- $SETPRN_S - PRCNAM = PROC_NAME BLBC R0,10$ ;+ ; Transfer control to the standard symbiont ;- PUSHAL BUFSIZ ; Address of output buffer size PUSHAL STREAMS ; Address of number of streams CALLS #2,G^PSM$PRINT ; Invoke standard symbiont BLBC R0,10$ ; Exit if any errors 10$: RET ;+ ; Output routine - PSM$K_OUTPUT ;- OUTPUT: .WORD 0 ; Save nothing ;+ ; Check function code ;- CMPL #PSM$K_START_TASK,@FUNC(AP) ; Start of task ? BNEQ 100$ BRW 140$ 100$: CMPL #PSM$K_CANCEL,@FUNC(AP) ; Cancel task ? BNEQ 110$ BRW 150$ 110$: CMPL #PSM$K_WRITE,@FUNC(AP) ; Write ? BNEQ 120$ BRW 160$ 120$: CMPL #PSM$K_WRITE_NOFORMAT,@FUNC(AP) ; Write unformatted ? BNEQ 130$ BRW 170$ 130$: MOVL #PSM$_FUNNOTSUP,R0 ; Unsupported function RET ; Return to symbiont ;+ ; PSM$K_START_TASK ;- 140$: BSBW OPEN_TERM ; Set up terminal chan, etc MOVL #SS$_NORMAL,R0 ; Errors handled in OPEN_TERM RET ; Return to symbiont ;+ ; PSM$K_CANCEL ;- 150$: BSBW CLOSE_TERM ; Close down terminal chan, etc MOVL #SS$_NORMAL,R0 ; Errors handled in CLOSE_TERM RET ; Return to symbiont ;+ ; PSM$K_WRITE ;- 160$: PUSHAL B_ADDR ; Address of symbiont buffer PUSHAL B_SIZE ; Size of symbiont buffer PUSHL FUNC_DESC(AP) ; Descriptor for string to send CALLS #3,G^STR$ANALYZE_SDESC ; Get address & size of string MOVZWL B_SIZE,R1 ; Get size $QIOW_S - ; QIO to terminal CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK,- IOSB = IO_STATUS,- P1 = @B_ADDR,- P2 = R1,- P4 = #^X00000000 ; No carriage control BSBW IO_ERROR ; Check for IO errors CMPL #0,COUNT ; Is this the last write BNEQ 161$ ; No - branch round ... BSBW CLOSE_TERM ; Close down terminal chan, etc 161$: MOVL #SS$_NORMAL,R0 RET ; Return to symbiont ;+ ; PSM$K_WRITE_NOFORMAT ;- 170$: PUSHAL B_ADDR ; See comments above .... PUSHAL B_SIZE PUSHL FUNC_DESC(AP) CALLS #3,G^STR$ANALYZE_SDESC MOVZWL B_SIZE,R1 $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = @B_ADDR,- P2 = R1 BSBW IO_ERROR CMPL #0,COUNT BNEQ 171$ BSBW CLOSE_TERM 171$: MOVL #SS$_NORMAL,R0 RET ; Return to symbiont ;+ ; Subroutine OPEN_TERM - Sets up terminal chan, etc. ;- OPEN_TERM: ; Get PARAMETER_1 -> TT_NAME. MOVZBL #SMBMSG$K_PARAMETER_1,CODE ; Set item code PUSHAL TT_NAME ; Address of descriptor PUSHAL CODE ; Address of item code PUSHAL @CONTEXT(AP) ; Address of symbiont ctx value CALLS #3,G^PSM$READ_ITEM_DX ; Read PARAMETER_1 BSBW ERROR ; Check system service ; If TT_NAME is a terminal, assign a channel to it. ; If it isn't, send an OPCOM message and open a channel to NL: MOVZBL #DVI$_DEVCLASS,CODE ; Item code to get device type PUSHAL TT_TYPE ; Receives device type PUSHAL TT_NAME ; Device name from /PARAMETER PUSHL #0 ; Channel not available yet PUSHAL CODE ; Item code CALLS #4,G^LIB$GETDVI ; Get device information BLBC R0,190$ ; Any errors, open NL: CMPL #DC$_TERM,TT_TYPE ; Is device a terminal BNEQ 190$ ; If not, open NL: BRW 191$ ; OK - go on to next bit ... 190$: BRW 195$ ; Assign channel to TT: 191$: $ASSIGN_S DEVNAM = TT_NAME,- ; TT: CHAN = TT_CHAN ; TT channel BSBW ERROR ; Check system service ; Set terminal to VT200 8bit mode $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = VT200_8BIT,- P2 = #VT200_8BIT_LEN BSBW IO_ERROR ; Check for IO errors ; Lock keyboard. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = LOCK_1,- P2 = #LOCK_1_LEN BSBW IO_ERROR ; Check for IO errors ; Wait 3 seconds before setting up transparent printing. BSBW DELAY_3 ; Enter transparent print mode. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = XPRINT_1,- P2 = #XPRINT_1_LEN BSBW IO_ERROR ; Check for IO errors RSB ; Assign channel to NL: and send OPCOM message. 195$: $ASSIGN_S DEVNAM = NL_NAME,- ; NL: CHAN = TT_CHAN ; TT channel BSBW ERROR ; Check system service $SNDOPR_S MSGBUF = BAD_TT,- ; Send OPCOM message CHAN = #0 BSBW ERROR ; Check system service RSB ;+ ; Subroutine CLOSE_TERM - Closes down terminal chan, etc. ;- CLOSE_TERM: ; Exit transparent print mode. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = XPRINT_0,- P2 = #XPRINT_0_LEN BSBW IO_ERROR ; Check for IO errors ; Unlock keyboard. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = LOCK_0,- P2 = #LOCK_0_LEN BSBW IO_ERROR ; Check for IO errors ; Set term to VT100 mode $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = VT100,- P2 = #VT100_LEN BSBW IO_ERROR ; Check for IO errors ; Deassign channel to TT $DASSGN_S CHAN = TT_CHAN ; Deassign TT channel BSBW ERROR ; Check system service RSB ;+ ; Subroutine DELAY_3 - Waits 3 seconds. ;- DELAY_DELTA: .ASCID /0 00:00:03.00/ ; 3 seconds delta DELAY_TIME: .BLKQ 1 ; Binary rep. of above DELAY_3: ; Convert ASCII representation into 64 bit binary $BINTIM_S - TIMBUF = DELAY_DELTA, - TIMADR = DELAY_TIME BSBW ERROR ; Check system service ; Set time to wait $SETIMR_S - EFN = #2, - DAYTIM = DELAY_TIME BSBW ERROR ; Check system service ; Do the actual wait $WAITFR_S - EFN = #2 BSBW ERROR ; Check system service RSB ;+ ; Subroutine IO_ERROR / ERROR - Checks for errors ;- IO_ERROR: ; Check system service and I/O status BLBC R0,ERR ; If low bit clear then error MOVZWL IO_STATUS,R0 ; Test I/O status ERROR: ; Check system service status (R0) BLBC R0,ERR ; If low bit clear then error RSB ; No errors so return ERR: $EXIT_S - ; Error occurred so exit CODE = R0 ; with status ;+ ; Input routine - PSM$K_JOB_COMPLETION ;- COMPLETE: .WORD 0 ; Save nothing ;+ ; Check function code ;- CMPL #PSM$K_START_TASK,@FUNC(AP) ; Start of task ? BNEQ 200$ BRW 220$ 200$: CMPL #PSM$K_READ,@FUNC(AP) ; Read ? BNEQ 210$ BRW 230$ 210$: MOVL #PSM$_FUNNOTSUP,R0 ; Unsupported function RET ; Return to symbiont ;+ ; PSM$K_START_TASK ;- 220$: MOVZBL #2,COUNT ; Reset READ call count MOVL #SS$_NORMAL,R0 ; Set success exit code RET ; Return to symbiont ;+ ; PSM$K_READ ;- 230$: DECL COUNT ; Decrement READ call count BEQL 240$ ; Branch if second ; Send a <FF> to flush output PUSHAB FORM_FEED ; <FF> descriptor PUSHL FUNC_DESC(AP) ; Symbiont descriptor CALLS #2,G^STR$COPY_DX ; Copy to symbiont buffer RET ; Return to symbiont ; Done - return PSM$_EOF 240$: MOVL #PSM$_EOF,R0 ; Set EOF exit code RET ; Return to symbiont ;+ ; End of SLAVE_SMB ;- .END SLAVE_SMB -------------------------------------------------------------------------------- .TITLE SLAVE_SMB - An symbiont for terminal slave printers ;+ ; This printer symbiont routes print jobs back to the user's terminal ; for printing on the terminal connected slave printer (if there is one ; and if the user is still logged on). This enables slave printing to ; be seamlessly integrated into the VMS system as a queue. If it is ; likely that more than one user will want to use this facility, then ; several such queues should be set up, all fed from the same generic ; queue. The symbiont is multithreaded, supporting up to 16 streams. ; Note, however, that there is a complication in the case of clusters. ; The generic and multiple execution queues should (in the homogeneous ; case) be duplicated on each node with cluster unique names. The slave ; queue complex should therefore be referenced through a cluster common ; logical pointing to a node's specific slave generic queue. ;- ;+ ; Modification history ; 24-JAN-1990 : Created. ; 08-FEB-1990 : Single threaded version to named device. ; 09-FEB-1990 : Single threaded version to device named in /PARAMETER. ; 10-FEB-1990 : Legal device checking & terminal state control added. ; 18-FEB-1990 : Modified to delay (in EXEC mode) between keyboard lock ; and terminal -> transparent print mode. ; Note _strange_ system bug fix. ; 02-JUN-1990 : LIB$WAIT replaced by $SETIMR & $WAITFR_S to avoid kludge. ; 21-NOV-1990 : Set term to VT200-8bit and reset to VT100 mode, to allow ; for printing of graphics character set. ; 1999-04-15 John Simmonds ; Port to OpenVMS Alpha. ;- .LIBRARY 'SYS$LIBRARY:LIB' ;+ ; System definitions ;- $PSMDEF ; PSM definitions $SMBDEF ; SMB definitions $DSCDEF ; DSC definitions $OPCDEF ; OPC definitions $PRVDEF ; PRV definitions $DVIDEF ; GETDVI item codes $IODEF ; I/O function codes $SSDEF ; Status codes $DCDEF ; Device class symbols ;+ ; Define argument offsets for user supplied services called by symbiont ;- CONTEXT = 04 ; Symbiont context WORK_AREA = 08 ; User context FUNC = 12 ; Function code FUNC_DESC = 16 ; Function dependent descriptor FUNC_ARG = 20 ; Function dependent argument ;+ ; D_DESC - Macro to create dynamic descriptors ;- .MACRO D_DESC .WORD 0 ; DSC$W_LENGTH = 0 .BYTE DSC$K_DTYPE_T ; DSC$B_DTYPE = STRING .BYTE DSC$K_CLASS_D ; DSC$B_CLASS = DYNAMIC .LONG 0 ; DSC$A_POINTER = 0 .ENDM ;+ ; STR_DESC - Macro to create string descriptors ;- .MACRO STR_DESC TEXT,?STR .WORD %LENGTH(TEXT) .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_D .LONG STR STR: .ASCII /TEXT/ .ENDM ;+ ; Symbiont data ;- .psect SMB_DATA NOEXE,RD,WRT,QUAD TT_CHAN: .BLKW 1 ; Channel to user's TT TT_NAME: D_DESC ; TT name from PARAMETER_1 TT_TYPE: .BLKL 1 ; Device class from LIB$GETDVI NL_NAME: .ASCID /NL:/ ; Null device for junking IO_STATUS: .BLKQ 1 ; I/O status block ;+ ; Symbiont buffer pointers ;- B_ADDR: .LONG 0 B_SIZE: .LONG 0 ;+ ; Create form feed string descriptor ;- FF = 12 FORM_FEED: .WORD 1 .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_D .LONG FF_ADDR FF_ADDR: .ASCII <FF> ;+ ; Terminal control sequences ;- ESC = 27 LOCK_1: .BYTE ESC .ASCII /[2h/ ; lock keyboard LOCK_1_LEN = < . - LOCK_1 > LOCK_0: .BYTE ESC .ASCII /[2l/ ; unlock keyboard LOCK_0_LEN = < . - LOCK_0 > XPRINT_1: .BYTE ESC .ASCII /[5i/ ; transparent print on XPRINT_1_LEN = < . - XPRINT_1 > XPRINT_0: .BYTE ESC .ASCII /[4i/ ; transparent print off XPRINT_0_LEN = < . - XPRINT_0 > VT200_8BIT: .BYTE ESC .ASCII /[62;2"p/ ; VT200 8-bit Terminal mode on .BYTE ESC .ASCII / G/ ; 8-bit Trasmission mode on VT200 VT200_8BIT_LEN = < . - VT200_8BIT > VT100: .BYTE ESC .ASCII /[61"p/ ; VT100 Terminal mode on VT100_LEN = < . - VT100 > ;+ ; OPR_DESC - Macro to create operator message descriptors ;- .MACRO OPR_DESC TEXT,?OPR .WORD %LENGTH(TEXT)+8 .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_D .LONG OPR OPR: .BYTE OPC$_RQ_RQST .BYTE OPC$M_NM_CENTRL .WORD 0 .LONG 0 .ASCII /TEXT/ .ENDM ;+ ; Create operator messages ;- BAD_TT: OPR_DESC <Slave Symbiont - Invalid TERM device> ;+ ; Process name descriptor ;- PROC_NAME: .ASCID /Slave Symbiont/ ;+ ; Own storage for values passed by reference ;- CODE: .LONG 0 ; Service or item code STREAMS: .LONG 1 ; Number of simultaneous streams BUFSIZ: .LONG 512 ; Output buffer size ;+ ; Own storage for symbiont status ;- COUNT: .LONG 0 ; # calls to COMPLETE ;+ ; Privilege mask - NETMBX + BYPASS + LOG_IO + PHY_IO + CMEXEC ;- PRVMSK: .LONG PRV$M_NETMBX ! - PRV$M_BYPASS ! - PRV$M_LOG_IO ! - PRV$M_PHY_IO ! - PRV$M_CMEXEC .LONG 0 ;+ ; Main routine - Invoked at image startup ;- .psect SMB_CODE EXE,RD,NOWRT,QUAD ; .ENTRY SLAVE_SMB,^M<> ; Save nothing SLAVE_SMB:: .call_entry home_args=<TRUE>,max_args=<6>,preserve=<> ;+ ; Supply private output routine - PSM$K_OUTPUT ;- MOVZBL #PSM$K_OUTPUT,CODE ; Set the service code PUSHAL OUTPUT ; Address of modified routine PUSHAL CODE ; Address of service code CALLS #2,G^PSM$REPLACE ; Replace the routine BLBC R0,10$ ; Exit if any errors ;+ ; Supply private input routine - PSM$K_JOB_COMPLETION ;- MOVZBL #PSM$K_JOB_COMPLETION,CODE ; Set the service code PUSHAL COMPLETE ; Address of modified routine PUSHAL CODE ; Address of service code CALLS #2,G^PSM$REPLACE ; Replace the routine BLBC R0,10$ ; Exit if any errors ;+ ; Set privileges required for symbiont operation ;- $SETPRV_S - ENBFLG = #1, - PRVADR = PRVMSK BLBC R0,10$ ;+ ; Set process name ;- $SETPRN_S - PRCNAM = PROC_NAME BLBC R0,10$ ;+ ; Transfer control to the standard symbiont ;- PUSHAL BUFSIZ ; Address of output buffer size PUSHAL STREAMS ; Address of number of streams CALLS #2,G^PSM$PRINT ; Invoke standard symbiont BLBC R0,10$ ; Exit if any errors 10$: RET ;+ ; Output routine - PSM$K_OUTPUT ;- OUTPUT: ;.WORD 0 ; Save nothing .call_entry home_args=<TRUE>,max_args=<6>,preserve=<> ;+ ; Check function code ;- CMPL #PSM$K_START_TASK,@FUNC(AP) ; Start of task ? BNEQ 100$ BRW 140$ 100$: CMPL #PSM$K_CANCEL,@FUNC(AP) ; Cancel task ? BNEQ 110$ BRW 150$ 110$: CMPL #PSM$K_WRITE,@FUNC(AP) ; Write ? BNEQ 120$ BRW 160$ 120$: CMPL #PSM$K_WRITE_NOFORMAT,@FUNC(AP) ; Write unformatted ? BNEQ 130$ BRW 170$ 130$: MOVL #PSM$_FUNNOTSUP,R0 ; Unsupported function RET ; Return to symbiont ;+ ; PSM$K_START_TASK ;- 140$: BSBW OPEN_TERM ; Set up terminal chan, etc MOVL #SS$_NORMAL,R0 ; Errors handled in OPEN_TERM RET ; Return to symbiont ;+ ; PSM$K_CANCEL ;- 150$: BSBW CLOSE_TERM ; Close down terminal chan, etc MOVL #SS$_NORMAL,R0 ; Errors handled in CLOSE_TERM RET ; Return to symbiont ;+ ; PSM$K_WRITE ;- 160$: PUSHAL B_ADDR ; Address of symbiont buffer PUSHAL B_SIZE ; Size of symbiont buffer PUSHL FUNC_DESC(AP) ; Descriptor for string to send CALLS #3,G^STR$ANALYZE_SDESC ; Get address & size of string MOVZWL B_SIZE,R1 ; Get size $QIOW_S - ; QIO to terminal CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK,- IOSB = IO_STATUS,- P1 = @B_ADDR,- P2 = R1,- P4 = #^X00000000 ; No carriage control BSBW IO_ERROR ; Check for IO errors CMPL #0,COUNT ; Is this the last write BNEQ 161$ ; No - branch round ... BSBW CLOSE_TERM ; Close down terminal chan, etc 161$: MOVL #SS$_NORMAL,R0 RET ; Return to symbiont ;+ ; PSM$K_WRITE_NOFORMAT ;- 170$: PUSHAL B_ADDR ; See comments above .... PUSHAL B_SIZE PUSHL FUNC_DESC(AP) CALLS #3,G^STR$ANALYZE_SDESC MOVZWL B_SIZE,R1 $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = @B_ADDR,- P2 = R1 BSBW IO_ERROR CMPL #0,COUNT BNEQ 171$ BSBW CLOSE_TERM 171$: MOVL #SS$_NORMAL,R0 RET ; Return to symbiont ;+ ; Subroutine OPEN_TERM - Sets up terminal chan, etc. ;- OPEN_TERM: .jsb_entry ; Get PARAMETER_1 -> TT_NAME. MOVZBL #SMBMSG$K_PARAMETER_1,CODE ; Set item code PUSHAL TT_NAME ; Address of descriptor PUSHAL CODE ; Address of item code PUSHAL @CONTEXT(AP) ; Address of symbiont ctx value CALLS #3,G^PSM$READ_ITEM_DX ; Read PARAMETER_1 BSBW ERROR ; Check system service ; If TT_NAME is a terminal, assign a channel to it. ; If it isn't, send an OPCOM message and open a channel to NL: MOVZBL #DVI$_DEVCLASS,CODE ; Item code to get device type PUSHAL TT_TYPE ; Receives device type PUSHAL TT_NAME ; Device name from /PARAMETER PUSHL #0 ; Channel not available yet PUSHAL CODE ; Item code CALLS #4,G^LIB$GETDVI ; Get device information BLBC R0,190$ ; Any errors, open NL: CMPL #DC$_TERM,TT_TYPE ; Is device a terminal BNEQ 190$ ; If not, open NL: BRW 191$ ; OK - go on to next bit ... 190$: BRW 195$ ; Assign channel to TT: 191$: $ASSIGN_S DEVNAM = TT_NAME,- ; TT: CHAN = TT_CHAN ; TT channel BSBW ERROR ; Check system service ; Set terminal to VT200 8bit mode $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = VT200_8BIT,- P2 = #VT200_8BIT_LEN BSBW IO_ERROR ; Check for IO errors ; Lock keyboard. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = LOCK_1,- P2 = #LOCK_1_LEN BSBW IO_ERROR ; Check for IO errors ; Wait 3 seconds before setting up transparent printing. BSBW DELAY_3 ; Enter transparent print mode. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = XPRINT_1,- P2 = #XPRINT_1_LEN BSBW IO_ERROR ; Check for IO errors RSB ; Assign channel to NL: and send OPCOM message. 195$: $ASSIGN_S DEVNAM = NL_NAME,- ; NL: CHAN = TT_CHAN ; TT channel BSBW ERROR ; Check system service $SNDOPR_S MSGBUF = BAD_TT,- ; Send OPCOM message CHAN = #0 BSBW ERROR ; Check system service RSB ;+ ; Subroutine CLOSE_TERM - Closes down terminal chan, etc. ;- CLOSE_TERM: .jsb_entry ; Exit transparent print mode. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = XPRINT_0,- P2 = #XPRINT_0_LEN BSBW IO_ERROR ; Check for IO errors ; Unlock keyboard. $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = LOCK_0,- P2 = #LOCK_0_LEN BSBW IO_ERROR ; Check for IO errors ; Set term to VT100 mode $QIOW_S - CHAN = TT_CHAN,- FUNC = #IO$_WRITEVBLK!IO$M_NOFORMAT,- IOSB = IO_STATUS,- P1 = VT100,- P2 = #VT100_LEN BSBW IO_ERROR ; Check for IO errors ; Deassign channel to TT $DASSGN_S CHAN = TT_CHAN ; Deassign TT channel BSBW ERROR ; Check system service RSB ;+ ; Subroutine DELAY_3 - Waits 3 seconds. ;- .save_psect .psect SMB_DATA NOEXE,RD,WRT,QUAD DELAY_DELTA: .ASCID /0 00:00:03.00/ ; 3 seconds delta DELAY_TIME: .BLKQ 1 ; Binary rep. of above .restore_psect DELAY_3: .jsb_entry ; Convert ASCII representation into 64 bit binary $BINTIM_S - TIMBUF = DELAY_DELTA, - TIMADR = DELAY_TIME BSBW ERROR ; Check system service ; Set time to wait $SETIMR_S - EFN = #2, - DAYTIM = DELAY_TIME BSBW ERROR ; Check system service ; Do the actual wait $WAITFR_S - EFN = #2 BSBW ERROR ; Check system service RSB ;+ ; Subroutine IO_ERROR / ERROR - Checks for errors ;- IO_ERROR: ; Check system service and I/O status .jsb_entry BLBC R0,ERR ; If low bit clear then error MOVZWL IO_STATUS,R0 ; Test I/O status ERROR: ; Check system service status (R0) .jsb_entry BLBC R0,ERR ; If low bit clear then error RSB ; No errors so return ERR: .jsb_entry input=<R0> $EXIT_S - ; Error occurred so exit CODE = R0 ; with status rsb ;+ ; Input routine - PSM$K_JOB_COMPLETION ;- COMPLETE: ;.WORD 0 ; Save nothing .call_entry preserve=<> ;+ ; Check function code ;- CMPL #PSM$K_START_TASK,@FUNC(AP) ; Start of task ? BNEQ 200$ BRW 220$ 200$: CMPL #PSM$K_READ,@FUNC(AP) ; Read ? BNEQ 210$ BRW 230$ 210$: MOVL #PSM$_FUNNOTSUP,R0 ; Unsupported function RET ; Return to symbiont ;+ ; PSM$K_START_TASK ;- 220$: MOVZBL #2,COUNT ; Reset READ call count MOVL #SS$_NORMAL,R0 ; Set success exit code RET ; Return to symbiont ;+ ; PSM$K_READ ;- 230$: DECL COUNT ; Decrement READ call count BEQL 240$ ; Branch if second ; Send a <FF> to flush output PUSHAB FORM_FEED ; <FF> descriptor PUSHL FUNC_DESC(AP) ; Symbiont descriptor CALLS #2,G^STR$COPY_DX ; Copy to symbiont buffer RET ; Return to symbiont ; Done - return PSM$_EOF 240$: MOVL #PSM$_EOF,R0 ; Set EOF exit code RET ; Return to symbiont ;+ ; End of SLAVE_SMB ;- .END SLAVE_SMB
|