DAVID W. DELEY

System services and itemlists

A system service routine like SYS$GETJPI (get job process information)
can return many various things, like the username or the PID (process
identification number).  Rather than call the system service over again
for each item you want, system service routines use item lists so you
only have to call the system service once to obtain everything you want.

An itemlist is a list of the items you want.  An item list needs to
contain:
     (1).  A list of the items you want, like USERNAME, PID, etc.
           This is the item code.
     (2).  Where to place the desired information.  i.e. what character
           string to put the USERNAME in and what integer variable to
           put the PID in.  This is the user supplied buffer.  (What
           you actually place in the item list is not the character
           string or integer itself, you place the location of the
           character string or integer.  This is done in fortran using
           the %LOC(variable). )

Along with the obvious an actual item list also contains:
     (3).  The length of the place to put the desired information.  If
           you requested USERNAME this is the length of the character
           string to put the username in.  If you requested PID, this
           is the length of the integer variable to put the PID in,
           which is always 4, since a standard integer consists of
           4 bytes.  (That's why declaring INTEGER and INTEGER*4 are
           equivalent.)  This is the user supplied buffer length.

     (4).  An integer for the system service to return the actual length
           it returned.  If you requested USERNAME, this is the actual
           length of the username, (unless your character string was too
           short, in which case it fills the character string and
           returns the length of the character string.  It's actually
           the length in bytes of the information it actually returned.)
           This is the return length buffer.  (Again what you actually
           place in the item list is not the integer itself, but the
           location of the integer.  This is done in fortran by using
           the %LOC(variable). )  (You may pass a 0 instead of
           %LOC(variable) if you do not care for this information.)
           (If you requested something like PID which goes into an
           integer*4 variable, the returned value here is always 4.)


FORMAT OF ITEM LIST
An item list is a continuous section of memory divided up as follows:
     INTEGER*2  buffer length
     INTEGER*2  item code
     INTEGER*4  location of user supplied buffer
     INTEGER*4  location of user supplied return length buffer

The structure above requests one item.  At this point you could request
two items by appending another structure as follows:
     INTEGER*2  buffer length for item #1
     INTEGER*2  item code of item #1
     INTEGER*4  location of user supplied buffer for item #1
     INTEGER*4  location of user supplied return length buffer for item #1
     INTEGER*2  buffer length for item #2
     INTEGER*2  item code for item #2
     INTEGER*4  location of user supplied buffer for item #2
     INTEGER*4  location of user supplied return length buffer for item #2

You can continue appending structures until you have requested all the
items you want.  You indicate the end of an item list by appending an
integer containing the value 0 to the end of the list.  Thus a complete
item list requesting two items would be:
     INTEGER*2  buffer length for item #1
     INTEGER*2  item code of item #1
     INTEGER*4  location of user supplied buffer for item #1
     INTEGER*4  location of user supplied return length buffer for item #1
     INTEGER*2  buffer length for item #2
     INTEGER*2  item code for item #2
     INTEGER*4  location of user supplied buffer for item #2
     INTEGER*4  location of user supplied return length buffer for item #2
     INTEGER*4  0


FORTRAN EXAMPLE:
To achieve this item list structure in fortran use the STRUCTURE
directive when declaring variables.

	! Define item list structure
	STRUCTURE	/ITMLST/
	  UNION
	    MAP
	      INTEGER*2 BUFLEN,ITMCOD
	      INTEGER*4 BUFADR, RETADR
	    END MAP
	    MAP
	      INTEGER*4 END_LIST
	    END MAP
	  END UNION
	END STRUCTURE

The above structure definition defines the structure of a record where
each record either consists of:
         INTEGER*2  BUFLEN
         INTEGER*2  ITMCOD
         INTEGER*4  BUFADR
         INTEGER*4  RETADR
which requests an item, or it consists of:
         INTEGER*4  END_LIST
which is to contain the 0 indicating the end of the list.  (This briefly
explains the UNION and MAP statements.  This isn't important to fully
understand.)

The only other stuff you need is the item code definitions for your
system service routine.  The item codes are usually obtained by
including a system defined file of the name ($xxxDEF)  at the top of
your program where xxx are the identifying letters of the system service
routine you're using.
Here's an example program now.  Examples usually make more sense than
words:

	PROGRAM GET_USERNAME

	INCLUDE  '($JPIDEF)'			!Get jpi$_xxx definitions

	INTEGER		SYS$GETJPIW		!Declare as integer so can call as status = sys$getjpi(...)
	INTEGER		STATUS			!Return status from call to sys$getjpi
	INTEGER*4	USERNAME_LEN		!Length of username returned
	CHARACTER*12	USERNAME		!Username returned

	! Define item list structure
	STRUCTURE	/ITMLST/
	  UNION
	    MAP
	      INTEGER*2 BUFLEN,ITMCOD
	      INTEGER*4 BUFADR, RETADR
	    END MAP
	    MAP
	      INTEGER*4 END_LIST
	    END MAP
	  END UNION
	END STRUCTURE

	! Declare $GETJPI item list
	RECORD  /ITMLST/  GETJPI_LIST(2)
C----------------------------------------------------------------------
	!Initialize item list
	GETJPI_LIST(1).BUFLEN =  12			!Length of character string USERNAME
	GETJPI_LIST(1).ITMCOD =  JPI$_USERNAME		!Item code requesting username
	GETJPI_LIST(1).BUFADR =  %LOC(USERNAME)		!Location of character string USERNAME
	GETJPI_LIST(1).RETADR =  %LOC(USERNAME_LEN)	!Location of integer USERNAME_LEN
	GETJPI_LIST(2).END_LIST = 0			!Mark end of item list

	!Call the system service
	STATUS = SYS$GETJPIW(, , , GETJPI_LIST, , ,)
	IF (.NOT. STATUS)  CALL LIB$SIGNAL( %VAL(STATUS))

	PRINT*, USERNAME(1:USERNAME_LEN)
	END

Back