Greetings! This page contains a description of and links to my device driver for Alpha/VMS that allows you to monitor a terminal. The device driver inserts itself between the port and class driver of a terminal line and logs all characters sent to the terminal line into an internal buffer. A program with CMKRNL can read the buffer. The device driver does have a number of limitations. Among them are: Only one device may be monitored at any given time. DECnet RT devices may not be monitored. These devices do not use the normal port/class driver arrangement, so this device driver cannot insert itself into those lines. You can only watch. You cannot cannot interact with the line you are monitoring. Although I am working on some of these limitations, I cannot at the moment predict when an updated version of the driver will be available. Installation of the device driver consists of these steps: Copying the source files from the distribution medium. Compiling the device driver. Loading the device driver. Copying the Device Driver The device driver installation package contains five files: LPDRIVER.MAR is the source code for the device driver. LPDRIVER.OPT is a LINK options file for the device driver. LPBUILD.COM is a DCL command file that compiles and links the device driver. LPLOAD.COM is a DCL command file that loads the device driver. BIGBOOGER.FOR is a sample application using the device driver. Copy the files into a suitable working directory. Compiling the Device Driver You must compile and link the device driver before it can be installed into the operating system. Do this by executing the LPBUILD command procedure. The compiler will generate many informational messages that should be ignored. The build procedure looks something like this: $ set proc/priv=all $ @lpbuild 1040$: MOVQ @Ucb$L_SvaPte(R5),@Ucb$L_WindowSvaPte(R5) ^ %AMAC-I-QUADMEMREF, quadword memory references... at line number 438 in file USERS:[IVIE.USU20.... BRB 1010$ ^ %AMAC-I-BRANCHBET, branch between routines from... at line number 433 in file USERS:[IVIE.USU20.... BNEQ 1040$ ^ %AMAC-I-BRANCHBET, branch between routines... at line number 415 in file USERS:[IVIE.USU20.... BRB 1100$ ^ %AMAC-I-BRANCHBET, branch between routines from... at line number 416 in file USERS:[IVIE.USU20... $ The build procedure copies the device driver into SYS$LOADABLE_IMAGES:. After building the device driver, you should see a file named SYS$LPDRIVER.EXE in SYS$LOADABLE_IMAGES:. Loading the Device Driver After the device driver has been assembled and linked, it must be installed into the operating system using SYSMAN. This is done by the LPLOAD command procedure. LPLOAD loads the device driver and assigns it the name LPA0:. After loading the device driver, you should see a device named LPA0: that is online, like this: $ @LPLOAD $ SHOW DEVICE LP Device Device Error Name Status Count LPA0: Online 0 $ To the casual observer, LPA0: looks like a line printer: $ SHOW DEVICE/FULL LPA0: Printer LPA0:, device type LA11, is online, record-oriented device, carriage control. Error count 0 Operations completed... Owner process "" Owner UIC... Owner process ID 00000000 Dev Prot S:RWLP,... Reference count 0 Default buffer size... Page width 80 Page Length... No Carriage_return Formfeed Uppercase No Passall No Wrap No Printall No Fallback No Tab No Truncate $ Note that a normal user can see the owner UIC and process name of a process connected to LPA0:. If you wish to hide your snooping from normal users, you may want to change your process name to something innocuous (for example, SYMB0003) when you use the device driver. Using the Device Driver The device driver is used by a front-end program. It understands only the $QIO commands necessary to do its job: IO$SenseMode, IO$SenseChar, IO$ConIntRead, IO$ConIntWrite, IO$ReadVBlk, IO$ReadLBlk, and IO$ReadPBlk. IO$SenseMode and IO$SenseChar These functions are supported to allow the device driver to put up the facade of being a line printer. They work in the manner described by the I/O Users Guide for the line printer driver. IO$ConIntRead This function is used to attach the device driver to a terminal line that is to be monitored. It takes the following parameters: P1: The name of the controller to which the driver is to be attached. This is passed by value and contains a .ASCIC specification of the three-character controller name. For example, to attach to a line named TCA1:, P1 would be passed (in FORTRAN) as %val( '41435403'X ). P2: The unit number of the line to which the driver is to be attached. This is passed by value. For example, to attach to a line named TCA1:, P2 would be passed (in FORTRAN) as %val( 1 ). The remaining QIO parameters are not used. This QIO may return the following error codes: SS$IllIoFunc: The process issuing the $QIO does not have the CMKRNL privilege. SS$BadParam: P1 does not appear to be a .ASCIC specification of a three-letter controller name. SS$TermNetDev: The specified terminal line appears to be a DECnet remote terminal. Only local terminals, TCP/IP pseudoterminals, and DECwindows pseudoterminals may be monitored. SS$DevOffLine: The specified terminal line is marked offline. It is probably a template device used to create pseudoterminals as TCP/IP or DECwindows terminals are needed. SS$IvDevNam: The specified device is not a terminal. SS$NoSuchDev: There is no device in the system with the specified name. Once connected to the terminal line, all data sent to the terminal is copied into a local buffer. The Read $QIOs may be used to extract this data. When the buffer fills up, data is not copied until some of the data in the buffer is read. However, data flowing to the terminal is not stopped; the data sent while the buffer is full is lost. IO$ConIntWrite This function causes the driver to disconnect itself from any terminal line to which it may be connected. No parameters are required (the driver knows to which line it is connected). The following error codes may be generated: SS$IllIoFunc: The process issuing the $QIO does not have the CMKRNL privilege. SS$Normal: Either the device driver has disconnected itself or it was not connected to a terminal. IO$ReadVBlk, IO$ReadLBlk, and IO$ReadPBlk Once the device driver has been connected to a terminal line, all data sent to the terminal line is copied into a buffer in the device driver. These functions read data from that buffer. If there is data in the buffer, the $QIO reads the data that is available and then terminates. If there is no data in the buffer, the $QIO will wait for data to arrive in the buffer before reading that data and terminating. When the buffer becomes full, the device driver stops logging data in the buffer until some of the data has been read, making room for new data. While the buffer is full, data can still flow to the terminal, it is just not logged; that data is lost. The Read $QIOs take the following parameters: P1: The address of the buffer that will receive the data. P2: The maximum number of bytes that may be read by this $QIO. The $QIO terminates when either the buffer has become empty or this many bytes have been read. The Read $QIOs may return the following status: SS$IllIoFunc: The process issuing the $QIO does not have the CMKRNL privilege. SS$Normal: The $QIO has been completed. On completion, the high-order word of the first longword of the I/O Status Block indicates the number of bytes that were read. This limits transfers to 64KBytes. The Example Application BIGBOOGER is an example front end for the device driver. It allows the user to connect to any terminal line and display the data sent to that terminal line. To compile BIGBOOGER, you need the FORTRAN compiler. Do this: $ FORTRAN BIGBOOGER $ LINK BIGBOOGER $ When run, BIGBOOGER prompts for the controller name and unit number of the device that you want to monitor. It then connects to that device and continuously displays what is in the device driver's buffer. You exit BIGBOOGER by typing Y. To monitor the terminal TCA1, do this: $ RUN BIGBOOGER Controller (e.g. TXA)? TCA Unit? 1