From:	CSBVAX::MRGATE!@KL.SRI.Com,@wiscvm.wisc.edu:BMW6957@TAMCHEM.BITNET@SMTP 15-JUL-1987 02:37
To:	EVERHART
Subj:	Getting the Job Name Table

Received: from wiscvm.wisc.edu by KL.SRI.COM with TCP; Sun 12 Jul 87 15:33:04-PDT
Received: from TAMCHEM.BITNET by wiscvm.wisc.edu ; Sun, 12 Jul 87 17:30:42 CDT
Date:      Sun, 12-JUL-1987 17:28:48.88 CDT
From:      <bmw6957%TAMCHEM.BITNET@wiscvm.wisc.edu> (Brad Wilson)
Subject:   Getting the Job Name Table
To:        <info-vax@sri-kl.arpa>

> Does anyone have a program to return the remote node and id of a process
> that has logged in via SET HOST ?
>
> I can get this information about the CURRENT process via the logical names
> SYS$REM_NODE and SYS$REM_ID in the job logical name table, but how can I
> access the job table of another process ?  It appears that job tables have
> names of the form LNM$JOB_<jib> where <jib> is the value of PCB$L_JIB in the
> process's Process Control Block, but I don't have enough "internals" experienc
> to get at other process's PCBs.  If someone has a piece of code to get this
> far, then I can take it from there.

Ok, Dave, here is the code to get the job logical name table.  I'm posting
to the net in case anyone else is interested.  I originally wrote this code
for the purpose of obtaining the remote node and id, but never finished the
project beyond this point (It's not difficult, I just ran out of time).

Extract the following into a command procedure file and invoke it as
@file.  It will create three files: GETJIB.MAR, JOBTABLE.FOR and
TEST.FOR.  If the checksums are ok it will go ahead and compile and
link the test routine.  Good luck.

Brad Wilson
-------------------- (cut here) -------------------
$ copy:=copy
$ create:=create
$ write:=write
$ create getjib.mar
$deck/dollars="$END-OF-FILE$"
        .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
$END-OF-FILE$
$ create jobtable.for
$deck/dollars="$END-OF-FILE$"
      Subroutine JobTable (Epid, Name)
*
*     Author:   Brad Wilson
*               Department of Chemistry
*               Texas A&M University
*               College Station, TX  77843
*               BMW6957@TAMCHEM.BITNET
*
*     VMS version 4.x
*     Additional routines necessary: GETJIB
*
*     Arguments:        EPID    Longword, passed by reference.  This
*                               is the external PID of the process for
*                               which the routine returns the JOB logical
*                               name table.  The Epid is available via
*                               the $GETJPI system service.
*
*                       NAME    16 byte character string, passed by
*                               descriptor.  The routine returns the
*                               logical name table's name here.
*
*     Constructs the name of the job logical name table for the process
*     specified by 'Epid'.  The constructed name is returned in 'Name'
*     which must be at least 16 characters long.  The job logical name
*     table has a name of the form:
*
*       LNM$JOB_xxxxxxxx
*
*     where xxxxxxxx is the hexadecimal address of the process's JIB
*     (Job Information Block).  This routine calls GETJIB to retrieve
*     the JIB address for the given process.  If GETJIB fails, a blank
*     name is returned.
*
*
      Implicit Integer*4 (A-Z)
      Character*(*)     Name
*
      JIB=GETJIB(Epid)
      If(JIB.ge.0) Then
          Name=' '
      Else
          Write(Name,Fmt='(''LNM$JOB_'',Z8.8)') JIB
      End If
*
      End
$END-OF-FILE$
$ create test.for
$deck/dollars="$END-OF-FILE$"
      Program Test_jobtable
      Implicit  Integer*4 (A-Z)
      Include           '($JPIDEF)'
      Character*16      Table_Name
*
*     Get the Epid for our process
*
      Iret = Lib$Getjpi(JPI$_PID,,,Epid)
      If ( .not. Iret ) Call Exit ( Iret )
*
*     Find the name of the Job table
*
      Call JobTable( Epid, Table_Name )
      Write(Unit=6,Fmt='('' The Job table for the current'//
     1  ' process is: '',A16)') Table_Name
      End
$END-OF-FILE$
$ all_OK = "TRUE"
$ checksum getjib.mar
$ if checksum$checksum.eqs."503979704" Then goto OK1
$ Write sys$output "GETJIB.MAR may be corrupt -- checksum failed"
$ all_OK = "FALSE"
$OK1:
$ checksum jobtable.for
$ if checksum$checksum.eqs."604439292" Then goto OK2
$ Write sys$output "JOBTABLE.FOR may be corrupt -- checksum failed"
$ all_OK = "FALSE"
$OK2:
$ checksum test.for
$ if checksum$checksum.eqs."558121729" Then goto OK3
$ Write sys$output "TEST.FOR may be corrupt -- checksum failed"
$ all_OK = "FALSE"
$OK3:
$ if all_OK then goto linkit
$ Copy sys$input sys$output

 Due to errors encountered, the test program will not be built.
 Please check the files listed above and correct the problem.

$ exit
$linkit:
$ macro:=macro
$ fortram:=fortran
$ link:=link
$ macro getjib
$ fortran/nocheck jobtable
$ fortran/nocheck test
$ link test,jobtable,getjib
$ Copy sys$input sys$output

 The test program TEST.EXE has been built.  You will need CMKRNL privilege
 to run it.  It should tell you the name of the current process's logical
 name table.

$ exit
