Have you every tried to retrieve profile information from the RACF database for use in a Rexx program? If so, you have most likely issued a RACF list (listuser, rlist, etc.) command, and then parse the output to find what was needed. While not quite up there with classic problems in the field of computer science, it does end up being surprisingly time consuming and quite fiddly. RACF command output seems to have intentionally designed to be as difficult to parse as possible.
Starting in z/OSv1R11, it is much easier to get this information into your favorite Rexx programs using the IRRXUTIL utility. IRRXUTIL is a program which reads RACF profile information, and stores it into Rexx stem variables for easy reference and use. No more parsing of RACF list command output, unless you're in to that sort of thing.
Saying it is easy to retrieve the profile information doesn't mean that just anyone can do it. You still need to have permission to the data being retrieved. If you are not allowed to list the data with a RACF command, you won't be able to get it with IRRXUTIL either. You also need permission to use the r_admin callable service which is used by IRRXUTIL on your behalf. RACF documentation cover all of these exciting details.
Using IRRXUTIL you can retrieve profile information about users, groups, general resources, and general RACF settings administered by the setropts command. There is no IRRXUTIL support for dataset profiles. IRRXUTIL can extract the specified profile via the Extract function or the profile following the specified profile with the Extractn function.
Here is a very simple example. It displays the unix UID of a user and the GID of the user's default group. All it does is call IRRXUTIL to extract the user, retrieve the default group using information from the user profile, then prints the user UID and group GID.
/* REXX */
arg usermyrc=IRRXUTIL("EXTRACT","USER",user,"USR","R_") /* extract user */
groupId=USR.R_BASE.R_DFLTGRP.1 /* get default group from user profile */
myrc=IRRXUTIL("EXTRACT","GROUP",groupId,"GRP","R_") /* extract default group */
Say "User: "user /* Output user id */
say "OMVS uid="USR.R_OMVS.R_UID.1 /* Output user OMVS uid */
Say "Default group:"groupId /* Output group name */
say "OMVS gid="GRP.R_OMVS.R_GID.1 /* Output group GID */
For brevity, this example is missing vital return code checking, it is meant to be an example of the simplicity of the interface.
Using the Rexx variables:
The user profile was extracted into Rexx stem variable USR, as specified on the call to IRRXUTIL. The profile data is retrieved using RACF segment and field names. To get the OMVS(UID(xx)) (segment=OMVS, field=UID) field, simply reference it by its newly defined variable name USR.R_OMVS.R_UID.1 (the R_ prefix is discussed later). All fields are represented as potential list fields. A non-list field is treated like a list field with one element so we simply reference the '.1' element of the list. Following standard Rexx conventions, the '.0' element of each field indicates how many items are in the list.
IRRXUTIL returns a string containing a space separated list of return codes. If the first code in the list is 0, the request succeeded, go get your data. Otherwise look up the return codes in the aforementioned exciting documentation. Some common ones are '12 12 8 8 24' means you lack access to the r_admin function and '12 12 4 4 4' means profile not found.
Note that IRRXUTIL does not have any facility to make changes to profiles, but you can easily create and issue your favorite RACF commands directly from REXX.
Although IRRXUTIL gives you the ability
to iterate through all profiles of a given type via the Extractn
function, doing so frequently may increase RACF database activity to the point where it may impact
other parts of the system which are using RACF. Be nice to your database!
Referring the the above example, note that the segment and field name portion of the Rexx stem variable name are prefixed with 'R_'. The 'R_' corresponds to the 'R_' specified in the call to IRRXUTIL. You can change this prefix to anything you want, bit it should be something that you would never use as part of one of your Rexx variable names. Omitting the prefix is not a good idea because you risk variable name collisions.