From:	CSBVAX::MRGATE!@KL.SRI.Com,@wiscvm.wisc.edu:MCKEEVER@UMKCVAX2.BITNET@SMTP 27-JUL-1987 23:48
To:	EVERHART
Subj:	Program to get remote user and node names.

Received: from wiscvm.wisc.edu by KL.SRI.COM with TCP; Mon 27 Jul 87 11:18:19-PDT
Received: from UMKCVAX2.BITNET by wiscvm.wisc.edu ; Mon, 27 Jul 87 13:16:18 CDT
Date:     Mon, 27 Jul 87 09:13 CDT
From:     <MCKEEVER%UMKCVAX2.BITNET@wiscvm.wisc.edu>
Subject:  Program to get remote user and node names.
To:       INFO-VAX@SRI-KL.ARPA
X-Original-To:  INFO-VAX@SRI-KL.ARPA


I was trying to pretty it up before I sent it out, but there are so many
requests on how to get the remote username and node name on the network that
I decided to send it out, and let hackers, techies, or whatever, taylor it
to their needs.  Basically, the program scans the system, getting the PIDs
of each user on the system with a $GETJPI call.  If the user is on an "RT"
terminal, the program uses Brad Wilson's kernel mode routine to get the JIB
number and the name of the users job logical name table.  It then translates
the users SYS$REM_ID and SYS$REM_NODE logical names to get the remote
username and node name, respectively.  I realize that the code is not the
most elegant in the world, I just hacked a program I wrote several months
ago when I was first learning MACRO just to see if it would work.  Please
excuse any superfluous code.  I intend to incorporate this program's
functionality into my OPMON (Operations Monitor) program so that operators
can know where people are coming from.  Any comments from the wizzards on
the network on how to improve this program, or progress reports on how other
people are using the program are welcomed.  I'm always willing to learn new
tricks.

BTW:  My OPMON program is written in MACRO and uses SMG routine's to manage
      menus and windows (I like to use SMuGgies).  When I get it to the
      stage that I wouldn't be ashamed of it of the messy, uncommented
      code, I'll put a message out on the net and send it to interested
      parties.  It shows all interactive users, batch jobs, subprocesses,
      detached jobs, and system processes, by catagory, at the same time.
      And allows the operator to stop processes, suspend/resume processes,
      watch a single process in detail...and a lot more.  We find it quite
      useful.

+-------------------CUT HERE--------------------------------------------+
$ Write Sys$Output " - Creating JIB.MAR"
$ Create JIB.MAR
$ Deck
        .TITLE  JP
;
        .LIBRARY        "SYS$LIBRARY:LIB"
        .LINK           "SYS$SYSTEM:SYS.STB"/SELECTIVE_SEARCH
;
        $JPIDEF
        $IODEF
        $PCBDEF
        $PRDEF
        $IPLDEF
        $lnmdef
;
        .PSECT  NONSHARED_DATA  PIC, NOEXE, LONG, NOSHR
;
HEXPID:         .BLKL           1
GRP:            .LONG           0       ; Group UIC
MEM:            .LONG           0       ; Member UIC
WILD_CARD:      .LONG           -1      ; Wildcard PID
HEXPID_RET:     .WORD           4
GRP_RET:        .WORD           4
MEM_RET:        .WORD           4
CR      = 13                            ; Carriage return
LF      = 10                            ; Line feed
SYNCH:          .LONG   IPL$_SYNCH      ; IPL level to sync access
;
USERNAME_LEN = 12
USERNAME_OUT = USERNAME_LEN + 1
USERNAME:       .BLKB           USERNAME_LEN
USERNAME_DSC:   .LONG           USERNAME_LEN
                .ADDRESS        USERNAME
;
IMAGE_LEN = 39
IMAGE_OUT = IMAGE_LEN + 1
IMAGE_FILE:     .BLKB           IMAGE_LEN
IMAGE:          .LONG           IMAGE_LEN
                .ADDRESS        IMAGE_FILE
;
UIC_LEN = 9
UIC_OUT = UIC_LEN + 2
UIC:            .BLKB           UIC_LEN
UIC_DSC:        .LONG           UIC_LEN
                .ADDRESS        UIC
;
CTRSTR_PID:     .ASCID          /!8XL/
CTRSTR_UIC:     .ASCID          /[!3OL,!3OL]/
JIB_CTRSTR:     .ASCID          "LNM$JOB_!8XL"
;
JIB_LEN = 16
JIB_OUT = JIB_LEN + 2
JIB:            .BLKB           JIB_LEN
JIB_DSC:        .LONG           JIB_LEN
                .ADDRESS        JIB
;
PID_LEN = 8
PID_OUT = PID_LEN + 2
PID:            .BLKB           PID_LEN
PID_DSC:        .LONG           PID_LEN
                .ADDRESS        PID
;
TERM_LEN = 7
TERM_OUT = TERM_LEN + 1
TERM_LOC:       .BLKB           TERM_LEN
TERM:           .LONG           TERM_LEN
                .ADDRESS        TERM_LOC
;
ARGLST:
                .LONG           1
                .ADDRESS        HEXPID
HEXJIB:         .LONG           0
EPID:           .LONG           0
;
DETAIL_LEN = 81
DETAIL_END = DETAIL_LEN - 1
DETAIL_LINE:    .BLKB           DETAIL_LEN
DETAIL_DSC:     .LONG           DETAIL_LEN
                .ADDRESS        DETAIL_LINE
rt:             .ascii          "RT"
;
terminal_dsc:   .ascid          "TT:"
FILL_CHAR:      .ASCII          / /
;
trnlnm_list:    .word           255, lnm$_string
                .address        actual_buf, actual_dsc
                .long           0
;
index:          .word           0
index_ret:      .word           0
actual_dsc:     .long           255
                .address        actual_buf
actual_buf:     .blkb           255
;
rem_id:         .ascid          "SYS$REM_ID"
rem_node:       .ascid          "SYS$REM_NODE"
;
JPI_LIST:       .WORD           IMAGE_LEN, JPI$_IMAGNAME
                .ADDRESS        IMAGE_FILE, IMAGE
                .WORD           TERM_LEN, JPI$_TERMINAL
                .ADDRESS        TERM_LOC, TERM
                .WORD           4, JPI$_GRP
                .ADDRESS        GRP, GRP_RET
                .WORD           USERNAME_LEN, JPI$_USERNAME
                .ADDRESS        USERNAME, USERNAME_DSC
                .WORD           4, JPI$_PID
                .ADDRESS        HEXPID, HEXPID_RET
                .WORD           4, JPI$_MEM
                .ADDRESS        MEM, MEM_RET
                .LONG           0
;
        .PSECT  CODE            PIC, SHR, NOWRT, LONG, EXE
        .ENTRY  BEGIN   ^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;
;       Start GETJPI loop.
;
LOOP:   $GETJPI_S       EFN=#1, PIDADR=Wild_Card, ITMLST=Jpi_List
        BLBS            R0, WAIT
        CMPW            R0, #SS$_NOPRIV
        BEQL            LOOP
        CMPW            R0, #SS$_SUSPENDED
        BEQL            LOOP
        CMPW            R0, #SS$_NOMOREPROC
        BNEQ            NO_JUMP
        JMP             DONE
NO_JUMP:
        BRW             ERROR_EXIT
;
WAIT:
        $WAITFR_S       EFN=#1
        BLBS            R0, 10$
        BRW             ERROR_EXIT
;
10$:    CMPL            GRP, #1
        BGTR            PRINT           ; Not a system group number.
        BRW             LOOP            ; Is a system group number.
PRINT:
;
;       Format and Print current Terminal, Username, and Image.
;
;       Let's try to call the KERNAL mode routine.
;
        CALLG   ARGLST, G^GETJIB
        MOVL    R0, HEXJIB
;
40$:
        MOVAL   DETAIL_LINE, R8
        MOVC5   TERM, TERM_LOC, FILL_CHAR, #TERM_OUT, (R8)
        ADDL2   #TERM_OUT, R8
        MOVC5   USERNAME_DSC, USERNAME, FILL_CHAR, #USERNAME_OUT, (R8)
        ADDL2   #USERNAME_OUT, R8
        $FAO_S  CTRSTR=CTRSTR_PID, OUTBUF=PID_DSC, P1=HEXPID
        MOVC5   PID_DSC, PID, FILL_CHAR, #PID_OUT, (R8)
        ADDL2   #PID_OUT, R8
        $FAO_S  CTRSTR=CTRSTR_UIC, OUTBUF=UIC_DSC, P1=GRP, P2=MEM
        MOVC5   UIC_DSC, UIC, FILL_CHAR, #UIC_OUT, (R8)
        ADDL2   #UIC_OUT, R8
        $FAO_S  CTRSTR=JIB_CTRSTR, OUTBUF=JIB_DSC, P1=HEXJIB
        MOVC5   JIB_DSC, JIB, FILL_CHAR, #JIB_OUT, (R8)
        ADDL2   #JIB_OUT, R8
        MOVAL   IMAGE_FILE, R6
;
        LOCC    #^A/]/, IMAGE, (R6)     ; Locate the first right bracket.
        BEQL    31$                     ; Was it found.
        ADDL3   #1, R1, R6              ; Save Location of good char.
        SUBL3   #1, R0, R7
        MOVL    R0, R10
;
        LOCC    #^A/]/, R10, (R6)       ; Locate the second right bracket.
        BEQL    29$
        ADDL3   #1, R1, R6              ; Save Location of good char.
        SUBL3   #1, R0, R7
        MOVL    R0, R10
;
29$:    MOVL    R6, R11                 ; Save last useable character.
        LOCC    #^A/./, R10, (R6)       ; Locate the second right bracket.
        BEQL    31$
        MOVL    R1, R6                  ; Save Location of good char.
;
        SUBL3   R11, R6, R7
        MOVC3   R7, (R11), (R8)
        ADDL2   R7, R8
31$:
        SUBL3   #DETAIL_LINE, R8, DETAIL_DSC
        PUSHAL  DETAIL_DSC
        CALLS   #1, G^LIB$PUT_OUTPUT
        BLBS    R0, 20$
        BRW     ERROR_EXIT
20$:
OOPS:
        cmpc3   #2, term_loc, rt
        beql    99$
        brw     loop
99$:
        $trnlnm_s       tabnam=jib_dsc, lognam=rem_id, -
                        itmlst=trnlnm_list
        blbs    r0, 121$
        brw     error_exit
121$:
        PUSHAL  actual_dsc
        CALLS   #1, G^LIB$PUT_OUTPUT
        BLBS    R0, 122$
        BRW     ERROR_EXIT
122$:
        $trnlnm_s       tabnam=jib_dsc, lognam=rem_node, -
                        itmlst=trnlnm_list
        blbs    r0, 123$
        brw     error_exit
123$:
        PUSHAL  actual_dsc
        calls   #1, g^lib$put_output
        blbs    r0, 124$
        brw     error_exit
124$:
        BRW     LOOP            ; Do it again.
;
DONE:
        MOVL    #1, R0
        RET
;
ERROR_EXIT:
        PUSHL   R0
        CALLS   #1, G^LIB$STOP
        RET
;
        .END    BEGIN
$ EOD
$ Write Sys$Output " - Creating GETJIB.MAR"
$ Create GetJib.Mar
$ Deck
        .title  GETJIB - get JIB address from EPID
;+
;       Author: Brad Wilson
;               Department of Chemistry
;               Texas A&M University
;               College Station, TX 77843
;               BMW6957@TAMCHEM.BITNET
;
;       VMS Version 4.x
;
;       This routine will return the Job Information Block address for a process
;       with a given External Process IDentification (EPID).  The routine
;       operates in kernel mode and requires CMKRNL privilege to execute.
;       The calling sequence is:
;
;       jib.wlv = getjib(epid.rlr)
;
;               jib     -- The longword JIB address or zero if an error occurred
;                          If the process does not have CMKRNL privilege, then
;                          the value SS$_NOPRIV will be returned here.  Note
;                          that all valid JIB addresses are negative when
;                          interpreted as a signed value (JIB's reside in
;                          system P0 space) and this can be used to determine
;                          if the routine has returned a JIB or a status.
;               epid    -- The longword EPID of the process for which info is to
;                          be returned, passed by reference.
;
;       NOTES:
;
;       Portions of the following code execute at elevated IPL (IPL$_SYNCH).
;       Since IPL is raised above IPL$_ASTDEL, page faults MUST NOT OCCUR!
;       Anyone modifying the code below should understand the complete
;       ramifications of this before proceeding.  Important points to note
;       are:
;               1) EXE$EPID_TO_PCB is located in non-paged memory, so
;                  references to it are safe.
;               2) The routine EXE$EPID_TO_PCB will not cause page
;                  faults (or so the microfiche claim) and is safe to
;                  call at elevated IPL.
;               3) The PCB structure is in non-paged pool and references
;                  to it will not cause page faults.
;               4) The DSBINT macro below uses a trick to ensure that
;                  the code here is all locked into the working set.
;                  In particular, since the macro references the
;                  longward "SYNCH", the instruction cannot execute
;                  until both the instruction AND the value at "SYNCH"
;                  are in the working set.  As long as "SYNCH" and the
;                  DSBINT macro are less than one page apart, we are
;                  then guaranteed that all code lying between them
;                  is in the working set when the DSBINT macro raises
;                  IPL.  Once the IPL has been raised, page faults
;                  cannot occur, so the code will remain in the
;                  working set until IPL is lowered by the ENBINT
;                  macro.
;-
;
        .Library        "SYS$LIBRARY:LIB"       ;Get special macros from here
        .Link           "SYS$SYSTEM:SYS.STB"/Selective_Search   ;Ease the link
;                                                               ;process a bit
;
        $PCBDEF         ; define PCB offsets
        $PRDEF          ; define privileged registers
        $IPLDEF         ; define IPL values
;
        .Psect          CODE,EXE,RD,NOWRT,PIC,SHR,PAGE
;
        .entry  getjib,^M<>
        $cmkrnl_s       routin=b^20$,arglst=(ap)        ; change to kernel mode
        ret                                     ; return whatever k-mode does
;
20$:    .WORD   ^M<R2,R3,R4,R5>                 ; EXE$EPID_TO_PCB uses up to R5
        CLRL    R0                              ; Assume an error
        IFNORD  #<2*4>,(AP),EXIT                ; Probe the arglist for read
        CMPB    #1,(AP)                         ; Check for one argument
        BNEQ    EXIT                            ; Wrong number of arguments
        IFNORD  #4,@4(AP),EXIT                  ; Probe EPID for read
        MOVL    @4(AP),R0                       ; Move EPID into R0
        BEQL    EXIT                            ; EPID was omitted, return
BEGIN_LOCK:
        DSBINT  SYNCH                           ; Raise IPL, lock pages
        JSB     @#EXE$EPID_TO_PCB               ; convert EPID to PCB
        BEQL    10$                             ; oops, bad news
        MOVL    PCB$L_JIB(R0),R0                ; read JIB field of PCB
10$:    ENBINT                                  ; Lower IPL
EXIT:   RET                                     ; Return from kernel mode
SYNCH:  .LONG   IPL$_SYNCH                      ; IPL level to sync access
END_LOCK:
        ASSUME  <END_LOCK-BEGIN_LOCK> LE 512    ; ensure < 1 page locked
        .end
$ EOD
$ Write Sys$Output " - MACROing JIB and GETJIB"
$ Macro JIB,GetJib
$ Write Sys$Output " - LINKing JIB and GETJIB"
$ Link/NoTrace JIB,GetJib
$ Type Sys$Input

      Ok.  JIB.EXE has been created.  It's not elegant but it works.
      With a little effort you should be able to pretty it up, or
      include it in your own programs.  Remember, you will need CMKRNL,
      and SYSPRV before this thing works correctly.  If you see a
      job table name of LNM$JOB_00000024, you didn't have the privs you
      needed to run the program.  CMKRNL gives you the JIB and SYSPRV
      allows you to look at someone elses job table.  My thanks to
      Brad Wilson for writing the kernel mode psect for me.

-------------------------------------------------------------------------
     UMU   UMUMUMUMUM            Brian McKeever
     UMU   UMUMUMUMUM
     UMU   UMUMUMUMUM            University of Missouri Kansas City
      U   UM        U            Computer Science
  U      UM     UM      UM       4747 Building Rm. 219
  UMUMUMUM     UMUM    UMUM      5100 RockHill Rd.
  UMUMUMUM     UMUM    UMUM      Kansas City, MO  64110
  UMUMUMUM     UMUM    UMUM      BITNET:  MCKEEVER@UMKCVAX1
-------------------------------------------------------------------------
