Chapter 4. Building TMF for User Exits

User exits allow customers to add special routines to communicate with TMF without having access to the TMF source code. User exits allow a system process to examine and modify a structure associated with a tape file.

You can install the TMF release package with or without user exits. If you do not require user exits, then no further building of TMF is needed. If you require user exits, follow the instructions in “User Exit Implementation”.

For descriptions of the individual user exits, see “User Exits Requiring Configuration” and “User Exits Not Requiring Configuration”

User Exit Implementation

To implement user exits, it is necessary to modify and recompile the user exit files in the uex directory (uexcmd.c, uexmsg.c, uextmf.c, and vsnexit.c). To switch the individual or all user exits on or off, make an entry in the TMF configuration file.

Some user exits do not require configuration; those exits, which are defined in uexcmd.c, are used only by the TMF commands and do not require configuration (see “User Exits Not Requiring Configuration”).

The following is an example of the entry to add to the OPTIONS statement of the TMF configuration file:

user_exit_mask = (UEX_ASK_EXPDT,UEX_ASK_LBSW,UEX_ASK_RETRY),

The options for this entry are as follows:

UEX_ALL 

Enables all user exits

UEX_ASK_EXPDT 

Enables all uex_askexpdt user exits

UEX_ASK_HDR1 

Enables all uex_ask_hdr1 user exits

UEX_ASK_LBSW 

Enables all uex_asklbsw user exits

UEX_ASK_RETRY 

Enables all uex_askretry user exits

UEX_ASK_VERSCR 

Enables all uex_askverscr user exits

UEX_ASK_VSN 

Enables all uex_askvsn user exits

UEX_ASK_SCR_VSN 

Enables all uex_scr_vsn user exits

UEX_CHK_ACCESS 

Enable all uex_chk_access user exits

UEX_CLS_FILE 

Enable all uex_cls_file user exits

UEX_MAC_HDR2 

Enables all uex_mac_hdr2 user exits

UEX_MNT_MSG 

Enables all uex_mnt_msg user exits

UEX_SM_DEX 

Enables all uex_sm_dex user exits

UEX_SM_DUX 

Enables all uex_sm_dux user exits

UEX_SM_VAX 

Enables all uex_sm_vax user exits

UEX_SM_VUX 

Enables all uex_sm_vux user exits

UEX_START 

Enables the uex_start user exit

UEX_STOP 

Enables the uex_stop user exit

If an invalid option is used, an error message appears in the daemon.stderr file similar to the following:

TM425 - Error in file /etc/tmf/tmf.config, line 122, offset 49, with value "UEX_STOPP" : 
syntax error: expecting:

To modify and recompile the user exits, unpack the user exit code by entering the following instructions:

$ cd /usr/lib/tmf
$ tar -xvf uex.tar

These commands unpack the user exit tar file and create the uex directory. Examples on how to code user exits can be found in the distributed user exit files in the uex directory. Once the user exits have been modified, they can be recompiled by using the following commands:

$ cd /usr/lib/tmf
$ make TOPDIR=`pwd` uex

To complete the integration of the modified user exits into TMF, enter the following command:

$ make TOPDIR=`pwd` install

The TMF installation is now complete.

User Exits Requiring Configuration

User exits returning the values of 0 or -1 can use the defined symbolic values of YES (0) or NO (-1) defined in the tmuex.h file. Descriptions of TMF user exits that require configuration follow:

uex_askexpdt(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO. This exit returns an answer to the question “Can user userid write on unexpired VSN vsn?”

uex_asklbsw(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO. This exit returns an answer to the question “Can user userid switch from the original label label to new label for VSN vsn ?”

uex_askretry(uex_table, message_type, server_or_front-end, message_id, reason_for_retrying)
 

Receives the uex_table structure and the additional parameters as shown above and returns an integer value of YES or NO. It is called when the TMF daemon is unable to send a request to a front end or server and returns an answer to the question “Should message to the front end be re-sent or aborted?” The returned value of YES means to retry the request; NO means to cancel the request.

uex_askverscr(uex_table, vsn)
 

Receives the uex_table structure and a VSN. It returns an integer value of YES or NO. This exit returns an answer to the question “Is the vsn volume on the dvn device a valid scratch volume for the session identifier ?”

uex_askvsn(uex_table)
 

Receives the uex_table structure and returns either a character pointer with the value NULL or an address of a string. This exit returns an answer to the question “What is the VSN on the dvn device ?” The returned value of NULL means no VSN was returned while a pointer to a string is used as the value of the scratch VSN. If no VSN is returned, then the TMF daemon will call the askvsn() routine, just as if the user exit had not been taken.

uex_ask_hdr1(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO. This user exit is called from a child process in the TMF daemon at the point where the volume header (VOL1) and first file header (HDR1) labels have been read from a tape and the child process prepares to check some of the values in the HDR1 label against values that are kept by the TMF daemon and its child processes.

This user exit provides a site an opportunity to add code that enables the TMF daemon to do the following:

  • Obtain a number that controls how many characters of the file identifier field in a HDR1 label are compared to a character string kept by the TMF daemon or to an alternate character string that is provided by this user exit.

    The TMF daemon uses the number in the user_fidl field of the uex_table structure. If the site changes this number, the modified number must have a value that is equal to or greater than 1 and less than or equal to 16. The number must be returned in the user_fidl field, while the return value from this user exit must be YES. If NO is returned, the user_fidl field is not examined.

  • Obtain an alternate character string for the file identifier to be compared to the character string in the file identifier field in the HDR1 label from the tape.

    The character string that the TMF daemon uses is in the user_fid field of the uex_table structure. If the site changes this string, the modified character string must be stored in the user_fid field, while the return value from this user exit must be YES. If NO is returned, the user_fid field is not examined.

  • Obtain an alternate one-character string that, in the case of ANSI labels, is compared to the accessibility character string in the accessibility field in the HDR1 label from the tape. If the character strings match, the action that is taken is the same as the action taken for the space character as defined in the ANSI standard.

    The character string that the TMF daemon uses is in the user_vac field of the uex_table structure. If the site changes this string, the modified character string must be stored in the user_vac field, while the return value from this user exit must be YES. If NO is returned, the user_vac field is not examined.

If this user exit returns YES, the following actions occur:

  • The user_fidl field is checked for a number that is equal to or greater than 1 and less than or equal to 16. If the returned number is outside this range, the default value of 17 is used.

  • The contents of the user_fid field is copied into a TMF daemon structure.

  • The contents of the user_vac field is copied into a TMF daemon structure after it is checked against the following characters:

    A ... Z, 0 ... 9, " !\"%&'()*+,-./:;<=>?_"

If NO is returned, uex_table information is not used to update data structures in the TMF daemon.

uex_chk_access(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO.

This user exit is called from a child process in the TMF daemon at the point where the TMF daemon has accepted a tape volume to read from or to write to. It provides a site an opportunity to add code. For example, the code could allow or reject access to a tape volume after it has checked a locally maintained permission file.

When this user exit has been entered to check permission to access an output tape, the TMF daemon upon return from this user exit checks the user_error field of the uex_table structure. If this field contains error code ETNSC (90089 - not scratch), the TMF daemon rejects the tape volume. If more tape volumes have been specified in the tmmnt(1) command, tmmnt(1) tries the next tape volume.

Besides setting the user_error field to ETNSC, this user exit also sets the uex_table bit field uex_lst.flg.nsc to 1. The TMF daemon updates the fit field lst.flg.nsc with this information from the uex_table field.

If the user_error field contains any other error number, the TMF daemon upon return aborts the child process with error code EACCES (13 - permission denied). If this user exit returns the value NO, the TMF daemon aborts the child process with error code EACCES. If this user exit returns the value YES, the TMF daemon accepts the tape volume and processing continues.

When this user exit has been entered to check permission to access an input tape, the TMF daemon upon return from the user exit checks the return code. If the return code is NO, the tape volume is rejected and the child process aborts with error code EACCES . If the return code is YES, the tape volume is accepted and processing continues.

Besides the possible update of the lst.flg.nsc bit field in fit, no other information from uex_table is used to update data structures in the TMF daemon.

uex_cls_file(uex_table)
 

Receives the uex_table structure and returns. The TMF daemon upon return from this user exit does not update any of its information with information from uex_table.

This user exit is called from a child process in the TMF daemon after the tape processing is completed and when the tape file is about to be closed. The exit provides a site an opportunity to add code. For example, the code could enable the TMF daemon to add information to the tape.msg file concerning the tape volumes that were used while processing the tape file.

uex_mac_hdr2(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO.

This user exit is called from a child process in the TMF daemon after the TMF daemon reads the label information from the tape and has called the security code to check proper beginning-of-tape structure: VOL1, HDR1, and HDR2 labels. The user exit is called when a tape has a VOL1 and a HDR1 label, but not a HDR2 label. It provides a site an opportunity to add code, which could allow or reject access to the tape volume.

If this user exit returns the value NO, the TMF daemon continues its normal processing. It allows the tape to be overwritten, but not to be read. If the exit returns the value YES, the TMF daemon allows the user access to the tape. A return code of NO complies with security guidelines.

No information from the uex_table structure is used to update data structures in the TMF daemon.

uex_mnt_msg(uex_table)
 

Receives the uex_table structure and returns.

This user exit is called from either a child process or the TMF daemon itself after it has built a tape mount message and before it is sent to be processed. The exit provides a site an opportunity to add code, which could add information to the existing mount message or change it in any other way.

When the TMF daemon transfers control to this user exit, the user_buff field of the uex_table structure contains the address of the mount message character string and the user_bytes field of the uex_table structure contains the length in bytes of the memory block that are allocated to hold the mount message.

If this user exit extends the length of the delivered character string beyond the size of the allocated memory block, the user exit allocates the necessary memory to store the newly composed mount message. The address is returned to the TMF daemon in the user_buff location. The length in bytes of the newly allocated memory block is returned in the user_bytes field.

The update field in uex_table has to be set to a nonzero value.

If this user exit does not extend the length of the delivered character string beyond the size of the allocated memory block, the user exit does not have to allocate another memory block and the address in the user_buff field is left unaltered. The length in bytes of the allocated memory block in the user_bytes field also remains unaltered. The update field of the uex_table structure has to be set to zero.

When this user exit returns, the TMF daemon checks the value of the update field. If its value is zero, the TMF daemon continues its normal processing. It sends the mount message from the location it has allocated off to be processed.

If the value in the update field is nonzero, the TMF daemon compares the address of the memory block it has allocated for its mount message and the address that has been returned in the user_buff field. If these addresses are the same, the TMF daemon continues its normal processing. If these addresses differ, the TMF daemon frees the memory block it had allocated for its mount message and takes the address from the user_buff field as its replacement.

No other uex_table information is used to update data structures in the TMF daemon.

uex_scr_vsn(uex_table)
 

Receives the uex_table structure and returns either a character pointer with the value NULL or an address of a string.

This exit allows a site to specify the VSN for a scratch request.

The returned value of NULL means no VSN was returned while a pointer to a string is used as the value of the scratch VSN. If no VSN is returned, the TMF daemon uses the default scratch VSN, just as if the user exit had not been taken.

uex_sm_dex_1(uex_table)
 

Receives the uex_table structure and returns.

This user exit is called from a child process in the TMF daemon after the TMF daemon has built a dataset enquiry (dex) request for a servicing front end and before it is sent to be processed. The exit provides a site an opportunity to add code, which could add information to the existing dex request or change it in any other way.

When the TMF daemon transfers control to this user exit, the user_buff field of the uex_table structure contains the address of the dex request and the user_bytes field of the uex_table structure contains the length in bytes of the memory block that are allocated to hold the dex request. The festbls.h header file contains a layout of the data structures making up the format for the delivered dex request.

If this user exit extends the length of the delivered dex request beyond the size of the allocated memory block, it allocates the necessary memory to store the newly composed dex request. The address of this allocated memory block is returned to the TMF daemon in the user_buff location. The length in bytes of the newly allocated memory block is returned in the user_bytes field. The length in words of the newly composed dex request is returned in the user_wc field of the uex_table structure. The update field of the uex_table structure must be returned set to a nonzero value, while the yes_no field is returned set to YES.

If this user exit does not extend the length of the delivered dex request beyond the size of the allocated memory block, it does not have to allocate another memory block and the address in user_buff field remains unaltered. The length in bytes of the allocated memory block in the user_bytes field also remains unaltered. The length in words of the newly composed dex request is returned in the user_wc field. The update field is returned set to a nonzero value, while the yes_no field must be returned set to YES. If this user exit does not change the delivered dex request in any way, the update field must be returned set to zero, while the yes_no field is returned set to YES. If the user exit determines that the dex request should not be sent to the servicing front end, the yes_no field is returned set to NO.

When this user exit returns, the TMF daemon checks the value returned in the yes_no field. If the value in this field is NO, the TMF daemon does not send the request to the servicing front end and continues its processing.

If the value returned in the yes_no field is YES, the TMF daemon checks the value of the update field. If its value is zero, the TMF daemon continues its normal processing. It sends the dex request from the location it has allocated to the servicing front end to be processed. If the value in the update field is nonzero, the TMF daemon replaces its value of the length in words of the dex request with the value which is returned in the user_wc field. It compares the address of the memory block it has allocated for its dex request and the address which has been returned in the user_buff field. If these addresses are the same, the TMF daemon continues its normal processing. If these addresses differ, the TMF daemon frees the memory block it allocated for its dex request and takes the address from the user_buff field as its replacement, after which it continues its normal processing.

No other uex_table information is used to update data structures in the TMF daemon.

uex_sm_dux_2(uex_table)
 

Receives the uex_table structure and returns.

This user exit is called from a child process in the TMF daemon at the point where the TMF daemon receives a reply from the servicing front end to a dataset enquiry (dex) request and before it processes this reply. The exit provides a site an opportunity to add code, which could process the reply in accordance to site local requirements. When the TMF daemon transfers control to this user exit, the user_buff field of the uex_table structure contains the address of the dex reply and the user_bytes field contains the length in bytes of the memory block which has been allocated to hold the dex reply. The festbls.h header file contains a layout of the data structures making up the format of the delivered dex reply.

If the user exit determines that the servicing front end has returned a message in the reply, the address of the message is returned to the TMF daemon in the user_tmsgp field of the uex_table structure. It assures the message is properly processed. If the servicing front end has not returned a message in the reply field, user_tmsgp is zero.

The user_error field is provided in case the user exit encounters an error condition that has to abort the TMF daemon child process. When the user exit returns this field set to a nonzero value and the yes_no field of the uex_table structure set to value NO, the TMF daemon passes the value in user_error on to the abort function.

If this user exit completes without errors and updates information in the uex_table structure from the information delivered in the dex reply, it returns a nonzero value to the TMF daemon in the update field of the uex_table structure and in the yes_no field of the uex_table structure value YES. This causes various data structures in the TMF daemon to be updated with uex_table information. The uex_sm_dex_2() in the tmuex.c file contains an example which is based on the way the TMF daemon processes the dex reply. It shows the uex_table fields which have to be updated. If this user exit has determined that the TMF daemon has to do the processing of the dex reply and completes without updating the uex_table fields, exit returns to the TMF daemon with the yes_no field set to YES and the update field set to zero. This prevents the TMF daemon from updating its data structures with information from the uex_table structure. If the user exit relies on the TMF daemon to process the dex reply, the reply must be in the format the TMF daemon can handle.

uex_sm_vax(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO.

This exit returns an answer to the question “Can user uid access volume vsn?” It is called in place of the volume access request made to the front-end system.

This routine must validate access for a VSN and set the following:

  • Expiration information for the file

  • The allowed-permission-bits structure

Returning a nonzero value denies access to the dataset.

uex_sm_vux(uex_table)
 

Receives the uex_table structure and returns an integer value of YES or NO.

This exit provides the opportunity to update tables and log fields after a volume has been accessed. It is called in place of the volume access request made to the front-end system.

The return value YES means that the update was successful, while the return value NO means that the update failed.

User Exits Not Requiring Configuration

The following user exits are used by TMF commands and do not require user configuration:

uex_blp 

This exit allows a site to specify who, besides root, can bypass label processing.

Returning zero denies permission to bypass label processing.

uex_vsn_ok_to_use 

This exit allows a site to cancel a mount if the user is not allowed to use the specified volumes.

Returning zero denies use of the volumes.