;++ ; LASTCMD.MAR - Peek at Terminal Typeahead Buffer ; (c) Copyright 1994, Chris Olive & Siemens Medical Systems ; All rights reserved ; ; ENVIRONMENT ; ; OpenVMS AXP v1.5-1H1, OpenVMS VAX v5.5-2 ; OpenVMS MACRO ; ; ABSTRACT ; ; Swipes the typeahead buffer from a terminal device's UCB -> TTYTA ; area and prints it to the screen (my screen, not theirs!). This ; effectively gets the last command entered by a user on his terminal ; regardless of the environment in which he is (mostly), unlike Hunter ; Goatley's GETCMD which returns the DCL recall command buffer. ; ; BTW, this will also effectively beat a program written by David ; North, called DO, which hooks SYS$CLI with a custom built command ; descriptor block in an attempt to avoid placing a DCL cmd in the recall ; buffer. ; ; Special thanks to Hunter Goatley (goathunter@wkuvx1.wku.edu) for ; testing this for both VAX and Alpha VMS, and doing a little patch ; work on saved registers in kernel mode for me. ; ; Requires: CMKRNL (as a matter of course...) ; ; AUTHOR, INSTALLATION and DATE ; ; Chris Olive ; VMS System Consultant ; Aerotek Engineering Services ; Rolling Meadows, IL ; 12-SEP-1994 ; ; CODE GENERATION ; ; VAX _______________________________________________________ ; Assemble: $ MACRO/NOLIST LASTCMD ; Link: $ LINK/NOMAP/NOTRACEBACK LASTCMD ; Setup: $ LASTC*MD :== $device:[directory]LASTCMD ; Usage: $ LASTCMD ; ; AXP _______________________________________________________ ; "Assemble": $ MACRO/NOLIST LASTCMD ; Link: $ LINK/NOMAP/NOTRACEBACK LASTCMD, SYS$INPUT/OPT ; SYS$LOADABLE_IMAGES:SYS$BASE_IMAGE.EXE/SHARE ; ; Setup: $ LASTC*MD :== $device:[directory]LASTCMD ; Usage: $ LASTCMD ; ; MODIFICATION HISTORY ; ; Date Author Revision ; ----------- ----------------------- --------- ; 14-SEP-1994 Hunter Goatley v1.00-001 ; ; o Added Alpha-compliant PUSHREG and POPREG macros. ; o Save R4 in krnl mode to keep from stomping on PCB ptr. ; o Longword align itmlst and return typahd block areas. ; ; 14-SEP-1994 Chris Olive v1.00-002 ; ; o Added code to eliminate RT devices from being probed. ; (That's right... *another* program which doesn't ; support the RT device!) ;-- .page .title lastcmd Display Last Command .ident 'v1.00-002' ;--- Determine architecture --- .ntype $$$isaxp, r20 ; Do we have a register 20? $$$isaxp=<$$$isaxp@-4&^xF>-5 ; See if it's a hardware reg .iif eq, $$$isaxp, alpha=1 ; If it is, define ALPHA ;--- Directives --- .library 'sys$library:lib' .if ndf ALPHA .link 'sys$system:sys.stb'/selective_search .endc ;--- Macro definitions section -- ; Push a register, Alpha or VAX .macro pushreg, reg .if defined alpha $push64 reg ; Alpha PUSH .iff pushl reg ; VAX PUSH .endc .endm pushreg ; Pop a register, Alpha or VAX .macro popreg, reg .if defined alpha $pop64 reg ; Alpha POP .iff popl reg ; VAX POP .endc .endm popreg ; Error handling macro .macro on_err, reg=r0, do=ret, ?lbl blbs reg, lbl ; Got an error? do ; Yep, so do something about it lbl: ; No, so continue on .endm on_err ; Item list 3 item short cut macro .macro .item3, itmcod=0, buflen=0, retadr=0, retlen=0 .word buflen ; Buffer length .word itmcod ; Item code .address retadr ; Reference return buffer .address retlen ; Reference return length .endm .item3 ;--- Macro inherits section --- $dcdef ; Device Class defs $dvidef ; Device items defs $rmsdef ; RMS codes defs $ssdef ; System Status codes defs $ttytadef ; TTY typeahead defs $ttyucbdef ; TTY Unit Control Blk defs $ucbdef ; Unit Control Blk defs ;--- Data section --- .page .sbttl Data section .psect lastcmd_data, rd, wrt, noexe, long devnam_dsc: .long 64 ; Device name descriptor .address .+4 ; .blkb 64 ; Device name buffer prompt_dsc: .ascid '_Terminal: ' ; Prompt descriptor .align long ; Longword align block dvi_itmlst: .item3 DVI$_DEVCLASS, 4, dev_class .item3 0 dev_class: .long 0 typahd_len: .word 0 ; Typeahead length .align long ; Longword align block typahd_buf: .blkb TTY$K_TA_RCLLEN ; Typeahead buffer ;--- Code section --- .page .sbttl Code section (user-mode) .psect lastcmd_code, rd, nowrt, exe, long .entry lastcmd, ^m<> ; Get the device name of the terminal from which to grab the ; typeahead buffer. pushaw devnam_dsc ; Reference return length pushaq prompt_dsc ; Reference prompt descriptor pushaq devnam_dsc ; Reference return devnam desc calls #3, g^lib$get_foreign ; Bang... Get the device name cmpl r0, #RMS$_EOF ; Was entered? bneq 20$ ; No, so go on 10$: movl #SS$_NORMAL, r0 ; Stuff return status ret ; Return to caller 20$: on_err ; Check for other errors tstw devnam_dsc ; Was anything entered? beql 10$ ; No, so quit ; Make sure this is a terminal device we are trying to grab from. $getdvi_s devnam=devnam_dsc, - ; Bang... Get device information itmlst=dvi_itmlst ; on_err ; Handle any return errors cmpl dev_class, #DC$_TERM ; Is this a terminal device? beql 30$ ; Yep, so go on movl #SS$_IVDEVNAM, r0 ; Stuff return status ret ; Return to caller ; Go get the typeahead buffer 30$: $cmkrnl_s routin=grab_typahd ; Bang, go fetch typeahead buf on_err ; Handle any return errors ; Setup a descriptor, and print the typeahead buffer. clrq -(sp) ; Pardon me, I need 8 bytes... movzwl typahd_len, (sp) ; Stuff typahead length movab typahd_buf, 4(sp) ; Stuff typahead reference pushaq (sp) ; Reference stack descriptor calls #1, g^lib$put_output ; Bang... Print it ret ; Return to caller ;--- Kernel mode code section --- .page .sbttl Code section (kernel mode) .psect last_cmd_k, rd, nowrt, exe, long .entry grab_typahd, ^m moval krnl_handler, (fp) ;* Handle KRNL errors (ACCVIO) jsb g^sch$iolockr ;* Read lock I/O database movaq devnam_dsc, r1 ;* Reference devnam descriptor jsb g^ioc$searchdev ;* Get UCB address for device on_err do= ;* Handle any errors movl UCB$L_TL_PHYUCB(r1), r1 ;* Chain to physical UCB movl #SS$_IVDEVNAM, r0 ;* Ready error status for chk cmpw UCB$W_SIZE(r1),#UCB$K_TT_LENGTH ;* Make sure UCB is right size blss 10$ ;* Get outta here if not movl UCB$L_TT_TYPAHD(r1), r11 ;* Get typeahead blk address movw TTY$W_TA_RCLSIZ(r11), - ;* Copy typeahead buffer size typahd_len ;* to typeahead length pushreg r4 ;* Save PCB address movc3 TTY$W_TA_RCLSIZ(r11), - ;* Copy contents of typeahead TTY$A_TA_RCL(r11), - ;* buffer to local buffer typahd_buf ;* to print later popreg r4 ;* Restore PCB address movl #SS$_NORMAL, r0 ;* Set success status 10$: pushreg r0 ;* Save return status jsb g^sch$iounlock ;* Unlock the I/O database popreg r0 ;* Restore return status ret ;* Return to caller .sbttl Kernel mode error handler .entry krnl_handler, ^m<> $unwind_s ;* Unwind the stack ret ;* Return to caller .end lastcmd