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